diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 0b700b2a01d..e08d00c2cc2 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -1,6 +1,6 @@ --- # MegaLinter GitHub Action configuration file -# More info at https://oxsecurity.github.io/megalinter +# More info at https://megalinter.io name: MegaLinter 'on': [pull_request_target] @@ -17,7 +17,7 @@ concurrency: cancel-in-progress: true jobs: - build: + megalinter: name: MegaLinter runs-on: ubuntu-latest steps: @@ -38,11 +38,11 @@ jobs: - name: MegaLinter id: ml # You can override MegaLinter flavor used to have faster performances - # More info at https://oxsecurity.github.io/megalinter/flavors/ - uses: oxsecurity/megalinter@v6 + # More info at https://megalinter.io/flavors/ + uses: oxsecurity/megalinter@v7 env: # All available variables are described in documentation: - # https://oxsecurity.github.io/megalinter/configuration/ + # https://megalinter.io/configuration/ # Validates all source when push on master, else just the diff with # master. Override with true if you always want to lint all sources. VALIDATE_ALL_CODEBASE: false @@ -83,7 +83,7 @@ jobs: yourself and update the pull request, or merge this PR in yours. You can find how to run MegaLinter locally at - . + . # We do not create PRs if the branch is not there. continue-on-error: true diff --git a/.gitignore b/.gitignore index 14be3e78db7..4bc463b2cfc 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ compile_commands.json megalinter-reports/ .mypy_cache/ github_conf/ +.cache diff --git a/.mega-linter.yml b/.mega-linter.yml index 9e3581c67c9..7706edad085 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -17,10 +17,11 @@ DISABLE_LINTERS: - YAML_V8R - YAML_PRETTIER - REPOSITORY_DEVSKIM + - REPOSITORY_KICS - REPOSITORY_SECRETLINT - REPOSITORY_TRIVY DISABLE_ERRORS_LINTERS: # If errors are found by these linters, they will be considered as non blocking. - - PYTHON_BANDIT # The bandit check is overly broad and complains about subprocess usage in Scripts/update_ccdb.py. + - PYTHON_BANDIT # The bandit check is overly broad and complains about subprocess usage. SHOW_ELAPSED_TIME: true FILEIO_REPORTER: false GITHUB_COMMENT_REPORTER: false @@ -28,3 +29,6 @@ UPDATED_SOURCES_REPORTER: false PRINT_ALPACA: false # Don't print ASCII alpaca in the log PRINT_ALL_FILES: true # Print all processed files FLAVOR_SUGGESTIONS: false # Don't show suggestions about different MegaLinter flavors +PYTHON_ISORT_CONFIG_FILE: pyproject.toml +PYTHON_PYRIGHT_CONFIG_FILE: pyproject.toml +PYTHON_RUFF_CONFIG_FILE: pyproject.toml diff --git a/ALICE3/Core/DelphesO2TrackSmearer.cxx b/ALICE3/Core/DelphesO2TrackSmearer.cxx index 74e14591f74..f4ea4ebdf3c 100644 --- a/ALICE3/Core/DelphesO2TrackSmearer.cxx +++ b/ALICE3/Core/DelphesO2TrackSmearer.cxx @@ -110,7 +110,7 @@ bool TrackSmearer::loadTable(int pdg, const char* filename, bool forceReload) /*****************************************************************/ lutEntry_t* - TrackSmearer::getLUTEntry(int pdg, float nch, float radius, float eta, float pt) + TrackSmearer::getLUTEntry(int pdg, float nch, float radius, float eta, float pt, float& interpolatedEff) { auto ipdg = getIndexPDG(pdg); if (!mLUTHeader[ipdg]) @@ -119,13 +119,56 @@ lutEntry_t* auto irad = mLUTHeader[ipdg]->radmap.find(radius); auto ieta = mLUTHeader[ipdg]->etamap.find(eta); auto ipt = mLUTHeader[ipdg]->ptmap.find(pt); + + // Interpolate if requested + auto fraction = mLUTHeader[ipdg]->nchmap.fracPositionWithinBin(nch); + if (mInterpolateEfficiency) { + if (fraction > 0.5) { + if (mWhatEfficiency == 1) { + if (inch < mLUTHeader[ipdg]->nchmap.nbins - 1) { + interpolatedEff = (1.5f - fraction) * mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff + (-0.5f + fraction) * mLUTEntry[ipdg][inch + 1][irad][ieta][ipt]->eff; + } else { + interpolatedEff = mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff; + } + } + if (mWhatEfficiency == 2) { + if (inch < mLUTHeader[ipdg]->nchmap.nbins - 1) { + interpolatedEff = (1.5f - fraction) * mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff2 + (-0.5f + fraction) * mLUTEntry[ipdg][inch + 1][irad][ieta][ipt]->eff2; + } else { + interpolatedEff = mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff2; + } + } + } else { + float comparisonValue = mLUTHeader[ipdg]->nchmap.log ? log10(nch) : nch; + if (mWhatEfficiency == 1) { + if (inch > 0 && comparisonValue < mLUTHeader[ipdg]->nchmap.max) { + interpolatedEff = (0.5f + fraction) * mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff + (0.5f - fraction) * mLUTEntry[ipdg][inch - 1][irad][ieta][ipt]->eff; + } else { + interpolatedEff = mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff; + } + } + if (mWhatEfficiency == 2) { + if (inch > 0 && comparisonValue < mLUTHeader[ipdg]->nchmap.max) { + interpolatedEff = (0.5f + fraction) * mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff2 + (0.5f - fraction) * mLUTEntry[ipdg][inch - 1][irad][ieta][ipt]->eff2; + } else { + interpolatedEff = mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff2; + } + } + } + } else { + if (mWhatEfficiency == 1) + interpolatedEff = mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff; + if (mWhatEfficiency == 2) + interpolatedEff = mLUTEntry[ipdg][inch][irad][ieta][ipt]->eff2; + } return mLUTEntry[ipdg][inch][irad][ieta][ipt]; } //; /*****************************************************************/ -bool TrackSmearer::smearTrack(O2Track& o2track, lutEntry_t* lutEntry) +bool TrackSmearer::smearTrack(O2Track& o2track, lutEntry_t* lutEntry, float interpolatedEff) { + bool isReconstructed = true; // generate efficiency if (mUseEfficiency) { auto eff = 0.; @@ -133,9 +176,16 @@ bool TrackSmearer::smearTrack(O2Track& o2track, lutEntry_t* lutEntry) eff = lutEntry->eff; if (mWhatEfficiency == 2) eff = lutEntry->eff2; + if (mInterpolateEfficiency) + eff = interpolatedEff; if (gRandom->Uniform() > eff) - return false; + isReconstructed = false; } + + // return false already now in case not reco'ed + if (!isReconstructed && mSkipUnreconstructed) + return false; + // transform params vector and smear double params_[5]; for (int i = 0; i < 5; ++i) { @@ -158,7 +208,7 @@ bool TrackSmearer::smearTrack(O2Track& o2track, lutEntry_t* lutEntry) // set covariance matrix for (int i = 0; i < 15; ++i) o2track.setCov(lutEntry->covm[i], i); - return true; + return isReconstructed; } /*****************************************************************/ @@ -171,31 +221,62 @@ bool TrackSmearer::smearTrack(O2Track& o2track, int pdg, float nch) pt *= 2.f; } auto eta = o2track.getEta(); - auto lutEntry = getLUTEntry(pdg, nch, 0., eta, pt); + float interpolatedEff = 0.0f; + auto lutEntry = getLUTEntry(pdg, nch, 0., eta, pt, interpolatedEff); if (!lutEntry || !lutEntry->valid) return false; - return smearTrack(o2track, lutEntry); + return smearTrack(o2track, lutEntry, interpolatedEff); } /*****************************************************************/ // relative uncertainty on pt double TrackSmearer::getPtRes(int pdg, float nch, float eta, float pt) { - auto lutEntry = getLUTEntry(pdg, nch, 0., eta, pt); + float dummy = 0.0f; + auto lutEntry = getLUTEntry(pdg, nch, 0., eta, pt, dummy); auto val = sqrt(lutEntry->covm[14]) * lutEntry->pt; return val; } + /*****************************************************************/ // relative uncertainty on eta double TrackSmearer::getEtaRes(int pdg, float nch, float eta, float pt) { - auto lutEntry = getLUTEntry(pdg, nch, 0., eta, pt); - auto sigmatgl = sqrt(lutEntry->covm[9]); // sigmatgl2 - auto etaRes = 1 / (sqrt(1 + sigmatgl * sigmatgl)); // propagate tgl to eta uncertainty - etaRes /= lutEntry->eta; // relative uncertainty + float dummy = 0.0f; + auto lutEntry = getLUTEntry(pdg, nch, 0., eta, pt, dummy); + auto sigmatgl = sqrt(lutEntry->covm[9]); // sigmatgl2 + auto etaRes = fabs(sin(2.0 * atan(exp(-eta)))) * sigmatgl; // propagate tgl to eta uncertainty + etaRes /= lutEntry->eta; // relative uncertainty return etaRes; } +/*****************************************************************/ +// absolute uncertainty on pt +double TrackSmearer::getAbsPtRes(int pdg, float nch, float eta, float pt) +{ + float dummy = 0.0f; + auto lutEntry = getLUTEntry(pdg, nch, 0., eta, pt, dummy); + auto val = sqrt(lutEntry->covm[14]) * pow(lutEntry->pt, 2); + return val; +} +/*****************************************************************/ +// absolute uncertainty on eta +double TrackSmearer::getAbsEtaRes(int pdg, float nch, float eta, float pt) +{ + float dummy = 0.0f; + auto lutEntry = getLUTEntry(pdg, nch, 0., eta, pt, dummy); + auto sigmatgl = sqrt(lutEntry->covm[9]); // sigmatgl2 + auto etaRes = fabs(sin(2.0 * atan(exp(-eta)))) * sigmatgl; // propagate tgl to eta uncertainty + return etaRes; +} +/*****************************************************************/ +// efficiency +double TrackSmearer::getEfficiency(int pdg, float nch, float eta, float pt) +{ + float efficiency = 0.0f; + getLUTEntry(pdg, nch, 0., eta, pt, efficiency); + return efficiency; +} /*****************************************************************/ // Only in DelphesO2 // bool TrackSmearer::smearTrack(Track& track, bool atDCA) diff --git a/ALICE3/Core/DelphesO2TrackSmearer.h b/ALICE3/Core/DelphesO2TrackSmearer.h index 279fd9e3046..22a0bbd1346 100644 --- a/ALICE3/Core/DelphesO2TrackSmearer.h +++ b/ALICE3/Core/DelphesO2TrackSmearer.h @@ -53,7 +53,23 @@ struct map_t { if (log) return pow(10., val); return val; - } //; + } + // function needed to interpolate some dimensions + float fracPositionWithinBin(float val) + { + float width = (max - min) / nbins; + int bin; + float returnVal = 0.5f; + if (log) { + bin = static_cast((log10(val) - min) / width); + returnVal = ((log10(val) - min) / width) - bin; + } else { + bin = static_cast((val - min) / width); + returnVal = val / width - bin; + } + return returnVal; + } + int find(float val) { float width = (max - min) / nbins; @@ -162,15 +178,20 @@ class TrackSmearer /** LUT methods **/ bool loadTable(int pdg, const char* filename, bool forceReload = false); void useEfficiency(bool val) { mUseEfficiency = val; } //; + void interpolateEfficiency(bool val) { mInterpolateEfficiency = val; } //; + void skipUnreconstructed(bool val) { mSkipUnreconstructed = val; } //; void setWhatEfficiency(int val) { mWhatEfficiency = val; } //; lutHeader_t* getLUTHeader(int pdg) { return mLUTHeader[getIndexPDG(pdg)]; } //; - lutEntry_t* getLUTEntry(int pdg, float nch, float radius, float eta, float pt); + lutEntry_t* getLUTEntry(int pdg, float nch, float radius, float eta, float pt, float& interpolatedEff); - bool smearTrack(O2Track& o2track, lutEntry_t* lutEntry); + bool smearTrack(O2Track& o2track, lutEntry_t* lutEntry, float interpolatedEff); bool smearTrack(O2Track& o2track, int pdg, float nch); // bool smearTrack(Track& track, bool atDCA = true); // Only in DelphesO2 double getPtRes(int pdg, float nch, float eta, float pt); double getEtaRes(int pdg, float nch, float eta, float pt); + double getAbsPtRes(int pdg, float nch, float eta, float pt); + double getAbsEtaRes(int pdg, float nch, float eta, float pt); + double getEfficiency(int pdg, float nch, float eta, float pt); int getIndexPDG(int pdg) { @@ -203,6 +224,8 @@ class TrackSmearer lutHeader_t* mLUTHeader[nLUTs] = {nullptr}; lutEntry_t***** mLUTEntry[nLUTs] = {nullptr}; bool mUseEfficiency = true; + bool mInterpolateEfficiency = false; + bool mSkipUnreconstructed = true; // don't smear tracks that are not reco'ed int mWhatEfficiency = 1; float mdNdEta = 1600.; }; diff --git a/ALICE3/DataModel/A3DecayFinderTables.h b/ALICE3/DataModel/A3DecayFinderTables.h new file mode 100644 index 00000000000..cc7e8f3d3c7 --- /dev/null +++ b/ALICE3/DataModel/A3DecayFinderTables.h @@ -0,0 +1,61 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file A3DecayFinderTables.h +/// \since 04/07/2023 +/// \brief Set of tables for ALICE 3 decay finder +/// + +#ifndef ALICE3_DATAMODEL_A3DECAYFINDERTABLES_H_ +#define ALICE3_DATAMODEL_A3DECAYFINDERTABLES_H_ + +// O2 includes +#include "Framework/AnalysisDataModel.h" + +enum a3selectionBit : uint32_t { kDCAxy = 0, + kInnerTOFPion, + kInnerTOFKaon, + kInnerTOFProton, + kOuterTOFPion, + kOuterTOFKaon, + kOuterTOFProton, + kRICHPion, + kRICHKaon, + kRICHProton, + kTruePion, + kTrueKaon, + kTrueProton, + kTruePiPlusFromD, + kTrueKaPlusFromD, + kTruePiMinusFromD, + kTrueKaMinusFromD, + kTruePiPlusFromLc, + kTrueKaPlusFromLc, + kTruePrPlusFromLc, + kTruePiMinusFromLc, + kTrueKaMinusFromLc, + kTruePrMinusFromLc }; + +namespace o2::aod +{ +namespace a3DecayMap +{ +DECLARE_SOA_COLUMN(DecayMap, decayMap, uint32_t); //! simple map to process passing / not passing criteria +} // namespace a3DecayMap +DECLARE_SOA_TABLE(Alice3DecayMaps, "AOD", "ALICE3DECAYMAP", + a3DecayMap::DecayMap); + +using Alice3DecayMap = Alice3DecayMaps::iterator; + +} // namespace o2::aod + +#endif // ALICE3_DATAMODEL_A3DECAYFINDERTABLES_H_ diff --git a/ALICE3/DataModel/OTFRICH.h b/ALICE3/DataModel/OTFRICH.h new file mode 100644 index 00000000000..e853a2ff30f --- /dev/null +++ b/ALICE3/DataModel/OTFRICH.h @@ -0,0 +1,46 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file OTFRICH.h +/// \author Nicola Nicassio, University and INFN Bari +/// \since 15/05/2023 +/// \brief Set of tables for the ALICE 3 OTFRICH information +/// + +#ifndef ALICE3_DATAMODEL_OTFRICH_H_ +#define ALICE3_DATAMODEL_OTFRICH_H_ + +// O2 includes +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace upgrade_rich +{ +DECLARE_SOA_COLUMN(NSigmaElectronRich, nSigmaElectronRich, float); //! NSigma electron BarrelRich +DECLARE_SOA_COLUMN(NSigmaMuonRich, nSigmaMuonRich, float); //! NSigma muon BarrelRich +DECLARE_SOA_COLUMN(NSigmaPionRich, nSigmaPionRich, float); //! NSigma pion BarrelRich +DECLARE_SOA_COLUMN(NSigmaKaonRich, nSigmaKaonRich, float); //! NSigma kaon BarrelRich +DECLARE_SOA_COLUMN(NSigmaProtonRich, nSigmaProtonRich, float); //! NSigma proton BarrelRich +} // namespace upgrade_rich +DECLARE_SOA_TABLE(UpgradeRichs, "AOD", "UPGRADERICH", + upgrade_rich::NSigmaElectronRich, + upgrade_rich::NSigmaMuonRich, + upgrade_rich::NSigmaPionRich, + upgrade_rich::NSigmaKaonRich, + upgrade_rich::NSigmaProtonRich); + +using UpgradeRich = UpgradeRichs::iterator; + +} // namespace o2::aod + +#endif // ALICE3_DATAMODEL_OTFRICH_H_ diff --git a/ALICE3/DataModel/tracksAlice3.h b/ALICE3/DataModel/tracksAlice3.h new file mode 100644 index 00000000000..c3a3e82a994 --- /dev/null +++ b/ALICE3/DataModel/tracksAlice3.h @@ -0,0 +1,38 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file tracksAlice3.h +/// \author David Dobrigkeit Chinellato +/// \since 11/05/2023 +/// \brief Table for ALICE 3 track-related info +/// + +#ifndef ALICE3_DATAMODEL_TRACKSALICE3_H_ +#define ALICE3_DATAMODEL_TRACKSALICE3_H_ + +// O2 includes +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace track_alice3 +{ +DECLARE_SOA_COLUMN(IsReconstructed, isReconstructed, bool); //! is reconstructed or not +} // namespace track_alice3 +DECLARE_SOA_TABLE(TracksAlice3, "AOD", "TRACKSALICE3", + track_alice3::IsReconstructed); + +using TrackAlice3 = TracksAlice3::iterator; + +} // namespace o2::aod + +#endif // ALICE3_DATAMODEL_TRACKSALICE3_H_ diff --git a/ALICE3/TableProducer/CMakeLists.txt b/ALICE3/TableProducer/CMakeLists.txt index 72178be3179..52300bfc644 100644 --- a/ALICE3/TableProducer/CMakeLists.txt +++ b/ALICE3/TableProducer/CMakeLists.txt @@ -9,6 +9,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +add_subdirectory(OTF) + o2physics_add_dpl_workflow(alice3-trackselection SOURCES alice3-trackselection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -29,12 +31,8 @@ o2physics_add_dpl_workflow(alice3-centrality PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(onthefly-tracker - SOURCES onTheFlyTracker.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2Physics::ALICE3Core +o2physics_add_dpl_workflow(alice3-decayfinder + SOURCES alice3-decayfinder.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(onthefly-tofpid - SOURCES onTheFlyTOFPID.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats - COMPONENT_NAME Analysis) diff --git a/ALICE3/TableProducer/OTF/CMakeLists.txt b/ALICE3/TableProducer/OTF/CMakeLists.txt new file mode 100644 index 00000000000..305fcce4b66 --- /dev/null +++ b/ALICE3/TableProducer/OTF/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2physics_add_dpl_workflow(onthefly-tracker + SOURCES onTheFlyTracker.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2::DetectorsVertexing O2Physics::ALICE3Core + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(onthefly-tofpid + SOURCES onTheFlyTOFPID.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2Physics::ALICE3Core + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(onthefly-richpid + SOURCES onTheFlyRICHPID.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsCommonDataFormats O2Physics::ALICE3Core + COMPONENT_NAME Analysis) diff --git a/ALICE3/TableProducer/OTF/onTheFlyRICHPID.cxx b/ALICE3/TableProducer/OTF/onTheFlyRICHPID.cxx new file mode 100644 index 00000000000..82090899472 --- /dev/null +++ b/ALICE3/TableProducer/OTF/onTheFlyRICHPID.cxx @@ -0,0 +1,624 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// +// Task to add a table of track parameters propagated to the primary vertex +// + +#include +#include +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "CommonUtils/NameConf.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "TRandom3.h" +#include "TVector3.h" +#include "TString.h" +#include "ALICE3/DataModel/OTFRICH.h" +#include "DetectorsVertexing/HelixHelper.h" + +#include "TableHelper.h" +#include "ALICE3/Core/DelphesO2TrackSmearer.h" + +/// \file onTheFlyRichPid.cxx +/// +/// \brief This task goes straight from a combination of track table and mcParticles +/// and a projective bRICH configuration to a table of TOF NSigmas for the particles +/// being analysed. It currently contemplates 5 particle types: +/// electrons, pions, kaons, protons and muons. +/// +/// More particles could be added but would have to be added to the LUT +/// being used in the onTheFly tracker task. +/// +/// \warning Geometry parameters are configurable, but resolution values should be adapted. +/// Since angular resolution depends on the specific geometric details, it is better to +/// calculate it from full simulation and add new input. Alternatively, an analytical +/// expression can be provided as a function of the main parameters. +/// +/// \author David Dobrigkeit Chinellato, UNICAMP, Nicola Nicassio, University and INFN Bari + +using namespace o2; +using namespace o2::framework; + +struct OnTheFlyRichPid { + Produces upgradeRich; + + // necessary for particle charges + Service pdg; + + // master setting: magnetic field + Configurable dBz{"dBz", 20, "magnetic field (kilogauss)"}; + + // add rich-specific configurables here + Configurable bRichNumberOfSectors{"bRichNumberOfSectors", 21, "barrel RICH number of sectors"}; + Configurable bRichPhotodetectorCentralModuleHalfLength{"bRichPhotodetectorCentralModuleHalfLength", 18.4 / 2.0, "barrel RICH photodetector central module half length (cm)"}; + Configurable bRichPhotodetectorOtherModuleLength{"bRichPhotodetectorOtherModuleLength", 18.4, "barrel RICH photodetector other module length (cm)"}; + Configurable bRichRadiatorInnerRadius{"bRichRadiatorInnerRadius", 85., "barrel RICH radiator inner radius (cm)"}; + Configurable bRichPhotodetectorOuterRadius{"bRichPhotodetectorOuterRadius", 112., "barrel RICH photodetector outer radius (cm)"}; + Configurable bRichRadiatorThickness{"bRichRadiatorThickness", 2., "barrel RICH radiator thickness (cm)"}; + Configurable bRichRefractiveIndex{"bRichRefractiveIndex", 1.03, "barrel RICH refractive index"}; + Configurable bRichFlagAbsorbingWalls{"bRichFlagAbsorbingWalls", false, "barrel RICH flag absorbing walls between sectors"}; + Configurable nStepsLIntegrator{"nStepsLIntegrator", 200, "number of steps in length integrator"}; + Configurable doQAplots{"doQAplots", true, "do basic velocity plot qa"}; + Configurable nBinsThetaRing{"nBinsThetaRing", 3000, "number of bins in theta ring"}; + Configurable nBinsP{"nBinsP", 400, "number of bins in momentum"}; + Configurable nBinsNsigmaCorrectSpecies{"nBinsNsigmaCorrectSpecies", 200, "number of bins in Nsigma plot (correct speies)"}; + Configurable nBinsNsigmaWrongSpecies{"nBinsNsigmaWrongSpecies", 200, "number of bins in Nsigma plot (wrong species)"}; + Configurable nBinsAngularRes{"nBinsAngularRes", 400, "number of bins plots angular resolution"}; + Configurable nBinsRelativeEtaPt{"nBinsRelativeEtaPt", 400, "number of bins plots pt and eta relative errors"}; + Configurable nBinsEta{"nBinsEta", 400, "number of bins plot relative eta error"}; + Configurable flagIncludeTrackAngularRes{"flagIncludeTrackAngularRes", true, "flag to include or exclude track time resolution"}; + Configurable multiplicityEtaRange{"multiplicityEtaRange", 0.800000012, "eta range to compute the multiplicity"}; + Configurable flagRICHLoadDelphesLUTs{"flagRICHLoadDelphesLUTs", false, "flag to load Delphes LUTs for tracking correction (use recoTrack parameters if false)"}; + + Configurable lutEl{"lutEl", "lutCovm.el.dat", "LUT for electrons"}; + Configurable lutMu{"lutMu", "lutCovm.mu.dat", "LUT for muons"}; + Configurable lutPi{"lutPi", "lutCovm.pi.dat", "LUT for pions"}; + Configurable lutKa{"lutKa", "lutCovm.ka.dat", "LUT for kaons"}; + Configurable lutPr{"lutPr", "lutCovm.pr.dat", "LUT for protons"}; + + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + // Track smearer (here used to get relative pt and eta uncertainties) + o2::delphes::DelphesO2TrackSmearer mSmearer; + + // needed: random number generator for smearing + TRandom3 pRandomNumberGenerator; + + // for handling basic QA histograms if requested + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + /// Flag unphysical and unavailable values + float error_value = -1000; + + // Variables projective/hybrid layout + int mNumberSectors = bRichNumberOfSectors; // 21; + float mTileLength = bRichPhotodetectorOtherModuleLength; // 18.4; // [cm] + float mTileLengthCentral = bRichPhotodetectorCentralModuleHalfLength; // 18.4 / 2.0; // [cm] + float mProjectiveLengthInner = mTileLengthCentral; + float mRadiusProjIn = bRichRadiatorInnerRadius; // 85.; // [cm] + float mRadiusProjOut = bRichPhotodetectorOuterRadius; // 112.; // [cm] + std::vector det_centers; + std::vector rad_centers; + std::vector angle_centers; + std::vector theta_min; + std::vector theta_max; + + // Update projective geometry + void updateProjectiveParameters() + { + const int number_of_sectors_in_z = mNumberSectors; + det_centers.resize(number_of_sectors_in_z); + rad_centers.resize(number_of_sectors_in_z); + angle_centers.resize(number_of_sectors_in_z); + theta_min.resize(number_of_sectors_in_z); + theta_max.resize(number_of_sectors_in_z); + float square_size_barrel_cylinder = 2.0 * mTileLengthCentral; + float square_size_z = mTileLength; + float R_min = mRadiusProjIn; + float R_max = mRadiusProjOut; + std::vector theta_bi; + std::vector R0_tilt; + std::vector z0_tilt; + std::vector T_r_plus_g; + std::vector l_aerogel_z; + std::vector l_detector_z; + theta_bi.resize(number_of_sectors_in_z); + R0_tilt.resize(number_of_sectors_in_z); + z0_tilt.resize(number_of_sectors_in_z); + T_r_plus_g.resize(number_of_sectors_in_z); + l_aerogel_z.resize(number_of_sectors_in_z); + l_detector_z.resize(number_of_sectors_in_z); + + // Central sector + int i_central_mirror = static_cast((number_of_sectors_in_z) / 2.0); + float m_val = std::tan(0.0); + theta_bi[i_central_mirror] = std::atan(m_val); + R0_tilt[i_central_mirror] = R_max; + z0_tilt[i_central_mirror] = R0_tilt[i_central_mirror] * std::tan(theta_bi[i_central_mirror]); + l_detector_z[i_central_mirror] = square_size_barrel_cylinder; + l_aerogel_z[i_central_mirror] = std::sqrt(1.0 + m_val * m_val) * R_min * square_size_barrel_cylinder / (std::sqrt(1.0 + m_val * m_val) * R_max - m_val * square_size_barrel_cylinder); + T_r_plus_g[i_central_mirror] = R_max - R_min; + float t = std::tan(atan(m_val) + std::atan(square_size_barrel_cylinder / (2.0 * R_max * std::sqrt(1.0 + m_val * m_val) - square_size_barrel_cylinder * m_val))); + theta_max[i_central_mirror] = M_PI / 2.0 - std::atan(t); + theta_min[i_central_mirror] = M_PI / 2.0 + std::atan(t); + mProjectiveLengthInner = R_min * t; + for (int i = static_cast((number_of_sectors_in_z) / 2.0) + 1; i < number_of_sectors_in_z; i++) { + float par_a = t; + float par_b = 2.0 * R_max / square_size_z; + m_val = (std::sqrt(par_a * par_a * par_b * par_b + par_b * par_b - 1.0) + par_a * par_b * par_b) / (par_b * par_b - 1.0); + theta_min[i] = M_PI / 2.0 - std::atan(t); + theta_max[2 * i_central_mirror - i] = M_PI / 2.0 + std::atan(t); + t = std::tan(std::atan(m_val) + std::atan(square_size_z / (2.0 * R_max * std::sqrt(1.0 + m_val * m_val) - square_size_z * m_val))); + theta_max[i] = M_PI / 2.0 - std::atan(t); + theta_min[2 * i_central_mirror - i] = M_PI / 2.0 + std::atan(t); + // Forward sectors + theta_bi[i] = std::atan(m_val); + R0_tilt[i] = R_max - square_size_z / 2.0 * std::sin(std::atan(m_val)); + z0_tilt[i] = R0_tilt[i] * std::tan(theta_bi[i]); + l_detector_z[i] = square_size_z; + l_aerogel_z[i] = std::sqrt(1.0 + m_val * m_val) * R_min * square_size_z / (std::sqrt(1.0 + m_val * m_val) * R_max - m_val * square_size_z); + T_r_plus_g[i] = std::sqrt(1.0 + m_val * m_val) * (R_max - R_min) - m_val / 2.0 * (square_size_z + l_aerogel_z[i]); + // Backword sectors + theta_bi[2 * i_central_mirror - i] = -std::atan(m_val); + R0_tilt[2 * i_central_mirror - i] = R_max - square_size_z / 2.0 * std::sin(std::atan(m_val)); + z0_tilt[2 * i_central_mirror - i] = -R0_tilt[i] * std::tan(theta_bi[i]); + l_detector_z[2 * i_central_mirror - i] = square_size_z; + l_aerogel_z[2 * i_central_mirror - i] = std::sqrt(1.0 + m_val * m_val) * R_min * square_size_z / (std::sqrt(1.0 + m_val * m_val) * R_max - m_val * square_size_z); + T_r_plus_g[2 * i_central_mirror - i] = std::sqrt(1.0 + m_val * m_val) * (R_max - R_min) - m_val / 2.0 * (square_size_z + l_aerogel_z[i]); + mProjectiveLengthInner = R_min * t; // <-- At the end of the loop this will be the maximum Z + } + // Coordinate radiali layer considerati + std::vector R0_detector; + std::vector R0_aerogel; + R0_detector.resize(number_of_sectors_in_z); + R0_aerogel.resize(number_of_sectors_in_z); + for (int i = 0; i < number_of_sectors_in_z; i++) { + R0_detector[i] = R0_tilt[i]; + det_centers[i].SetXYZ(R0_detector[i], 0, R0_detector[i] * std::tan(theta_bi[i])); + R0_aerogel[i] = R0_tilt[i] - (T_r_plus_g[i]) * std::cos(theta_bi[i]); + rad_centers[i].SetXYZ(R0_aerogel[i], 0, R0_aerogel[i] * std::tan(theta_bi[i])); + angle_centers[i] = theta_bi[i]; + } + } + + void init(o2::framework::InitContext& initContext) + { + pRandomNumberGenerator.SetSeed(0); // fully randomize + + // Load LUT for pt and eta smearing + if (flagIncludeTrackAngularRes && flagRICHLoadDelphesLUTs) { + std::map mapPdgLut; + const char* lutElChar = lutEl->c_str(); + const char* lutMuChar = lutMu->c_str(); + const char* lutPiChar = lutPi->c_str(); + const char* lutKaChar = lutKa->c_str(); + const char* lutPrChar = lutPr->c_str(); + + LOGF(info, "Will load electron lut file ..: %s for RICH PID", lutElChar); + LOGF(info, "Will load muon lut file ......: %s for RICH PID", lutMuChar); + LOGF(info, "Will load pion lut file ......: %s for RICH PID", lutPiChar); + LOGF(info, "Will load kaon lut file ......: %s for RICH PID", lutKaChar); + LOGF(info, "Will load proton lut file ....: %s for RICH PID", lutPrChar); + + mapPdgLut.insert(std::make_pair(11, lutElChar)); + mapPdgLut.insert(std::make_pair(13, lutMuChar)); + mapPdgLut.insert(std::make_pair(211, lutPiChar)); + mapPdgLut.insert(std::make_pair(321, lutKaChar)); + mapPdgLut.insert(std::make_pair(2212, lutPrChar)); + + for (auto e : mapPdgLut) { + if (!mSmearer.loadTable(e.first, e.second)) { + LOG(fatal) << "Having issue with loading the LUT " << e.first << " " << e.second; + } + } + } + + if (doQAplots) { + const AxisSpec axisMomentum{static_cast(nBinsP), 0.0f, +20.0f, "#it{p} (GeV/#it{c})"}; + const AxisSpec axisAngle{static_cast(nBinsThetaRing), 0.0f, +0.30f, "Measured Cherenkov angle (rad)"}; + histos.add("h2dAngleVsMomentumBarrelRICH", "h2dAngleVsMomentumBarrelRICH", kTH2F, {axisMomentum, axisAngle}); + + std::string particle_names1[5] = {"#it{e}", "#it{#mu}", "#it{#pi}", "#it{K}", "#it{p}"}; + std::string particle_names2[5] = {"Elec", "Muon", "Pion", "Kaon", "Prot"}; + for (int i_true = 0; i_true < 5; i_true++) { + std::string name_title_barrel_track_res = "h2dBarrelAngularResTrack" + particle_names2[i_true] + "VsP"; + std::string name_title_barrel_total_res = "h2dBarrelAngularResTotal" + particle_names2[i_true] + "VsP"; + const AxisSpec axisTrackAngularRes{static_cast(nBinsAngularRes), 0.0f, +5.0f, "Track angular resolution - " + particle_names1[i_true] + " (mrad)"}; + const AxisSpec axisTotalAngularRes{static_cast(nBinsAngularRes), 0.0f, +5.0f, "Total angular resolution - " + particle_names1[i_true] + " (mrad)"}; + histos.add(name_title_barrel_track_res.c_str(), name_title_barrel_track_res.c_str(), kTH2F, {axisMomentum, axisTrackAngularRes}); + histos.add(name_title_barrel_total_res.c_str(), name_title_barrel_total_res.c_str(), kTH2F, {axisMomentum, axisTotalAngularRes}); + } + for (int i_true = 0; i_true < 5; i_true++) { + for (int i_hyp = 0; i_hyp < 5; i_hyp++) { + std::string name_title = "h2dBarrelNsigmaTrue" + particle_names2[i_true] + "Vs" + particle_names2[i_hyp] + "Hypothesis"; + if (i_true == i_hyp) { + const AxisSpec axisNsigmaCorrect{static_cast(nBinsNsigmaCorrectSpecies), -10.0f, +10.0f, "N#sigma - True " + particle_names1[i_true] + " vs " + particle_names1[i_hyp] + " hypothesis"}; + histos.add(name_title.c_str(), name_title.c_str(), kTH2F, {axisMomentum, axisNsigmaCorrect}); + } else { + const AxisSpec axisNsigmaWrong{static_cast(nBinsNsigmaWrongSpecies), -10.0f, +10.0f, "N#sigma - True " + particle_names1[i_true] + " vs " + particle_names1[i_hyp] + " hypothesis"}; + histos.add(name_title.c_str(), name_title.c_str(), kTH2F, {axisMomentum, axisNsigmaWrong}); + } + } + } + } + + // Update projective parameters + updateProjectiveParameters(); + } + + /// Function to convert a McParticle into a perfect Track + /// \param particle the particle to convert (mcParticle) + /// \param o2track the address of the resulting TrackParCov + template + o2::track::TrackParCov convertMCParticleToO2Track(McParticleType& particle) + { + // FIXME: this is a fundamentally important piece of code. + // It could be placed in a utility file instead of here. + auto pdgInfo = pdg->GetParticle(particle.pdgCode()); + int charge = 0; + if (pdgInfo != nullptr) { + charge = pdgInfo->Charge() / 3; + } + std::array params; + std::array covm = {0.}; + float s, c, x; + o2::math_utils::sincos(particle.phi(), s, c); + o2::math_utils::rotateZInv(particle.vx(), particle.vy(), x, params[0], s, c); + params[1] = particle.vz(); + params[2] = 0.; // since alpha = phi + auto theta = 2. * std::atan(std::exp(-particle.eta())); + params[3] = 1. / std::tan(theta); + params[4] = charge / particle.pt(); + + // Return TrackParCov + return o2::track::TrackParCov(x, particle.phi(), params, covm); + } + + /// check if particle reaches radiator + /// \param track the input track + /// \param radius the radius of the layer you're calculating the length to + /// \param magneticField the magnetic field to use when propagating + bool checkMagfieldLimit(o2::track::TrackParCov track, float radius, float magneticField) + { + o2::math_utils::CircleXYf_t trcCircle; + float sna, csa; + track.getCircleParams(magneticField, trcCircle, sna, csa); + + // distance between circle centers (one circle is at origin -> easy) + float centerDistance = std::hypot(trcCircle.xC, trcCircle.yC); + + // condition of circles touching - if not satisfied returned value if false + if (centerDistance < trcCircle.rC + radius && centerDistance > std::fabs(trcCircle.rC - radius)) { + return true; + } else { + return false; + } + } + + /// returns radiator radius in cm at considered eta (accounting for sector inclination) + /// \param eta the pseudorapidity of the tarck (assuming primary vertex at origin) + float radiusRipple(float eta) + { + float polar = 2.0 * std::atan(std::exp(-eta)); + float i_sector = 0; + bool flag_sector = false; + for (int j_sec = 0; j_sec < mNumberSectors; j_sec++) { + if (polar > theta_max[j_sec] && polar < theta_min[j_sec]) { + flag_sector = true; + i_sector = j_sec; + } + } + if (flag_sector) { + float R_sec_rich = rad_centers[i_sector].X(); + float z_sec_rich = rad_centers[i_sector].Z(); + return (std::pow(R_sec_rich, 2) + std::pow(z_sec_rich, 2)) / (R_sec_rich + z_sec_rich / std::tan(polar)); + } else { + return error_value; + } + } + + /// returns Cherenkov angle in rad (above threshold) or bad flag (below threshold) + /// \param momentum the momentum of the tarck + /// \param mass the mass of the particle + float CherenkovAngle(float momentum, float mass) + { + // Check if particle is above the threshold + if (momentum > mass / std::sqrt(bRichRefractiveIndex * bRichRefractiveIndex - 1.0)) { + // Calculate angle + float angle = std::acos(std::sqrt(momentum * momentum + mass * mass) / (momentum * bRichRefractiveIndex)); + + // Mean number of detected photons (SiPM PDE is accountd in multiplicative factor!!!) + float meanNumberofDetectedPhotons = 230. * std::sin(angle) * std::sin(angle) * bRichRadiatorThickness; + + // Require at least 3 photons on average for real angle reconstruction + if (meanNumberofDetectedPhotons > 3.) { + return angle; + } else { + return error_value; + } + } else { + return error_value; + } + } + + /// returns linear interpolation + /// \param x the eta we want the resolution for + /// \param x0 the closest smaller available eta + /// \param x1 the closest larger available eta + /// \param y0 the resolution corresponding to x0 + /// \param y1 the resolution corresponding to x1 + float interpolate(double x, double x0, double x1, double y0, double y1) + { + float y = y0 + ((y1 - y0) / (x1 - x0)) * (x - x0); + return y; + } + + /// returns angular resolution for considered track eta + /// \param eta the pseudorapidity of the tarck (assuming primary vertex at origin) + float AngularResolution(float eta) + { + // Vectors for sampling (USE ANALYTICAL EXTRAPOLATION FOR BETTER RESULTS) + float eta_sampling[] = {-2.000000, -1.909740, -1.731184, -1.552999, -1.375325, -1.198342, -1.022276, -0.847390, -0.673976, -0.502324, -0.332683, -0.165221, 0.000000, 0.165221, 0.332683, 0.502324, 0.673976, 0.847390, 1.022276, 1.198342, 1.375325, 1.552999, 1.731184, 1.909740, 2.000000}; + float res_ring_sampling_with_abs_walls[] = {0.0009165, 0.000977, 0.001098, 0.001198, 0.001301, 0.001370, 0.001465, 0.001492, 0.001498, 0.001480, 0.001406, 0.001315, 0.001241, 0.001325, 0.001424, 0.001474, 0.001480, 0.001487, 0.001484, 0.001404, 0.001273, 0.001197, 0.001062, 0.000965, 0.0009165}; + float res_ring_sampling_without_abs_walls[] = {0.0009165, 0.000977, 0.001095, 0.001198, 0.001300, 0.001369, 0.001468, 0.001523, 0.001501, 0.001426, 0.001299, 0.001167, 0.001092, 0.001179, 0.001308, 0.001407, 0.001491, 0.001508, 0.001488, 0.001404, 0.001273, 0.001196, 0.001061, 0.000965, 0.0009165}; + int size_res_vector = sizeof(eta_sampling) / sizeof(eta_sampling[0]); + // Use binary search to find the lower and upper indices + int lowerIndex = std::lower_bound(eta_sampling, eta_sampling + size_res_vector, eta) - eta_sampling - 1; + int upperIndex = lowerIndex + 1; + if (lowerIndex >= 0 && upperIndex < size_res_vector) { + // Resolution interpolation + if (bRichFlagAbsorbingWalls) { + float interpolatedResRing = interpolate(eta, eta_sampling[lowerIndex], eta_sampling[upperIndex], res_ring_sampling_with_abs_walls[lowerIndex], res_ring_sampling_with_abs_walls[upperIndex]); + // std::cout << "Interpolated y value: " << interpolatedY << std::endl; + return interpolatedResRing; + } else { + float interpolatedResRing = interpolate(eta, eta_sampling[lowerIndex], eta_sampling[upperIndex], res_ring_sampling_without_abs_walls[lowerIndex], res_ring_sampling_without_abs_walls[upperIndex]); + // std::cout << "Interpolated y value: " << interpolatedY << std::endl; + return interpolatedResRing; + } + } else { + // std::cout << "Unable to interpolate. Target x value is outside the range of available data." << std::endl; + return error_value; + } + } + + /// returns track angular resolution + /// \param pt the transverse momentum of the tarck + /// \param eta the pseudorapidity of the tarck + /// \param track_pt_resolution the absolute resolution on pt + /// \param track_pt_resolution the absolute resolution on eta + /// \param mass the mass of the particle + /// \param refractive_index the refractive index of the radiator + double calculate_track_time_resolution_advanced(float pt, float eta, float track_pt_resolution, float track_eta_resolution, float mass, float refractive_index) + { + // Compute tracking contribution to timing using the error propagation formula + // Uses light speed in m/ps, magnetic field in T (*0.1 for conversion kGauss -> T) + double a0 = mass * mass; + double a1 = refractive_index; + double dtheta_on_dpt = a0 / (pt * std::sqrt(a0 + std::pow(pt * std::cosh(eta), 2)) * std::sqrt(std::pow(pt * std::cosh(eta), 2) * (std::pow(a1, 2) - 1.0) - a0)); + double dtheta_on_deta = (a0 * std::tanh(eta)) / (std::sqrt(a0 + std::pow(pt * std::cosh(eta), 2)) * std::sqrt(std::pow(pt * std::cosh(eta), 2) * (std::pow(a1, 2) - 1.0) - a0)); + double track_angular_resolution = std::hypot(std::fabs(dtheta_on_dpt) * track_pt_resolution, std::fabs(dtheta_on_deta) * track_eta_resolution); + return track_angular_resolution; + } + + void process(soa::Join::iterator const& collision, soa::Join const& tracks, aod::McParticles const&, aod::McCollisions const&) + { + + o2::dataformats::VertexBase pvVtx({collision.posX(), collision.posY(), collision.posZ()}, + {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}); + + std::array mcPvCov = {0.}; + o2::dataformats::VertexBase mcPvVtx({0.0f, 0.0f, 0.0f}, mcPvCov); + if (collision.has_mcCollision()) { + auto mcCollision = collision.mcCollision(); + mcPvVtx.setX(mcCollision.posX()); + mcPvVtx.setY(mcCollision.posY()); + mcPvVtx.setZ(mcCollision.posZ()); + } // else remains untreated for now + + // First we compute the number of charged particles in the event + float dNdEta = 0.f; + if (flagRICHLoadDelphesLUTs) { + for (const auto& track : tracks) { + if (!track.has_mcParticle()) + continue; + auto mcParticle = track.mcParticle(); + if (std::abs(mcParticle.eta()) > multiplicityEtaRange) { + continue; + } + if (mcParticle.has_daughters()) { + continue; + } + const auto& pdgInfo = pdg->GetParticle(mcParticle.pdgCode()); + if (!pdgInfo) { + // LOG(warning) << "PDG code " << mcParticle.pdgCode() << " not found in the database"; + continue; + } + if (pdgInfo->Charge() == 0) { + continue; + } + dNdEta += 1.f; + } + } + + for (const auto& track : tracks) { + // first step: find precise arrival time (if any) + // --- convert track into perfect track + if (!track.has_mcParticle()) // should always be OK but check please + continue; + + auto mcParticle = track.mcParticle(); + o2::track::TrackParCov o2track = convertMCParticleToO2Track(mcParticle); + + // float xPv = error_value; + if (o2track.propagateToDCA(mcPvVtx, dBz)) { + // xPv = o2track.getX(); + } + + // get particle to calculate Cherenkov angle and resolution + auto pdgInfo = pdg->GetParticle(mcParticle.pdgCode()); + if (pdgInfo == nullptr) { + continue; + } + float expectedAngleBarrelRich = CherenkovAngle(o2track.getP(), pdgInfo->Mass()); + float barrelRICHAngularResolution = AngularResolution(o2track.getEta()); + float projectiveRadiatorRadius = radiusRipple(o2track.getEta()); + bool flagReachesRadiator = false; + if (projectiveRadiatorRadius > error_value + 1.) { + flagReachesRadiator = checkMagfieldLimit(o2track, projectiveRadiatorRadius, dBz); + } + /// DISCLAIMER: Exact extrapolation of angular resolution would require track propagation + /// to the RICH radiator (accounting sector inclination) in terms of (R,z). + /// The extrapolation with Eta is correct only if the primary vertex is at origin. + /// Discrepancies may be negligible, but would be more rigorous if propagation tool is available + + // Smear with expected resolutions + float measuredAngleBarrelRich = pRandomNumberGenerator.Gaus(expectedAngleBarrelRich, barrelRICHAngularResolution); + + // Now we calculate the expected arrival time following certain mass hypotheses + // and the (imperfect!) reconstructed track parametrizations + auto recoTrack = getTrackParCov(track); + if (recoTrack.propagateToDCA(pvVtx, dBz)) { + // xPv = recoTrack.getX(); + } + + // Straight to Nsigma + float deltaThetaBarrelRich[5], nSigmaBarrelRich[5]; + int lpdg_array[5] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton}; + float masses[5]; + + for (int ii = 0; ii < 5; ii++) { + nSigmaBarrelRich[ii] = error_value; + + auto pdgInfoThis = pdg->GetParticle(lpdg_array[ii]); + masses[ii] = pdgInfoThis->Mass(); + float hypothesisAngleBarrelRich = CherenkovAngle(recoTrack.getP(), masses[ii]); + + // Evaluate total sigma (layer + tracking resolution) + float barrelTotalAngularReso = barrelRICHAngularResolution; + if (flagIncludeTrackAngularRes) { + double pt_resolution = std::pow(recoTrack.getP() / std::cosh(recoTrack.getEta()), 2) * std::sqrt(recoTrack.getSigma1Pt2()); + double eta_resolution = std::fabs(std::sin(2.0 * std::atan(std::exp(-recoTrack.getEta())))) * std::sqrt(recoTrack.getSigmaTgl2()); + if (flagRICHLoadDelphesLUTs) { + pt_resolution = mSmearer.getAbsPtRes(pdgInfoThis->PdgCode(), dNdEta, recoTrack.getEta(), recoTrack.getP() / std::cosh(recoTrack.getEta())); + eta_resolution = mSmearer.getAbsEtaRes(pdgInfoThis->PdgCode(), dNdEta, recoTrack.getEta(), recoTrack.getP() / std::cosh(recoTrack.getEta())); + } + // cout << endl << "Pt resolution: " << pt_resolution << ", Eta resolution: " << eta_resolution << endl << endl; + float barrelTrackAngularReso = calculate_track_time_resolution_advanced(recoTrack.getP() / std::cosh(recoTrack.getEta()), recoTrack.getEta(), pt_resolution, eta_resolution, masses[ii], bRichRefractiveIndex); + barrelTotalAngularReso = std::hypot(barrelRICHAngularResolution, barrelTrackAngularReso); + if (doQAplots && hypothesisAngleBarrelRich > error_value + 1. && measuredAngleBarrelRich > error_value + 1. && barrelRICHAngularResolution > error_value + 1. && flagReachesRadiator) { + float momentum = recoTrack.getP(); + // float pseudorapidity = recoTrack.getEta(); + // float transverse_momentum = momentum / std::cosh(pseudorapidity); + if (ii == 0 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[0])->PdgCode()) { + histos.fill(HIST("h2dBarrelAngularResTrackElecVsP"), momentum, 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalElecVsP"), momentum, 1000.0 * barrelTotalAngularReso); + } + if (ii == 1 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[1])->PdgCode()) { + histos.fill(HIST("h2dBarrelAngularResTrackMuonVsP"), momentum, 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalMuonVsP"), momentum, 1000.0 * barrelTotalAngularReso); + } + if (ii == 2 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[2])->PdgCode()) { + histos.fill(HIST("h2dBarrelAngularResTrackPionVsP"), momentum, 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalPionVsP"), momentum, 1000.0 * barrelTotalAngularReso); + } + if (ii == 3 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[3])->PdgCode()) { + histos.fill(HIST("h2dBarrelAngularResTrackKaonVsP"), momentum, 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalKaonVsP"), momentum, 1000.0 * barrelTotalAngularReso); + } + if (ii == 4 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[4])->PdgCode()) { + histos.fill(HIST("h2dBarrelAngularResTrackProtVsP"), momentum, 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalProtVsP"), momentum, 1000.0 * barrelTotalAngularReso); + } + } + } + + /// DISCLAIMER: here tracking is accounted only for momentum value, but not for track parameters at impact point on the + /// RICH radiator, since exact resolution would require photon generation and transport to photodetector. + /// Effects are expected to be negligible (a few tenths of a milliradian) but further studies are required ! + if (hypothesisAngleBarrelRich > error_value + 1. && measuredAngleBarrelRich > error_value + 1. && barrelRICHAngularResolution > error_value + 1. && flagReachesRadiator) { + deltaThetaBarrelRich[ii] = hypothesisAngleBarrelRich - measuredAngleBarrelRich; + nSigmaBarrelRich[ii] = deltaThetaBarrelRich[ii] / barrelTotalAngularReso; + } + } + + // Fill histograms + if (doQAplots) { + float momentum = recoTrack.getP(); + float barrelRichTheta = measuredAngleBarrelRich; + + if (barrelRichTheta > error_value + 1. && barrelRICHAngularResolution > error_value + 1. && flagReachesRadiator) { + histos.fill(HIST("h2dAngleVsMomentumBarrelRICH"), momentum, barrelRichTheta); + + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[0])->PdgCode()) { + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[1])->PdgCode()) { + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[2])->PdgCode()) { + histos.fill(HIST("h2dBarrelNsigmaTruePionVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTruePionVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTruePionVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTruePionVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTruePionVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[3])->PdgCode()) { + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[4])->PdgCode()) { + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); + } + } + } + + // Sigmas have been fully calculated. Please populate the NSigma helper table (once per track) + upgradeRich(nSigmaBarrelRich[0], nSigmaBarrelRich[1], nSigmaBarrelRich[2], nSigmaBarrelRich[3], nSigmaBarrelRich[4]); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/TableProducer/OTF/onTheFlyTOFPID.cxx b/ALICE3/TableProducer/OTF/onTheFlyTOFPID.cxx new file mode 100644 index 00000000000..f9d0aa4cb7e --- /dev/null +++ b/ALICE3/TableProducer/OTF/onTheFlyTOFPID.cxx @@ -0,0 +1,604 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// +// Task to add a table of track parameters propagated to the primary vertex +// + +#include +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "CommonUtils/NameConf.h" +#include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "TRandom3.h" +#include "ALICE3/DataModel/OTFTOF.h" +#include "DetectorsVertexing/HelixHelper.h" +#include "TableHelper.h" +#include "ALICE3/Core/DelphesO2TrackSmearer.h" + +/// \file onTheFlyTOFPID.cxx +/// +/// \brief This task goes straight from a combination of track table and mcParticles +/// and a custom TOF configuration to a table of TOF NSigmas for the particles +/// being analysed. It currently contemplates 5 particle types: +/// electrons, pions, kaons, protons and muons +/// +/// More particles could be added but would have to be added to the LUT +/// being used in the onTheFly tracker task. +/// +/// \author David Dobrigkeit Chinellato, UNICAMP, Nicola Nicassio, University and INFN Bari + +using namespace o2; +using namespace o2::framework; + +struct OnTheFlyTOFPID { + Produces upgradeTof; + + // necessary for particle charges + Service pdg; + + // these are the settings governing the TOF layers to be used + // note that there are two layers foreseen for now: inner and outer TOF + // more could be added (especially a disk TOF at a certain z?) + // in the evolution of this effort + Configurable dBz{"dBz", 20, "magnetic field (kilogauss)"}; + Configurable innerTOFRadius{"innerTOFRadius", 20, "barrel inner TOF radius (cm)"}; + Configurable outerTOFRadius{"outerTOFRadius", 80, "barrel outer TOF radius (cm)"}; + Configurable innerTOFTimeReso{"innerTOFTimeReso", 20, "barrel inner TOF time error (ps)"}; + Configurable outerTOFTimeReso{"outerTOFTimeReso", 20, "barrel outer TOF time error (ps)"}; + Configurable nStepsLIntegrator{"nStepsLIntegrator", 200, "number of steps in length integrator"}; + Configurable doQAplots{"doQAplots", true, "do basic velocity plot qa"}; + Configurable nBinsBeta{"nBinsBeta", 2200, "number of bins in beta"}; + Configurable nBinsP{"nBinsP", 80, "number of bins in momentum"}; + Configurable nBinsTrackLengthInner{"nBinsTrackLengthInner", 300, "number of bins in track length"}; + Configurable nBinsTrackLengthOuter{"nBinsTrackLengthOuter", 300, "number of bins in track length"}; + Configurable nBinsTrackDeltaLength{"nBinsTrackDeltaLength", 100, "number of bins in delta track length"}; + Configurable nBinsNsigmaCorrectSpecies{"nBinsNsigmaCorrectSpecies", 200, "number of bins in Nsigma plot (correct speies)"}; + Configurable nBinsNsigmaWrongSpecies{"nBinsNsigmaWrongSpecies", 200, "number of bins in Nsigma plot (wrong species)"}; + Configurable nBinsTimeRes{"nBinsTimeRes", 400, "number of bins plots time resolution"}; + Configurable nBinsRelativeEtaPt{"nBinsRelativeEtaPt", 400, "number of bins plots pt and eta relative errors"}; + Configurable nBinsEta{"nBinsEta", 400, "number of bins plot relative eta error"}; + Configurable flagIncludeTrackTimeRes{"flagIncludeTrackTimeRes", true, "flag to include or exclude track time resolution"}; + Configurable multiplicityEtaRange{"multiplicityEtaRange", 0.800000012, "eta range to compute the multiplicity"}; + Configurable flagTOFLoadDelphesLUTs{"flagTOFLoadDelphesLUTs", false, "flag to load Delphes LUTs for tracking correction (use recoTrack parameters if false)"}; + + Configurable lutEl{"lutEl", "lutCovm.el.dat", "LUT for electrons"}; + Configurable lutMu{"lutMu", "lutCovm.mu.dat", "LUT for muons"}; + Configurable lutPi{"lutPi", "lutCovm.pi.dat", "LUT for pions"}; + Configurable lutKa{"lutKa", "lutCovm.ka.dat", "LUT for kaons"}; + Configurable lutPr{"lutPr", "lutCovm.pr.dat", "LUT for protons"}; + + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + // Track smearer (here used to get absolute pt and eta uncertainties if flagTOFLoadDelphesLUTs is true) + o2::delphes::DelphesO2TrackSmearer mSmearer; + + // needed: random number generator for smearing + TRandom3 pRandomNumberGenerator; + + // for handling basic QA histograms if requested + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext& initContext) + { + pRandomNumberGenerator.SetSeed(0); // fully randomize + + // Load LUT for pt and eta smearing + if (flagIncludeTrackTimeRes && flagTOFLoadDelphesLUTs) { + std::map mapPdgLut; + const char* lutElChar = lutEl->c_str(); + const char* lutMuChar = lutMu->c_str(); + const char* lutPiChar = lutPi->c_str(); + const char* lutKaChar = lutKa->c_str(); + const char* lutPrChar = lutPr->c_str(); + + LOGF(info, "Will load electron lut file ..: %s for TOF PID", lutElChar); + LOGF(info, "Will load muon lut file ......: %s for TOF PID", lutMuChar); + LOGF(info, "Will load pion lut file ......: %s for TOF PID", lutPiChar); + LOGF(info, "Will load kaon lut file ......: %s for TOF PID", lutKaChar); + LOGF(info, "Will load proton lut file ....: %s for TOF PID", lutPrChar); + + mapPdgLut.insert(std::make_pair(11, lutElChar)); + mapPdgLut.insert(std::make_pair(13, lutMuChar)); + mapPdgLut.insert(std::make_pair(211, lutPiChar)); + mapPdgLut.insert(std::make_pair(321, lutKaChar)); + mapPdgLut.insert(std::make_pair(2212, lutPrChar)); + + for (auto e : mapPdgLut) { + if (!mSmearer.loadTable(e.first, e.second)) { + LOG(fatal) << "Having issue with loading the LUT " << e.first << " " << e.second; + } + } + } + + if (doQAplots) { + const AxisSpec axisMomentum{static_cast(nBinsP), 0.0f, +4.0f, "#it{p} (GeV/#it{c})"}; + const AxisSpec axisMomentumSmall{static_cast(nBinsP), 0.0f, +1.0f, "#it{p} (GeV/#it{c})"}; + const AxisSpec axisVelocity{static_cast(nBinsBeta), 0.0f, +1.1f, "Measured #beta"}; + const AxisSpec axisTrackLengthInner{static_cast(nBinsTrackLengthInner), 0.0f, 60.0f, "Track length (cm)"}; + const AxisSpec axisTrackLengthOuter{static_cast(nBinsTrackLengthOuter), 0.0f, 300.0f, "Track length (cm)"}; + const AxisSpec axisTrackDeltaLength{static_cast(nBinsTrackDeltaLength), 0.0f, 30.0f, "Delta Track length (cm)"}; + histos.add("h2dVelocityVsMomentumInner", "h2dVelocityVsMomentumInner", kTH2F, {axisMomentum, axisVelocity}); + histos.add("h2dVelocityVsMomentumOuter", "h2dVelocityVsMomentumOuter", kTH2F, {axisMomentum, axisVelocity}); + histos.add("h2dTrackLengthInnerVsPt", "h2dTrackLengthInnerVsPt", kTH2F, {axisMomentumSmall, axisTrackLengthInner}); + histos.add("h2dTrackLengthOuterVsPt", "h2dTrackLengthOuterVsPt", kTH2F, {axisMomentumSmall, axisTrackLengthOuter}); + + histos.add("h2dTrackLengthInnerRecoVsPt", "h2dTrackLengthInnerRecoVsPt", kTH2F, {axisMomentumSmall, axisTrackLengthInner}); + histos.add("h2dTrackLengthOuterRecoVsPt", "h2dTrackLengthOuterRecoVsPt", kTH2F, {axisMomentumSmall, axisTrackLengthOuter}); + + histos.add("h2dDeltaTrackLengthInnerVsPt", "h2dDeltaTrackLengthInnerVsPt", kTH2F, {axisMomentumSmall, axisTrackDeltaLength}); + histos.add("h2dDeltaTrackLengthOuterVsPt", "h2dDeltaTrackLengthOuterVsPt", kTH2F, {axisMomentumSmall, axisTrackDeltaLength}); + + const AxisSpec axisPt{static_cast(nBinsP), 0.0f, +4.0f, "#it{p_{T}} (GeV/#it{c})"}; + const AxisSpec axisEta{static_cast(nBinsEta), -2.0f, +2.0f, "#eta"}; + const AxisSpec axisRelativePt{static_cast(nBinsRelativeEtaPt), 0.0f, +10.0f, "#it{#sigma_{p_{T}}} / #it{p_{T}} (%)"}; + const AxisSpec axisRelativeEta{static_cast(nBinsRelativeEtaPt), 0.0f, +10.0f, "#it{#sigma_{#eta}} / #it{#eta} (%)"}; + histos.add("h2dRelativePtResolution", "h2dRelativePtResolution", kTH2F, {axisPt, axisRelativePt}); + histos.add("h2dRelativeEtaResolution", "h2dRelativeEtaResolution", kTH2F, {axisEta, axisRelativeEta}); + + std::string particle_names1[5] = {"#it{e}", "#it{#mu}", "#it{#pi}", "#it{K}", "#it{p}"}; + std::string particle_names2[5] = {"Elec", "Muon", "Pion", "Kaon", "Prot"}; + for (int i_true = 0; i_true < 5; i_true++) { + std::string name_title_inner_track_res = "h2dInnerTimeResTrack" + particle_names2[i_true] + "VsP"; + std::string name_title_inner_total_res = "h2dInnerTimeResTotal" + particle_names2[i_true] + "VsP"; + std::string name_title_outer_track_res = "h2dOuterTimeResTrack" + particle_names2[i_true] + "VsP"; + std::string name_title_outer_total_res = "h2dOuterTimeResTotal" + particle_names2[i_true] + "VsP"; + const AxisSpec axisTrackTimeRes{static_cast(nBinsTimeRes), 0.0f, +200.0f, "Track time resolution - " + particle_names1[i_true] + " (ps)"}; + const AxisSpec axisTotalTimeRes{static_cast(nBinsTimeRes), 0.0f, +200.0f, "Total time resolution - " + particle_names1[i_true] + " (ps)"}; + histos.add(name_title_inner_track_res.c_str(), name_title_inner_track_res.c_str(), kTH2F, {axisMomentum, axisTrackTimeRes}); + histos.add(name_title_inner_total_res.c_str(), name_title_inner_total_res.c_str(), kTH2F, {axisMomentum, axisTotalTimeRes}); + histos.add(name_title_outer_track_res.c_str(), name_title_outer_track_res.c_str(), kTH2F, {axisMomentum, axisTrackTimeRes}); + histos.add(name_title_outer_total_res.c_str(), name_title_outer_total_res.c_str(), kTH2F, {axisMomentum, axisTotalTimeRes}); + } + + for (int i_true = 0; i_true < 5; i_true++) { + for (int i_hyp = 0; i_hyp < 5; i_hyp++) { + std::string name_title_inner = "h2dInnerNsigmaTrue" + particle_names2[i_true] + "Vs" + particle_names2[i_hyp] + "Hypothesis"; + std::string name_title_outer = "h2dOuterNsigmaTrue" + particle_names2[i_true] + "Vs" + particle_names2[i_hyp] + "Hypothesis"; + if (i_true == i_hyp) { + const AxisSpec axisNsigmaCorrect{static_cast(nBinsNsigmaCorrectSpecies), -10.0f, +10.0f, "N#sigma - True " + particle_names1[i_true] + " vs " + particle_names1[i_hyp] + " hypothesis"}; + histos.add(name_title_inner.c_str(), name_title_inner.c_str(), kTH2F, {axisMomentum, axisNsigmaCorrect}); + histos.add(name_title_outer.c_str(), name_title_outer.c_str(), kTH2F, {axisMomentum, axisNsigmaCorrect}); + } else { + const AxisSpec axisNsigmaWrong{static_cast(nBinsNsigmaWrongSpecies), -10.0f, +10.0f, "N#sigma - True " + particle_names1[i_true] + " vs " + particle_names1[i_hyp] + " hypothesis"}; + histos.add(name_title_inner.c_str(), name_title_inner.c_str(), kTH2F, {axisMomentum, axisNsigmaWrong}); + histos.add(name_title_outer.c_str(), name_title_outer.c_str(), kTH2F, {axisMomentum, axisNsigmaWrong}); + } + } + } + } + } + + /// Function to convert a McParticle into a perfect Track + /// \param particle the particle to convert (mcParticle) + /// \param o2track the address of the resulting TrackParCov + template + o2::track::TrackParCov convertMCParticleToO2Track(McParticleType& particle) + { + // FIXME: this is a fundamentally important piece of code. + // It could be placed in a utility file instead of here. + auto pdgInfo = pdg->GetParticle(particle.pdgCode()); + int charge = 0; + if (pdgInfo != nullptr) { + charge = pdgInfo->Charge() / 3; + } + std::array params; + std::array covm = {0.}; + float s, c, x; + o2::math_utils::sincos(particle.phi(), s, c); + o2::math_utils::rotateZInv(particle.vx(), particle.vy(), x, params[0], s, c); + params[1] = particle.vz(); + params[2] = 0.; // since alpha = phi + auto theta = 2. * std::atan(std::exp(-particle.eta())); + params[3] = 1. / std::tan(theta); + params[4] = charge / particle.pt(); + + // Return TrackParCov + return o2::track::TrackParCov(x, particle.phi(), params, covm); + } + + /// function to calculate track length of this track up to a certain radius + /// \param track the input track + /// \param radius the radius of the layer you're calculating the length to + /// \param magneticField the magnetic field to use when propagating + float trackLength(o2::track::TrackParCov track, float radius, float magneticField) + { + // don't make use of the track parametrization + float length = -100; + + o2::math_utils::CircleXYf_t trcCircle; + float sna, csa; + track.getCircleParams(magneticField, trcCircle, sna, csa); + + // distance between circle centers (one circle is at origin -> easy) + float centerDistance = std::hypot(trcCircle.xC, trcCircle.yC); + + // condition of circles touching - if not satisfied returned length will be -100 + if (centerDistance < trcCircle.rC + radius && centerDistance > fabs(trcCircle.rC - radius)) { + length = 0.0f; + + // base radical direction + float ux = trcCircle.xC / centerDistance; + float uy = trcCircle.yC / centerDistance; + // calculate perpendicular vector (normalized) for +/- displacement + float vx = -uy; + float vy = +ux; + // calculate coordinate for radical line + float radical = (centerDistance * centerDistance - trcCircle.rC * trcCircle.rC + radius * radius) / (2.0f * centerDistance); + // calculate absolute displacement from center-to-center axis + float displace = (0.5f / centerDistance) * TMath::Sqrt( + (-centerDistance + trcCircle.rC - radius) * + (-centerDistance - trcCircle.rC + radius) * + (-centerDistance + trcCircle.rC + radius) * + (centerDistance + trcCircle.rC + radius)); + + // possible intercept points of track and TOF layer in 2D plane + float point1[2] = {radical * ux + displace * vx, radical * uy + displace * vy}; + float point2[2] = {radical * ux - displace * vx, radical * uy - displace * vy}; + + // decide on correct intercept point + std::array mom; + track.getPxPyPzGlo(mom); + float scalarProduct1 = point1[0] * mom[0] + point1[1] * mom[1]; + float scalarProduct2 = point2[0] * mom[0] + point2[1] * mom[1]; + + // get start point + std::array startPoint; + track.getXYZGlo(startPoint); + + float cosAngle = -1000, modulus = -1000; + + if (scalarProduct1 > scalarProduct2) { + modulus = std::hypot(point1[0] - trcCircle.xC, point1[1] - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); + cosAngle = (point1[0] - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (point1[1] - trcCircle.yC) * (startPoint[0] - trcCircle.yC); + } else { + modulus = std::hypot(point2[0] - trcCircle.xC, point2[1] - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); + cosAngle = (point2[0] - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (point2[1] - trcCircle.yC) * (startPoint[0] - trcCircle.yC); + } + cosAngle /= modulus; + length = trcCircle.rC * TMath::ACos(cosAngle); + length *= sqrt(1.0f + track.getTgl() * track.getTgl()); + } + return length; + } + + /// returns velocity in centimeters per picoseconds + /// \param momentum the momentum of the tarck + /// \param mass the mass of the particle + float velocity(float momentum, float mass) + { + float a = std::pow(momentum / mass, 2); + // uses light speed in cm/ps so output is in those units + return (o2::constants::physics::LightSpeedCm2NS / 1e+3) * std::sqrt(a / (1 + a)); + } + + /// returns track time resolution + /// \param pt the transverse momentum of the tarck + /// \param eta the pseudorapidity of the tarck + /// \param track_pt_resolution the absolute resolution on pt + /// \param track_pt_resolution the absolute resolution on eta + /// \param mass the mass of the particle + /// \param det_radius the radius of the cylindrical layer + /// \param magneticField the magnetic field (along Z) + double calculate_track_time_resolution_advanced(float pt, float eta, float track_pt_resolution, float track_eta_resolution, float mass, float det_radius, float magneticField) + { + // Compute tracking contribution to timing using the error propagation formula + // Uses light speed in m/ps, magnetic field in T (*0.1 for conversion kGauss -> T) + double a0 = mass * mass; + double a1 = 0.299792458 * (0.1 * magneticField) * (0.01 * o2::constants::physics::LightSpeedCm2NS / 1e+3); + double a2 = (det_radius * 0.01) * (det_radius * 0.01) * (0.299792458) * (0.299792458) * (0.1 * magneticField) * (0.1 * magneticField) / 2.0; + double dtof_on_dpt = (std::pow(pt, 4) * std::pow(std::cosh(eta), 2) * std::acos(1.0 - a2 / std::pow(pt, 2)) - 2.0 * a2 * std::pow(pt, 2) * (a0 + std::pow(pt * std::cosh(eta), 2)) / std::sqrt(a2 * (2.0 * std::pow(pt, 2) - a2))) / (a1 * std::pow(pt, 3) * std::sqrt(a0 + std::pow(pt * std::cosh(eta), 2))); + double dtof_on_deta = std::pow(pt, 2) * std::sinh(eta) * std::cosh(eta) * std::acos(1.0 - a2 / std::pow(pt, 2)) / (a1 * std::sqrt(a0 + std::pow(pt * std::cosh(eta), 2))); + double track_time_resolution = std::hypot(std::fabs(dtof_on_dpt) * track_pt_resolution, std::fabs(dtof_on_deta) * track_eta_resolution); + return track_time_resolution; + } + + void process(soa::Join::iterator const& collision, soa::Join const& tracks, aod::McParticles const&, aod::McCollisions const&) + { + o2::dataformats::VertexBase pvVtx({collision.posX(), collision.posY(), collision.posZ()}, + {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}); + + std::array mcPvCov = {0.}; + o2::dataformats::VertexBase mcPvVtx({0.0f, 0.0f, 0.0f}, mcPvCov); + if (collision.has_mcCollision()) { + auto mcCollision = collision.mcCollision(); + mcPvVtx.setX(mcCollision.posX()); + mcPvVtx.setY(mcCollision.posY()); + mcPvVtx.setZ(mcCollision.posZ()); + } // else remains untreated for now + + // First we compute the number of charged particles in the event if LUTs are loaded + float dNdEta = 0.f; + if (flagTOFLoadDelphesLUTs) { + for (const auto& track : tracks) { + if (!track.has_mcParticle()) + continue; + auto mcParticle = track.mcParticle(); + if (std::abs(mcParticle.eta()) > multiplicityEtaRange) { + continue; + } + if (mcParticle.has_daughters()) { + continue; + } + const auto& pdgInfo = pdg->GetParticle(mcParticle.pdgCode()); + if (!pdgInfo) { + // LOG(warning) << "PDG code " << mcParticle.pdgCode() << " not found in the database"; + continue; + } + if (pdgInfo->Charge() == 0) { + continue; + } + dNdEta += 1.f; + } + } + + for (const auto& track : tracks) { + // first step: find precise arrival time (if any) + // --- convert track into perfect track + if (!track.has_mcParticle()) // should always be OK but check please + continue; + + auto mcParticle = track.mcParticle(); + o2::track::TrackParCov o2track = convertMCParticleToO2Track(mcParticle); + + float xPv = -100, trackLengthInnerTOF = -1, trackLengthOuterTOF = -1; + if (o2track.propagateToDCA(mcPvVtx, dBz)) + xPv = o2track.getX(); + if (xPv > -99.) { + trackLengthInnerTOF = trackLength(o2track, innerTOFRadius, dBz); + trackLengthOuterTOF = trackLength(o2track, outerTOFRadius, dBz); + } + + // get mass to calculate velocity + auto pdgInfo = pdg->GetParticle(mcParticle.pdgCode()); + if (pdgInfo == nullptr) { + continue; + } + float expectedTimeInnerTOF = trackLengthInnerTOF / velocity(o2track.getP(), pdgInfo->Mass()); + float expectedTimeOuterTOF = trackLengthOuterTOF / velocity(o2track.getP(), pdgInfo->Mass()); + + // Smear with expected resolutions + float measuredTimeInnerTOF = pRandomNumberGenerator.Gaus(expectedTimeInnerTOF, innerTOFTimeReso); + float measuredTimeOuterTOF = pRandomNumberGenerator.Gaus(expectedTimeOuterTOF, outerTOFTimeReso); + + // Now we calculate the expected arrival time following certain mass hypotheses + // and the (imperfect!) reconstructed track parametrizations + float trackLengthRecoInnerTOF = -1, trackLengthRecoOuterTOF = -1; + auto recoTrack = getTrackParCov(track); + if (recoTrack.propagateToDCA(pvVtx, dBz)) + xPv = recoTrack.getX(); + if (xPv > -99.) { + trackLengthRecoInnerTOF = trackLength(recoTrack, innerTOFRadius, dBz); + trackLengthRecoOuterTOF = trackLength(recoTrack, outerTOFRadius, dBz); + } + + // Straight to Nsigma + float deltaTimeInnerTOF[5], nSigmaInnerTOF[5]; + float deltaTimeOuterTOF[5], nSigmaOuterTOF[5]; + int lpdg_array[5] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton}; + float masses[5]; + + if (doQAplots) { + float momentum = recoTrack.getP(); + // unit conversion: length in cm, time in ps + float innerBeta = 1e+3 * (trackLengthInnerTOF / measuredTimeInnerTOF) / o2::constants::physics::LightSpeedCm2NS; + float outerBeta = 1e+3 * (trackLengthOuterTOF / measuredTimeOuterTOF) / o2::constants::physics::LightSpeedCm2NS; + if (trackLengthRecoInnerTOF > 0) { + histos.fill(HIST("h2dVelocityVsMomentumInner"), momentum, innerBeta); + histos.fill(HIST("h2dTrackLengthInnerVsPt"), o2track.getPt(), trackLengthInnerTOF); + histos.fill(HIST("h2dTrackLengthInnerRecoVsPt"), o2track.getPt(), trackLengthRecoInnerTOF); + } + if (trackLengthRecoOuterTOF > 0) { + histos.fill(HIST("h2dVelocityVsMomentumOuter"), momentum, outerBeta); + histos.fill(HIST("h2dTrackLengthOuterVsPt"), o2track.getPt(), trackLengthOuterTOF); + histos.fill(HIST("h2dTrackLengthOuterRecoVsPt"), o2track.getPt(), trackLengthRecoOuterTOF); + } + } + + for (int ii = 0; ii < 5; ii++) { + nSigmaInnerTOF[ii] = -100; + nSigmaOuterTOF[ii] = -100; + + auto pdgInfoThis = pdg->GetParticle(lpdg_array[ii]); + masses[ii] = pdgInfoThis->Mass(); + deltaTimeInnerTOF[ii] = trackLengthRecoInnerTOF / velocity(recoTrack.getP(), masses[ii]) - measuredTimeInnerTOF; + deltaTimeOuterTOF[ii] = trackLengthRecoOuterTOF / velocity(recoTrack.getP(), masses[ii]) - measuredTimeOuterTOF; + + // Evaluate total sigma (layer + tracking resolution) + float innerTotalTimeReso = innerTOFTimeReso; + float outerTotalTimeReso = outerTOFTimeReso; + if (flagIncludeTrackTimeRes) { + double pt_resolution = std::pow(recoTrack.getP() / std::cosh(recoTrack.getEta()), 2) * std::sqrt(recoTrack.getSigma1Pt2()); + double eta_resolution = std::fabs(std::sin(2.0 * std::atan(std::exp(-recoTrack.getEta())))) * std::sqrt(recoTrack.getSigmaTgl2()); + if (flagTOFLoadDelphesLUTs) { + pt_resolution = mSmearer.getAbsPtRes(pdgInfoThis->PdgCode(), dNdEta, recoTrack.getEta(), recoTrack.getP() / std::cosh(recoTrack.getEta())); + eta_resolution = mSmearer.getAbsEtaRes(pdgInfoThis->PdgCode(), dNdEta, recoTrack.getEta(), recoTrack.getP() / std::cosh(recoTrack.getEta())); + } + float innerTrackTimeReso = calculate_track_time_resolution_advanced(recoTrack.getP() / std::cosh(recoTrack.getEta()), recoTrack.getEta(), pt_resolution, eta_resolution, masses[ii], innerTOFRadius, dBz); + float outerTrackTimeReso = calculate_track_time_resolution_advanced(recoTrack.getP() / std::cosh(recoTrack.getEta()), recoTrack.getEta(), pt_resolution, eta_resolution, masses[ii], outerTOFRadius, dBz); + innerTotalTimeReso = std::hypot(innerTOFTimeReso, innerTrackTimeReso); + outerTotalTimeReso = std::hypot(outerTOFTimeReso, outerTrackTimeReso); + + if (doQAplots && trackLengthRecoInnerTOF > 0) { + float momentum = recoTrack.getP(); + if (ii == 0 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[0])->PdgCode()) { + histos.fill(HIST("h2dInnerTimeResTrackElecVsP"), momentum, innerTrackTimeReso); + histos.fill(HIST("h2dInnerTimeResTotalElecVsP"), momentum, innerTotalTimeReso); + } + if (ii == 1 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[1])->PdgCode()) { + histos.fill(HIST("h2dInnerTimeResTrackMuonVsP"), momentum, innerTrackTimeReso); + histos.fill(HIST("h2dInnerTimeResTotalMuonVsP"), momentum, innerTotalTimeReso); + } + if (ii == 2 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[2])->PdgCode()) { + histos.fill(HIST("h2dInnerTimeResTrackPionVsP"), momentum, innerTrackTimeReso); + histos.fill(HIST("h2dInnerTimeResTotalPionVsP"), momentum, innerTotalTimeReso); + } + if (ii == 3 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[3])->PdgCode()) { + histos.fill(HIST("h2dInnerTimeResTrackKaonVsP"), momentum, innerTrackTimeReso); + histos.fill(HIST("h2dInnerTimeResTotalKaonVsP"), momentum, innerTotalTimeReso); + } + if (ii == 4 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[4])->PdgCode()) { + histos.fill(HIST("h2dInnerTimeResTrackProtVsP"), momentum, innerTrackTimeReso); + histos.fill(HIST("h2dInnerTimeResTotalProtVsP"), momentum, innerTotalTimeReso); + } + } + if (doQAplots && trackLengthRecoOuterTOF > 0) { + float momentum = recoTrack.getP(); + float pseudorapidity = recoTrack.getEta(); + float transverse_momentum = momentum / std::cosh(pseudorapidity); + if (ii == 0 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[0])->PdgCode()) { + histos.fill(HIST("h2dOuterTimeResTrackElecVsP"), momentum, outerTrackTimeReso); + histos.fill(HIST("h2dOuterTimeResTotalElecVsP"), momentum, outerTotalTimeReso); + } + if (ii == 1 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[1])->PdgCode()) { + histos.fill(HIST("h2dOuterTimeResTrackMuonVsP"), momentum, outerTrackTimeReso); + histos.fill(HIST("h2dOuterTimeResTotalMuonVsP"), momentum, outerTotalTimeReso); + } + if (ii == 2 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[2])->PdgCode()) { + histos.fill(HIST("h2dOuterTimeResTrackPionVsP"), momentum, outerTrackTimeReso); + histos.fill(HIST("h2dOuterTimeResTotalPionVsP"), momentum, outerTotalTimeReso); + + histos.fill(HIST("h2dRelativePtResolution"), transverse_momentum, 100.0 * pt_resolution / transverse_momentum); + histos.fill(HIST("h2dRelativeEtaResolution"), pseudorapidity, 100.0 * eta_resolution / (std::fabs(pseudorapidity) + 1e-6)); + } + if (ii == 3 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[3])->PdgCode()) { + histos.fill(HIST("h2dOuterTimeResTrackKaonVsP"), momentum, outerTrackTimeReso); + histos.fill(HIST("h2dOuterTimeResTotalKaonVsP"), momentum, outerTotalTimeReso); + } + if (ii == 4 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[4])->PdgCode()) { + histos.fill(HIST("h2dOuterTimeResTrackProtVsP"), momentum, outerTrackTimeReso); + histos.fill(HIST("h2dOuterTimeResTotalProtVsP"), momentum, outerTotalTimeReso); + } + } + } + + // Fixme: assumes dominant resolution effect is the TOF resolution + // and not the tracking itself. It's *probably* a fair assumption + // but it should be tested further! --> FIXED IN THIS VERSION + if (trackLengthInnerTOF > 0 && trackLengthRecoInnerTOF > 0) + nSigmaInnerTOF[ii] = deltaTimeInnerTOF[ii] / innerTotalTimeReso; + if (trackLengthOuterTOF > 0 && trackLengthRecoOuterTOF > 0) + nSigmaOuterTOF[ii] = deltaTimeOuterTOF[ii] / outerTotalTimeReso; + } + + if (doQAplots) { + float momentum = recoTrack.getP(); + if (trackLengthRecoInnerTOF > 0) { + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[0])->PdgCode()) { + histos.fill(HIST("h2dInnerNsigmaTrueElecVsElecHypothesis"), momentum, nSigmaInnerTOF[0]); + histos.fill(HIST("h2dInnerNsigmaTrueElecVsMuonHypothesis"), momentum, nSigmaInnerTOF[1]); + histos.fill(HIST("h2dInnerNsigmaTrueElecVsPionHypothesis"), momentum, nSigmaInnerTOF[2]); + histos.fill(HIST("h2dInnerNsigmaTrueElecVsKaonHypothesis"), momentum, nSigmaInnerTOF[3]); + histos.fill(HIST("h2dInnerNsigmaTrueElecVsProtHypothesis"), momentum, nSigmaInnerTOF[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[1])->PdgCode()) { + histos.fill(HIST("h2dInnerNsigmaTrueMuonVsElecHypothesis"), momentum, nSigmaInnerTOF[0]); + histos.fill(HIST("h2dInnerNsigmaTrueMuonVsMuonHypothesis"), momentum, nSigmaInnerTOF[1]); + histos.fill(HIST("h2dInnerNsigmaTrueMuonVsPionHypothesis"), momentum, nSigmaInnerTOF[2]); + histos.fill(HIST("h2dInnerNsigmaTrueMuonVsKaonHypothesis"), momentum, nSigmaInnerTOF[3]); + histos.fill(HIST("h2dInnerNsigmaTrueMuonVsProtHypothesis"), momentum, nSigmaInnerTOF[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[2])->PdgCode()) { + histos.fill(HIST("h2dInnerNsigmaTruePionVsElecHypothesis"), momentum, nSigmaInnerTOF[0]); + histos.fill(HIST("h2dInnerNsigmaTruePionVsMuonHypothesis"), momentum, nSigmaInnerTOF[1]); + histos.fill(HIST("h2dInnerNsigmaTruePionVsPionHypothesis"), momentum, nSigmaInnerTOF[2]); + histos.fill(HIST("h2dInnerNsigmaTruePionVsKaonHypothesis"), momentum, nSigmaInnerTOF[3]); + histos.fill(HIST("h2dInnerNsigmaTruePionVsProtHypothesis"), momentum, nSigmaInnerTOF[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[3])->PdgCode()) { + histos.fill(HIST("h2dInnerNsigmaTrueKaonVsElecHypothesis"), momentum, nSigmaInnerTOF[0]); + histos.fill(HIST("h2dInnerNsigmaTrueKaonVsMuonHypothesis"), momentum, nSigmaInnerTOF[1]); + histos.fill(HIST("h2dInnerNsigmaTrueKaonVsPionHypothesis"), momentum, nSigmaInnerTOF[2]); + histos.fill(HIST("h2dInnerNsigmaTrueKaonVsKaonHypothesis"), momentum, nSigmaInnerTOF[3]); + histos.fill(HIST("h2dInnerNsigmaTrueKaonVsProtHypothesis"), momentum, nSigmaInnerTOF[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[4])->PdgCode()) { + histos.fill(HIST("h2dInnerNsigmaTrueProtVsElecHypothesis"), momentum, nSigmaInnerTOF[0]); + histos.fill(HIST("h2dInnerNsigmaTrueProtVsMuonHypothesis"), momentum, nSigmaInnerTOF[1]); + histos.fill(HIST("h2dInnerNsigmaTrueProtVsPionHypothesis"), momentum, nSigmaInnerTOF[2]); + histos.fill(HIST("h2dInnerNsigmaTrueProtVsKaonHypothesis"), momentum, nSigmaInnerTOF[3]); + histos.fill(HIST("h2dInnerNsigmaTrueProtVsProtHypothesis"), momentum, nSigmaInnerTOF[4]); + } + } + if (trackLengthRecoOuterTOF > 0) { + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[0])->PdgCode()) { + histos.fill(HIST("h2dOuterNsigmaTrueElecVsElecHypothesis"), momentum, nSigmaOuterTOF[0]); + histos.fill(HIST("h2dOuterNsigmaTrueElecVsMuonHypothesis"), momentum, nSigmaOuterTOF[1]); + histos.fill(HIST("h2dOuterNsigmaTrueElecVsPionHypothesis"), momentum, nSigmaOuterTOF[2]); + histos.fill(HIST("h2dOuterNsigmaTrueElecVsKaonHypothesis"), momentum, nSigmaOuterTOF[3]); + histos.fill(HIST("h2dOuterNsigmaTrueElecVsProtHypothesis"), momentum, nSigmaOuterTOF[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[1])->PdgCode()) { + histos.fill(HIST("h2dOuterNsigmaTrueMuonVsElecHypothesis"), momentum, nSigmaOuterTOF[0]); + histos.fill(HIST("h2dOuterNsigmaTrueMuonVsMuonHypothesis"), momentum, nSigmaOuterTOF[1]); + histos.fill(HIST("h2dOuterNsigmaTrueMuonVsPionHypothesis"), momentum, nSigmaOuterTOF[2]); + histos.fill(HIST("h2dOuterNsigmaTrueMuonVsKaonHypothesis"), momentum, nSigmaOuterTOF[3]); + histos.fill(HIST("h2dOuterNsigmaTrueMuonVsProtHypothesis"), momentum, nSigmaOuterTOF[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[2])->PdgCode()) { + histos.fill(HIST("h2dOuterNsigmaTruePionVsElecHypothesis"), momentum, nSigmaOuterTOF[0]); + histos.fill(HIST("h2dOuterNsigmaTruePionVsMuonHypothesis"), momentum, nSigmaOuterTOF[1]); + histos.fill(HIST("h2dOuterNsigmaTruePionVsPionHypothesis"), momentum, nSigmaOuterTOF[2]); + histos.fill(HIST("h2dOuterNsigmaTruePionVsKaonHypothesis"), momentum, nSigmaOuterTOF[3]); + histos.fill(HIST("h2dOuterNsigmaTruePionVsProtHypothesis"), momentum, nSigmaOuterTOF[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[3])->PdgCode()) { + histos.fill(HIST("h2dOuterNsigmaTrueKaonVsElecHypothesis"), momentum, nSigmaOuterTOF[0]); + histos.fill(HIST("h2dOuterNsigmaTrueKaonVsMuonHypothesis"), momentum, nSigmaOuterTOF[1]); + histos.fill(HIST("h2dOuterNsigmaTrueKaonVsPionHypothesis"), momentum, nSigmaOuterTOF[2]); + histos.fill(HIST("h2dOuterNsigmaTrueKaonVsKaonHypothesis"), momentum, nSigmaOuterTOF[3]); + histos.fill(HIST("h2dOuterNsigmaTrueKaonVsProtHypothesis"), momentum, nSigmaOuterTOF[4]); + } + if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[4])->PdgCode()) { + histos.fill(HIST("h2dOuterNsigmaTrueProtVsElecHypothesis"), momentum, nSigmaOuterTOF[0]); + histos.fill(HIST("h2dOuterNsigmaTrueProtVsMuonHypothesis"), momentum, nSigmaOuterTOF[1]); + histos.fill(HIST("h2dOuterNsigmaTrueProtVsPionHypothesis"), momentum, nSigmaOuterTOF[2]); + histos.fill(HIST("h2dOuterNsigmaTrueProtVsKaonHypothesis"), momentum, nSigmaOuterTOF[3]); + histos.fill(HIST("h2dOuterNsigmaTrueProtVsProtHypothesis"), momentum, nSigmaOuterTOF[4]); + } + } + } + + float deltaTrackLengthInnerTOF = abs(trackLengthInnerTOF - trackLengthRecoInnerTOF); + if (trackLengthInnerTOF > 0 && trackLengthRecoInnerTOF > 0) { + histos.fill(HIST("h2dDeltaTrackLengthInnerVsPt"), o2track.getPt(), deltaTrackLengthInnerTOF); + } + float deltaTrackLengthOuterTOF = abs(trackLengthOuterTOF - trackLengthRecoOuterTOF); + if (trackLengthOuterTOF > 0 && trackLengthRecoOuterTOF > 0) { + histos.fill(HIST("h2dDeltaTrackLengthOuterVsPt"), o2track.getPt(), deltaTrackLengthInnerTOF); + } + + // Sigmas have been fully calculated. Please populate the NSigma helper table (once per track) + upgradeTof(nSigmaInnerTOF[0], nSigmaInnerTOF[1], nSigmaInnerTOF[2], nSigmaInnerTOF[3], nSigmaInnerTOF[4], trackLengthInnerTOF, trackLengthRecoInnerTOF, deltaTrackLengthInnerTOF, + nSigmaOuterTOF[0], nSigmaOuterTOF[1], nSigmaOuterTOF[2], nSigmaOuterTOF[3], nSigmaOuterTOF[4], trackLengthOuterTOF, trackLengthRecoOuterTOF, deltaTrackLengthOuterTOF); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx new file mode 100644 index 00000000000..531d1d088cb --- /dev/null +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -0,0 +1,552 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file onTheFlyTracker.cxx +/// +/// \brief LUT-based on-the-fly analysis task-level tracking +/// +/// This task allows for the calculation of aod::collisions and aod::Tracks in a synthetic manner, +/// smearing MC particles with very configurable settings. This will allow for the usage of +/// custom LUTs (obtained through separate studies) and the subsequent estimate of the performance +/// of a future detector even in very statistics-hungry analyses. +/// +/// \author David Dobrigkeit Chinellato, UNICAMP +/// \author Nicolò Jacazio , UniBo +/// \author Roberto Preghenella preghenella@bo.infn.it +/// + +#include + +#include + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include +#include "Framework/O2DatabasePDGPlugin.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "ReconstructionDataFormats/DCA.h" +#include "DetectorsBase/Propagator.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsVertexing/PVertexer.h" +#include "DetectorsVertexing/PVertexerHelpers.h" +#include "SimulationDataFormat/InteractionSampler.h" +#include "Field/MagneticField.h" + +#include "ALICE3/Core/DelphesO2TrackSmearer.h" +#include "ALICE3/DataModel/collisionAlice3.h" +#include "ALICE3/DataModel/tracksAlice3.h" + +using namespace o2; +using namespace o2::framework; + +struct OnTheFlyTracker { + Produces collisions; + Produces collLabels; + Produces tracksPar; + Produces tracksParExtension; + Produces tracksParCov; + Produces tracksParCovExtension; + Produces tracksLabels; + Produces tracksDCA; + Produces collisionsAlice3; + Produces TracksAlice3; + + // optionally produced, empty (to be tuned later) + Produces tracksExtra; // base table, extend later + Produces trackSelection; + Produces trackSelectionExtension; + + Configurable magneticField{"magneticField", 20.0f, "magnetic field in kG"}; + Configurable maxEta{"maxEta", 1.5, "maximum eta to consider viable"}; + Configurable multEtaRange{"multEtaRange", 0.8, "eta range to compute the multiplicity"}; + Configurable minPt{"minPt", 0.1, "minimum pt to consider viable"}; + Configurable enableLUT{"enableLUT", false, "Enable track smearing"}; + Configurable enableNucleiSmearing{"enableNucleiSmearing", false, "Enable smearing of nuclei"}; + Configurable enablePrimaryVertexing{"enablePrimaryVertexing", true, "Enable primary vertexing"}; + Configurable interpolateLutEfficiencyVsNch{"interpolateLutEfficiencyVsNch", true, "interpolate LUT efficiency as f(Nch)"}; + + Configurable populateTracksDCA{"populateTracksDCA", true, "populate TracksDCA table"}; + Configurable populateTracksExtra{"populateTracksExtra", false, "populate TracksExtra table (legacy)"}; + Configurable populateTrackSelection{"populateTrackSelection", false, "populate TrackSelection table (legacy)"}; + + Configurable processUnreconstructedTracks{"processUnreconstructedTracks", false, "process (smear) unreco-ed tracks"}; + Configurable doExtraQA{"doExtraQA", false, "do extra 2D QA plots"}; + Configurable extraQAwithoutDecayDaughters{"extraQAwithoutDecayDaughters", false, "remove decay daughters from qa plots (yes/no)"}; + + Configurable lutEl{"lutEl", "lutCovm.el.dat", "LUT for electrons"}; + Configurable lutMu{"lutMu", "lutCovm.mu.dat", "LUT for muons"}; + Configurable lutPi{"lutPi", "lutCovm.pi.dat", "LUT for pions"}; + Configurable lutKa{"lutKa", "lutCovm.ka.dat", "LUT for kaons"}; + Configurable lutPr{"lutPr", "lutCovm.pr.dat", "LUT for protons"}; + Configurable lutDe{"lutDe", "lutCovm.de.dat", "LUT for deuterons"}; + Configurable lutTr{"lutTr", "lutCovm.tr.dat", "LUT for tritons"}; + Configurable lutHe3{"lutHe3", "lutCovm.he3.dat", "LUT for Helium-3"}; + + ConfigurableAxis axisMomentum{"axisMomentum", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "#it{p} (GeV/#it{c})"}; + ConfigurableAxis axisNVertices{"axisNVertices", {20, -0.5, 19.5}, "N_{vertices}"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {100, -0.5, 99.5}, "N_{contributors}"}; + ConfigurableAxis axisVertexZ{"axisVertexZ", {40, -20, 20}, "vertex Z (cm)"}; + ConfigurableAxis axisDCA{"axisDCA", {400, -200, 200}, "DCA (#mum)"}; + ConfigurableAxis axisX{"axisX", {250, -50, 200}, "track X (cm)"}; + + using PVertex = o2::dataformats::PrimaryVertex; + + // Class to hold the track information for the O2 vertexing + class TrackAlice3 : public o2::track::TrackParCov + { + using TimeEst = o2::dataformats::TimeStampWithError; + + public: + TrackAlice3() = default; + ~TrackAlice3() = default; + TrackAlice3(const TrackAlice3& src) = default; + TrackAlice3(const o2::track::TrackParCov& src, const int64_t label, const float t = 0, const float te = 1, bool decayDauInput = false) : o2::track::TrackParCov(src), mcLabel{label}, timeEst{t, te}, isDecayDau(decayDauInput) {} + const TimeEst& getTimeMUS() const { return timeEst; } + int64_t mcLabel; + TimeEst timeEst; ///< time estimate in ns + bool isDecayDau; + }; + + // necessary for particle charges + Service pdgDB; + + // for handling basic QA histograms if requested + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + // Track smearer + o2::delphes::DelphesO2TrackSmearer mSmearer; + + // For processing and vertexing + std::vector tracksAlice3; + std::vector ghostTracksAlice3; + std::vector bcData; + o2::steer::InteractionSampler irSampler; + o2::vertexing::PVertexer vertexer; + + void init(o2::framework::InitContext& initContext) + { + if (enableLUT) { + std::map mapPdgLut; + const char* lutElChar = lutEl->c_str(); + const char* lutMuChar = lutMu->c_str(); + const char* lutPiChar = lutPi->c_str(); + const char* lutKaChar = lutKa->c_str(); + const char* lutPrChar = lutPr->c_str(); + + LOGF(info, "Will load electron lut file ..: %s", lutElChar); + LOGF(info, "Will load muon lut file ......: %s", lutMuChar); + LOGF(info, "Will load pion lut file ......: %s", lutPiChar); + LOGF(info, "Will load kaon lut file ......: %s", lutKaChar); + LOGF(info, "Will load proton lut file ....: %s", lutPrChar); + + mapPdgLut.insert(std::make_pair(11, lutElChar)); + mapPdgLut.insert(std::make_pair(13, lutMuChar)); + mapPdgLut.insert(std::make_pair(211, lutPiChar)); + mapPdgLut.insert(std::make_pair(321, lutKaChar)); + mapPdgLut.insert(std::make_pair(2212, lutPrChar)); + + if (enableNucleiSmearing) { + const char* lutDeChar = lutDe->c_str(); + const char* lutTrChar = lutTr->c_str(); + const char* lutHe3Char = lutHe3->c_str(); + mapPdgLut.insert(std::make_pair(1000010020, lutDeChar)); + mapPdgLut.insert(std::make_pair(1000010030, lutTrChar)); + mapPdgLut.insert(std::make_pair(1000020030, lutHe3Char)); + } + for (auto e : mapPdgLut) { + if (!mSmearer.loadTable(e.first, e.second)) { + LOG(fatal) << "Having issue with loading the LUT " << e.first << " " << e.second; + } + } + // interpolate efficiencies if requested to do so + mSmearer.interpolateEfficiency(static_cast(interpolateLutEfficiencyVsNch)); + + // smear un-reco'ed tracks if asked to do so + mSmearer.skipUnreconstructed(static_cast(!processUnreconstructedTracks)); + } + + // Basic QA + histos.add("hPtGenerated", "hPtGenerated", kTH1F, {axisMomentum}); + histos.add("hPtGeneratedEl", "hPtGeneratedEl", kTH1F, {axisMomentum}); + histos.add("hPtGeneratedPi", "hPtGeneratedPi", kTH1F, {axisMomentum}); + histos.add("hPtGeneratedKa", "hPtGeneratedKa", kTH1F, {axisMomentum}); + histos.add("hPtGeneratedPr", "hPtGeneratedPr", kTH1F, {axisMomentum}); + histos.add("hPtReconstructed", "hPtReconstructed", kTH1F, {axisMomentum}); + histos.add("hPtReconstructedEl", "hPtReconstructedEl", kTH1F, {axisMomentum}); + histos.add("hPtReconstructedPi", "hPtReconstructedPi", kTH1F, {axisMomentum}); + histos.add("hPtReconstructedKa", "hPtReconstructedKa", kTH1F, {axisMomentum}); + histos.add("hPtReconstructedPr", "hPtReconstructedPr", kTH1F, {axisMomentum}); + + // Collision QA + histos.add("hPVz", "hPVz", kTH1F, {axisVertexZ}); + histos.add("hLUTMultiplicity", "hLUTMultiplicity", kTH1F, {axisMultiplicity}); + histos.add("hSimMultiplicity", "hSimMultiplicity", kTH1F, {axisMultiplicity}); + histos.add("hRecoMultiplicity", "hRecoMultiplicity", kTH1F, {axisMultiplicity}); + + if (doExtraQA) { + histos.add("h2dVerticesVsContributors", "h2dVerticesVsContributors", kTH2F, {axisMultiplicity, axisNVertices}); + histos.add("hRecoVsSimMultiplicity", "hRecoVsSimMultiplicity", kTH2F, {axisMultiplicity, axisMultiplicity}); + histos.add("h2dDCAxy", "h2dDCAxy", kTH2F, {axisMomentum, axisDCA}); + + histos.add("hSimTrackX", "hSimTrackX", kTH1F, {axisX}); + histos.add("hRecoTrackX", "hRecoTrackX", kTH1F, {axisX}); + histos.add("hTrackXatDCA", "hTrackXatDCA", kTH1F, {axisX}); + } + + LOGF(info, "Initializing magnetic field to value: %.3f kG", static_cast(magneticField)); + o2::parameters::GRPMagField grpmag; + grpmag.setFieldUniformity(true); + grpmag.setL3Current(30000.f * (magneticField / 5.0f)); + auto field = grpmag.getNominalL3Field(); + o2::base::Propagator::initFieldFromGRP(&grpmag); + + auto fieldInstance = static_cast(TGeoGlobalMagField::Instance()->GetField()); + if (!fieldInstance) { + LOGF(fatal, "Failed to set up magnetic field! Stopping now!"); + } + + // Cross-check + LOGF(info, "Check field at (0, 0, 0): %.1f kG, nominal: %.1f", static_cast(fieldInstance->GetBz(0, 0, 0)), static_cast(field)); + + LOGF(info, "Initializing empty material cylinder LUT - could be better in the future"); + o2::base::MatLayerCylSet* lut = new o2::base::MatLayerCylSet(); + lut->addLayer(200, 200.1, 2, 1.0f, 100.0f); + LOGF(info, "MatLayerCylSet::optimizePhiSlices()"); + lut->optimizePhiSlices(); + LOGF(info, "Setting lut now..."); + o2::base::Propagator::Instance()->setMatLUT(lut); + + irSampler.setInteractionRate(100); + irSampler.setFirstIR(o2::InteractionRecord(0, 0)); + irSampler.init(); + + vertexer.setValidateWithIR(kFALSE); + vertexer.setBunchFilling(irSampler.getBunchFilling()); + vertexer.init(); + } + + /// Function to convert a McParticle into a perfect Track + /// \param particle the particle to convert (mcParticle) + /// \param o2track the address of the resulting TrackParCov + template + void convertMCParticleToO2Track(McParticleType& particle, o2::track::TrackParCov& o2track) + { + auto pdgInfo = pdgDB->GetParticle(particle.pdgCode()); + int charge = 0; + if (pdgInfo != nullptr) { + charge = pdgInfo->Charge() / 3; + } + std::array params; + std::array covm = {0.}; + float s, c, x; + o2::math_utils::sincos(particle.phi(), s, c); + o2::math_utils::rotateZInv(particle.vx(), particle.vy(), x, params[0], s, c); + params[1] = particle.vz(); + params[2] = 0.; // since alpha = phi + auto theta = 2. * std::atan(std::exp(-particle.eta())); + params[3] = 1. / std::tan(theta); + params[4] = charge / particle.pt(); + + // Initialize TrackParCov in-place + new (&o2track)(o2::track::TrackParCov)(x, particle.phi(), params, covm); + } + + float dNdEta = 0.f; // Charged particle multiplicity to use in the efficiency evaluation + void process(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) + { + tracksAlice3.clear(); + ghostTracksAlice3.clear(); + bcData.clear(); + + o2::dataformats::DCA dcaInfo; + o2::dataformats::VertexBase vtx; + + // generate collision time + auto ir = irSampler.generateCollisionTime(); + + // First we compute the number of charged particles in the event + dNdEta = 0.f; + for (const auto& mcParticle : mcParticles) { + if (std::abs(mcParticle.eta()) > multEtaRange) { + continue; + } + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + const auto pdg = std::abs(mcParticle.pdgCode()); + if (pdg != kElectron && pdg != kMuonMinus && pdg != kPiPlus && pdg != kKPlus && pdg != kProton) { + continue; + } + const auto& pdgInfo = pdgDB->GetParticle(mcParticle.pdgCode()); + if (!pdgInfo) { + LOG(warning) << "PDG code " << mcParticle.pdgCode() << " not found in the database"; + continue; + } + if (pdgInfo->Charge() == 0) { + continue; + } + dNdEta += 1.f; + } + + dNdEta /= (multEtaRange * 2.0f); + uint32_t multiplicityCounter = 0; + histos.fill(HIST("hLUTMultiplicity"), dNdEta); + + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + const auto pdg = std::abs(mcParticle.pdgCode()); + if (pdg != kElectron && pdg != kMuonMinus && pdg != kPiPlus && pdg != kKPlus && pdg != kProton) { + continue; + } + if (std::fabs(mcParticle.eta()) > maxEta) { + continue; + } + + histos.fill(HIST("hPtGenerated"), mcParticle.pt()); + if (TMath::Abs(mcParticle.pdgCode()) == 11) + histos.fill(HIST("hPtGeneratedEl"), mcParticle.pt()); + if (TMath::Abs(mcParticle.pdgCode()) == 211) + histos.fill(HIST("hPtGeneratedPi"), mcParticle.pt()); + if (TMath::Abs(mcParticle.pdgCode()) == 321) + histos.fill(HIST("hPtGeneratedKa"), mcParticle.pt()); + if (TMath::Abs(mcParticle.pdgCode()) == 2212) + histos.fill(HIST("hPtGeneratedPr"), mcParticle.pt()); + + if (mcParticle.pt() < minPt) { + continue; + } + + bool isDecayDaughter = false; + if (mcParticle.getProcess() == 4) + isDecayDaughter = true; + + multiplicityCounter++; + o2::track::TrackParCov trackParCov; + convertMCParticleToO2Track(mcParticle, trackParCov); + + if (doExtraQA) { + histos.fill(HIST("hSimTrackX"), trackParCov.getX()); + } + + bool reconstructed = mSmearer.smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta); + if (!reconstructed && !processUnreconstructedTracks) { + continue; + } + if (TMath::IsNaN(trackParCov.getZ())) { + // capture rare smearing mistakes / corrupted tracks + continue; + } + + // Base QA (note: reco pT here) + histos.fill(HIST("hPtReconstructed"), trackParCov.getPt()); + if (TMath::Abs(mcParticle.pdgCode()) == 11) + histos.fill(HIST("hPtReconstructedEl"), mcParticle.pt()); + if (TMath::Abs(mcParticle.pdgCode()) == 211) + histos.fill(HIST("hPtReconstructedPi"), mcParticle.pt()); + if (TMath::Abs(mcParticle.pdgCode()) == 321) + histos.fill(HIST("hPtReconstructedKa"), mcParticle.pt()); + if (TMath::Abs(mcParticle.pdgCode()) == 2212) + histos.fill(HIST("hPtReconstructedPr"), mcParticle.pt()); + + if (doExtraQA) { + histos.fill(HIST("hRecoTrackX"), trackParCov.getX()); + } + + // populate vector with track if we reco-ed it + const float t = (ir.timeInBCNS + gRandom->Gaus(0., 100.)) * 1e-3; + if (reconstructed) { + tracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), t, 100.f * 1e-3, isDecayDaughter}); + } else { + ghostTracksAlice3.push_back(TrackAlice3{trackParCov, mcParticle.globalIndex(), t, 100.f * 1e-3, isDecayDaughter}); + } + } + + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + // Calculate primary vertex with tracks from this collision + // data preparation + o2::vertexing::PVertex primaryVertex; + + if (enablePrimaryVertexing) { + std::vector lblTracks; + std::vector vertices; + std::vector vertexTrackIDs; + std::vector v2tRefs; + std::vector lblVtx; + lblVtx.emplace_back(mcCollision.globalIndex(), 1); + std::vector idxVec; // store IDs + + idxVec.reserve(tracksAlice3.size()); + for (unsigned i = 0; i < tracksAlice3.size(); i++) { + lblTracks.emplace_back(tracksAlice3[i].mcLabel, mcCollision.globalIndex(), 1, false); + idxVec.emplace_back(i, o2::dataformats::GlobalTrackID::ITS); // let's say ITS + } + + // Calculate vertices + const int n_vertices = vertexer.process(tracksAlice3, // track array + idxVec, + gsl::span{bcData}, + vertices, + vertexTrackIDs, + v2tRefs, + gsl::span{lblTracks}, + lblVtx); + + if (n_vertices < 1) { + return; // primary vertex not reconstructed + } + + // Find largest vertex + int largestVertex = 0; + for (Int_t iv = 1; iv < n_vertices; iv++) { + if (vertices[iv].getNContributors() > vertices[largestVertex].getNContributors()) { + largestVertex = iv; + } + } + primaryVertex = vertices[largestVertex]; + if (doExtraQA) { + histos.fill(HIST("h2dVerticesVsContributors"), primaryVertex.getNContributors(), n_vertices); + } + } else { + primaryVertex.setXYZ(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + } + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + + // debug / informational + histos.fill(HIST("hSimMultiplicity"), multiplicityCounter); + histos.fill(HIST("hRecoMultiplicity"), tracksAlice3.size()); + histos.fill(HIST("hPVz"), primaryVertex.getZ()); + + if (doExtraQA) { + histos.fill(HIST("hRecoVsSimMultiplicity"), multiplicityCounter, tracksAlice3.size()); + } + + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + // populate collisions + collisions(-1, // BC is irrelevant in synthetic MC tests for now, could be adjusted in future + primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), + primaryVertex.getSigmaX2(), primaryVertex.getSigmaXY(), primaryVertex.getSigmaY2(), + primaryVertex.getSigmaXZ(), primaryVertex.getSigmaYZ(), primaryVertex.getSigmaZ2(), + 0, primaryVertex.getChi2(), primaryVertex.getNContributors(), + 0, 0); + collLabels(mcCollision.globalIndex(), 0); + collisionsAlice3(dNdEta); + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + + // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* + // populate tracks + for (const auto& trackParCov : tracksAlice3) { + // Fixme: collision index could be changeable + aod::track::TrackTypeEnum trackType = aod::track::Track; + + if (populateTracksDCA) { + float dcaXY = 1e+10, dcaZ = 1e+10; + o2::track::TrackParCov trackParametrization(trackParCov); + if (trackParametrization.propagateToDCA(primaryVertex, magneticField, &dcaInfo)) { + dcaXY = dcaInfo.getY(); + dcaZ = dcaInfo.getZ(); + } + if (doExtraQA && (!extraQAwithoutDecayDaughters || (extraQAwithoutDecayDaughters && !trackParCov.isDecayDau))) { + histos.fill(HIST("h2dDCAxy"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + histos.fill(HIST("hTrackXatDCA"), trackParametrization.getX()); + } + tracksDCA(dcaXY, dcaZ); + } + + tracksPar(collisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); + tracksParExtension(trackParCov.getPt(), trackParCov.getP(), trackParCov.getEta(), trackParCov.getPhi()); + + // TODO do we keep the rho as 0? Also the sigma's are duplicated information + tracksParCov(std::sqrt(trackParCov.getSigmaY2()), std::sqrt(trackParCov.getSigmaZ2()), std::sqrt(trackParCov.getSigmaSnp2()), + std::sqrt(trackParCov.getSigmaTgl2()), std::sqrt(trackParCov.getSigma1Pt2()), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + tracksParCovExtension(trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), trackParCov.getSigmaSnpY(), + trackParCov.getSigmaSnpZ(), trackParCov.getSigmaSnp2(), trackParCov.getSigmaTglY(), trackParCov.getSigmaTglZ(), trackParCov.getSigmaTglSnp(), + trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), + trackParCov.getSigma1Pt2()); + tracksLabels(trackParCov.mcLabel, 0); + + // populate extra tables if required to do so + if (populateTracksExtra) { + tracksExtra(0.0f, (uint32_t)0, (uint8_t)0, (uint8_t)0, + (int8_t)0, (int8_t)0, (uint8_t)0, (uint8_t)0, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + } + if (populateTrackSelection) { + trackSelection((uint8_t)0, false, false, false, false, false, false); + trackSelectionExtension(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); + } + TracksAlice3(true); + } + // populate ghost tracks + for (const auto& trackParCov : ghostTracksAlice3) { + // Fixme: collision index could be changeable + aod::track::TrackTypeEnum trackType = aod::track::Track; + + if (populateTracksDCA) { + float dcaXY = 1e+10, dcaZ = 1e+10; + o2::track::TrackParCov trackParametrization(trackParCov); + if (trackParametrization.propagateToDCA(primaryVertex, magneticField, &dcaInfo)) { + dcaXY = dcaInfo.getY(); + dcaZ = dcaInfo.getZ(); + } + if (doExtraQA && (!extraQAwithoutDecayDaughters || (extraQAwithoutDecayDaughters && !trackParCov.isDecayDau))) { + histos.fill(HIST("h2dDCAxy"), trackParametrization.getPt(), dcaXY * 1e+4); // in microns, please + histos.fill(HIST("hTrackXatDCA"), trackParametrization.getX()); + } + tracksDCA(dcaXY, dcaZ); + } + + tracksPar(collisions.lastIndex(), trackType, trackParCov.getX(), trackParCov.getAlpha(), trackParCov.getY(), trackParCov.getZ(), trackParCov.getSnp(), trackParCov.getTgl(), trackParCov.getQ2Pt()); + tracksParExtension(trackParCov.getPt(), trackParCov.getP(), trackParCov.getEta(), trackParCov.getPhi()); + + // TODO do we keep the rho as 0? Also the sigma's are duplicated information + tracksParCov(std::sqrt(trackParCov.getSigmaY2()), std::sqrt(trackParCov.getSigmaZ2()), std::sqrt(trackParCov.getSigmaSnp2()), + std::sqrt(trackParCov.getSigmaTgl2()), std::sqrt(trackParCov.getSigma1Pt2()), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + tracksParCovExtension(trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), trackParCov.getSigmaSnpY(), + trackParCov.getSigmaSnpZ(), trackParCov.getSigmaSnp2(), trackParCov.getSigmaTglY(), trackParCov.getSigmaTglZ(), trackParCov.getSigmaTglSnp(), + trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), + trackParCov.getSigma1Pt2()); + tracksLabels(trackParCov.mcLabel, 0); + + // populate extra tables if required to do so + if (populateTracksExtra) { + tracksExtra(0.0f, (uint32_t)0, (uint8_t)0, (uint8_t)0, + (int8_t)0, (int8_t)0, (uint8_t)0, (uint8_t)0, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + } + if (populateTrackSelection) { + trackSelection((uint8_t)0, false, false, false, false, false, false); + trackSelectionExtension(false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false); + } + TracksAlice3(false); + } + } +}; + +/// Extends TracksExtra if necessary +struct onTheFlyTrackerInitializer { + Spawns tracksExtra; + void init(InitContext const&) {} +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/TableProducer/alice3-decayfinder.cxx b/ALICE3/TableProducer/alice3-decayfinder.cxx new file mode 100644 index 00000000000..04f8284e3c4 --- /dev/null +++ b/ALICE3/TableProducer/alice3-decayfinder.cxx @@ -0,0 +1,598 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// Decay finder task for ALICE 3 +// *+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* +// +// Uses specific ALICE 3 PID and performance for studying +// HF decays. Work in progress: use at your own risk! +// + +#include +#include +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "DCAFitter/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "ALICE3/DataModel/OTFTOF.h" +#include "ALICE3/DataModel/RICH.h" +#include "ALICE3/DataModel/A3DecayFinderTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +// simple checkers +#define biton(var, nbit) ((var) |= (static_cast(1) << (nbit))) +#define bitoff(var, nbit) ((var) &= ~(static_cast(1) << (nbit))) //((a) &= ~(1ULL<<(b))) +#define bitcheck(var, nbit) ((var) & (static_cast(1) << (nbit))) + +using FullTracksExt = soa::Join; + +// For MC association in pre-selection +using labeledTracks = soa::Join; +using tofTracks = soa::Join; +using richTracks = soa::Join; +using alice3tracks = soa::Join; + +struct alice3decayPreselector { + Produces a3decayMaps; + + // Operation and minimisation criteria + Configurable nSigmaTOF{"nSigmaTOF", 4.0f, "Nsigma for TOF PID (if enabled)"}; + Configurable nSigmaRICH{"nSigmaRICH", 4.0f, "Nsigma for RICH PID (if enabled)"}; + + // Define o2 fitter, 2-prong, active memory (no need to redefine per event) + o2::vertexing::DCAFitterN<2> fitter; + + // for bit-packed maps + std::vector selectionMap; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + /// function to check PDG + PDG mother + template + bool checkPDG(TTrack const& track, int pdgMother, int pdg) + { + bool returnValue = false; + // Association check + if (track.has_mcParticle()) { + auto mcParticle = track.template mcParticle_as(); + if (mcParticle.has_mothers()) { + for (auto& mcParticleMother : mcParticle.template mothers_as()) { + if (mcParticle.pdgCode() == pdg && mcParticleMother.pdgCode() == pdgMother) + returnValue = true; + } + } + } // end association check + return returnValue; + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + void init(InitContext& context) + { + // future dev if needed + } + + // go declarative: use partitions instead of "if", then just toggle bits to allow for mask selection later + Partition pInnerTOFPi = nabs(aod::upgrade_tof::nSigmaPionInnerTOF) > nSigmaTOF; + Partition pInnerTOFKa = nabs(aod::upgrade_tof::nSigmaKaonInnerTOF) > nSigmaTOF; + Partition pInnerTOFPr = nabs(aod::upgrade_tof::nSigmaProtonInnerTOF) > nSigmaTOF; + Partition pOuterTOFPi = nabs(aod::upgrade_tof::nSigmaPionOuterTOF) > nSigmaTOF; + Partition pOuterTOFKa = nabs(aod::upgrade_tof::nSigmaKaonOuterTOF) > nSigmaTOF; + Partition pOuterTOFPr = nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) > nSigmaTOF; + Partition pRICHPi = nabs(aod::alice3rich::richNsigmaPi) > nSigmaRICH; + Partition pRICHKa = nabs(aod::alice3rich::richNsigmaKa) > nSigmaRICH; + Partition pRICHPr = nabs(aod::alice3rich::richNsigmaPr) > nSigmaRICH; + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + /// Initialization of mask vectors if uninitialized + void initializeMasks(int size) + { + selectionMap.clear(); + selectionMap.resize(size, 0xFFFFFFFF); // all bits 1, please + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + /// This process function ensures that all V0s are built. It will simply tag everything as true. + void processInitialize(aod::Tracks const& tracks) + { + initializeMasks(tracks.size()); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFilterInnerTOF(tofTracks const& tracks) + { + for (auto const& track : pInnerTOFPi) + bitoff(selectionMap[track.globalIndex()], kInnerTOFPion); + for (auto const& track : pInnerTOFKa) + bitoff(selectionMap[track.globalIndex()], kInnerTOFKaon); + for (auto const& track : pInnerTOFPr) + bitoff(selectionMap[track.globalIndex()], kInnerTOFProton); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFilterOuterTOF(tofTracks const& tracks) + { + for (auto const& track : pOuterTOFPi) + bitoff(selectionMap[track.globalIndex()], kOuterTOFPion); + for (auto const& track : pOuterTOFKa) + bitoff(selectionMap[track.globalIndex()], kOuterTOFKaon); + for (auto const& track : pOuterTOFPr) + bitoff(selectionMap[track.globalIndex()], kOuterTOFProton); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFilterRICH(richTracks const& tracks) + { + for (auto const& track : pRICHPi) + bitoff(selectionMap[track.globalIndex()], kRICHPion); + for (auto const& track : pRICHKa) + bitoff(selectionMap[track.globalIndex()], kRICHKaon); + for (auto const& track : pRICHPr) + bitoff(selectionMap[track.globalIndex()], kRICHProton); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFilterOnMonteCarloTruth(labeledTracks const& tracks, aod::McParticles const&) + { + for (auto const& track : tracks) { + // D mesons + if (!checkPDG(track, 421, -321)) //+421 -> -321 +211 + bitoff(selectionMap[track.globalIndex()], kTrueKaMinusFromD); + if (!checkPDG(track, -421, +321)) //-421 -> +321 -211 + bitoff(selectionMap[track.globalIndex()], kTrueKaPlusFromD); + if (!checkPDG(track, 421, +211)) //+421 -> -321 +211 + bitoff(selectionMap[track.globalIndex()], kTruePiPlusFromD); + if (!checkPDG(track, -421, -211)) //-421 -> +321 -211 + bitoff(selectionMap[track.globalIndex()], kTruePiMinusFromD); + + // Lambdac baryons + if (!checkPDG(track, +4122, +2212)) //+4122 -> +2212 -321 +211 + bitoff(selectionMap[track.globalIndex()], kTruePrPlusFromLc); + if (!checkPDG(track, +4122, -321)) //+4122 -> +2212 -321 +211 + bitoff(selectionMap[track.globalIndex()], kTrueKaMinusFromLc); + if (!checkPDG(track, +4122, +211)) //+4122 -> +2212 -321 +211 + bitoff(selectionMap[track.globalIndex()], kTruePiPlusFromLc); + if (!checkPDG(track, -4122, -2212)) //-4122 -> -2212 +321 -211 + bitoff(selectionMap[track.globalIndex()], kTruePrMinusFromLc); + if (!checkPDG(track, -4122, +321)) //-4122 -> -2212 +321 -211 + bitoff(selectionMap[track.globalIndex()], kTrueKaPlusFromLc); + if (!checkPDG(track, -4122, -211)) //-4122 -> -2212 +321 -211 + bitoff(selectionMap[track.globalIndex()], kTruePiMinusFromLc); + } + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processPublishDecision(aod::Tracks const& tracks) + { + for (uint32_t i = 0; i < tracks.size(); i++) { + a3decayMaps(selectionMap[i]); + } + selectionMap.clear(); + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* + PROCESS_SWITCH(alice3decayPreselector, processInitialize, "Initialize (MUST be on)", true); + PROCESS_SWITCH(alice3decayPreselector, processFilterInnerTOF, "Switch to use inner TOF PID", false); + PROCESS_SWITCH(alice3decayPreselector, processFilterOuterTOF, "Switch to use outer TOF PID", false); + PROCESS_SWITCH(alice3decayPreselector, processFilterRICH, "Switch to use RICH", false); + PROCESS_SWITCH(alice3decayPreselector, processFilterOnMonteCarloTruth, "Switch to use MC truth", false); + PROCESS_SWITCH(alice3decayPreselector, processPublishDecision, "Fill decision mask table (MUST be on)", true); + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* +}; + +struct alice3decayFinder { + SliceCache cache; + + // Operation and minimisation criteria + Configurable magneticField{"magneticField", 20.0f, "Magnetic field (in kilogauss)"}; + Configurable doDCAplotsD{"doDCAplotsD", true, "do daughter prong DCA plots for D mesons"}; + Configurable doDCAplotsLc{"doDCAplotsLc", true, "do daughter prong DCA plots for Lc baryons"}; + Configurable mcSameMotherCheck{"mcSameMotherCheck", true, "check if tracks come from the same MC mother"}; + Configurable dcaDaughtersSelection{"dcaDaughtersSelection", 1000.0f, "DCA between daughters (cm)"}; + + Configurable piFromD_dcaXYconstant{"piFromD_dcaXYconstant", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable piFromD_dcaXYpTdep{"piFromD_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable kaFromD_dcaXYconstant{"kaFromD_dcaXYconstant", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable kaFromD_dcaXYpTdep{"kaFromD_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + + Configurable piFromLc_dcaXYconstant{"piFromLc_dcaXYconstant", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable piFromLc_dcaXYpTdep{"piFromLc_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable kaFromLc_dcaXYconstant{"kaFromLc_dcaXYconstant", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable kaFromLc_dcaXYpTdep{"kaFromLc_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + Configurable prFromLc_dcaXYconstant{"prFromLc_dcaXYconstant", -1.0f, "[0] in |DCAxy| > [0]+[1]/pT"}; + Configurable prFromLc_dcaXYpTdep{"prFromLc_dcaXYpTdep", 0.0, "[1] in |DCAxy| > [0]+[1]/pT"}; + + ConfigurableAxis axisEta{"axisEta", {8, -4.0f, +4.0f}, "#eta"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + ConfigurableAxis axisDCA{"axisDCA", {200, -100, 100}, "DCA (#mum)"}; + ConfigurableAxis axisDMass{"axisDMass", {200, 1.765f, 1.965f}, "D Inv Mass (GeV/c^{2})"}; + ConfigurableAxis axisLcMass{"axisLcMass", {200, 2.186f, 2.386f}, "#Lambda_{c} Inv Mass (GeV/c^{2})"}; + + o2::vertexing::DCAFitterN<2> fitter; + o2::vertexing::DCAFitterN<3> fitter3; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Partition trueD = aod::mcparticle::pdgCode == 421; + Partition trueDbar = aod::mcparticle::pdgCode == -421; + Partition trueLc = aod::mcparticle::pdgCode == 4122; + Partition trueLcbar = aod::mcparticle::pdgCode == -4122; + + // filter expressions for D mesons + static constexpr uint32_t trackSelectionPiPlusFromD = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiPlusFromD; + static constexpr uint32_t trackSelectionPiMinusFromD = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiMinusFromD; + static constexpr uint32_t trackSelectionKaPlusFromD = 1 << kInnerTOFKaon | 1 << kOuterTOFKaon | 1 << kRICHKaon | 1 << kTrueKaPlusFromD; + static constexpr uint32_t trackSelectionKaMinusFromD = 1 << kInnerTOFKaon | 1 << kOuterTOFKaon | 1 << kRICHKaon | 1 << kTrueKaMinusFromD; + + // filter expressions for Lambdac baryons + static constexpr uint32_t trackSelectionPiPlusFromLc = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiPlusFromLc; + static constexpr uint32_t trackSelectionKaPlusFromLc = 1 << kInnerTOFKaon | 1 << kOuterTOFKaon | 1 << kRICHKaon | 1 << kTrueKaPlusFromLc; + static constexpr uint32_t trackSelectionPrPlusFromLc = 1 << kInnerTOFProton | 1 << kOuterTOFProton | 1 << kRICHProton | 1 << kTruePrPlusFromLc; + static constexpr uint32_t trackSelectionPiMinusFromLc = 1 << kInnerTOFPion | 1 << kOuterTOFPion | 1 << kRICHPion | 1 << kTruePiMinusFromLc; + static constexpr uint32_t trackSelectionKaMinusFromLc = 1 << kInnerTOFKaon | 1 << kOuterTOFKaon | 1 << kRICHKaon | 1 << kTrueKaMinusFromLc; + static constexpr uint32_t trackSelectionPrMinusFromLc = 1 << kInnerTOFProton | 1 << kOuterTOFProton | 1 << kRICHProton | 1 << kTruePrMinusFromLc; + + // partitions for D mesons + Partition tracksPiPlusFromD = + ((aod::a3DecayMap::decayMap & trackSelectionPiPlusFromD) == trackSelectionPiPlusFromD) && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > piFromD_dcaXYconstant + piFromD_dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition tracksPiMinusFromD = + ((aod::a3DecayMap::decayMap & trackSelectionPiMinusFromD) == trackSelectionPiMinusFromD) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > piFromD_dcaXYconstant + piFromD_dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition tracksKaPlusFromD = + ((aod::a3DecayMap::decayMap & trackSelectionKaPlusFromD) == trackSelectionKaPlusFromD) && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > kaFromD_dcaXYconstant + kaFromD_dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition tracksKaMinusFromD = + ((aod::a3DecayMap::decayMap & trackSelectionKaMinusFromD) == trackSelectionKaMinusFromD) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > kaFromD_dcaXYconstant + kaFromD_dcaXYpTdep* nabs(aod::track::signed1Pt); + + // partitions for Lc baryons + Partition tracksPiPlusFromLc = + ((aod::a3DecayMap::decayMap & trackSelectionPiPlusFromLc) == trackSelectionPiPlusFromLc) && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > piFromLc_dcaXYconstant + piFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition tracksKaPlusFromLc = + ((aod::a3DecayMap::decayMap & trackSelectionKaPlusFromLc) == trackSelectionKaPlusFromLc) && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > kaFromLc_dcaXYconstant + kaFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition tracksPrPlusFromLc = + ((aod::a3DecayMap::decayMap & trackSelectionPrPlusFromLc) == trackSelectionPrPlusFromLc) && aod::track::signed1Pt > 0.0f && nabs(aod::track::dcaXY) > prFromLc_dcaXYconstant + prFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); + // partitions for Lc baryons + Partition tracksPiMinusFromLc = + ((aod::a3DecayMap::decayMap & trackSelectionPiMinusFromLc) == trackSelectionPiMinusFromLc) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > piFromLc_dcaXYconstant + piFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition tracksKaMinusFromLc = + ((aod::a3DecayMap::decayMap & trackSelectionKaMinusFromLc) == trackSelectionKaMinusFromLc) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > kaFromLc_dcaXYconstant + kaFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); + Partition tracksPrMinusFromLc = + ((aod::a3DecayMap::decayMap & trackSelectionPrMinusFromLc) == trackSelectionPrMinusFromLc) && aod::track::signed1Pt < 0.0f && nabs(aod::track::dcaXY) > prFromLc_dcaXYconstant + prFromLc_dcaXYpTdep* nabs(aod::track::signed1Pt); + + // Helper struct to pass candidate information + struct { + float mass; + float pt; + float eta; + } dmeson; + + struct { + float mass; + float pt; + float eta; + } lcbaryon; + + template + bool buildDecayCandidateTwoBody(TTrackType const& posTrackRow, TTrackType const& negTrackRow, float posMass, float negMass) + { + o2::track::TrackParCov posTrack = getTrackParCov(posTrackRow); + o2::track::TrackParCov negTrack = getTrackParCov(negTrackRow); + + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + // Move close to minima + int nCand = 0; + try { + nCand = fitter.process(posTrack, negTrack); + } catch (...) { + return false; + } + if (nCand == 0) { + return false; + } + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + + posTrack = fitter.getTrack(0); + negTrack = fitter.getTrack(1); + std::array posP; + std::array negP; + posTrack.getPxPyPzGlo(posP); + negTrack.getPxPyPzGlo(negP); + + float dcaDau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + if (dcaDau > dcaDaughtersSelection) + return false; + + // return mass + dmeson.mass = RecoDecay::m(array{array{posP[0], posP[1], posP[2]}, array{negP[0], negP[1], negP[2]}}, array{posMass, negMass}); + dmeson.pt = std::hypot(posP[0] + negP[0], posP[1] + negP[1]); + dmeson.eta = RecoDecay::eta(array{posP[0] + negP[0], posP[1] + negP[1], posP[2] + negP[2]}); + return true; + } + + template + bool buildDecayCandidateThreeBody(TTrackType const& prong0, TTrackType const& prong1, TTrackType const& prong2, float p0mass, float p1mass, float p2mass) + { + o2::track::TrackParCov t0 = getTrackParCov(prong0); + o2::track::TrackParCov t1 = getTrackParCov(prong1); + o2::track::TrackParCov t2 = getTrackParCov(prong2); + + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + // Move close to minima + int nCand = 0; + try { + nCand = fitter3.process(t0, t1, t2); + } catch (...) { + return false; + } + if (nCand == 0) { + return false; + } + //}-{}-{}-{}-{}-{}-{}-{}-{}-{} + + t0 = fitter.getTrack(0); + t1 = fitter.getTrack(1); + t2 = fitter.getTrack(2); + std::array P0; + std::array P1; + std::array P2; + t0.getPxPyPzGlo(P0); + t1.getPxPyPzGlo(P1); + t2.getPxPyPzGlo(P2); + + float dcaDau = TMath::Sqrt(fitter3.getChi2AtPCACandidate()); + if (dcaDau > dcaDaughtersSelection) + return false; + + // return mass + lcbaryon.mass = RecoDecay::m(array{array{P0[0], P0[1], P0[2]}, array{P1[0], P1[1], P1[2]}, array{P2[0], P2[1], P2[2]}}, array{p0mass, p1mass, p2mass}); + lcbaryon.pt = std::hypot(P0[0] + P1[0] + P2[0], P0[1] + P1[1] + P2[1]); + lcbaryon.eta = RecoDecay::eta(array{P0[0] + P1[0] + P2[0], P0[1] + P1[1] + P2[1], P0[2] + P1[2] + P2[2]}); + return true; + } + + /// function to check if tracks have the same mother in MC + template + bool checkSameMother(TTrackType const& track1, TTrackType const& track2) + { + bool returnValue = false; + // Association check + // There might be smarter ways of doing this in the future + if (track1.has_mcParticle() && track2.has_mcParticle()) { + auto mcParticle1 = track1.template mcParticle_as(); + auto mcParticle2 = track2.template mcParticle_as(); + if (mcParticle1.has_mothers() && mcParticle2.has_mothers()) { + for (auto& mcParticleMother1 : mcParticle1.template mothers_as()) { + for (auto& mcParticleMother2 : mcParticle2.template mothers_as()) { + if (mcParticleMother1.globalIndex() == mcParticleMother2.globalIndex()) { + returnValue = true; + } + } + } + } + } // end association check + return returnValue; + } + + void init(InitContext& context) + { + // initialize O2 2-prong fitter (only once) + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); + fitter.setWeightedFinalPCA(false); + fitter.setBz(magneticField); + fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + fitter3.setPropagateToPCA(true); + fitter3.setMaxR(200.); + fitter3.setMinParamChange(1e-3); + fitter3.setMinRelChi2Change(0.9); + fitter3.setMaxDZIni(1e9); + fitter3.setMaxChi2(1e9); + fitter3.setUseAbsDCA(true); + fitter3.setWeightedFinalPCA(false); + fitter3.setBz(magneticField); + fitter3.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); + + if (doprocessFindDmesons) { + histos.add("h2dGenD", "h2dGenD", kTH2F, {axisPt, axisEta}); + histos.add("h2dGenDbar", "h2dGenDbar", kTH2F, {axisPt, axisEta}); + histos.add("h3dRecD", "h2dRecD", kTH3F, {axisPt, axisEta, axisDMass}); + histos.add("h3dRecDbar", "h2dRecDbar", kTH3F, {axisPt, axisEta, axisDMass}); + + histos.add("hMassD", "hMassD", kTH1F, {axisDMass}); + histos.add("hMassDbar", "hMassDbar", kTH1F, {axisDMass}); + + if (doDCAplotsD) { + histos.add("h2dDCAxyVsPtPiPlusFromD", "h2dDCAxyVsPtPiPlusFromD", kTH2F, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtPiMinusFromD", "h2dDCAxyVsPtPiMinusFromD", kTH2F, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtKaPlusFromD", "h2dDCAxyVsPtKaPlusFromD", kTH2F, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtKaMinusFromD", "h2dDCAxyVsPtKaMinusFromD", kTH2F, {axisPt, axisDCA}); + } + } + if (doprocessFindLcBaryons) { + histos.add("h2dGenLc", "h2dGenLc", kTH2F, {axisPt, axisEta}); + histos.add("h2dGenLcbar", "h2dGenLcbar", kTH2F, {axisPt, axisEta}); + histos.add("h3dRecLc", "h2dRecLc", kTH3F, {axisPt, axisEta, axisLcMass}); + histos.add("h3dRecLcbar", "h2dRecLcbar", kTH3F, {axisPt, axisEta, axisLcMass}); + + histos.add("hMassLc", "hMassLc", kTH1F, {axisLcMass}); + histos.add("hMassLcbar", "hMassLcbar", kTH1F, {axisLcMass}); + + if (doDCAplotsD) { + histos.add("h2dDCAxyVsPtPiPlusFromLc", "h2dDCAxyVsPtPiPlusFromLc", kTH2F, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtPiMinusFromLc", "h2dDCAxyVsPtPiMinusFromLc", kTH2F, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtKaPlusFromLc", "h2dDCAxyVsPtKaPlusFromLc", kTH2F, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtKaMinusFromLc", "h2dDCAxyVsPtKaMinusFromLc", kTH2F, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtPrPlusFromLc", "h2dDCAxyVsPtPrPlusFromLc", kTH2F, {axisPt, axisDCA}); + histos.add("h2dDCAxyVsPtPrMinusFromLc", "h2dDCAxyVsPtPrMinusFromLc", kTH2F, {axisPt, axisDCA}); + } + } + } + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processGenerated(aod::McParticles const& mcParticles) + { + // no grouping for MC particles -> as intended + if (doprocessFindDmesons) { + for (auto const& mcParticle : trueD) + histos.fill(HIST("h2dGenD"), mcParticle.pt(), mcParticle.eta()); + for (auto const& mcParticle : trueDbar) + histos.fill(HIST("h2dGenDbar"), mcParticle.pt(), mcParticle.eta()); + } + if (doprocessFindLcBaryons) { + for (auto const& mcParticle : trueLc) + histos.fill(HIST("h2dGenLc"), mcParticle.pt(), mcParticle.eta()); + for (auto const& mcParticle : trueLcbar) + histos.fill(HIST("h2dGenLcbar"), mcParticle.pt(), mcParticle.eta()); + } + } + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFindDmesons(aod::Collision const& collision, alice3tracks const& tracks, aod::McParticles const& mcParticles) + { + // group with this collision + auto tracksPiPlusFromDgrouped = tracksPiPlusFromD->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto tracksKaMinusFromDgrouped = tracksKaMinusFromD->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto tracksKaPlusFromDgrouped = tracksKaPlusFromD->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto tracksPiMinusFromDgrouped = tracksPiMinusFromD->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + if (doDCAplotsD) { + for (auto const& track : tracksPiPlusFromDgrouped) + histos.fill(HIST("h2dDCAxyVsPtPiPlusFromD"), track.pt(), track.dcaXY() * 1e+4); + for (auto const& track : tracksPiMinusFromDgrouped) + histos.fill(HIST("h2dDCAxyVsPtPiMinusFromD"), track.pt(), track.dcaXY() * 1e+4); + for (auto const& track : tracksKaPlusFromDgrouped) + histos.fill(HIST("h2dDCAxyVsPtKaPlusFromD"), track.pt(), track.dcaXY() * 1e+4); + for (auto const& track : tracksKaMinusFromDgrouped) + histos.fill(HIST("h2dDCAxyVsPtKaMinusFromD"), track.pt(), track.dcaXY() * 1e+4); + } + + // D mesons + for (auto const& posTrackRow : tracksPiPlusFromDgrouped) { + for (auto const& negTrackRow : tracksKaMinusFromDgrouped) { + if (mcSameMotherCheck && !checkSameMother(posTrackRow, negTrackRow)) + continue; + if (!buildDecayCandidateTwoBody(posTrackRow, negTrackRow, o2::constants::physics::MassPionCharged, o2::constants::physics::MassKaonCharged)) + continue; + histos.fill(HIST("hMassD"), dmeson.mass); + histos.fill(HIST("h3dRecD"), dmeson.pt, dmeson.eta, dmeson.mass); + } + } + // D mesons + for (auto const& posTrackRow : tracksKaPlusFromDgrouped) { + for (auto const& negTrackRow : tracksPiMinusFromDgrouped) { + if (mcSameMotherCheck && !checkSameMother(posTrackRow, negTrackRow)) + continue; + if (!buildDecayCandidateTwoBody(posTrackRow, negTrackRow, o2::constants::physics::MassKaonCharged, o2::constants::physics::MassPionCharged)) + continue; + histos.fill(HIST("hMassDbar"), dmeson.mass); + histos.fill(HIST("h3dRecDbar"), dmeson.pt, dmeson.eta, dmeson.mass); + } + } + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + void processFindLcBaryons(aod::Collision const& collision, alice3tracks const& tracks, aod::McParticles const& mcParticles) + { + // group with this collision + auto tracksPiPlusFromLcgrouped = tracksPiPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto tracksKaPlusFromLcgrouped = tracksKaPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto tracksPrPlusFromLcgrouped = tracksPrPlusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + auto tracksPiMinusFromLcgrouped = tracksPiMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto tracksKaMinusFromLcgrouped = tracksKaMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto tracksPrMinusFromLcgrouped = tracksPrMinusFromLc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + if (doDCAplotsLc) { + for (auto const& track : tracksPiPlusFromLcgrouped) + histos.fill(HIST("h2dDCAxyVsPtPiPlusFromLc"), track.pt(), track.dcaXY() * 1e+4); + for (auto const& track : tracksPiMinusFromLcgrouped) + histos.fill(HIST("h2dDCAxyVsPtPiMinusFromLc"), track.pt(), track.dcaXY() * 1e+4); + for (auto const& track : tracksKaPlusFromLcgrouped) + histos.fill(HIST("h2dDCAxyVsPtKaPlusFromLc"), track.pt(), track.dcaXY() * 1e+4); + for (auto const& track : tracksKaMinusFromLcgrouped) + histos.fill(HIST("h2dDCAxyVsPtKaMinusFromLc"), track.pt(), track.dcaXY() * 1e+4); + for (auto const& track : tracksPrPlusFromLcgrouped) + histos.fill(HIST("h2dDCAxyVsPtPrPlusFromLc"), track.pt(), track.dcaXY() * 1e+4); + for (auto const& track : tracksPrMinusFromLcgrouped) + histos.fill(HIST("h2dDCAxyVsPtPrMinusFromLc"), track.pt(), track.dcaXY() * 1e+4); + } + + // Lc+ baryons +4122 -> +2212 -321 +211 + for (auto const& proton : tracksPrPlusFromLcgrouped) { + for (auto const& pion : tracksPiPlusFromLcgrouped) { + if (pion.globalIndex() == proton.globalIndex()) + continue; // avoid self + for (auto const& kaon : tracksKaMinusFromLcgrouped) { + if (mcSameMotherCheck && (!checkSameMother(proton, kaon) || !checkSameMother(proton, pion))) + continue; + if (!buildDecayCandidateThreeBody(proton, kaon, pion, o2::constants::physics::MassProton, o2::constants::physics::MassKaonCharged, o2::constants::physics::MassPionCharged)) + continue; + histos.fill(HIST("hMassLc"), lcbaryon.mass); + histos.fill(HIST("h3dRecLc"), lcbaryon.pt, lcbaryon.eta, lcbaryon.mass); + } + } + } + // Lc- baryons -4122 -> -2212 +321 -211 + for (auto const& proton : tracksPrMinusFromLcgrouped) { + for (auto const& pion : tracksPiMinusFromLcgrouped) { + if (pion.globalIndex() == proton.globalIndex()) + continue; // avoid self + for (auto const& kaon : tracksKaPlusFromLcgrouped) { + if (mcSameMotherCheck && (!checkSameMother(proton, kaon) || !checkSameMother(proton, pion))) + continue; + if (!buildDecayCandidateThreeBody(proton, kaon, pion, o2::constants::physics::MassProton, o2::constants::physics::MassKaonCharged, o2::constants::physics::MassPionCharged)) + continue; + histos.fill(HIST("hMassLcbar"), lcbaryon.mass); + histos.fill(HIST("h3dRecLcbar"), lcbaryon.pt, lcbaryon.eta, lcbaryon.mass); + } + } + } + } + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* + PROCESS_SWITCH(alice3decayFinder, processGenerated, "fill MC-only histograms", true); + PROCESS_SWITCH(alice3decayFinder, processFindDmesons, "find D mesons", true); + PROCESS_SWITCH(alice3decayFinder, processFindLcBaryons, "find Lc Baryons", true); + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/ALICE3/TableProducer/onTheFlyTOFPID.cxx b/ALICE3/TableProducer/onTheFlyTOFPID.cxx deleted file mode 100644 index db7932bf4c0..00000000000 --- a/ALICE3/TableProducer/onTheFlyTOFPID.cxx +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -// -// Task to add a table of track parameters propagated to the primary vertex -// - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "ReconstructionDataFormats/DCA.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "CommonUtils/NameConf.h" -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "CommonConstants/GeomConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "TRandom3.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "DetectorsVertexing/HelixHelper.h" - -/// \file onTheFlyTOFPID.cxx -/// -/// \brief This task goes straight from a combination of track table and mcParticles -/// and a custom TOF configuration to a table of TOF NSigmas for the particles -/// being analysed. It currently contemplates 5 particle types: -/// electrons, pions, kaons, protons and muons -/// -/// More particles could be added but would have to be added to the LUT -/// being used in the onTheFly tracker task. -/// -/// \author David Dobrigkeit Chinellato, UNICAMP - -using namespace o2; -using namespace o2::framework; - -struct OnTheFlyTOFPID { - Produces upgradeTof; - - // necessary for particle charges - Service pdg; - - // these are the settings governing the TOF layers to be used - // note that there are two layers foreseen for now: inner and outer TOF - // more could be added (especially a disk TOF at a certain z?) - // in the evolution of this effort - Configurable dBz{"dBz", 20, "magnetic field (kilogauss)"}; - Configurable innerTOFRadius{"innerTOFRadius", 20, "barrel inner TOF radius (cm)"}; - Configurable outerTOFRadius{"outerTOFRadius", 80, "barrel outer TOF radius (cm)"}; - Configurable innerTOFTimeReso{"innerTOFTimeReso", 20, "barrel inner TOF time error (ps)"}; - Configurable outerTOFTimeReso{"outerTOFTimeReso", 20, "barrel outer TOF time error (ps)"}; - Configurable nStepsLIntegrator{"nStepsLIntegrator", 200, "number of steps in length integrator"}; - Configurable doQAplots{"doQAplots", true, "do basic velocity plot qa"}; - Configurable nBinsBeta{"nBinsBeta", 2200, "number of bins in beta"}; - Configurable nBinsP{"nBinsP", 80, "number of bins in momentum"}; - Configurable nBinsTrackLengthInner{"nBinsTrackLengthInner", 300, "number of bins in track length"}; - Configurable nBinsTrackLengthOuter{"nBinsTrackLengthOuter", 300, "number of bins in track length"}; - Configurable nBinsTrackDeltaLength{"nBinsTrackDeltaLength", 100, "number of bins in delta track length"}; - - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - // needed: random number generator for smearing - TRandom3 pRandomNumberGenerator; - - // for handling basic QA histograms if requested - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - void init(o2::framework::InitContext& initContext) - { - pRandomNumberGenerator.SetSeed(0); // fully randomize - - if (doQAplots) { - const AxisSpec axisMomentum{static_cast(nBinsP), 0.0f, +4.0f, "#it{p} (GeV/#it{c})"}; - const AxisSpec axisMomentumSmall{static_cast(nBinsP), 0.0f, +1.0f, "#it{p} (GeV/#it{c})"}; - const AxisSpec axisVelocity{static_cast(nBinsBeta), 0.0f, +1.1f, "Measured #beta"}; - const AxisSpec axisTrackLengthInner{static_cast(nBinsTrackLengthInner), 0.0f, 60.0f, "Track length (cm)"}; - const AxisSpec axisTrackLengthOuter{static_cast(nBinsTrackLengthOuter), 0.0f, 300.0f, "Track length (cm)"}; - const AxisSpec axisTrackDeltaLength{static_cast(nBinsTrackDeltaLength), 0.0f, 30.0f, "Delta Track length (cm)"}; - histos.add("h2dVelocityVsMomentumInner", "h2dVelocityVsMomentumInner", kTH2F, {axisMomentum, axisVelocity}); - histos.add("h2dVelocityVsMomentumOuter", "h2dVelocityVsMomentumOuter", kTH2F, {axisMomentum, axisVelocity}); - histos.add("h2dTrackLengthInnerVsPt", "h2dTrackLengthInnerVsPt", kTH2F, {axisMomentumSmall, axisTrackLengthInner}); - histos.add("h2dTrackLengthOuterVsPt", "h2dTrackLengthOuterVsPt", kTH2F, {axisMomentumSmall, axisTrackLengthOuter}); - - histos.add("h2dTrackLengthInnerRecoVsPt", "h2dTrackLengthInnerRecoVsPt", kTH2F, {axisMomentumSmall, axisTrackLengthInner}); - histos.add("h2dTrackLengthOuterRecoVsPt", "h2dTrackLengthOuterRecoVsPt", kTH2F, {axisMomentumSmall, axisTrackLengthOuter}); - - histos.add("h2dDeltaTrackLengthInnerVsPt", "h2dDeltaTrackLengthInnerVsPt", kTH2F, {axisMomentumSmall, axisTrackDeltaLength}); - histos.add("h2dDeltaTrackLengthOuterVsPt", "h2dDeltaTrackLengthOuterVsPt", kTH2F, {axisMomentumSmall, axisTrackDeltaLength}); - } - } - - /// Function to convert a McParticle into a perfect Track - /// \param particle the particle to convert (mcParticle) - /// \param o2track the address of the resulting TrackParCov - template - void convertMCParticleToO2Track(McParticleType& particle, o2::track::TrackParCov& o2track) - { - // FIXME: this is a fundamentally important piece of code. - // It could be placed in a utility file instead of here. - auto pdgInfo = pdg->GetParticle(particle.pdgCode()); - int charge = 0; - if (pdgInfo != nullptr) { - charge = pdgInfo->Charge() / 3; - } - std::array params; - std::array covm = {0.}; - float s, c, x; - o2::math_utils::sincos(particle.phi(), s, c); - o2::math_utils::rotateZInv(particle.vx(), particle.vy(), x, params[0], s, c); - params[1] = particle.vz(); - params[2] = 0.; // since alpha = phi - auto theta = 2. * std::atan(std::exp(-particle.eta())); - params[3] = 1. / std::tan(theta); - params[4] = charge / particle.pt(); - - // Initialize TrackParCov in-place - new (&o2track)(o2::track::TrackParCov)(x, particle.phi(), params, covm); - } - - /// function to calculate track length of this track up to a certain radius - /// \param track the input track - /// \param radius the radius of the layer you're calculating the length to - /// \param magneticField the magnetic field to use when propagating - float trackLength(o2::track::TrackParCov track, float radius, float magneticField) - { - // don't make use of the track parametrization - float length = -100; - - o2::math_utils::CircleXYf_t trcCircle; - float sna, csa; - track.getCircleParams(magneticField, trcCircle, sna, csa); - - // distance between circle centers (one circle is at origin -> easy) - float centerDistance = std::hypot(trcCircle.xC, trcCircle.yC); - - // condition of circles touching - if not satisfied returned length will be -100 - if (centerDistance < trcCircle.rC + radius && centerDistance > fabs(trcCircle.rC - radius)) { - length = 0.0f; - - // base radical direction - float ux = trcCircle.xC / centerDistance; - float uy = trcCircle.yC / centerDistance; - // calculate perpendicular vector (normalized) for +/- displacement - float vx = -uy; - float vy = +ux; - // calculate coordinate for radical line - float radical = (centerDistance * centerDistance - trcCircle.rC * trcCircle.rC + radius * radius) / (2.0f * centerDistance); - // calculate absolute displacement from center-to-center axis - float displace = (0.5f / centerDistance) * TMath::Sqrt( - (-centerDistance + trcCircle.rC - radius) * - (-centerDistance - trcCircle.rC + radius) * - (-centerDistance + trcCircle.rC + radius) * - (centerDistance + trcCircle.rC + radius)); - - // possible intercept points of track and TOF layer in 2D plane - float point1[2] = {radical * ux + displace * vx, radical * uy + displace * vy}; - float point2[2] = {radical * ux - displace * vx, radical * uy - displace * vy}; - - // decide on correct intercept point - std::array mom; - track.getPxPyPzGlo(mom); - float scalarProduct1 = point1[0] * mom[0] + point1[1] * mom[1]; - float scalarProduct2 = point2[0] * mom[0] + point2[1] * mom[1]; - - // get start point - std::array startPoint; - track.getXYZGlo(startPoint); - - float cosAngle = -1000, modulus = -1000; - - if (scalarProduct1 > scalarProduct2) { - modulus = std::hypot(point1[0] - trcCircle.xC, point1[1] - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); - cosAngle = (point1[0] - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (point1[1] - trcCircle.yC) * (startPoint[0] - trcCircle.yC); - } else { - modulus = std::hypot(point2[0] - trcCircle.xC, point2[1] - trcCircle.yC) * std::hypot(startPoint[0] - trcCircle.xC, startPoint[1] - trcCircle.yC); - cosAngle = (point2[0] - trcCircle.xC) * (startPoint[0] - trcCircle.xC) + (point2[1] - trcCircle.yC) * (startPoint[0] - trcCircle.yC); - } - cosAngle /= modulus; - length = trcCircle.rC * TMath::ACos(cosAngle); - length *= sqrt(1.0f + track.getTgl() * track.getTgl()); - } - return length; - } - - /// returns velocity in centimeters per picoseconds - /// \param momentum the momentum of the tarck - /// \param mass the mass of the particle - float velocity(float momentum, float mass) - { - float a = std::pow(momentum / mass, 2); - // uses light speed in cm/ps so output is in those units - return (o2::constants::physics::LightSpeedCm2NS / 1e+3) * std::sqrt(a / (1 + a)); - } - - void process(soa::Join::iterator const& collision, soa::Join const& tracks, aod::McParticles const&, aod::McCollisions const&) - { - o2::dataformats::VertexBase pvVtx({collision.posX(), collision.posY(), collision.posZ()}, - {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}); - - std::array mcPvCov = {0.}; - o2::dataformats::VertexBase mcPvVtx({0.0f, 0.0f, 0.0f}, mcPvCov); - if (collision.has_mcCollision()) { - auto mcCollision = collision.mcCollision(); - mcPvVtx.setX(mcCollision.posX()); - mcPvVtx.setY(mcCollision.posY()); - mcPvVtx.setZ(mcCollision.posZ()); - } // else remains untreated for now - - for (const auto& track : tracks) { - // first step: find precise arrival time (if any) - // --- convert track into perfect track - if (!track.has_mcParticle()) // should always be OK but check please - continue; - - o2::track::TrackParCov o2track; - auto mcParticle = track.mcParticle(); - convertMCParticleToO2Track(mcParticle, o2track); - - float xPv = -100, trackLengthInnerTOF = -1, trackLengthOuterTOF = -1; - if (o2track.propagateToDCA(mcPvVtx, dBz)) - xPv = o2track.getX(); - if (xPv > -99.) { - trackLengthInnerTOF = trackLength(o2track, innerTOFRadius, dBz); - trackLengthOuterTOF = trackLength(o2track, outerTOFRadius, dBz); - } - - // get mass to calculate velocity - auto pdgInfo = pdg->GetParticle(mcParticle.pdgCode()); - if (pdgInfo == nullptr) { - continue; - } - float expectedTimeInnerTOF = trackLengthInnerTOF / velocity(o2track.getP(), pdgInfo->Mass()); - float expectedTimeOuterTOF = trackLengthOuterTOF / velocity(o2track.getP(), pdgInfo->Mass()); - - // Smear with expected resolutions - float measuredTimeInnerTOF = pRandomNumberGenerator.Gaus(expectedTimeInnerTOF, innerTOFTimeReso); - float measuredTimeOuterTOF = pRandomNumberGenerator.Gaus(expectedTimeOuterTOF, outerTOFTimeReso); - - // Now we calculate the expected arrival time following certain mass hypotheses - // and the (imperfect!) reconstructed track parametrizations - float trackLengthRecoInnerTOF = -1, trackLengthRecoOuterTOF = -1; - auto recoTrack = getTrackParCov(track); - if (recoTrack.propagateToDCA(pvVtx, dBz)) - xPv = recoTrack.getX(); - if (xPv > -99.) { - trackLengthRecoInnerTOF = trackLength(recoTrack, innerTOFRadius, dBz); - trackLengthRecoOuterTOF = trackLength(recoTrack, outerTOFRadius, dBz); - } - - // Straight to Nsigma - float deltaTimeInnerTOF[5], nSigmaInnerTOF[5]; - float deltaTimeOuterTOF[5], nSigmaOuterTOF[5]; - int lpdg_array[5] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton}; - float masses[5]; - - if (doQAplots) { - float momentum = recoTrack.getP(); - // unit conversion: length in cm, time in ps - float innerBeta = 1e+3 * (trackLengthInnerTOF / measuredTimeInnerTOF) / o2::constants::physics::LightSpeedCm2NS; - float outerBeta = 1e+3 * (trackLengthOuterTOF / measuredTimeOuterTOF) / o2::constants::physics::LightSpeedCm2NS; - if (trackLengthRecoInnerTOF > 0) { - histos.fill(HIST("h2dVelocityVsMomentumInner"), momentum, innerBeta); - histos.fill(HIST("h2dTrackLengthInnerVsPt"), o2track.getPt(), trackLengthInnerTOF); - histos.fill(HIST("h2dTrackLengthInnerRecoVsPt"), o2track.getPt(), trackLengthRecoInnerTOF); - } - if (trackLengthRecoOuterTOF > 0) { - histos.fill(HIST("h2dVelocityVsMomentumOuter"), momentum, outerBeta); - histos.fill(HIST("h2dTrackLengthOuterVsPt"), o2track.getPt(), trackLengthOuterTOF); - histos.fill(HIST("h2dTrackLengthOuterRecoVsPt"), o2track.getPt(), trackLengthRecoOuterTOF); - } - } - - for (int ii = 0; ii < 5; ii++) { - nSigmaInnerTOF[ii] = -100; - nSigmaOuterTOF[ii] = -100; - - auto pdgInfoThis = pdg->GetParticle(lpdg_array[ii]); - masses[ii] = pdgInfoThis->Mass(); - deltaTimeInnerTOF[ii] = trackLengthRecoInnerTOF / velocity(recoTrack.getP(), masses[ii]) - measuredTimeInnerTOF; - deltaTimeOuterTOF[ii] = trackLengthRecoOuterTOF / velocity(recoTrack.getP(), masses[ii]) - measuredTimeOuterTOF; - - // Fixme: assumes dominant resolution effect is the TOF resolution - // and not the tracking itself. It's *probably* a fair assumption - // but it should be tested further! - if (trackLengthInnerTOF > 0 && trackLengthRecoInnerTOF > 0) - nSigmaInnerTOF[ii] = deltaTimeInnerTOF[ii] / innerTOFTimeReso; - if (trackLengthOuterTOF > 0 && trackLengthRecoOuterTOF > 0) - nSigmaOuterTOF[ii] = deltaTimeOuterTOF[ii] / outerTOFTimeReso; - } - - float deltaTrackLengthInnerTOF = abs(trackLengthInnerTOF - trackLengthRecoInnerTOF); - if (trackLengthInnerTOF > 0 && trackLengthRecoInnerTOF > 0) { - histos.fill(HIST("h2dDeltaTrackLengthInnerVsPt"), o2track.getPt(), deltaTrackLengthInnerTOF); - } - float deltaTrackLengthOuterTOF = abs(trackLengthOuterTOF - trackLengthRecoOuterTOF); - if (trackLengthOuterTOF > 0 && trackLengthRecoOuterTOF > 0) { - histos.fill(HIST("h2dDeltaTrackLengthOuterVsPt"), o2track.getPt(), deltaTrackLengthInnerTOF); - } - - // Sigmas have been fully calculated. Please populate the NSigma helper table (once per track) - upgradeTof(nSigmaInnerTOF[0], nSigmaInnerTOF[1], nSigmaInnerTOF[2], nSigmaInnerTOF[3], nSigmaInnerTOF[4], trackLengthInnerTOF, trackLengthRecoInnerTOF, deltaTrackLengthInnerTOF, - nSigmaOuterTOF[0], nSigmaOuterTOF[1], nSigmaOuterTOF[2], nSigmaOuterTOF[3], nSigmaOuterTOF[4], trackLengthOuterTOF, trackLengthRecoOuterTOF, deltaTrackLengthOuterTOF); - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} diff --git a/ALICE3/TableProducer/onTheFlyTracker.cxx b/ALICE3/TableProducer/onTheFlyTracker.cxx deleted file mode 100644 index ebfb4d29d2c..00000000000 --- a/ALICE3/TableProducer/onTheFlyTracker.cxx +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file onTheFlyTracker.cxx -/// -/// \brief LUT-based on-the-fly analysis task-level tracking -/// -/// This task allows for the calculation of aod::collisions and aod::Tracks in a synthetic manner, -/// smearing MC particles with very configurable settings. This will allow for the usage of -/// custom LUTs (obtained through separate studies) and the subsequent estimate of the performance -/// of a future detector even in very statistics-hungry analyses. -/// -/// \author David Dobrigkeit Chinellato, UNICAMP -/// \author Nicolò Jacazio , UniBo -/// \author Roberto Preghenella preghenella@bo.infn.it -/// - -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "ReconstructionDataFormats/DCA.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "CommonUtils/NameConf.h" -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "CommonConstants/GeomConstants.h" -#include "TableHelper.h" - -#include "ALICE3/Core/DelphesO2TrackSmearer.h" -#include "ALICE3/DataModel/collisionAlice3.h" - -using namespace o2; -using namespace o2::framework; - -struct OnTheFlyTracker { - Produces collisions; - Produces collLabels; - Produces tracksPar; - Produces tracksParExtension; - Produces tracksParCov; - Produces tracksParCovExtension; - Produces tracksLabels; - Produces tracksDCA; - Produces collisionAlice3; - - Configurable maxEta{"maxEta", 1.5, "maximum eta to consider viable"}; - Configurable multEtaRange{"multEtaRange", 0.8, "eta range to compute the multiplicity"}; - Configurable minPt{"minPt", 0.1, "minimum pt to consider viable"}; - Configurable enableLUT{"enableLUT", false, "Enable track smearing"}; - Configurable enableNucleiSmearing{"enableNucleiSmearing", false, "Enable smearing of nuclei"}; - - Configurable lutEl{"lutEl", "lutCovm.el.dat", "LUT for electrons"}; - Configurable lutMu{"lutMu", "lutCovm.mu.dat", "LUT for muons"}; - Configurable lutPi{"lutPi", "lutCovm.pi.dat", "LUT for pions"}; - Configurable lutKa{"lutKa", "lutCovm.ka.dat", "LUT for kaons"}; - Configurable lutPr{"lutPr", "lutCovm.pr.dat", "LUT for protons"}; - Configurable lutDe{"lutDe", "lutCovm.de.dat", "LUT for deuterons"}; - Configurable lutTr{"lutTr", "lutCovm.tr.dat", "LUT for tritons"}; - Configurable lutHe3{"lutHe3", "lutCovm.he3.dat", "LUT for Helium-3"}; - - bool fillTracksDCA = false; - - // necessary for particle charges - Service pdgDB; - - // for handling basic QA histograms if requested - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - // Track smearer - o2::delphes::DelphesO2TrackSmearer mSmearer; - - void init(o2::framework::InitContext& initContext) - { - // Checking if the tables are requested in the workflow and enabling them - fillTracksDCA = isTableRequiredInWorkflow(initContext, "TracksDCA"); - - if (enableLUT) { - std::map mapPdgLut; - const char* lutElChar = lutEl->c_str(); - const char* lutMuChar = lutMu->c_str(); - const char* lutPiChar = lutPi->c_str(); - const char* lutKaChar = lutKa->c_str(); - const char* lutPrChar = lutPr->c_str(); - - LOGF(info, "Will load electron lut file ..: %s", lutElChar); - LOGF(info, "Will load muon lut file ......: %s", lutMuChar); - LOGF(info, "Will load pion lut file ......: %s", lutPiChar); - LOGF(info, "Will load kaon lut file ......: %s", lutKaChar); - LOGF(info, "Will load proton lut file ....: %s", lutPrChar); - - mapPdgLut.insert(std::make_pair(11, lutElChar)); - mapPdgLut.insert(std::make_pair(13, lutMuChar)); - mapPdgLut.insert(std::make_pair(211, lutPiChar)); - mapPdgLut.insert(std::make_pair(321, lutKaChar)); - mapPdgLut.insert(std::make_pair(2212, lutPrChar)); - // mapPdgLut.insert(std::make_pair(11, "lutCovm.el.dat")); - // mapPdgLut.insert(std::make_pair(13, "lutCovm.mu.dat")); - // mapPdgLut.insert(std::make_pair(211, "lutCovm.pi.dat")); - // mapPdgLut.insert(std::make_pair(321, "lutCovm.ka.dat")); - // mapPdgLut.insert(std::make_pair(2212, "lutCovm.pr.dat")); - if (enableNucleiSmearing) { - const char* lutDeChar = ((std::string)lutDe).c_str(); - const char* lutTrChar = ((std::string)lutTr).c_str(); - const char* lutHe3Char = ((std::string)lutHe3).c_str(); - mapPdgLut.insert(std::make_pair(1000010020, lutDeChar)); - mapPdgLut.insert(std::make_pair(1000010030, lutTrChar)); - mapPdgLut.insert(std::make_pair(1000020030, lutHe3Char)); - } - for (auto e : mapPdgLut) { - if (!mSmearer.loadTable(e.first, e.second)) { - LOG(fatal) << "Having issue with loading the LUT " << e.first << " " << e.second; - } - } - } - - // Basic QA - const AxisSpec axisMomentum{static_cast(1000), 0.0f, +10.0f, "#it{p} (GeV/#it{c})"}; - histos.add("hPtGenerated", "hPtGenerated", kTH1F, {axisMomentum}); - histos.add("hPtGeneratedEl", "hPtGeneratedEl", kTH1F, {axisMomentum}); - histos.add("hPtGeneratedPi", "hPtGeneratedPi", kTH1F, {axisMomentum}); - histos.add("hPtGeneratedKa", "hPtGeneratedKa", kTH1F, {axisMomentum}); - histos.add("hPtGeneratedPr", "hPtGeneratedPr", kTH1F, {axisMomentum}); - histos.add("hPtReconstructed", "hPtReconstructed", kTH1F, {axisMomentum}); - histos.add("hPtReconstructedEl", "hPtReconstructedEl", kTH1F, {axisMomentum}); - histos.add("hPtReconstructedPi", "hPtReconstructedPi", kTH1F, {axisMomentum}); - histos.add("hPtReconstructedKa", "hPtReconstructedKa", kTH1F, {axisMomentum}); - histos.add("hPtReconstructedPr", "hPtReconstructedPr", kTH1F, {axisMomentum}); - } - - /// Function to convert a McParticle into a perfect Track - /// \param particle the particle to convert (mcParticle) - /// \param o2track the address of the resulting TrackParCov - template - void convertMCParticleToO2Track(McParticleType& particle, o2::track::TrackParCov& o2track) - { - auto pdgInfo = pdgDB->GetParticle(particle.pdgCode()); - int charge = 0; - if (pdgInfo != nullptr) { - charge = pdgInfo->Charge() / 3; - } - std::array params; - std::array covm = {0.}; - float s, c, x; - o2::math_utils::sincos(particle.phi(), s, c); - o2::math_utils::rotateZInv(particle.vx(), particle.vy(), x, params[0], s, c); - params[1] = particle.vz(); - params[2] = 0.; // since alpha = phi - auto theta = 2. * std::atan(std::exp(-particle.eta())); - params[3] = 1. / std::tan(theta); - params[4] = charge / particle.pt(); - - // Initialize TrackParCov in-place - new (&o2track)(o2::track::TrackParCov)(x, particle.phi(), params, covm); - } - - /// Function to fill track parameter table - /// \param coll collision (for index) - /// \param trackType type of created track - /// \param trackPar track for parameters - template - void fillTracksPar(CollType& coll, aod::track::TrackTypeEnum trackType, TTrackPar& trackPar) - { - tracksPar(coll.globalIndex(), trackType, trackPar.getX(), trackPar.getAlpha(), trackPar.getY(), trackPar.getZ(), trackPar.getSnp(), trackPar.getTgl(), trackPar.getQ2Pt()); - tracksParExtension(trackPar.getPt(), trackPar.getP(), trackPar.getEta(), trackPar.getPhi()); - } - - float dNdEta = 0.f; // Charged particle multiplicity to use in the efficiency evaluation - void process(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) - { - o2::dataformats::DCA dcaInfoCov; - o2::dataformats::VertexBase vtx; - // First we compute the number of charged particles in the event - dNdEta = 0.f; - for (const auto& mcParticle : mcParticles) { - if (std::abs(mcParticle.eta()) > multEtaRange) { - continue; - } - if (mcParticle.has_daughters()) { - continue; - } - const auto& pdgInfo = pdgDB->GetParticle(mcParticle.pdgCode()); - if (!pdgInfo) { - LOG(warning) << "PDG code " << mcParticle.pdgCode() << " not found in the database"; - continue; - } - if (pdgInfo->Charge() == 0) { - continue; - } - dNdEta += 1.f; - } - - dNdEta /= (multEtaRange * 2.0f); - - for (const auto& mcParticle : mcParticles) { - if (!mcParticle.isPhysicalPrimary()) { - continue; - } - const auto pdg = std::abs(mcParticle.pdgCode()); - if (pdg != kElectron && pdg != kMuonMinus && pdg != kPiPlus && pdg != kKPlus && pdg != kProton) { - continue; - } - if (std::fabs(mcParticle.eta()) > maxEta) { - continue; - } - - histos.fill(HIST("hPtGenerated"), mcParticle.pt()); - if (TMath::Abs(mcParticle.pdgCode()) == 11) - histos.fill(HIST("hPtGeneratedEl"), mcParticle.pt()); - if (TMath::Abs(mcParticle.pdgCode()) == 211) - histos.fill(HIST("hPtGeneratedPi"), mcParticle.pt()); - if (TMath::Abs(mcParticle.pdgCode()) == 321) - histos.fill(HIST("hPtGeneratedKa"), mcParticle.pt()); - if (TMath::Abs(mcParticle.pdgCode()) == 2212) - histos.fill(HIST("hPtGeneratedPr"), mcParticle.pt()); - - if (mcParticle.pt() < minPt) { - continue; - } - o2::track::TrackParCov trackParCov; - convertMCParticleToO2Track(mcParticle, trackParCov); - - if (!mSmearer.smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta)) { - continue; - } - - // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* - // Calculate primary vertex - // To be added once smeared tracks are in place - // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+* - - // Base QA (note: reco pT here) - histos.fill(HIST("hPtReconstructed"), trackParCov.getPt()); - if (TMath::Abs(mcParticle.pdgCode()) == 11) - histos.fill(HIST("hPtReconstructedEl"), mcParticle.pt()); - if (TMath::Abs(mcParticle.pdgCode()) == 211) - histos.fill(HIST("hPtReconstructedPi"), mcParticle.pt()); - if (TMath::Abs(mcParticle.pdgCode()) == 321) - histos.fill(HIST("hPtReconstructedKa"), mcParticle.pt()); - if (TMath::Abs(mcParticle.pdgCode()) == 2212) - histos.fill(HIST("hPtReconstructedPr"), mcParticle.pt()); - - // Fixme: collision index could be changeable - aod::track::TrackTypeEnum trackType = aod::track::Track; - fillTracksPar(mcCollision, trackType, trackParCov); - if (fillTracksDCA) { - tracksDCA(1e-3, 1e-3); - } - // TODO do we keep the rho as 0? Also the sigma's are duplicated information - tracksParCov(std::sqrt(trackParCov.getSigmaY2()), std::sqrt(trackParCov.getSigmaZ2()), std::sqrt(trackParCov.getSigmaSnp2()), - std::sqrt(trackParCov.getSigmaTgl2()), std::sqrt(trackParCov.getSigma1Pt2()), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - tracksParCovExtension(trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), trackParCov.getSigmaSnpY(), - trackParCov.getSigmaSnpZ(), trackParCov.getSigmaSnp2(), trackParCov.getSigmaTglY(), trackParCov.getSigmaTglZ(), trackParCov.getSigmaTglSnp(), - trackParCov.getSigmaTgl2(), trackParCov.getSigma1PtY(), trackParCov.getSigma1PtZ(), trackParCov.getSigma1PtSnp(), trackParCov.getSigma1PtTgl(), - trackParCov.getSigma1Pt2()); - tracksLabels(mcParticle.globalIndex(), 0); - } - collisions(-1, // BC is irrelevant in synthetic MC tests for now, could be adjusted in future - mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), - 1e-3, 0.0, 1e-3, 0.0, 0.0, 1e-3, - 0, 1e-3, mcParticles.size(), - 0, 0); - collLabels(mcCollision.globalIndex(), 0); - collisionAlice3(dNdEta); - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/ALICE3/Tasks/alice3-dilepton.cxx b/ALICE3/Tasks/alice3-dilepton.cxx index f0366807040..2b2551371e3 100644 --- a/ALICE3/Tasks/alice3-dilepton.cxx +++ b/ALICE3/Tasks/alice3-dilepton.cxx @@ -24,6 +24,7 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisDataModel.h" #include "ALICE3/DataModel/OTFTOF.h" +#include "ALICE3/DataModel/tracksAlice3.h" using namespace o2; using namespace o2::aod; @@ -54,6 +55,12 @@ struct Alice3Dilepton { Configurable ptMax{"pt-max", 5.f, "Upper limit in pT"}; Configurable etaMin{"eta-min", -5.f, "Lower limit in eta"}; Configurable etaMax{"eta-max", 5.f, "Upper limit in eta"}; + Configurable useGen{"use-gen", false, "Use generated (true) or smeared/reconstructed (false) values for fiducial cuts"}; + Configurable selectReconstructed{"selectReconstructed", true, "Select only reconstructed tracks (true) or ghosts (false)"}; + Configurable nSigmaEleCutOuterTOF{"nSigmaEleCutOuterTOF", 3., "Electron inclusion in outer TOF"}; + Configurable nSigmaEleCutInnerTOF{"nSigmaEleCutInnerTOF", 3., "Electron inclusion in inner TOF"}; + Configurable nSigmaPionCutOuterTOF{"nSigmaPionCutOuterTOF", 3., "Pion exclusion in outer TOF"}; + Configurable nSigmaPionCutInnerTOF{"nSigmaPionCutInnerTOF", 3., "Pion exclusion in inner TOF"}; HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -80,6 +87,7 @@ struct Alice3Dilepton { registry.add("Generated/Particle/Pt", "Particle Pt", kTH1F, {axisPt}); registry.add("Generated/Particle/Eta", "Particle Eta", kTH1F, {axisEta}); registry.add("Generated/Particle/Phi", "Particle Phi", kTH1F, {axisPhi}); + registry.add("Generated/Particle/Eta_Pt", "Eta vs. Pt", kTH2F, {axisPt, axisEta}, true); registry.add("Generated/Particle/prodVx", "Particle Prod. Vertex X", kTH1F, {axisProdx}); registry.add("Generated/Particle/prodVy", "Particle Prod. Vertex Y", kTH1F, {axisPrody}); registry.add("Generated/Particle/prodVz", "Particle Prod. Vertex Z", kTH1F, {axisProdz}); @@ -89,39 +97,32 @@ struct Alice3Dilepton { registry.add("Generated/Pair/ULS/Eta", "Pair Eta", kTH1F, {axisEta}); registry.add("Generated/Pair/ULS/Phi", "Pair Phi", kTH1F, {axisPhi}); registry.add("Generated/Pair/ULS/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); - registry.add("Generated/Pair/LSpp/Mass", "Pair Mass", kTH1F, {axisM}); - registry.add("Generated/Pair/LSpp/Pt", "Pair Pt", kTH1F, {axisPt}); - registry.add("Generated/Pair/LSpp/Eta", "Pair Eta", kTH1F, {axisEta}); - registry.add("Generated/Pair/LSpp/Phi", "Pair Phi", kTH1F, {axisPhi}); - registry.add("Generated/Pair/LSpp/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); - registry.add("Generated/Pair/LSnn/Mass", "Pair Mass", kTH1F, {axisM}); - registry.add("Generated/Pair/LSnn/Pt", "Pair Pt", kTH1F, {axisPt}); - registry.add("Generated/Pair/LSnn/Eta", "Pair Eta", kTH1F, {axisEta}); - registry.add("Generated/Pair/LSnn/Phi", "Pair Phi", kTH1F, {axisPhi}); - registry.add("Generated/Pair/LSnn/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); + + registry.addClone("Generated/Pair/ULS/", "Generated/Pair/LSpp/"); + registry.addClone("Generated/Pair/ULS/", "Generated/Pair/LSnn/"); registry.add("Reconstructed/Event/VtxX", "Vertex X", kTH1F, {axisVx}); registry.add("Reconstructed/Event/VtxY", "Vertex Y", kTH1F, {axisVy}); registry.add("Reconstructed/Event/VtxZ", "Vertex Z", kTH1F, {axisVz}); + registry.add("Reconstructed/Track/Pt", "Track Pt", kTH1F, {axisPt}); registry.add("Reconstructed/Track/Eta", "Track Eta", kTH1F, {axisEta}); registry.add("Reconstructed/Track/Phi", "Track Eta", kTH1F, {axisPhi}); + registry.add("Reconstructed/Track/Eta_Pt", "Eta vs. Pt", kTH2F, {axisPt, axisEta}, true); registry.add("Reconstructed/Track/SigmaOTofvspt", "Track #sigma oTOF", kTH2F, {axisPt, axisSigmaEl}); registry.add("Reconstructed/Track/SigmaITofvspt", "Track #sigma iTOF", kTH2F, {axisPt, axisSigmaEl}); registry.add("Reconstructed/Track/outerTOFTrackLength", "Track length outer TOF", kTH1F, {axisTrackLengthOuterTOF}); + registry.addClone("Reconstructed/Track/", "Reconstructed/TrackPID/"); + registry.add("Reconstructed/Pair/ULS/Mass", "Pair Mass", kTH1F, {axisM}); registry.add("Reconstructed/Pair/ULS/Pt", "Pair Pt", kTH1F, {axisPt}); registry.add("Reconstructed/Pair/ULS/Eta", "Pair Eta", kTH1F, {axisEta}); registry.add("Reconstructed/Pair/ULS/Phi", "Pair Phi", kTH1F, {axisPhi}); - registry.add("Reconstructed/Pair/LSpp/Mass", "Pair Mass", kTH1F, {axisM}); - registry.add("Reconstructed/Pair/LSpp/Pt", "Pair Pt", kTH1F, {axisPt}); - registry.add("Reconstructed/Pair/LSpp/Eta", "Pair Eta", kTH1F, {axisEta}); - registry.add("Reconstructed/Pair/LSpp/Phi", "Pair Phi", kTH1F, {axisPhi}); - registry.add("Reconstructed/Pair/LSnn/Mass", "Pair Mass", kTH1F, {axisM}); - registry.add("Reconstructed/Pair/LSnn/Pt", "Pair Pt", kTH1F, {axisPt}); - registry.add("Reconstructed/Pair/LSnn/Eta", "Pair Eta", kTH1F, {axisEta}); - registry.add("Reconstructed/Pair/LSnn/Phi", "Pair Phi", kTH1F, {axisPhi}); + registry.add("Reconstructed/Pair/ULS/Mass_Pt", "Pair Mass vs. Pt", kTH2F, {axisM, axisPt}, true); + + registry.addClone("Reconstructed/Pair/ULS/", "Reconstructed/Pair/LSpp/"); + registry.addClone("Reconstructed/Pair/ULS/", "Reconstructed/Pair/LSnn/"); HistogramConfigSpec hs_rec{HistType::kTHnSparseF, {axisM, axisPt, axisDCAxy}, 3}; registry.add("Reconstructed/Pair/ULS/hs_rec", "", hs_rec); @@ -169,15 +170,15 @@ struct Alice3Dilepton { if (mother1_pdg != mother2_pdg) return -1; - if (abs(mother1_pdg) != 22 // photon - && abs(mother1_pdg) != 111 // pi0 - && abs(mother1_pdg) != 221 // eta - && abs(mother1_pdg) != 331 // eta' - && abs(mother1_pdg) != 113 // rho - && abs(mother1_pdg) != 223 // omega - && abs(mother1_pdg) != 333 // phi - && abs(mother1_pdg) != 443 // Jpsi - && abs(mother1_pdg) != 100443 // psi2S + if (std::abs(mother1_pdg) != 22 // photon + && std::abs(mother1_pdg) != 111 // pi0 + && std::abs(mother1_pdg) != 221 // eta + && std::abs(mother1_pdg) != 331 // eta' + && std::abs(mother1_pdg) != 113 // rho + && std::abs(mother1_pdg) != 223 // omega + && std::abs(mother1_pdg) != 333 // phi + && std::abs(mother1_pdg) != 443 // Jpsi + && std::abs(mother1_pdg) != 100443 // psi2S ) { return -1; } @@ -210,7 +211,7 @@ struct Alice3Dilepton { int mother1_pdg = mother_p1.pdgCode(); int mother2_pdg = mother_p2.pdgCode(); - if (((500 < abs(mother1_pdg) && abs(mother1_pdg) < 599) || (5000 < abs(mother1_pdg) && abs(mother1_pdg) < 5999)) && ((500 < abs(mother2_pdg) && abs(mother2_pdg) < 599) || (5000 < abs(mother2_pdg) && abs(mother2_pdg) < 5999))) { + if (((500 < std::abs(mother1_pdg) && std::abs(mother1_pdg) < 599) || (5000 < std::abs(mother1_pdg) && std::abs(mother1_pdg) < 5999)) && ((500 < std::abs(mother2_pdg) && std::abs(mother2_pdg) < 599) || (5000 < std::abs(mother2_pdg) && std::abs(mother2_pdg) < 5999))) { return HFllType::kBe_Be; // bb->ee, decay type = 2 } @@ -222,10 +223,10 @@ struct Alice3Dilepton { int grand_mother1_pdg = grand_mother_p1.pdgCode(); int grand_mother2_pdg = grand_mother_p2.pdgCode(); - if (((400 < abs(mother1_pdg) && abs(mother1_pdg) < 499) || (4000 < abs(mother1_pdg) && abs(mother1_pdg) < 4999)) && ((400 < abs(mother2_pdg) && abs(mother2_pdg) < 499) || (4000 < abs(mother2_pdg) && abs(mother2_pdg) < 4999))) { // mother is charm + if (((400 < std::abs(mother1_pdg) && std::abs(mother1_pdg) < 499) || (4000 < std::abs(mother1_pdg) && std::abs(mother1_pdg) < 4999)) && ((400 < std::abs(mother2_pdg) && std::abs(mother2_pdg) < 499) || (4000 < std::abs(mother2_pdg) && std::abs(mother2_pdg) < 4999))) { // mother is charm - if (((500 < abs(grand_mother1_pdg) && abs(grand_mother1_pdg) < 599) || (5000 < abs(grand_mother1_pdg) && abs(grand_mother1_pdg) < 5999)) && ((500 < abs(grand_mother2_pdg) && abs(grand_mother2_pdg) < 599) || (5000 < abs(grand_mother2_pdg) && abs(grand_mother2_pdg) < 5999))) { // grand mother is beauty - return kBCe_BCe; // b->c->e and b->c->e, decay type = 1 + if (((500 < std::abs(grand_mother1_pdg) && std::abs(grand_mother1_pdg) < 599) || (5000 < std::abs(grand_mother1_pdg) && std::abs(grand_mother1_pdg) < 5999)) && ((500 < std::abs(grand_mother2_pdg) && std::abs(grand_mother2_pdg) < 599) || (5000 < std::abs(grand_mother2_pdg) && std::abs(grand_mother2_pdg) < 5999))) { // grand mother is beauty + return kBCe_BCe; // b->c->e and b->c->e, decay type = 1 } else { return kCe_Ce; // prompt cc->ee, decay type = 0 } @@ -233,8 +234,8 @@ struct Alice3Dilepton { if (motherid_p1 == grand_motherid_p2 || grand_motherid_p1 == motherid_p2) { if ( - (((500 < abs(mother1_pdg) && abs(mother1_pdg) < 599) || (5000 < abs(mother1_pdg) && abs(mother1_pdg) < 5999)) && ((500 < abs(grand_mother2_pdg) && abs(grand_mother2_pdg) < 599) || (5000 < abs(grand_mother2_pdg) && abs(grand_mother2_pdg) < 5999))) || - (((500 < abs(mother2_pdg) && abs(mother2_pdg) < 599) || (5000 < abs(mother2_pdg) && abs(mother2_pdg) < 5999)) && ((500 < abs(grand_mother1_pdg) && abs(grand_mother1_pdg) < 599) || (5000 < abs(grand_mother1_pdg) && abs(grand_mother1_pdg) < 5999)))) { + (((500 < std::abs(mother1_pdg) && std::abs(mother1_pdg) < 599) || (5000 < std::abs(mother1_pdg) && std::abs(mother1_pdg) < 5999)) && ((500 < std::abs(grand_mother2_pdg) && std::abs(grand_mother2_pdg) < 599) || (5000 < std::abs(grand_mother2_pdg) && std::abs(grand_mother2_pdg) < 5999))) || + (((500 < std::abs(mother2_pdg) && std::abs(mother2_pdg) < 599) || (5000 < std::abs(mother2_pdg) && std::abs(mother2_pdg) < 5999)) && ((500 < std::abs(grand_mother1_pdg) && std::abs(grand_mother1_pdg) < 599) || (5000 < std::abs(grand_mother1_pdg) && std::abs(grand_mother1_pdg) < 5999)))) { return HFllType::kBCe_Be_SameB; // b->c->e and c->e, decay type = 3 } } @@ -273,8 +274,8 @@ struct Alice3Dilepton { if (motherid_p1 != grand_motherid_p2 && grand_motherid_p1 != motherid_p2) { // different mother and grand mother if ( - (((500 < abs(mother1_pdg) && abs(mother1_pdg) < 599) || (5000 < abs(mother1_pdg) && abs(mother1_pdg) < 5999)) && ((500 < abs(grand_mother2_pdg) && abs(grand_mother2_pdg) < 599) || (5000 < abs(grand_mother2_pdg) && abs(grand_mother2_pdg) < 5999))) || - (((500 < abs(mother2_pdg) && abs(mother2_pdg) < 599) || (5000 < abs(mother2_pdg) && abs(mother2_pdg) < 5999)) && ((500 < abs(grand_mother1_pdg) && abs(grand_mother1_pdg) < 599) || (5000 < abs(grand_mother1_pdg) && abs(grand_mother1_pdg) < 5999)))) { + (((500 < std::abs(mother1_pdg) && std::abs(mother1_pdg) < 599) || (5000 < std::abs(mother1_pdg) && std::abs(mother1_pdg) < 5999)) && ((500 < std::abs(grand_mother2_pdg) && std::abs(grand_mother2_pdg) < 599) || (5000 < std::abs(grand_mother2_pdg) && std::abs(grand_mother2_pdg) < 5999))) || + (((500 < std::abs(mother2_pdg) && std::abs(mother2_pdg) < 599) || (5000 < std::abs(mother2_pdg) && std::abs(mother2_pdg) < 5999)) && ((500 < std::abs(grand_mother1_pdg) && std::abs(grand_mother1_pdg) < 599) || (5000 < std::abs(grand_mother1_pdg) && std::abs(grand_mother1_pdg) < 5999)))) { return HFllType::kBCe_Be_DiffB; // b->c->e and c->e, decay type = 4 } } @@ -292,12 +293,12 @@ struct Alice3Dilepton { } auto mct1 = t1.template mcParticle_as(); - if (abs(mct1.pdgCode()) != pdg || !mct1.isPhysicalPrimary()) { + if (std::abs(mct1.pdgCode()) != pdg || !mct1.isPhysicalPrimary()) { continue; } auto mct2 = t2.template mcParticle_as(); - if (abs(mct2.pdgCode()) != pdg || !mct2.isPhysicalPrimary()) { + if (std::abs(mct2.pdgCode()) != pdg || !mct2.isPhysicalPrimary()) { continue; } @@ -315,14 +316,15 @@ struct Alice3Dilepton { // float dcaXY_res_t2 = sqrt(t2.cYY()); float pair_dca_xy = sqrt((pow(t2.dcaXY() / sqrt(t2.cYY()), 2) + pow(t1.dcaXY() / sqrt(t1.cYY()), 2)) / 2.); - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); // reconstructed pt/eta/phi - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); // reconstructed pt/eta/phi + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), std::abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); // reconstructed pt/eta/phi + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), std::abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); // reconstructed pt/eta/phi ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; registry.fill(HIST("Reconstructed/Pair/ULS/Mass"), v12.M()); registry.fill(HIST("Reconstructed/Pair/ULS/Pt"), v12.Pt()); registry.fill(HIST("Reconstructed/Pair/ULS/Eta"), v12.Eta()); registry.fill(HIST("Reconstructed/Pair/ULS/Phi"), v12.Phi() < 0.f ? v12.Phi() + TMath::TwoPi() : v12.Phi()); + registry.fill(HIST("Reconstructed/Pair/ULS/Mass_Pt"), v12.M(), v12.Pt()); registry.fill(HIST("Reconstructed/Pair/ULS/hs_rec"), v12.M(), v12.Pt(), pair_dca_xy); } // end of unlike-sign pair loop @@ -333,12 +335,12 @@ struct Alice3Dilepton { } auto mct1 = t1.template mcParticle_as(); - if (abs(mct1.pdgCode()) != pdg || !mct1.isPhysicalPrimary()) { + if (std::abs(mct1.pdgCode()) != pdg || !mct1.isPhysicalPrimary()) { continue; } auto mct2 = t2.template mcParticle_as(); - if (abs(mct2.pdgCode()) != pdg || !mct2.isPhysicalPrimary()) { + if (std::abs(mct2.pdgCode()) != pdg || !mct2.isPhysicalPrimary()) { continue; } @@ -356,20 +358,22 @@ struct Alice3Dilepton { // float dcaXY_res_t2 = sqrt(t2.cYY()); float pair_dca_xy = sqrt((pow(t2.dcaXY() / sqrt(t2.cYY()), 2) + pow(t1.dcaXY() / sqrt(t1.cYY()), 2)) / 2.); - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); // reconstructed pt/eta/phi - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); // reconstructed pt/eta/phi + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), std::abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); // reconstructed pt/eta/phi + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), std::abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); // reconstructed pt/eta/phi ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; if constexpr (pairtype == PairType::kLSpp) { registry.fill(HIST("Reconstructed/Pair/LSpp/Mass"), v12.M()); registry.fill(HIST("Reconstructed/Pair/LSpp/Pt"), v12.Pt()); registry.fill(HIST("Reconstructed/Pair/LSpp/Eta"), v12.Eta()); + registry.fill(HIST("Reconstructed/Pair/LSpp/Mass_Pt"), v12.M(), v12.Pt()); registry.fill(HIST("Reconstructed/Pair/LSpp/Phi"), v12.Phi() < 0.f ? v12.Phi() + TMath::TwoPi() : v12.Phi()); registry.fill(HIST("Reconstructed/Pair/LSpp/hs_rec"), v12.M(), v12.Pt(), pair_dca_xy); } else if constexpr (pairtype == PairType::kLSnn) { registry.fill(HIST("Reconstructed/Pair/LSnn/Mass"), v12.M()); registry.fill(HIST("Reconstructed/Pair/LSnn/Pt"), v12.Pt()); registry.fill(HIST("Reconstructed/Pair/LSnn/Eta"), v12.Eta()); + registry.fill(HIST("Reconstructed/Pair/LSnn/Mass_Pt"), v12.M(), v12.Pt()); registry.fill(HIST("Reconstructed/Pair/LSnn/Phi"), v12.Phi() < 0.f ? v12.Phi() + TMath::TwoPi() : v12.Phi()); registry.fill(HIST("Reconstructed/Pair/LSnn/hs_rec"), v12.M(), v12.Pt(), pair_dca_xy); } @@ -382,7 +386,7 @@ struct Alice3Dilepton { { if constexpr (pairtype == PairType::kULS) { for (auto& [t1, t2] : combinations(soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (abs(t1.pdgCode()) != pdg || abs(t2.pdgCode()) != pdg) { + if (std::abs(t1.pdgCode()) != pdg || std::abs(t2.pdgCode()) != pdg) { continue; } @@ -402,8 +406,8 @@ struct Alice3Dilepton { } // auto mother = mcparticles.iteratorAt(motherid); - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), std::abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), std::abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; registry.fill(HIST("Generated/Pair/ULS/Mass"), v12.M()); @@ -415,7 +419,7 @@ struct Alice3Dilepton { } else if constexpr (pairtype == PairType::kLSpp || pairtype == PairType::kLSnn) { for (auto& [t1, t2] : combinations(soa::CombinationsStrictlyUpperIndexPolicy(tracks1, tracks2))) { - if (abs(t1.pdgCode()) != pdg || abs(t2.pdgCode()) != pdg) { + if (std::abs(t1.pdgCode()) != pdg || std::abs(t2.pdgCode()) != pdg) { continue; } @@ -435,8 +439,8 @@ struct Alice3Dilepton { } // auto mother = mcparticles.iteratorAt(motherid); - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), std::abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), std::abs(pdg) == 11 ? o2::constants::physics::MassElectron : o2::constants::physics::MassMuon); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; if constexpr (pairtype == PairType::kLSpp) { @@ -470,7 +474,7 @@ struct Alice3Dilepton { auto mcParticles_per_coll = mcParticles.sliceBy(perMCCollision, mccollision.globalIndex()); for (const auto& mcParticle : mcParticles_per_coll) { - if (abs(mcParticle.pdgCode()) != pdg) { + if (std::abs(mcParticle.pdgCode()) != pdg) { continue; } if (!mcParticle.isPhysicalPrimary()) { @@ -483,6 +487,7 @@ struct Alice3Dilepton { registry.fill(HIST("Generated/Particle/Pt"), mcParticle.pt()); registry.fill(HIST("Generated/Particle/Eta"), mcParticle.eta()); registry.fill(HIST("Generated/Particle/Phi"), mcParticle.phi()); + registry.fill(HIST("Generated/Particle/Eta_Pt"), mcParticle.pt(), mcParticle.eta()); registry.fill(HIST("Generated/Particle/prodVx"), mcParticle.vx()); registry.fill(HIST("Generated/Particle/prodVy"), mcParticle.vy()); @@ -500,8 +505,13 @@ struct Alice3Dilepton { } // end of mc collision loop } // end of processGen - using MyTracksMC = soa::Join; - Filter trackFilter = etaMin < o2::aod::track::eta && o2::aod::track::eta < etaMax && ptMin < o2::aod::track::pt && o2::aod::track::pt < ptMax; + using MyTracksMC = soa::Join; + // Filter trackFilter = etaMin < o2::aod::track::eta && + // o2::aod::track::eta < etaMax && + // ptMin < o2::aod::track::pt && + // o2::aod::track::pt < ptMax && + // o2::aod::track_alice3::isReconstructed == selectReconstructed; + Filter trackFilter = o2::aod::track_alice3::isReconstructed == selectReconstructed; using MyFilteredTracksMC = soa::Filtered; Preslice perCollision = aod::track::collisionId; Partition posTracks = o2::aod::track::signed1Pt > 0.f; @@ -520,19 +530,31 @@ struct Alice3Dilepton { auto tracks_coll = tracks.sliceBy(perCollision, collision.globalIndex()); for (const auto& track : tracks_coll) { - // if (!IsInAcceptance(neg) || !IsInAcceptance(pos)) { - // continue; - // }// filtered already + if (!track.has_mcParticle()) { + continue; + } + const auto mcParticle = track.mcParticle_as(); + if (std::abs(mcParticle.pdgCode()) != pdg) { + continue; + } + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + if (useGen) { + if (!IsInAcceptance(mcParticle)) { + continue; + } + } else { + if (!IsInAcceptance(track)) { + continue; + } + } // if (fabs(track.nSigmaElectronOuterTOF())<3 ) { // continue; // } - if (!track.has_mcParticle()) { - continue; - } - const auto mcParticle = track.mcParticle_as(); - if (abs(mcParticle.pdgCode()) != pdg) { + if (std::abs(mcParticle.pdgCode()) != pdg) { continue; } if (!mcParticle.isPhysicalPrimary()) { @@ -544,6 +566,23 @@ struct Alice3Dilepton { registry.fill(HIST("Reconstructed/Track/Pt"), track.pt()); registry.fill(HIST("Reconstructed/Track/Eta"), track.eta()); registry.fill(HIST("Reconstructed/Track/Phi"), track.phi()); + registry.fill(HIST("Reconstructed/Track/Eta_Pt"), track.pt(), track.eta()); + // implement pid + bool isEleOuterTOF = std::abs(track.nSigmaElectronOuterTOF()) < nSigmaEleCutOuterTOF; + bool isNotPionOuterTOF = std::abs(track.nSigmaPionOuterTOF()) > nSigmaPionCutOuterTOF; + isEleOuterTOF = isEleOuterTOF && isNotPionOuterTOF; + bool isEleInnerTOF = std::abs(track.nSigmaElectronInnerTOF()) < nSigmaEleCutInnerTOF; + bool isNotPionInnerTOF = std::abs(track.nSigmaPionInnerTOF()) > nSigmaPionCutInnerTOF; + isEleInnerTOF = isEleInnerTOF && isNotPionInnerTOF; + if (isEleOuterTOF || isEleInnerTOF) { + registry.fill(HIST("Reconstructed/TrackPID/SigmaOTofvspt"), mcParticle.pt(), track.nSigmaElectronOuterTOF()); + registry.fill(HIST("Reconstructed/TrackPID/SigmaITofvspt"), mcParticle.pt(), track.nSigmaElectronInnerTOF()); + registry.fill(HIST("Reconstructed/TrackPID/outerTOFTrackLength"), track.outerTOFTrackLength()); + registry.fill(HIST("Reconstructed/TrackPID/Pt"), track.pt()); + registry.fill(HIST("Reconstructed/TrackPID/Eta"), track.eta()); + registry.fill(HIST("Reconstructed/TrackPID/Phi"), track.phi()); + registry.fill(HIST("Reconstructed/TrackPID/Eta_Pt"), track.pt(), track.eta()); + } } // end of track loop auto negTracks_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache_rec); diff --git a/ALICE3/Tasks/alice3-lutmaker.cxx b/ALICE3/Tasks/alice3-lutmaker.cxx index 27ce729f9f2..50c03099468 100644 --- a/ALICE3/Tasks/alice3-lutmaker.cxx +++ b/ALICE3/Tasks/alice3-lutmaker.cxx @@ -206,6 +206,8 @@ struct Alice3LutMaker { int ntrks = 0; for (const auto& track : tracks) { + if (!track.has_mcParticle()) + continue; const auto mcParticle = track.mcParticle_as(); if (mcParticle.pdgCode() != pdg) { continue; diff --git a/ALICE3/Tasks/alice3-qa-singleparticle.cxx b/ALICE3/Tasks/alice3-qa-singleparticle.cxx index 2f4b41deee5..83f68baf6b1 100644 --- a/ALICE3/Tasks/alice3-qa-singleparticle.cxx +++ b/ALICE3/Tasks/alice3-qa-singleparticle.cxx @@ -21,19 +21,20 @@ #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "TDatabasePDG.h" +#include "TMCProcess.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; struct Alice3SingleParticle { - Service pdg; + Service pdg; Configurable PDG{"PDG", 2212, "PDG code of the particle of interest"}; Configurable IsStable{"IsStable", 0, "Flag to check stable particles"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable ptBins{"pt-bins", 500, "Number of pT bins"}; Configurable ptMin{"pt-min", 0.f, "Lower limit in pT"}; - Configurable ptMax{"pt-max", 5.f, "Upper limit in pT"}; + Configurable ptMax{"pt-max", 10.f, "Upper limit in pT"}; Configurable etaBins{"eta-bins", 500, "Number of eta bins"}; Configurable etaMin{"eta-min", -3.f, "Lower limit in eta"}; Configurable etaMax{"eta-max", 3.f, "Upper limit in eta"}; @@ -42,11 +43,27 @@ struct Alice3SingleParticle { Configurable prodBins{"prod-bins", 100, "Number of production vertex bins"}; Configurable prodMin{"prod-min", -1.f, "Lower limit in production vertex"}; Configurable prodMax{"prod-max", 1.f, "Upper limit in production vertex"}; + Configurable prodBinsZ{"prod-bins-z", 100, "Number of production vertex bins"}; + Configurable prodMinZ{"prod-min-z", -10.f, "Lower limit in production vertex along Z"}; + Configurable prodMaxZ{"prod-max-z", 10.f, "Upper limit in production vertex along Z"}; Configurable charge{"charge", 1.f, "Particle charge to scale the reconstructed momentum"}; Configurable doPrint{"doPrint", false, "Flag to print debug messages"}; void init(InitContext&) { + int nEnabled = 0; + if (doprocessStandard) { + nEnabled++; + } + if (doprocessParticleOnly) { + nEnabled++; + } + if (doprocessNonIU) { + nEnabled++; + } + if (nEnabled == 0 || nEnabled > 1) { + LOG(fatal) << "You can't process with " << nEnabled << " process functions, pick one"; + } pdg->AddParticle("deuteron", "deuteron", 1.8756134, kTRUE, 0.0, 3, "Nucleus", 1000010020); pdg->AddAntiParticle("anti-deuteron", -1000010020); @@ -77,16 +94,22 @@ struct Alice3SingleParticle { const AxisSpec axisE{etaBins, 0, 1000, "E"}; const AxisSpec axisProdx{prodBins, prodMin, prodMax, "Prod. Vertex X (cm)"}; const AxisSpec axisPrody{prodBins, prodMin, prodMax, "Prod. Vertex Y (cm)"}; - const AxisSpec axisProdz{prodBins, prodMin, prodMax, "Prod. Vertex Z (cm)"}; + const AxisSpec axisProdz{prodBinsZ, prodMinZ, prodMaxZ, "Prod. Vertex Z (cm)"}; const AxisSpec axisProdRadius{prodBins, 0., 2. * prodMax, "Prod. Vertex Radius (cm)"}; - histos.add("event/VtxX", "Vertex X", kTH1D, {axisVx}); - histos.add("event/VtxY", "Vertex Y", kTH1D, {axisVy}); - histos.add("event/VtxZ", "Vertex Z", kTH1D, {axisVz}); + if (!doprocessParticleOnly) { + histos.add("event/VtxX", "Vertex X", kTH1D, {axisVx}); + histos.add("event/VtxY", "Vertex Y", kTH1D, {axisVy}); + histos.add("event/VtxZ", "Vertex Z", kTH1D, {axisVz}); + } histos.add("particle/PDGs", "Particle PDGs", kTH2D, {axisPDGs, axisCharge}); histos.add("particle/PDGsPrimaries", "Particle PDGs of Primaries", kTH2D, {axisPDGs, axisCharge}); histos.add("particle/PDGsSecondaries", "Particle PDGs of Secondaries", kTH2D, {axisPDGs, axisCharge}); + auto h = histos.add("particle/producedProcess", "Particle process of production " + tit, kTH1D, {{kMaxMCProcess, -0.5, -0.5 + kMaxMCProcess, "getProcess"}}); + for (int i = 0; i < kMaxMCProcess; i++) { + h->GetXaxis()->SetBinLabel(i + 1, TMCProcessName[i]); + } histos.add("particle/Pt", "Particle Pt " + tit, kTH1D, {axisPt}); histos.add("particle/P", "Particle P " + tit, kTH1D, {axisP}); histos.add("particle/primariesPt", "Particle Pt (primary) " + tit, kTH1D, {axisPt}); @@ -137,7 +160,9 @@ struct Alice3SingleParticle { histos.add("particle/mothers/prodVz", "Mothers Prod. Vertex Z " + tit, kTH1D, {axisProdz}); histos.add("particle/mothers/prodRadiusVsPt", "Mothers Prod. Vertex Radius " + tit, kTH2D, {axisPt, axisProdRadius}); histos.add("particle/mothers/prodRadius3DVsPt", "Mothers Prod. Vertex Radius XYZ " + tit, kTH2D, {axisPt, axisProdRadius}); - + if (doprocessParticleOnly) { + return; + } histos.add("track/PDGs", "Track PDGs", kTH2D, {axisPDGs, axisCharge}); histos.add("track/withoutParticle", "Tracks without particles", kTH1D, {axisPt}); histos.add("track/tofPDGs", "Track wTOF PDGs", kTH2D, {axisPDGs, axisCharge}); @@ -168,9 +193,298 @@ struct Alice3SingleParticle { return Form("%i", particle.pdgCode()); } - void process(const o2::aod::McCollisions& colls, - const soa::Join& tracks, - const aod::McParticles& mcParticles) + void processStandard(const o2::aod::McCollisions& colls, + const soa::Join& tracks, + const aod::McParticles& mcParticles) + { + for (const auto& col : colls) { + histos.fill(HIST("event/VtxX"), col.posX()); + histos.fill(HIST("event/VtxY"), col.posY()); + histos.fill(HIST("event/VtxZ"), col.posZ()); + } + std::vector ParticlesOfInterest; + for (const auto& mcParticle : mcParticles) { + const auto& pdgString = getPdgCodeString(mcParticle); + const auto& pdgCharge = getCharge(mcParticle); + histos.get(HIST("particle/PDGs"))->Fill(pdgString, pdgCharge, 1.f); + if (mcParticle.isPhysicalPrimary()) { + histos.get(HIST("particle/PDGsPrimaries"))->Fill(pdgString, pdgCharge, 1.f); + } else { + histos.get(HIST("particle/PDGsSecondaries"))->Fill(pdgString, pdgCharge, 1.f); + } + if (mcParticle.pdgCode() != PDG) { + continue; + } + if (mcParticle.y() < yMin || mcParticle.y() > yMax) { + continue; + } + if (mcParticle.eta() < etaMin || mcParticle.eta() > etaMax) { + continue; + } + if (mcParticle.pt() < ptMin || mcParticle.pt() > ptMax) { + continue; + } + if (mcParticle.vz() < prodMinZ || mcParticle.vz() > prodMaxZ) { + continue; + } + histos.fill(HIST("particle/producedProcess"), mcParticle.getProcess()); + histos.fill(HIST("particle/Pt"), mcParticle.pt()); + histos.fill(HIST("particle/P"), mcParticle.p()); + histos.fill(HIST("particle/Eta"), mcParticle.eta()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("particle/primariesPt"), mcParticle.pt()); + histos.fill(HIST("particle/primariesP"), mcParticle.p()); + histos.fill(HIST("particle/primariesEta"), mcParticle.eta()); + } else { + histos.fill(HIST("particle/secondariesPt"), mcParticle.pt()); + histos.fill(HIST("particle/secondariesP"), mcParticle.p()); + histos.fill(HIST("particle/secondariesEta"), mcParticle.eta()); + } + histos.fill(HIST("particle/EvsPz"), mcParticle.e(), mcParticle.pz()); + histos.fill(HIST("particle/Y"), mcParticle.y()); + histos.fill(HIST("particle/YvzPz"), mcParticle.y(), mcParticle.pz()); + histos.fill(HIST("particle/EtavzPz"), mcParticle.eta(), mcParticle.pz()); + histos.fill(HIST("particle/PvzPz"), mcParticle.p(), mcParticle.pz()); + histos.fill(HIST("particle/PtvzPz"), mcParticle.pt(), mcParticle.pz()); + histos.fill(HIST("particle/Px"), mcParticle.px()); + histos.fill(HIST("particle/Py"), mcParticle.py()); + histos.fill(HIST("particle/Pz"), mcParticle.pz()); + histos.fill(HIST("particle/prodVx"), mcParticle.vx()); + histos.fill(HIST("particle/prodVy"), mcParticle.vy()); + histos.fill(HIST("particle/prodVz"), mcParticle.vz()); + if (mcParticle.has_daughters()) { + auto daughters = mcParticle.daughters_as(); + for (const auto& daughter : daughters) { + const auto& pdgStringDau = getPdgCodeString(daughter); + const auto& pdgChargeDau = getCharge(daughter); + + histos.get(HIST("particle/daughters/PDGs"))->Fill(pdgStringDau, pdgChargeDau, 1.f); + if (mcParticle.isPhysicalPrimary()) { + histos.get(HIST("particle/daughters/PDGsPrimaries"))->Fill(pdgStringDau, pdgChargeDau, 1.f); + } else { + histos.get(HIST("particle/daughters/PDGsSecondaries"))->Fill(pdgStringDau, pdgChargeDau, 1.f); + } + + histos.fill(HIST("particle/daughters/prodVx"), daughter.vx()); + histos.fill(HIST("particle/daughters/prodVy"), daughter.vy()); + histos.fill(HIST("particle/daughters/prodVz"), daughter.vz()); + histos.fill(HIST("particle/daughters/prodRadiusVsPt"), mcParticle.pt(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy())); + histos.fill(HIST("particle/daughters/prodRadius3DVsPt"), mcParticle.pt(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy() + mcParticle.vz() * mcParticle.vz())); + } + } + if (mcParticle.has_mothers()) { + auto mothers = mcParticle.mothers_as(); + for (const auto& mother : mothers) { + const auto& pdgStringMot = getPdgCodeString(mother); + const auto& pdgChargeMot = getCharge(mother); + + histos.get(HIST("particle/mothers/PDGs"))->Fill(pdgStringMot, pdgChargeMot, 1.f); + if (mcParticle.isPhysicalPrimary()) { + histos.get(HIST("particle/mothers/PDGsPrimaries"))->Fill(pdgStringMot, pdgChargeMot, 1.f); + } else { + histos.get(HIST("particle/mothers/PDGsSecondaries"))->Fill(pdgStringMot, pdgChargeMot, 1.f); + } + + histos.fill(HIST("particle/mothers/prodVx"), mother.vx()); + histos.fill(HIST("particle/mothers/prodVy"), mother.vy()); + histos.fill(HIST("particle/mothers/prodVz"), mother.vz()); + histos.fill(HIST("particle/mothers/prodRadiusVsPt"), mother.pt(), std::sqrt(mother.vx() * mother.vx() + mother.vy() * mother.vy())); + histos.fill(HIST("particle/mothers/prodRadius3DVsPt"), mother.pt(), std::sqrt(mother.vx() * mother.vx() + mother.vy() * mother.vy() + mother.vz() * mother.vz())); + } + } + + histos.fill(HIST("particle/prodRadius"), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy())); + histos.fill(HIST("particle/prodVxVy"), mcParticle.vx(), mcParticle.vy()); + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == 4) { + histos.fill(HIST("particle/prodVxVyStr"), mcParticle.vx(), mcParticle.vy()); + } else { + histos.fill(HIST("particle/prodVxVyMat"), mcParticle.vx(), mcParticle.vy()); + } + } else { + histos.fill(HIST("particle/prodVxVyPrm"), mcParticle.vx(), mcParticle.vy()); + } + histos.fill(HIST("particle/prodVxVsPt"), mcParticle.pt(), mcParticle.vx()); + histos.fill(HIST("particle/prodVyVsPt"), mcParticle.pt(), mcParticle.vy()); + histos.fill(HIST("particle/prodVzVsPt"), mcParticle.pt(), mcParticle.vz()); + histos.fill(HIST("particle/prodRadiusVsPt"), mcParticle.pt(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy())); + histos.fill(HIST("particle/prodRadiusVsEta"), mcParticle.eta(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy())); + histos.fill(HIST("particle/prodRadius3DVsPt"), mcParticle.pt(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy() + mcParticle.vz() * mcParticle.vz())); + ParticlesOfInterest.push_back(mcParticle.globalIndex()); + } + + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + histos.fill(HIST("track/withoutParticle"), track.pt()); + continue; + } + const auto mcParticle = track.mcParticle_as(); + histos.get(HIST("track/PDGs"))->Fill(getPdgCodeString(mcParticle), getCharge(mcParticle), 1.f); + if (track.hasTOF()) { + histos.get(HIST("track/tofPDGs"))->Fill(getPdgCodeString(mcParticle), getCharge(mcParticle), 1.f); + } + if (!IsStable) { + if (!mcParticle.has_mothers()) { + continue; + } + // auto mothers = mcParticle.mothers(); + auto mothers = mcParticle.mothers_as(); + const auto ParticleIsInteresting = std::find(ParticlesOfInterest.begin(), ParticlesOfInterest.end(), mothers[0].globalIndex()) != ParticlesOfInterest.end(); + if (!ParticleIsInteresting) { + continue; + } + if (doPrint) { + LOG(info) << "Track " << track.globalIndex() << " comes from a " << mothers[0].pdgCode() << " and is a " << mcParticle.pdgCode(); + } + } else { + if (mcParticle.pdgCode() != PDG) { + continue; + } + histos.fill(HIST("track/Pt"), track.pt() * charge); + histos.fill(HIST("track/PtvsMCPt"), track.pt() * charge, mcParticle.pt()); + histos.fill(HIST("track/Eta"), track.eta()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("track/primariesPt"), track.pt() * charge); + histos.fill(HIST("track/primariesEta"), track.eta()); + } else { + histos.fill(HIST("track/secondariesPt"), track.pt() * charge); + histos.fill(HIST("track/secondariesEta"), track.eta()); + } + + if (!mcParticle.has_mothers()) { + if (doPrint) { + LOG(info) << "Track " << track.globalIndex() << " is a " << mcParticle.pdgCode(); + } + continue; + } + // auto mothers = mcParticle.mothers(); + auto mothers = mcParticle.mothers_as(); + if (mcParticle.isPhysicalPrimary()) { + histos.get(HIST("track/primaries"))->Fill(getPdgCodeString(mothers[0]), getCharge(mothers[0]), 1.f); + } else { + histos.get(HIST("track/secondaries"))->Fill(getPdgCodeString(mothers[0]), getCharge(mothers[0]), 1.f); + } + if (doPrint) { + LOG(info) << "Track " << track.globalIndex() << " is a " << mcParticle.pdgCode() << " and comes from a " << mothers[0].pdgCode() << " and is " << (mcParticle.isPhysicalPrimary() ? "" : "not") << " a primary"; + } + } + } + } + PROCESS_SWITCH(Alice3SingleParticle, processStandard, "Process IU tracks", true); + + void processParticleOnly(const aod::McParticles& mcParticles) + { + for (const auto& mcParticle : mcParticles) { + const auto& pdgString = getPdgCodeString(mcParticle); + const auto& pdgCharge = getCharge(mcParticle); + histos.get(HIST("particle/PDGs"))->Fill(pdgString, pdgCharge, 1.f); + if (mcParticle.isPhysicalPrimary()) { + histos.get(HIST("particle/PDGsPrimaries"))->Fill(pdgString, pdgCharge, 1.f); + } else { + histos.get(HIST("particle/PDGsSecondaries"))->Fill(pdgString, pdgCharge, 1.f); + } + if (mcParticle.pdgCode() != PDG) { + continue; + } + if (mcParticle.y() < yMin || mcParticle.y() > yMax) { + continue; + } + if (mcParticle.eta() < etaMin || mcParticle.eta() > etaMax) { + continue; + } + if (mcParticle.vz() < prodMinZ || mcParticle.vz() > prodMaxZ) { + continue; + } + histos.fill(HIST("particle/producedProcess"), mcParticle.getProcess()); + histos.fill(HIST("particle/Pt"), mcParticle.pt()); + histos.fill(HIST("particle/P"), mcParticle.p()); + histos.fill(HIST("particle/Eta"), mcParticle.eta()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("particle/primariesPt"), mcParticle.pt()); + histos.fill(HIST("particle/primariesP"), mcParticle.p()); + histos.fill(HIST("particle/primariesEta"), mcParticle.eta()); + } else { + histos.fill(HIST("particle/secondariesPt"), mcParticle.pt()); + histos.fill(HIST("particle/secondariesP"), mcParticle.p()); + histos.fill(HIST("particle/secondariesEta"), mcParticle.eta()); + } + histos.fill(HIST("particle/EvsPz"), mcParticle.e(), mcParticle.pz()); + histos.fill(HIST("particle/Y"), mcParticle.y()); + histos.fill(HIST("particle/YvzPz"), mcParticle.y(), mcParticle.pz()); + histos.fill(HIST("particle/EtavzPz"), mcParticle.eta(), mcParticle.pz()); + histos.fill(HIST("particle/PvzPz"), mcParticle.p(), mcParticle.pz()); + histos.fill(HIST("particle/PtvzPz"), mcParticle.pt(), mcParticle.pz()); + histos.fill(HIST("particle/Px"), mcParticle.px()); + histos.fill(HIST("particle/Py"), mcParticle.py()); + histos.fill(HIST("particle/Pz"), mcParticle.pz()); + histos.fill(HIST("particle/prodVx"), mcParticle.vx()); + histos.fill(HIST("particle/prodVy"), mcParticle.vy()); + histos.fill(HIST("particle/prodVz"), mcParticle.vz()); + if (mcParticle.has_daughters()) { + auto daughters = mcParticle.daughters_as(); + for (const auto& daughter : daughters) { + const auto& pdgStringDau = getPdgCodeString(daughter); + const auto& pdgChargeDau = getCharge(daughter); + + histos.get(HIST("particle/daughters/PDGs"))->Fill(pdgStringDau, pdgChargeDau, 1.f); + if (mcParticle.isPhysicalPrimary()) { + histos.get(HIST("particle/daughters/PDGsPrimaries"))->Fill(pdgStringDau, pdgChargeDau, 1.f); + } else { + histos.get(HIST("particle/daughters/PDGsSecondaries"))->Fill(pdgStringDau, pdgChargeDau, 1.f); + } + + histos.fill(HIST("particle/daughters/prodVx"), daughter.vx()); + histos.fill(HIST("particle/daughters/prodVy"), daughter.vy()); + histos.fill(HIST("particle/daughters/prodVz"), daughter.vz()); + histos.fill(HIST("particle/daughters/prodRadiusVsPt"), mcParticle.pt(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy())); + histos.fill(HIST("particle/daughters/prodRadius3DVsPt"), mcParticle.pt(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy() + mcParticle.vz() * mcParticle.vz())); + } + } + if (mcParticle.has_mothers()) { + auto mothers = mcParticle.mothers_as(); + for (const auto& mother : mothers) { + const auto& pdgStringMot = getPdgCodeString(mother); + const auto& pdgChargeMot = getCharge(mother); + + histos.get(HIST("particle/mothers/PDGs"))->Fill(pdgStringMot, pdgChargeMot, 1.f); + if (mcParticle.isPhysicalPrimary()) { + histos.get(HIST("particle/mothers/PDGsPrimaries"))->Fill(pdgStringMot, pdgChargeMot, 1.f); + } else { + histos.get(HIST("particle/mothers/PDGsSecondaries"))->Fill(pdgStringMot, pdgChargeMot, 1.f); + } + + histos.fill(HIST("particle/mothers/prodVx"), mother.vx()); + histos.fill(HIST("particle/mothers/prodVy"), mother.vy()); + histos.fill(HIST("particle/mothers/prodVz"), mother.vz()); + histos.fill(HIST("particle/mothers/prodRadiusVsPt"), mother.pt(), std::sqrt(mother.vx() * mother.vx() + mother.vy() * mother.vy())); + histos.fill(HIST("particle/mothers/prodRadius3DVsPt"), mother.pt(), std::sqrt(mother.vx() * mother.vx() + mother.vy() * mother.vy() + mother.vz() * mother.vz())); + } + } + + histos.fill(HIST("particle/prodRadius"), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy())); + histos.fill(HIST("particle/prodVxVy"), mcParticle.vx(), mcParticle.vy()); + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == 4) { + histos.fill(HIST("particle/prodVxVyStr"), mcParticle.vx(), mcParticle.vy()); + } else { + histos.fill(HIST("particle/prodVxVyMat"), mcParticle.vx(), mcParticle.vy()); + } + } else { + histos.fill(HIST("particle/prodVxVyPrm"), mcParticle.vx(), mcParticle.vy()); + } + histos.fill(HIST("particle/prodVxVsPt"), mcParticle.pt(), mcParticle.vx()); + histos.fill(HIST("particle/prodVyVsPt"), mcParticle.pt(), mcParticle.vy()); + histos.fill(HIST("particle/prodVzVsPt"), mcParticle.pt(), mcParticle.vz()); + histos.fill(HIST("particle/prodRadiusVsPt"), mcParticle.pt(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy())); + histos.fill(HIST("particle/prodRadiusVsEta"), mcParticle.eta(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy())); + histos.fill(HIST("particle/prodRadius3DVsPt"), mcParticle.pt(), std::sqrt(mcParticle.vx() * mcParticle.vx() + mcParticle.vy() * mcParticle.vy() + mcParticle.vz() * mcParticle.vz())); + } + } + PROCESS_SWITCH(Alice3SingleParticle, processParticleOnly, "Process Particle only", false); + + void processNonIU(const o2::aod::McCollisions& colls, + const soa::Join& tracks, + const aod::McParticles& mcParticles) { for (const auto& col : colls) { histos.fill(HIST("event/VtxX"), col.posX()); @@ -196,6 +510,9 @@ struct Alice3SingleParticle { if (mcParticle.eta() < etaMin || mcParticle.eta() > etaMax) { continue; } + if (mcParticle.pt() < ptMin || mcParticle.pt() > ptMax) { + continue; + } histos.fill(HIST("particle/Pt"), mcParticle.pt()); histos.fill(HIST("particle/P"), mcParticle.p()); histos.fill(HIST("particle/Eta"), mcParticle.eta()); @@ -338,6 +655,7 @@ struct Alice3SingleParticle { } } } + PROCESS_SWITCH(Alice3SingleParticle, processNonIU, "Process non IU tracks", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/CODEOWNERS b/CODEOWNERS index d42c0eb7b63..7966f8651f8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -14,10 +14,11 @@ * @AliceO2Group/core @alibuild @jgrosseo @iarsene @ktf @ddobrigk /Common/CCDB @alibuild @jgrosseo @iarsene @ekryshen @ddobrigk /Common/Tools/Multiplicity @alibuild @ddobrigk @victor-gonzalez -/ALICE3 @alibuild @njacazio @ginnocen @vkucera @hscheid +/Common/Tools/ML @alibuild @fcatalan92 @fmazzasc +/ALICE3 @alibuild @njacazio @vkucera @hscheid /DPG @alibuild @chiarazampolli @noferini /DPG/Tasks/AOTEvent @alibuild @ekryshen @strogolo -/DPG/Tasks/AOTTrack @alibuild @mfaggin @iouribelikov @njacazio +/DPG/Tasks/AOTTrack @alibuild @mfaggin @belikov @njacazio /EventFiltering @alibuild @mpuccio @strogolo /EventFiltering/PWGHF @alibuild @fgrosa @vkucera @mpuccio @strogolo /EventFiltering/PWGUD @alibuild @pbuehler @mpuccio @strogolo @@ -30,11 +31,7 @@ /PWGEM @alibuild @mikesas @rbailhac @feisenhu /PWGEM/Dilepton @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu /PWGEM/PhotonMeson @alibuild @mikesas @rbailhac @m-c-danisch @novitzky @mhemmer-cern -/PWGHF @alibuild @ginnocen @vkucera @fcolamar -/PWGHF/D2H @alibuild @ginnocen @vkucera @fcolamar @fcatalan92 @lvermunt -/PWGHF/HFC @alibuild @ginnocen @vkucera @fcolamar @mmazzilli @deepathoms -/PWGHF/HFJ @alibuild @ginnocen @vkucera @fcolamar @nzardosh @rvertesi -/PWGHF/HFL @alibuild @ginnocen @vkucera @fcolamar @NicoleBastid @mvolkl +/PWGHF @alibuild @vkucera @fcolamar @adubla @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @nzardosh @NicoleBastid @gtaillepied /PWGLF @alibuild @lramona @alcaliva @lbariogl @chiarapinto @BongHwi @lbarnby @mbombara @iravasen @njacazio @ChiaraDeMartin95 @skundu692 /PWGMM @alibuild @aalkin /PWGMM/Lumi @alibuild @aalkin @@ -46,7 +43,7 @@ /Tutorials/PWGCF @alibuild @jgrosseo @saganatt @victor-gonzalez @zchochu /Tutorials/PWGDQ @alibuild @iarsene @dsekihat @feisenhu /Tutorials/PWGEM @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu -/Tutorials/PWGHF @alibuild @ginnocen @vkucera @fcolamar +/Tutorials/PWGHF @alibuild @vkucera @fcolamar @adubla /Tutorials/PWGJE @alibuild @lhavener @maoyx @nzardosh @ddobrigk @mfasDa /Tutorials/PWGLF @alibuild @alcaliva @lbariogl @chiarapinto @BongHwi @lbarnby @mbombara @iravasen @njacazio @ChiaraDeMartin95 @skundu692 /Tutorials/PWGMM @alibuild @aalkin @ddobrigk diff --git a/CPPLINT.cfg b/CPPLINT.cfg index 8891b9c48f0..e050d1df67c 100644 --- a/CPPLINT.cfg +++ b/CPPLINT.cfg @@ -1 +1 @@ -filter=-build/c++11,-build/namespaces,-readability/todo,-runtime/references,-whitespace/blank_line,-whitespace/braces,-whitespace/comments,-whitespace/line_length,-whitespace/semicolon,-whitespace/todo +filter=-build/c++11,-build/namespaces,-readability/fn_size,-readability/todo,-runtime/references,-whitespace/blank_line,-whitespace/braces,-whitespace/comments,-whitespace/line_length,-whitespace/semicolon,-whitespace/todo diff --git a/Common/CCDB/EventSelectionParams.cxx b/Common/CCDB/EventSelectionParams.cxx index 7c90632d272..09997d41274 100644 --- a/Common/CCDB/EventSelectionParams.cxx +++ b/Common/CCDB/EventSelectionParams.cxx @@ -11,7 +11,7 @@ #include "EventSelectionParams.h" -namespace evsel +namespace o2::aod::evsel { const char* selectionLabels[kNsel] = { "kIsBBV0A", @@ -48,7 +48,9 @@ const char* selectionLabels[kNsel] = { "kNoPileupTPC", "kIsTriggerTVX", "kIsINT1"}; -} +} // namespace o2::aod::evsel + +using namespace o2::aod::evsel; EventSelectionParams::EventSelectionParams(int system, int run) { diff --git a/Common/CCDB/EventSelectionParams.h b/Common/CCDB/EventSelectionParams.h index 97948058c76..d4299b4abc1 100644 --- a/Common/CCDB/EventSelectionParams.h +++ b/Common/CCDB/EventSelectionParams.h @@ -15,7 +15,7 @@ #include #include -namespace evsel +namespace o2::aod::evsel { // Event selection criteria enum EventSelectionFlags { @@ -58,9 +58,7 @@ enum EventSelectionFlags { extern const char* selectionLabels[kNsel]; -} // namespace evsel - -using namespace evsel; +} // namespace o2::aod::evsel class EventSelectionParams { @@ -70,9 +68,9 @@ class EventSelectionParams void SetOnVsOfParams(float newV0MOnVsOfA, float newV0MOnVsOfB, float newSPDOnVsOfA, float newSPDOnVsOfB); bool* GetSelection(int iSelection); - bool selectionBarrel[kNsel]; - bool selectionMuonWithPileupCuts[kNsel]; - bool selectionMuonWithoutPileupCuts[kNsel]; + bool selectionBarrel[o2::aod::evsel::kNsel]; + bool selectionMuonWithPileupCuts[o2::aod::evsel::kNsel]; + bool selectionMuonWithoutPileupCuts[o2::aod::evsel::kNsel]; // time-of-flight offset float fV0ADist = 329.00 / TMath::Ccgs() * 1e9; // ns diff --git a/Common/CCDB/TriggerAliases.cxx b/Common/CCDB/TriggerAliases.cxx index 577007c5f03..789d293c1d0 100644 --- a/Common/CCDB/TriggerAliases.cxx +++ b/Common/CCDB/TriggerAliases.cxx @@ -38,6 +38,8 @@ std::string aliasLabels[kNaliases] = { "kTVXinTRD", "kTVXinEMC", "kTVXinPHOS", + "kTVXinHMP", + "kPHOS", "kALL"}; void TriggerAliases::AddClassIdToAlias(uint32_t aliasId, int classId) diff --git a/Common/CCDB/TriggerAliases.h b/Common/CCDB/TriggerAliases.h index e9cd1473400..f1baf04fdcc 100644 --- a/Common/CCDB/TriggerAliases.h +++ b/Common/CCDB/TriggerAliases.h @@ -43,6 +43,8 @@ enum triggerAliases { kTVXinTRD, kTVXinEMC, kTVXinPHOS, + kTVXinHMP, + kPHOS, kALL, kNaliases }; @@ -66,7 +68,7 @@ class TriggerAliases std::map mAliasToClassNames; std::map mAliasToTriggerMask; std::map mAliasToTriggerMaskNext50; - ClassDefNV(TriggerAliases, 7) + ClassDefNV(TriggerAliases, 8) }; #endif // COMMON_CCDB_TRIGGERALIASES_H_ diff --git a/Common/CCDB/macros/upload_trigger_aliases_run3.C b/Common/CCDB/macros/upload_trigger_aliases_run3.C index 2a9cafb4dcc..68259c07e35 100644 --- a/Common/CCDB/macros/upload_trigger_aliases_run3.C +++ b/Common/CCDB/macros/upload_trigger_aliases_run3.C @@ -24,9 +24,13 @@ using std::string; void createDefaultAliases(map& mAliases) { + mAliases[kEMC7] = "CTVXEMC-B-NOPF-EMC"; + mAliases[kDMC7] = "CTVXDMC-B-NOPF-EMC"; mAliases[kTVXinTRD] = "CMTVX-B-NOPF-TRD,minbias_TVX"; mAliases[kTVXinEMC] = "C0TVX-B-NOPF-EMC,minbias_TVX_L0"; mAliases[kTVXinPHOS] = "C0TVX-B-NOPF-PHSCPV,minbias_TVX_L0"; + mAliases[kTVXinHMP] = "C0TVX-B-NOPF-HMP,minbias_TVX_L0"; + mAliases[kPHOS] = "CTVXPH0-B-NOPF-PHSCPV,mb_PH0_TVX"; } void upload_trigger_aliases_run3() @@ -47,7 +51,7 @@ void upload_trigger_aliases_run3() map metadata, metadataRCT, header; // read list of runs from text file - std::ifstream f("runs_2023.txt"); + std::ifstream f("runs_run3.txt"); std::vector runs; int r = 0; while (f >> r) { @@ -90,7 +94,7 @@ void upload_trigger_aliases_run3() } std::vector classes = ctpcfg->getCTPClasses(); - // ctpcfg->printConfigString(); + ctpcfg->printConfigString(); // create trigger aliases TriggerAliases* aliases = new TriggerAliases(); for (auto& al : mAliases) { @@ -118,6 +122,9 @@ void upload_trigger_aliases_run3() if (aliasId == kTVXinPHOS && cluster != "PHSCPV") { // workaround for configs with ambiguous class names continue; } + if (aliasId == kTVXinHMP && cluster != "HMP") { // workaround for configs with ambiguous class names + continue; + } LOGP(debug, " class index = {}, name = {}, cluster = {}", classId, cl.name, cl.cluster->name); aliases->AddClassIdToAlias(aliasId, classId); break; diff --git a/Common/Core/CMakeLists.txt b/Common/Core/CMakeLists.txt index aac7a369732..9077a46321a 100644 --- a/Common/Core/CMakeLists.txt +++ b/Common/Core/CMakeLists.txt @@ -15,24 +15,16 @@ o2physics_add_library(AnalysisCore PID/ParamBase.cxx CollisionAssociation.cxx TrackSelectionDefaults.cxx - PUBLIC_LINK_LIBRARIES O2::Framework ROOT::EG O2::CCDB ROOT::Physics) + EventPlaneHelper.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsParameters ROOT::EG O2::CCDB ROOT::Physics O2::FT0Base O2::FV0Base) o2physics_target_root_dictionary(AnalysisCore HEADERS TrackSelection.h TrackSelectionDefaults.h OrbitRange.h + EventPlaneHelper.h PID/ParamBase.h PID/DetectorResponse.h PID/PIDTOF.h PID/TPCPIDResponse.h LINKDEF AnalysisCoreLinkDef.h) - -o2physics_add_executable(merger - COMPONENT_NAME aod - SOURCES aodMerger.cxx - PUBLIC_LINK_LIBRARIES ROOT::Core ROOT::Net) - -o2physics_add_executable(thinner - COMPONENT_NAME aod - SOURCES aodThinner.cxx - PUBLIC_LINK_LIBRARIES ROOT::Core ROOT::Net) diff --git a/Common/Core/CollisionAssociation.h b/Common/Core/CollisionAssociation.h index 1e681036b8c..f2206846183 100644 --- a/Common/Core/CollisionAssociation.h +++ b/Common/Core/CollisionAssociation.h @@ -22,6 +22,7 @@ #include #include + #include "CommonConstants/LHCConstants.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" @@ -41,9 +42,6 @@ enum TrackSelection { } // namespace track_association } // namespace o2::aod -using namespace o2; -using namespace o2::aod; - template class CollisionAssociation { @@ -57,9 +55,10 @@ class CollisionAssociation void setUsePvAssociation(bool enable = true) { mUsePvAssociation = enable; } void setIncludeUnassigned(bool enable = true) { mIncludeUnassigned = enable; } void setFillTableOfCollIdsPerTrack(bool fill = true) { mFillTableOfCollIdsPerTrack = fill; } + void setBcWindow(int bcWindow = 115) { mBcWindowForOneSigma = bcWindow; } template - void runStandardAssoc(Collisions const& collisions, + void runStandardAssoc(o2::aod::Collisions const& collisions, TTracks const& tracks, Slice& perCollisions, Assoc& association, @@ -72,23 +71,23 @@ class CollisionAssociation if constexpr (isCentralBarrel) { bool hasGoodQuality = true; switch (mTrackSelection) { - case track_association::TrackSelection::CentralBarrelRun2: { + case o2::aod::track_association::TrackSelection::CentralBarrelRun2: { unsigned char itsClusterMap = track.itsClusterMap(); - if (!(track.tpcNClsFound() >= 50 && track.flags() & track::ITSrefit && track.flags() & track::TPCrefit && (TESTBIT(itsClusterMap, 0) || TESTBIT(itsClusterMap, 1)))) { + if (!(track.tpcNClsFound() >= 50 && track.flags() & o2::aod::track::ITSrefit && track.flags() & o2::aod::track::TPCrefit && (TESTBIT(itsClusterMap, 0) || TESTBIT(itsClusterMap, 1)))) { hasGoodQuality = false; } break; } - case track_association::TrackSelection::None: { + case o2::aod::track_association::TrackSelection::None: { break; } - case track_association::TrackSelection::GlobalTrackWoDCA: { + case o2::aod::track_association::TrackSelection::GlobalTrackWoDCA: { if (!track.isGlobalTrackWoDCA()) { hasGoodQuality = false; } break; } - case track_association::TrackSelection::QualityTracksITS: { + case o2::aod::track_association::TrackSelection::QualityTracksITS: { if (!track.isQualityTrackITS()) { hasGoodQuality = false; } @@ -117,11 +116,11 @@ class CollisionAssociation } template - void runAssocWithTime(Collisions const& collisions, + void runAssocWithTime(o2::aod::Collisions const& collisions, TTracksUnfiltered const& tracksUnfiltered, TTracks const& tracks, TAmbiTracks const& ambiguousTracks, - BCs const& bcs, + o2::aod::BCs const& bcs, Assoc& association, RevIndices& reverseIndices) { @@ -134,6 +133,10 @@ class CollisionAssociation for (const auto& ambTrack : ambiguousTracks) { if constexpr (isCentralBarrel) { // FIXME: to be removed as soon as it is possible to use getId() for joined tables if (ambTrack.trackId() == track.globalIndex()) { + if (!ambTrack.has_bc() || ambTrack.bc().size() == 0) { + globalBC.push_back(-1); + break; + } globalBC.push_back(ambTrack.bc().begin().globalBC()); break; } @@ -152,7 +155,7 @@ class CollisionAssociation // loop over collisions to find time-compatible tracks auto trackBegin = tracks.begin(); - constexpr auto bOffsetMax = 241; // 6 mus (ITS) + auto bOffsetMax = mBcWindowForOneSigma * mNumSigmaForTimeCompat + mTimeMargin / o2::constants::lhc::LHCBunchSpacingNS; for (const auto& collision : collisions) { const float collTime = collision.collisionTime(); const float collTimeRes2 = collision.collisionTimeRes() * collision.collisionTimeRes(); @@ -162,21 +165,26 @@ class CollisionAssociation if (!mIncludeUnassigned && !track.has_collision()) { continue; } - const int64_t bcOffset = (int64_t)globalBC[track.filteredIndex()] - (int64_t)collBC; - if (std::abs(bcOffset) > bOffsetMax) { + + float trackTime = track.trackTime(); + if (globalBC[track.filteredIndex()] < 0) { + continue; + } + const int64_t bcOffsetWindow = (int64_t)globalBC[track.filteredIndex()] + trackTime / o2::constants::lhc::LHCBunchSpacingNS - (int64_t)collBC; + if (std::abs(bcOffsetWindow) > bOffsetMax) { continue; } - float trackTime = track.trackTime(); float trackTimeRes = track.trackTimeRes(); if constexpr (isCentralBarrel) { if (mUsePvAssociation && track.isPVContributor()) { trackTime = track.collision().collisionTime(); // if PV contributor, we assume the time to be the one of the collision - trackTimeRes = constants::lhc::LHCBunchSpacingNS; // 1 BC + trackTimeRes = o2::constants::lhc::LHCBunchSpacingNS; // 1 BC } } - const float deltaTime = trackTime - collTime + bcOffset * constants::lhc::LHCBunchSpacingNS; + const int64_t bcOffset = (int64_t)globalBC[track.filteredIndex()] - (int64_t)collBC; + const float deltaTime = trackTime - collTime + bcOffset * o2::constants::lhc::LHCBunchSpacingNS; float sigmaTimeRes2 = collTimeRes2 + trackTimeRes * trackTimeRes; LOGP(debug, "collision time={}, collision time res={}, track time={}, track time res={}, bc collision={}, bc track={}, delta time={}", collTime, collision.collisionTimeRes(), track.trackTime(), track.trackTimeRes(), collBC, globalBC[track.filteredIndex()], deltaTime); @@ -195,7 +203,7 @@ class CollisionAssociation if constexpr (isCentralBarrel) { if (mUsePvAssociation && track.isPVContributor()) { thresholdTime = trackTimeRes; - } else if (TESTBIT(track.flags(), track::TrackTimeResIsRange)) { + } else if (TESTBIT(track.flags(), o2::aod::track::TrackTimeResIsRange)) { thresholdTime = std::sqrt(sigmaTimeRes2) + mTimeMargin; } else { thresholdTime = mNumSigmaForTimeCompat * std::sqrt(sigmaTimeRes2) + mTimeMargin; @@ -234,12 +242,13 @@ class CollisionAssociation } private: - float mNumSigmaForTimeCompat{4.}; // number of sigma for time compatibility - float mTimeMargin{500.}; // additional time margin in ns - int mTrackSelection{track_association::TrackSelection::GlobalTrackWoDCA}; // track selection for central barrel tracks (standard association only) - bool mUsePvAssociation{true}; // use the information of PV contributors - bool mIncludeUnassigned{true}; // include tracks that were originally not assigned to any collision - bool mFillTableOfCollIdsPerTrack{false}; // fill additional table with vectors of compatible collisions per track + float mNumSigmaForTimeCompat{4.}; // number of sigma for time compatibility + float mTimeMargin{500.}; // additional time margin in ns + int mTrackSelection{o2::aod::track_association::TrackSelection::GlobalTrackWoDCA}; // track selection for central barrel tracks (standard association only) + bool mUsePvAssociation{true}; // use the information of PV contributors + bool mIncludeUnassigned{true}; // include tracks that were originally not assigned to any collision + bool mFillTableOfCollIdsPerTrack{false}; // fill additional table with vectors of compatible collisions per track + int mBcWindowForOneSigma{115}; // BC window to be multiplied by the number of sigmas to define maximum window to be considered }; #endif // COMMON_CORE_COLLISIONASSOCIATION_H_ diff --git a/Common/Core/EventPlaneHelper.cxx b/Common/Core/EventPlaneHelper.cxx new file mode 100644 index 00000000000..6272932017b --- /dev/null +++ b/Common/Core/EventPlaneHelper.cxx @@ -0,0 +1,214 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file EventPlaneHelper.cxx +/// \author Cindy Mordasini +/// \author Anna Önnerstad +/// +/// \brief Helper methods to calculate information needed for the event plane +/// calculations with FIT. +/// + +#include "Common/Core/EventPlaneHelper.h" + +#include +#include +#include +#include + +#include "FT0Base/Geometry.h" +// #include "FV0Base/Geometry.h" + +#include "TMath.h" +#include "TVector3.h" + +double EventPlaneHelper::GetPhiFV0(int chno) +{ + /* Calculate the azimuthal angle in FV0 for the channel number 'chno'. The offset + on the A-side is taken into account here. */ + + // Set the offset of the left and right side of FV0. + float offsetX = 0.; + float offsetY = 0.; + + int cellsInLeft[] = {0, 1, 2, 3, 8, 9, 10, 11, 16, 17, 18, 19, 24, 25, 26, 27, + 32, 40, 33, 41, 34, 42, 35, 43}; + bool isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + + if (isChnoInLeft) { + offsetX = mOffsetFV0leftX; + offsetY = mOffsetFV0leftY; + } else { + offsetX = mOffsetFV0rightX; + offsetY = mOffsetFV0rightY; + } + + // const auto fv0Det = o2::fv0::Geometry::instance(o2::fv0::Geometry::eFull); + + // TODO: Get position of the readout center with getReadoutCenter(chno) in a Point3Dsimple + // and extract the x and y positions. + + float x = 0.; + float y = 0.; + return TMath::ATan2(y + offsetY, x + offsetX); +} + +double EventPlaneHelper::GetPhiFT0(int chno) +{ + /* Calculate the azimuthal angle in FT0 for the channel number 'chno'. The offset + of FT0-A is taken into account if chno is between 0 and 95. */ + + float offsetX = 0.; + float offsetY = 0.; // No offset for FT0-C (default case). + + if (chno < 96) { // Channel in FT0-A, non-zero offset must be applied. // LOKI: make general. + offsetX = mOffsetFT0AX; + offsetY = mOffsetFT0AY; + } + + o2::ft0::Geometry ft0Det; + ft0Det.calculateChannelCenter(); + auto chPos = ft0Det.getChannelCenter(chno); + /// printf("Channel id: %d X: %.3f Y: %.3f\n", chno, chPos.X(), chPos.Y()); + + return TMath::ATan2(chPos.Y() + offsetY, chPos.X() + offsetX); +} + +void EventPlaneHelper::SumQvectors(int det, int chno, float ampl, TComplex& Qvec, double& sum) +{ + /* Calculate the complex Q-vector for the provided detector and channel number, + before adding it to the total Q-vector given as argument. */ + double phi = -999.; + + switch (det) { + case 0: // FT0. Note: the channel number for FT0-C should + phi = GetPhiFT0(chno); // already be given in the right range. + break; + case 1: // FV0. + phi = GetPhiFV0(chno); + break; + default: + printf("'int det' value does not correspond to any accepted case.\n"); + break; + } + + /// printf("Phi: %.3f\n", phi); + + if (phi < -900) { + printf("Error on phi. Skip\n"); + return; + } // TODO: ensure proper safety check. + Qvec += TComplex(ampl * TMath::Cos(2. * phi), ampl * TMath::Sin(2. * phi)); + sum += ampl; +} + +int EventPlaneHelper::GetCentBin(float cent) +{ + const float centClasses[] = {0., 5., 10., 20., 30., 40., 50., 60., 80.}; + + for (int i = 0; i < 9; i++) { + if (cent >= centClasses[i]) { + continue; + } else { + return i - 1; + } + } + + // We went through all centrality edges without returning --> The measured percentile + // is larger than the final class we consider. + return -1; +} + +void EventPlaneHelper::DoCorrections(float& qx, float& qy, + const std::vector& corrections) +{ + // Recentering of the Qx-Qy distribution to (0,0). + qx -= corrections[0]; + qy -= corrections[1]; + + // Twisting of the Qx-Qy distribution. + qx = (qx - corrections[3] * qy) / (1.0 - corrections[3] * corrections[2]); + qy = (qy - corrections[2] * qx) / (1.0 - corrections[3] * corrections[2]); + + // Rescaling of the Qx-Qy into a circle. + if (fabs(corrections[4]) > 1e-8) { + qx /= corrections[4]; + } + if (fabs(corrections[5]) > 1e-8) { + qy /= corrections[5]; + } +} + +void EventPlaneHelper::DoRecenter(float& qx, float& qy, float x0, float y0) +{ + qx -= x0; + qy -= y0; +} + +void EventPlaneHelper::DoTwist(float& qx, float& qy, float lp, float lm) +{ + qx = (qx - lm * qy) / (1.0 - lm * lp); + qy = (qy - lp * qx) / (1.0 - lm * lp); +} + +void EventPlaneHelper::DoRescale(float& qx, float& qy, float ap, float am) +{ + if (fabs(ap) > 1e-8) + qx /= ap; + if (fabs(am) > 1e-8) + qy /= am; +} + +void EventPlaneHelper::GetCorrRecentering(const std::shared_ptr histQ, float& meanX, float& meanY) +{ + meanX = histQ->GetMean(1); + meanY = histQ->GetMean(2); +} + +void EventPlaneHelper::GetCorrWidth(const std::shared_ptr histQ, float& stdX, float& stdY) +{ + stdX = histQ->GetStdDev(1); + stdY = histQ->GetStdDev(2); +} + +void EventPlaneHelper::GetCorrTwistRecale(const std::shared_ptr histQ, + float& aPlus, float& aMinus, + float& lambdaPlus, float& lambdaMinus) +{ + // Get first information from the provided TH2D. + float rho = histQ->GetCorrelationFactor(); + float sigmax = histQ->GetStdDev(1); + float sigmay = histQ->GetStdDev(2); + + // Combine them in the "b" parameter LOKI: define it better in the comment. + float b = rho * sigmax * sigmay * TMath::Sqrt(2.0 * (sigmax * sigmax + sigmay * sigmay - 2.0 * sigmax * sigmay * TMath::Sqrt(1.0 - rho * rho)) / ((sigmax * sigmax - sigmay * sigmay) * (sigmax * sigmax - sigmay * sigmay) + 4.0 * (sigmax * sigmay * rho) * (sigmax * sigmay * rho))); + + // Calculate finally the correction constants. + aPlus = TMath::Sqrt(2. * TMath::Power(sigmax, 2.) - TMath::Power(b, 2.)); + aMinus = TMath::Sqrt(2. * TMath::Power(sigmay, 2.) - TMath::Power(b, 2.)); + lambdaPlus = b / aPlus; + lambdaMinus = b / aMinus; +} + +float EventPlaneHelper::GetEventPlane(const float qx, const float qy) +{ + return (TMath::ATan2(qy, qx)); +} + +double EventPlaneHelper::GetResolution(const std::shared_ptr prof) +{ + double avgAB = prof->GetBinContent(1); + double avgAC = prof->GetBinContent(2); + double avgBC = prof->GetBinContent(3); + + return TMath::Sqrt(avgAB * avgAC / avgBC); +} diff --git a/Common/Core/EventPlaneHelper.h b/Common/Core/EventPlaneHelper.h new file mode 100644 index 00000000000..01db74f3aea --- /dev/null +++ b/Common/Core/EventPlaneHelper.h @@ -0,0 +1,111 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file EventPlaneHelper.h +/// \author Cindy Mordasini +/// \author Anna Önnerstad +/// +/// \brief Helper methods to calculate information needed for the event plane +/// calculations with FIT. +/// + +#ifndef COMMON_CORE_EVENTPLANEHELPER_H_ +#define COMMON_CORE_EVENTPLANEHELPER_H_ + +#include +#include + +#include "TNamed.h" + +#include +#include +#include + +class EventPlaneHelper +{ + public: + EventPlaneHelper() = default; + + // Setters/getters for the data members. + void SetOffsetFT0A(double offsetX, double offsetY) + { + mOffsetFT0AX = offsetX; + mOffsetFT0AY = offsetY; + } + void SetOffsetFT0C(double offsetX, double offsetY) + { + mOffsetFT0CX = offsetX; + mOffsetFT0CY = offsetY; + } + void SetOffsetFV0left(double offsetX, double offsetY) + { + mOffsetFV0leftX = offsetX; + mOffsetFV0leftY = offsetY; + } + void SetOffsetFV0right(double offsetX, double offsetY) + { + mOffsetFV0rightX = offsetX; + mOffsetFV0rightY = offsetY; + } + + // Methods to calculate the azimuthal angles for each part of FIT, given the channel number. + double GetPhiFT0(int chno); + double GetPhiFV0(int chno); + + // Method to get the Q-vector and sum of amplitudes for any channel in FIT, given + // the detector and amplitude. + void SumQvectors(int det, int chno, float ampl, TComplex& Qvec, double& sum); + + // Method to get the bin corresponding to a centrality percentile, according to the + // centClasses[] array defined in Tasks/qVectorsQA.cxx. + // Note: Any change in one task should be reflected in the other. + int GetCentBin(float cent); + + // Method to apply the vector of correction constant passed as a configurable + // to the calculated Q-vectors. + void DoCorrections(float& qx, float& qy, const std::vector& corrections); + + void DoRecenter(float& qx, float& qy, float x0, float y0); + void DoTwist(float& qx, float& qy, float lp, float lm); + void DoRescale(float& qx, float& qy, float ap, float am); + + // Method to get the recentering correction on the Qx-Qy distribution. + void GetCorrRecentering(const std::shared_ptr histQ, float& meanX, float& meanY); + + // Method to get the std. deviation on the Qx-Qy distribution. + void GetCorrWidth(const std::shared_ptr histQ, float& stdX, float& stdY); + + // Method to get the twist and rescale correction on the Qx-Qy distribution. + void GetCorrTwistRecale(const std::shared_ptr histQ, + float& aPlus, float& aMinus, + float& lambdaPlus, float& lambdaMinus); + + // Method to calculate the event plane from the provided (Qx, Qy), for n = 2. + float GetEventPlane(const float qx, const float qy); + + // Method to calculate the resolution R2 for the provided profile. + double GetResolution(const std::shared_ptr prof); + + private: + double mOffsetFT0AX = 0.; // X-coordinate of the offset of FT0-A. + double mOffsetFT0AY = 0.; // Y-coordinate of the offset of FT0-A. + double mOffsetFT0CX = 0.; // X-coordinate of the offset of FT0-C. + double mOffsetFT0CY = 0.; // Y-coordinate of the offset of FT0-C. + double mOffsetFV0leftX = 0.; // X-coordinate of the offset of FV0-A left. + double mOffsetFV0leftY = 0.; // Y-coordinate of the offset of FV0-A left. + double mOffsetFV0rightX = 0.; // X-coordinate of the offset of FV0-A right. + double mOffsetFV0rightY = 0.; // Y-coordinate of the offset of FV0-A right. + + ClassDefNV(EventPlaneHelper, 2) +}; + +#endif // COMMON_CORE_EVENTPLANEHELPER_H_ diff --git a/Common/Core/RecoDecay.h b/Common/Core/RecoDecay.h index c3c0ee1e96e..ee1dd8dbb7e 100644 --- a/Common/Core/RecoDecay.h +++ b/Common/Core/RecoDecay.h @@ -29,10 +29,6 @@ #include "CommonConstants/MathConstants.h" #include "Framework/Logger.h" -using std::array; -using namespace o2; -using namespace o2::constants::math; - /// Base class for calculating properties of reconstructed decays /// /// Provides static helper functions for: @@ -109,9 +105,9 @@ class RecoDecay /// \param args pack of 3-vector arrays /// \return sum of vectors template - static auto sumOfVec(const array&... args) + static auto sumOfVec(const std::array&... args) { - return array{getElement(0, args...), getElement(1, args...), getElement(2, args...)}; + return std::array{getElement(0, args...), getElement(1, args...), getElement(2, args...)}; } /// Calculates scalar product of vectors. @@ -120,7 +116,7 @@ class RecoDecay /// \param vec1,vec2 vectors /// \return scalar product template - static double dotProd(const array& vec1, const array& vec2) + static double dotProd(const std::array& vec1, const std::array& vec2) { double res{0}; for (std::size_t iDim = 0; iDim < N; ++iDim) { @@ -135,11 +131,11 @@ class RecoDecay /// \param vec1,vec2 vectors /// \return cross-product vector template - static array crossProd(const array& vec1, const array& vec2) + static std::array crossProd(const std::array& vec1, const std::array& vec2) { - return array{(static_cast(vec1[1]) * static_cast(vec2[2])) - (static_cast(vec1[2]) * static_cast(vec2[1])), - (static_cast(vec1[2]) * static_cast(vec2[0])) - (static_cast(vec1[0]) * static_cast(vec2[2])), - (static_cast(vec1[0]) * static_cast(vec2[1])) - (static_cast(vec1[1]) * static_cast(vec2[0]))}; + return std::array{(static_cast(vec1[1]) * static_cast(vec2[2])) - (static_cast(vec1[2]) * static_cast(vec2[1])), + (static_cast(vec1[2]) * static_cast(vec2[0])) - (static_cast(vec1[0]) * static_cast(vec2[2])), + (static_cast(vec1[0]) * static_cast(vec2[1])) - (static_cast(vec1[1]) * static_cast(vec2[0]))}; } /// Calculates magnitude squared of a vector. @@ -147,7 +143,7 @@ class RecoDecay /// \param vec vector /// \return magnitude squared template - static double mag2(const array& vec) + static double mag2(const std::array& vec) { return dotProd(vec, vec); } @@ -176,11 +172,11 @@ class RecoDecay /// \param mom 3-momentum array /// \return pseudorapidity template - static double eta(const array& mom) + static double eta(const std::array& mom) { // eta = arctanh(pz/p) - if (std::abs(mom[0]) < Almost0 && std::abs(mom[1]) < Almost0) { // very small px and py - return static_cast(mom[2] > 0 ? VeryBig : -VeryBig); + if (std::abs(mom[0]) < o2::constants::math::Almost0 && std::abs(mom[1]) < o2::constants::math::Almost0) { // very small px and py + return static_cast(mom[2] > 0 ? o2::constants::math::VeryBig : -o2::constants::math::VeryBig); } return static_cast(std::atanh(mom[2] / p(mom))); } @@ -190,7 +186,7 @@ class RecoDecay /// \param mass mass /// \return rapidity template - static double y(const array& mom, U mass) + static double y(const std::array& mom, U mass) { // y = arctanh(pz/E) return std::atanh(mom[2] / e(mom, mass)); @@ -239,10 +235,10 @@ class RecoDecay /// \param mom 3-momentum array /// \return cosine of pointing angle template - static double cpa(const T& posPV, const U& posSV, const array& mom) + static double cpa(const T& posPV, const U& posSV, const std::array& mom) { // CPA = (l . p)/(|l| |p|) - auto lineDecay = array{posSV[0] - posPV[0], posSV[1] - posPV[1], posSV[2] - posPV[2]}; + auto lineDecay = std::array{posSV[0] - posPV[0], posSV[1] - posPV[1], posSV[2] - posPV[2]}; auto cos = dotProd(lineDecay, mom) / std::sqrt(mag2(lineDecay) * mag2(mom)); if (cos < -1.) { return -1.; @@ -259,11 +255,11 @@ class RecoDecay /// \param mom {x, y, z} or {x, y} momentum array /// \return cosine of pointing angle in {x, y} template - static double cpaXY(const T& posPV, const U& posSV, const array& mom) + static double cpaXY(const T& posPV, const U& posSV, const std::array& mom) { // CPAXY = (r . pT)/(|r| |pT|) - auto lineDecay = array{posSV[0] - posPV[0], posSV[1] - posPV[1]}; - auto momXY = array{mom[0], mom[1]}; + auto lineDecay = std::array{posSV[0] - posPV[0], posSV[1] - posPV[1]}; + auto momXY = std::array{mom[0], mom[1]}; auto cos = dotProd(lineDecay, momXY) / std::sqrt(mag2(lineDecay) * mag2(momXY)); if (cos < -1.) { return -1.; @@ -281,7 +277,7 @@ class RecoDecay /// \param length decay length /// \return proper lifetime times c template - static double ct(const array& mom, U length, V mass) + static double ct(const std::array& mom, U length, V mass) { // c t = l m c^2/(p c) return static_cast(length) * static_cast(mass) / p(mom); @@ -295,7 +291,7 @@ class RecoDecay /// \param iProng index of the prong /// \return cosine of θ* of the i-th prong under the assumption of the invariant mass template - static double cosThetaStar(const array, 2>& arrMom, const array& arrMass, V mTot, int iProng) + static double cosThetaStar(const std::array, 2>& arrMom, const std::array& arrMass, V mTot, int iProng) { auto pVecTot = pVec(arrMom[0], arrMom[1]); // momentum of the mother particle auto pTot = p(pVecTot); // magnitude of the momentum of the mother particle @@ -315,7 +311,7 @@ class RecoDecay /// \param args pack of 3-momentum arrays /// \return total 3-momentum array template - static auto pVec(const array&... args) + static auto pVec(const std::array&... args) { return sumOfVec(args...); } @@ -332,7 +328,7 @@ class RecoDecay /// \param args pack of 3-momentum arrays /// \return total momentum squared template - static double p2(const array&... args) + static double p2(const std::array&... args) { return sumOfSquares(getElement(0, args...), getElement(1, args...), getElement(2, args...)); } @@ -358,7 +354,7 @@ class RecoDecay /// \param args pack of 3-(or 2-)momentum arrays /// \return total transverse momentum squared template - static double pt2(const array&... args) + static double pt2(const std::array&... args) { return sumOfSquares(getElement(0, args...), getElement(1, args...)); } @@ -387,7 +383,7 @@ class RecoDecay /// \param mass mass /// \return energy squared template - static double e2(const array& mom, U mass) + static double e2(const std::array& mom, U mass) { return e2(mom[0], mom[1], mom[2], mass); } @@ -417,7 +413,7 @@ class RecoDecay /// \param energy energy /// \return invariant mass squared template - static double m2(const array& mom, double energy) + static double m2(const std::array& mom, double energy) { return energy * energy - p2(mom); } @@ -428,9 +424,9 @@ class RecoDecay /// \param arrMass array of N masses (in the same order as arrMom) /// \return invariant mass squared template - static double m2(const array, N>& arrMom, const array& arrMass) + static double m2(const std::array, N>& arrMom, const std::array& arrMass) { - array momTotal{0., 0., 0.}; // candidate momentum vector + std::array momTotal{0., 0., 0.}; // candidate momentum vector double energyTot{0.}; // candidate energy for (std::size_t iProng = 0; iProng < N; ++iProng) { for (std::size_t iMom = 0; iMom < 3; ++iMom) { @@ -460,15 +456,15 @@ class RecoDecay /// \param mom {x, y, z} particle momentum array /// \return impact parameter in {x, y} template - static double impParXY(const T& point, const U& posSV, const array& mom) + static double impParXY(const T& point, const U& posSV, const std::array& mom) { // Ported from AliAODRecoDecay::ImpParXY - auto flightLineXY = array{posSV[0] - point[0], posSV[1] - point[1]}; - auto k = dotProd(flightLineXY, array{mom[0], mom[1]}) / pt2(mom); + auto flightLineXY = std::array{posSV[0] - point[0], posSV[1] - point[1]}; + auto k = dotProd(flightLineXY, std::array{mom[0], mom[1]}) / pt2(mom); auto dx = flightLineXY[0] - k * static_cast(mom[0]); auto dy = flightLineXY[1] - k * static_cast(mom[1]); auto absImpPar = sqrtSumOfSquares(dx, dy); - auto flightLine = array{posSV[0] - point[0], posSV[1] - point[1], posSV[2] - point[2]}; + auto flightLine = std::array{posSV[0] - point[0], posSV[1] - point[1], posSV[2] - point[2]}; auto cross = crossProd(mom, flightLine); return (cross[2] > 0. ? absImpPar : -1. * absImpPar); } @@ -483,8 +479,8 @@ class RecoDecay /// \param momProng {x, y, z} or {x, y} prong momentum array /// \return normalized difference between expected and observed impact parameter template - static double normImpParMeasMinusExpProng(T decLenXY, U errDecLenXY, const array& momMother, W impParProng, - X errImpParProng, const array& momProng) + static double normImpParMeasMinusExpProng(T decLenXY, U errDecLenXY, const std::array& momMother, W impParProng, + X errImpParProng, const std::array& momProng) { // Ported from AliAODRecoDecayHF::Getd0MeasMinusExpProng adding normalization directly in the function auto sinThetaP = (static_cast(momProng[0]) * static_cast(momMother[1]) - static_cast(momProng[1]) * static_cast(momMother[0])) / @@ -506,9 +502,9 @@ class RecoDecay /// \return maximum normalized difference between expected and observed impact parameters template - static double maxNormalisedDeltaIP(const T& posPV, const U& posSV, V errDecLenXY, const array& momMother, - const array& arrImpPar, const array& arrErrImpPar, - const array, N>& arrMom) + static double maxNormalisedDeltaIP(const T& posPV, const U& posSV, V errDecLenXY, const std::array& momMother, + const std::array& arrImpPar, const std::array& arrErrImpPar, + const std::array, N>& arrMom) { auto decLenXY = distanceXY(posPV, posSV); double maxNormDeltaIP{0.}; @@ -535,6 +531,12 @@ class RecoDecay /// \return particle mass static double getMassPDG(int pdg) { + if (!mErrorShown) { + LOGF(error, "Function RecoDecay::getMassPDG is deprecated and will be removed soon."); + LOGF(error, "Please use the Mass function in the O2DatabasePDG service instead."); + LOGF(error, "See the example of usage in Tutorials/src/usingPDGService.cxx."); + mErrorShown = true; + } // Try to get the particle mass from the list first. for (const auto& particle : mListMass) { if (std::get<0>(particle) == pdg) { @@ -655,7 +657,7 @@ class RecoDecay template static void getDaughters(const T& particle, std::vector* list, - const array& arrPDGFinal, + const std::array& arrPDGFinal, int8_t depthMax = -1, int8_t stage = 0) { @@ -720,9 +722,9 @@ class RecoDecay /// \return index of the mother particle if the mother and daughters are correct, -1 otherwise template static int getMatchedMCRec(const T& particlesMC, - const array& arrDaughters, + const std::array& arrDaughters, int PDGMother, - array arrPDGDaughters, + std::array arrPDGDaughters, bool acceptAntiParticles = false, int8_t* sign = nullptr, int depthMax = 1) @@ -731,7 +733,7 @@ class RecoDecay int8_t sgn = 0; // 1 if the expected mother is particle, -1 if antiparticle (w.r.t. PDGMother) int indexMother = -1; // index of the mother particle std::vector arrAllDaughtersIndex; // vector of indices of all daughters of the mother of the first provided daughter - array arrDaughtersIndex; // array of indices of provided daughters + std::array arrDaughtersIndex; // array of indices of provided daughters if (sign) { *sign = sgn; } @@ -828,7 +830,7 @@ class RecoDecay bool acceptAntiParticles = false, int8_t* sign = nullptr) { - array arrPDGDaughters; + std::array arrPDGDaughters; return isMatchedMCGen(particlesMC, candidate, PDGParticle, std::move(arrPDGDaughters), acceptAntiParticles, sign); } @@ -846,7 +848,7 @@ class RecoDecay static bool isMatchedMCGen(const T& particlesMC, const U& candidate, int PDGParticle, - array arrPDGDaughters, + std::array arrPDGDaughters, bool acceptAntiParticles = false, int8_t* sign = nullptr, int depthMax = 1, @@ -1000,8 +1002,10 @@ class RecoDecay private: static std::vector> mListMass; ///< list of particle masses in form (PDG code, mass) + static bool mErrorShown; }; std::vector> RecoDecay::mListMass; +bool RecoDecay::mErrorShown = false; #endif // COMMON_CORE_RECODECAY_H_ diff --git a/Common/Core/TableHelper.h b/Common/Core/TableHelper.h index b700e460dbf..48c0d30c40d 100644 --- a/Common/Core/TableHelper.h +++ b/Common/Core/TableHelper.h @@ -45,13 +45,15 @@ bool isTableRequiredInWorkflow(o2::framework::InitContext& initContext, const st /// @param flag int value of flag to set, only if initially set to -1. Initial values of 0 or 1 will be kept disregarding the table usage in the workflow. void enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, int& flag) { + if (flag > 0) { + flag = 1; + LOG(info) << "Table enabled: " + table; + return; + } if (isTableRequiredInWorkflow(initContext, table)) { if (flag < 0) { flag = 1; LOG(info) << "Auto-enabling table: " + table; - } else if (flag > 0) { - flag = 1; - LOG(info) << "Table enabled: " + table; } else { LOG(info) << "Table disabled: " + table; } diff --git a/Common/Core/TrackSelection.h b/Common/Core/TrackSelection.h index ee326530417..b27ee30e8fd 100644 --- a/Common/Core/TrackSelection.h +++ b/Common/Core/TrackSelection.h @@ -57,7 +57,7 @@ class TrackSelection }; // Flags for the selection of the DCAxy - enum GlobalTrackRun3DCAxyCut { + enum GlobalTrackRun3DCAxyCut : int { Default, ppPass3 }; diff --git a/Common/Core/TrackSelectionDefaults.cxx b/Common/Core/TrackSelectionDefaults.cxx index bca6561f9b3..1c576c8134f 100644 --- a/Common/Core/TrackSelectionDefaults.cxx +++ b/Common/Core/TrackSelectionDefaults.cxx @@ -40,7 +40,7 @@ TrackSelection getGlobalTrackSelection() } // Default track selection requiring a particular Run 3 ITS matching -TrackSelection getGlobalTrackSelectionRun3ITSMatch(int matching, TrackSelection::GlobalTrackRun3DCAxyCut passFlag) +TrackSelection getGlobalTrackSelectionRun3ITSMatch(int matching, int passFlag) { TrackSelection selectedTracks = getGlobalTrackSelection(); selectedTracks.SetTrackType(o2::aod::track::TrackTypeEnum::Track); // Requiring that this is a Run 3 track @@ -69,6 +69,7 @@ TrackSelection getGlobalTrackSelectionRun3ITSMatch(int matching, TrackSelection: selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.004f + 0.013f / pt; }); // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution break; default: + LOG(fatal) << "getGlobalTrackSelectionRun3ITSMatch with undefined DCA cut"; break; } return selectedTracks; diff --git a/Common/Core/TrackSelectionDefaults.h b/Common/Core/TrackSelectionDefaults.h index d5783e0d3c7..72c666456ae 100644 --- a/Common/Core/TrackSelectionDefaults.h +++ b/Common/Core/TrackSelectionDefaults.h @@ -26,7 +26,7 @@ TrackSelection getGlobalTrackSelection(); // Default track selection requiring a particular Run 3 ITS matching TrackSelection getGlobalTrackSelectionRun3ITSMatch(int matching, - TrackSelection::GlobalTrackRun3DCAxyCut passFlag = TrackSelection::GlobalTrackRun3DCAxyCut::Default); + int passFlag = TrackSelection::GlobalTrackRun3DCAxyCut::Default); // Default track selection requiring no hit in the SPD and one in the innermost // SDD -> complementary tracks to global selection diff --git a/Common/Core/TrackSelectorPID.h b/Common/Core/TrackSelectorPID.h index 1e591c946f8..e09969ba946 100644 --- a/Common/Core/TrackSelectorPID.h +++ b/Common/Core/TrackSelectorPID.h @@ -24,366 +24,313 @@ /// Class for track selection using PID detectors -class TrackSelectorPID +struct TrackSelectorPID { + /// Selection status + enum Status { + NotApplicable = 0, + Rejected, + Conditional, + Accepted + }; +}; + +template +class TrackSelectorPidBase { public: /// Default constructor - TrackSelectorPID() = default; + TrackSelectorPidBase() = default; - /// Standard constructor with PDG code initialisation - explicit TrackSelectorPID(int pdg) + /// Conversion operator + template + operator TrackSelectorPidBase() const { - setPDG(pdg); + TrackSelectorPidBase objNew; + // TPC + objNew.setRangePtTpc(mPtTpcMin, mPtTpcMax); + objNew.setRangeNSigmaTpc(mNSigmaTpcMin, mNSigmaTpcMax); + objNew.setRangeNSigmaTpcCondTof(mNSigmaTpcMinCondTof, mNSigmaTpcMaxCondTof); + // TOF + objNew.setRangePtTof(mPtTofMin, mPtTofMax); + objNew.setRangeNSigmaTof(mNSigmaTofMin, mNSigmaTofMax); + objNew.setRangeNSigmaTofCondTpc(mNSigmaTofMinCondTpc, mNSigmaTofMaxCondTpc); + // RICH + objNew.setRangePtRich(mPtRichMin, mPtRichMax); + objNew.setRangeNSigmaRich(mNSigmaRichMin, mNSigmaRichMax); + objNew.setRangeNSigmaRichCondTof(mNSigmaRichMinCondTof, mNSigmaRichMaxCondTof); + // Bayesian + objNew.setRangePtBayes(mPtBayesMin, mPtBayesMax); + objNew.setProbBayesMin(mProbBayesMin); + return objNew; } /// Default destructor - ~TrackSelectorPID() = default; - - /// Selection status - enum Status { - PIDNotApplicable = 0, - PIDRejected, - PIDConditional, - PIDAccepted - }; - - void setPDG(int pdg) - { - mPdg = std::abs(pdg); - switch (mPdg) { - case kElectron: { - mSpecies = o2::track::PID::Electron; - break; - } - case kMuonMinus: { - mSpecies = o2::track::PID::Muon; - break; - } - case kPiPlus: { - mSpecies = o2::track::PID::Pion; - break; - } - case kKPlus: { - mSpecies = o2::track::PID::Kaon; - break; - } - case kProton: { - mSpecies = o2::track::PID::Proton; - break; - } - default: { - LOGF(error, "ERROR: Species not implemented for PDG %d", mPdg); - assert(false); - } - } - } + ~TrackSelectorPidBase() = default; // TPC /// Set pT range where TPC PID is applicable. - void setRangePtTPC(float ptMin, float ptMax) + void setRangePtTpc(float ptMin, float ptMax) { - mPtTPCMin = ptMin; - mPtTPCMax = ptMax; + mPtTpcMin = ptMin; + mPtTpcMax = ptMax; } /// Set TPC nσ range in which a track should be accepted. - void setRangeNSigmaTPC(float nsMin, float nsMax) + void setRangeNSigmaTpc(float nsMin, float nsMax) { - mNSigmaTPCMin = nsMin; - mNSigmaTPCMax = nsMax; + mNSigmaTpcMin = nsMin; + mNSigmaTpcMax = nsMax; } /// Set TPC nσ range in which a track should be conditionally accepted if combined with TOF. Set to 0 to disable. - void setRangeNSigmaTPCCondTOF(float nsMin, float nsMax) + void setRangeNSigmaTpcCondTof(float nsMin, float nsMax) { - mNSigmaTPCMinCondTOF = nsMin; - mNSigmaTPCMaxCondTOF = nsMax; + mNSigmaTpcMinCondTof = nsMin; + mNSigmaTpcMaxCondTof = nsMax; } /// Checks if track is OK for TPC PID. /// \param track track /// \return true if track is OK for TPC PID template - bool isValidTrackPIDTPC(const T& track) + bool isValidForTpc(const T& track) { auto pt = track.pt(); - return mPtTPCMin <= pt && pt <= mPtTPCMax; + return mPtTpcMin <= pt && pt <= mPtTpcMax; } /// Checks if track is compatible with given particle species hypothesis within given TPC nσ range. /// \param track track - /// \param conditionalTOF variable to store the result of selection with looser cuts for conditional accepting of track if combined with TOF + /// \param conditionalTof variable to store the result of selection with looser cuts for conditional accepting of track if combined with TOF /// \return true if track satisfies TPC PID hypothesis for given TPC nσ range template - bool isSelectedTrackPIDTPC(const T& track, bool& conditionalTOF) + bool isSelectedByTpc(const T& track, bool& conditionalTof) { // Accept if selection is disabled via large values. - if (mNSigmaTPCMin < -999. && mNSigmaTPCMax > 999.) { + if (mNSigmaTpcMin < -999. && mNSigmaTpcMax > 999.) { return true; } // Get nσ for a given particle hypothesis. double nSigma = 100.; - switch (mPdg) { - case kElectron: { - nSigma = track.tpcNSigmaEl(); - break; - } - case kMuonMinus: { - nSigma = track.tpcNSigmaMu(); - break; - } - case kPiPlus: { - nSigma = track.tpcNSigmaPi(); - break; - } - case kKPlus: { - nSigma = track.tpcNSigmaKa(); - break; - } - case kProton: { - nSigma = track.tpcNSigmaPr(); - break; - } - default: { - LOGF(error, "ERROR: TPC PID not implemented for PDG %d", mPdg); - assert(false); - } + if constexpr (pdg == kElectron) { + nSigma = track.tpcNSigmaEl(); + } else if constexpr (pdg == kMuonMinus) { + nSigma = track.tpcNSigmaMu(); + } else if constexpr (pdg == kPiPlus) { + nSigma = track.tpcNSigmaPi(); + } else if constexpr (pdg == kKPlus) { + nSigma = track.tpcNSigmaKa(); + } else if constexpr (pdg == kProton) { + nSigma = track.tpcNSigmaPr(); + } else { + errorPdg(); } - if (mNSigmaTPCMinCondTOF < -999. && mNSigmaTPCMaxCondTOF > 999.) { - conditionalTOF = true; + if (mNSigmaTpcMinCondTof < -999. && mNSigmaTpcMaxCondTof > 999.) { + conditionalTof = true; } else { - conditionalTOF = mNSigmaTPCMinCondTOF <= nSigma && nSigma <= mNSigmaTPCMaxCondTOF; + conditionalTof = mNSigmaTpcMinCondTof <= nSigma && nSigma <= mNSigmaTpcMaxCondTof; } - return mNSigmaTPCMin <= nSigma && nSigma <= mNSigmaTPCMax; + return mNSigmaTpcMin <= nSigma && nSigma <= mNSigmaTpcMax; } /// Returns status of TPC PID selection for a given track. /// \param track track /// \return TPC selection status (see TrackSelectorPID::Status) template - int getStatusTrackPIDTPC(const T& track) - { - if (isValidTrackPIDTPC(track)) { - bool condTOF = false; - if (isSelectedTrackPIDTPC(track, condTOF)) { - return Status::PIDAccepted; // accepted - } else if (condTOF) { - return Status::PIDConditional; // potential to be accepted if combined with TOF - } else { - return Status::PIDRejected; // rejected - } + TrackSelectorPID::Status statusTpc(const T& track) + { + if (!isValidForTpc(track)) { + return TrackSelectorPID::NotApplicable; + } + bool condTof = false; + if (isSelectedByTpc(track, condTof)) { + return TrackSelectorPID::Accepted; + } else if (condTof) { + return TrackSelectorPID::Conditional; // potential to be accepted if combined with TOF } else { - return Status::PIDNotApplicable; // PID not applicable + return TrackSelectorPID::Rejected; } } // TOF /// Set pT range where TOF PID is applicable. - void setRangePtTOF(float ptMin, float ptMax) + void setRangePtTof(float ptMin, float ptMax) { - mPtTOFMin = ptMin; - mPtTOFMax = ptMax; + mPtTofMin = ptMin; + mPtTofMax = ptMax; } /// Set TOF nσ range in which a track should be accepted. - void setRangeNSigmaTOF(float nsMin, float nsMax) + void setRangeNSigmaTof(float nsMin, float nsMax) { - mNSigmaTOFMin = nsMin; - mNSigmaTOFMax = nsMax; + mNSigmaTofMin = nsMin; + mNSigmaTofMax = nsMax; } /// Set TOF nσ range in which a track should be conditionally accepted if combined with TPC. Set to 0 to disable. - void setRangeNSigmaTOFCondTPC(float nsMin, float nsMax) + void setRangeNSigmaTofCondTpc(float nsMin, float nsMax) { - mNSigmaTOFMinCondTPC = nsMin; - mNSigmaTOFMaxCondTPC = nsMax; + mNSigmaTofMinCondTpc = nsMin; + mNSigmaTofMaxCondTpc = nsMax; } /// Checks if track is OK for TOF PID. /// \param track track /// \return true if track is OK for TOF PID template - bool isValidTrackPIDTOF(const T& track) + bool isValidForTof(const T& track) { auto pt = track.pt(); - return mPtTOFMin <= pt && pt <= mPtTOFMax; + return mPtTofMin <= pt && pt <= mPtTofMax; } /// Checks if track is compatible with given particle species hypothesis within given TOF nσ range. /// \param track track - /// \param conditionalTPC variable to store the result of selection with looser cuts for conditional accepting of track if combined with TPC + /// \param conditionalTpc variable to store the result of selection with looser cuts for conditional accepting of track if combined with TPC /// \return true if track satisfies TOF PID hypothesis for given TOF nσ range template - bool isSelectedTrackPIDTOF(const T& track, bool& conditionalTPC) + bool isSelectedByTof(const T& track, bool& conditionalTpc) { // Accept if selection is disabled via large values. - if (mNSigmaTOFMin < -999. && mNSigmaTOFMax > 999.) { + if (mNSigmaTofMin < -999. && mNSigmaTofMax > 999.) { return true; } // Get nσ for a given particle hypothesis. double nSigma = 100.; - switch (mPdg) { - case kElectron: { - nSigma = track.tofNSigmaEl(); - break; - } - case kMuonMinus: { - nSigma = track.tofNSigmaMu(); - break; - } - case kPiPlus: { - nSigma = track.tofNSigmaPi(); - break; - } - case kKPlus: { - nSigma = track.tofNSigmaKa(); - break; - } - case kProton: { - nSigma = track.tofNSigmaPr(); - break; - } - default: { - LOGF(error, "ERROR: TOF PID not implemented for PDG %d", mPdg); - assert(false); - } + if constexpr (pdg == kElectron) { + nSigma = track.tofNSigmaEl(); + } else if constexpr (pdg == kMuonMinus) { + nSigma = track.tofNSigmaMu(); + } else if constexpr (pdg == kPiPlus) { + nSigma = track.tofNSigmaPi(); + } else if constexpr (pdg == kKPlus) { + nSigma = track.tofNSigmaKa(); + } else if constexpr (pdg == kProton) { + nSigma = track.tofNSigmaPr(); + } else { + errorPdg(); } - if (mNSigmaTOFMinCondTPC < -999. && mNSigmaTOFMaxCondTPC > 999.) { - conditionalTPC = true; + if (mNSigmaTofMinCondTpc < -999. && mNSigmaTofMaxCondTpc > 999.) { + conditionalTpc = true; } else { - conditionalTPC = mNSigmaTOFMinCondTPC <= nSigma && nSigma <= mNSigmaTOFMaxCondTPC; + conditionalTpc = mNSigmaTofMinCondTpc <= nSigma && nSigma <= mNSigmaTofMaxCondTpc; } - return mNSigmaTOFMin <= nSigma && nSigma <= mNSigmaTOFMax; + return mNSigmaTofMin <= nSigma && nSigma <= mNSigmaTofMax; } /// Returns status of TOF PID selection for a given track. /// \param track track /// \return TOF selection status (see TrackSelectorPID::Status) template - int getStatusTrackPIDTOF(const T& track) - { - if (isValidTrackPIDTOF(track)) { - bool condTPC = false; - if (isSelectedTrackPIDTOF(track, condTPC)) { - return Status::PIDAccepted; // accepted - } else if (condTPC) { - return Status::PIDConditional; // potential to be accepted if combined with TPC - } else { - return Status::PIDRejected; // rejected - } + TrackSelectorPID::Status statusTof(const T& track) + { + if (!isValidForTof(track)) { + return TrackSelectorPID::NotApplicable; + } + bool condTpc = false; + if (isSelectedByTof(track, condTpc)) { + return TrackSelectorPID::Accepted; + } else if (condTpc) { + return TrackSelectorPID::Conditional; // potential to be accepted if combined with TPC } else { - return Status::PIDNotApplicable; // PID not applicable + return TrackSelectorPID::Rejected; } } // RICH /// Set pT range where RICH PID is applicable. - void setRangePtRICH(float ptMin, float ptMax) + void setRangePtRich(float ptMin, float ptMax) { - mPtRICHMin = ptMin; - mPtRICHMax = ptMax; + mPtRichMin = ptMin; + mPtRichMax = ptMax; } /// Set RICH nσ range in which a track should be accepted. - void setRangeNSigmaRICH(float nsMin, float nsMax) + void setRangeNSigmaRich(float nsMin, float nsMax) { - mNSigmaRICHMin = nsMin; - mNSigmaRICHMax = nsMax; + mNSigmaRichMin = nsMin; + mNSigmaRichMax = nsMax; } /// Set RICH nσ range in which a track should be conditionally accepted if combined with TOF. - void setRangeNSigmaRICHCondTOF(float nsMin, float nsMax) + void setRangeNSigmaRichCondTof(float nsMin, float nsMax) { - mNSigmaRICHMinCondTOF = nsMin; - mNSigmaRICHMaxCondTOF = nsMax; + mNSigmaRichMinCondTof = nsMin; + mNSigmaRichMaxCondTof = nsMax; } /// Checks if track is OK for RICH PID. /// \param track track /// \return true if track is OK for RICH PID template - bool isValidTrackPIDRICH(const T& track) + bool isValidForRich(const T& track) { if (track.richId() < 0) { return false; } auto pt = track.pt(); - return mPtRICHMin <= pt && pt <= mPtRICHMax; + return mPtRichMin <= pt && pt <= mPtRichMax; } /// Checks if track is compatible with given particle species hypothesis within given RICH nσ range. /// \param track track - /// \param conditionalTOF variable to store the result of selection with looser cuts for conditional accepting of track if combined with TOF + /// \param conditionalTof variable to store the result of selection with looser cuts for conditional accepting of track if combined with TOF /// \return true if track satisfies RICH PID hypothesis for given RICH nσ range template - bool isSelectedTrackPIDRICH(const T& track, bool& conditionalTOF) + bool isSelectedByRich(const T& track, bool& conditionalTof) { // Accept if selection is disabled via large values. - if (mNSigmaRICHMin < -999. && mNSigmaRICHMax > 999.) { + if (mNSigmaRichMin < -999. && mNSigmaRichMax > 999.) { return true; } // Get nσ for a given particle hypothesis. double nSigma = 100.; - switch (mPdg) { - case kElectron: { - nSigma = track.rich().richNsigmaEl(); - break; - } - case kMuonMinus: { - nSigma = track.rich().richNsigmaMu(); - break; - } - case kPiPlus: { - nSigma = track.rich().richNsigmaPi(); - break; - } - case kKPlus: { - nSigma = track.rich().richNsigmaKa(); - break; - } - case kProton: { - nSigma = track.rich().richNsigmaPr(); - break; - } - default: { - LOGF(error, "ERROR: RICH PID not implemented for PDG %d", mPdg); - assert(false); - } + if constexpr (pdg == kElectron) { + nSigma = track.rich().richNsigmaEl(); + } else if constexpr (pdg == kMuonMinus) { + nSigma = track.rich().richNsigmaMu(); + } else if constexpr (pdg == kPiPlus) { + nSigma = track.rich().richNsigmaPi(); + } else if constexpr (pdg == kKPlus) { + nSigma = track.rich().richNsigmaKa(); + } else if constexpr (pdg == kProton) { + nSigma = track.rich().richNsigmaPr(); + } else { + errorPdg(); } - if (mNSigmaRICHMinCondTOF < -999. && mNSigmaRICHMaxCondTOF > 999.) { - conditionalTOF = true; + if (mNSigmaRichMinCondTof < -999. && mNSigmaRichMaxCondTof > 999.) { + conditionalTof = true; } else { - conditionalTOF = mNSigmaRICHMinCondTOF <= nSigma && nSigma <= mNSigmaRICHMaxCondTOF; + conditionalTof = mNSigmaRichMinCondTof <= nSigma && nSigma <= mNSigmaRichMaxCondTof; } - return mNSigmaRICHMin <= nSigma && nSigma <= mNSigmaRICHMax; + return mNSigmaRichMin <= nSigma && nSigma <= mNSigmaRichMax; } /// Returns status of RICH PID selection for a given track. /// \param track track /// \return RICH selection status (see TrackSelectorPID::Status) template - int getStatusTrackPIDRICH(const T& track) - { - if (isValidTrackPIDRICH(track)) { - bool condTOF = false; - if (isSelectedTrackPIDRICH(track, condTOF)) { - return Status::PIDAccepted; // accepted - } else if (condTOF) { - return Status::PIDConditional; // potential to be accepted if combined with TOF - } else { - return Status::PIDRejected; // rejected - } + TrackSelectorPID::Status statusRich(const T& track) + { + if (!isValidForRich(track)) { + return TrackSelectorPID::NotApplicable; + } + bool condTof = false; + if (isSelectedByRich(track, condTof)) { + return TrackSelectorPID::Accepted; + } else if (condTof) { + return TrackSelectorPID::Conditional; // potential to be accepted if combined with TOF } else { - return Status::PIDNotApplicable; // PID not applicable + return TrackSelectorPID::Rejected; } } @@ -393,40 +340,48 @@ class TrackSelectorPID /// \param track track /// \return true if track is OK for MID PID template - bool isValidTrackPIDMID(const T& track) + bool isValidForMid(const T& track) { - return track.midId() > -1; + if constexpr (pdg == kMuonMinus) { + return track.midId() > -1; + } else { + errorPdg(); + return false; + } } /// Checks if track is compatible with muon hypothesis in the MID detector. /// \param track track /// \return true if track has been identified as muon by the MID detector template - bool isSelectedTrackPIDMID(const T& track) + bool isSelectedByMid(const T& track) { - if (mPdg != kMuonMinus) { + if constexpr (pdg == kMuonMinus) { + return track.mid().midIsMuon() == 1; // FIXME: change to return track.midIsMuon() once the column is bool. + } else { + errorPdg(); return false; } - return track.mid().midIsMuon() == 1; // FIXME: change to return track.midIsMuon() once the column is bool. } /// Returns status of MID PID selection for a given track. /// \param track track /// \return MID selection status (see TrackSelectorPID::Status) template - int getStatusTrackPIDMID(const T& track) + TrackSelectorPID::Status statusMid(const T& track) { - if (mPdg != kMuonMinus) { - return Status::PIDRejected; - } - if (isValidTrackPIDMID(track)) { - if (isSelectedTrackPIDMID(track)) { - return Status::PIDAccepted; // accepted + if constexpr (pdg == kMuonMinus) { + if (!isValidForMid(track)) { + return TrackSelectorPID::NotApplicable; + } + if (isSelectedByMid(track)) { + return TrackSelectorPID::Accepted; } else { - return Status::PIDRejected; // rejected + return TrackSelectorPID::Rejected; } } else { - return Status::PIDNotApplicable; // PID not applicable + errorPdg(); + return TrackSelectorPID::Rejected; } } @@ -436,111 +391,112 @@ class TrackSelectorPID /// \param track track /// \return status of combined PID (TPC or TOF) (see TrackSelectorPID::Status) template - int getStatusTrackPIDTpcOrTof(const T& track) + TrackSelectorPID::Status statusTpcOrTof(const T& track) { - int statusTPC = getStatusTrackPIDTPC(track); - int statusTOF = getStatusTrackPIDTOF(track); + int pidTpc = statusTpc(track); + int pidTof = statusTof(track); - if (statusTPC == Status::PIDAccepted || statusTOF == Status::PIDAccepted) { - return Status::PIDAccepted; + if (pidTpc == TrackSelectorPID::Accepted || pidTof == TrackSelectorPID::Accepted) { + return TrackSelectorPID::Accepted; } - if (statusTPC == Status::PIDConditional && statusTOF == Status::PIDConditional) { - return Status::PIDAccepted; + if (pidTpc == TrackSelectorPID::Conditional && pidTof == TrackSelectorPID::Conditional) { + return TrackSelectorPID::Accepted; } - if (statusTPC == Status::PIDRejected || statusTOF == Status::PIDRejected) { - return Status::PIDRejected; + if (pidTpc == TrackSelectorPID::Rejected || pidTof == TrackSelectorPID::Rejected) { + return TrackSelectorPID::Rejected; } - return Status::PIDNotApplicable; // (NotApplicable for one detector) and (NotApplicable or Conditional for the other) + return TrackSelectorPID::NotApplicable; // (NotApplicable for one detector) and (NotApplicable or Conditional for the other) } /// Returns status of combined PID (TPC and TOF) selection for a given track when both detectors are applicable. Returns status of single PID otherwise. /// \param track track /// \return status of combined PID (TPC and TOF) (see TrackSelectorPID::Status) template - int getStatusTrackPIDTpcAndTof(const T& track) + TrackSelectorPID::Status statusTpcAndTof(const T& track) { - - int statusTPC = Status::PIDNotApplicable; + int pidTpc = TrackSelectorPID::NotApplicable; if (track.hasTPC()) { - statusTPC = getStatusTrackPIDTPC(track); + pidTpc = statusTpc(track); } - int statusTOF = Status::PIDNotApplicable; + int pidTof = TrackSelectorPID::NotApplicable; if (track.hasTOF()) { - statusTOF = getStatusTrackPIDTOF(track); + pidTof = statusTof(track); } - if (statusTPC == Status::PIDAccepted && statusTOF == Status::PIDAccepted) { - return Status::PIDAccepted; + if (pidTpc == TrackSelectorPID::Accepted && pidTof == TrackSelectorPID::Accepted) { + return TrackSelectorPID::Accepted; } - if (statusTPC == Status::PIDAccepted && (statusTOF == Status::PIDNotApplicable || statusTOF == Status::PIDConditional)) { - return Status::PIDAccepted; + if (pidTpc == TrackSelectorPID::Accepted && (pidTof == TrackSelectorPID::NotApplicable || pidTof == TrackSelectorPID::Conditional)) { + return TrackSelectorPID::Accepted; } - if ((statusTPC == Status::PIDNotApplicable || statusTPC == Status::PIDConditional) && statusTOF == Status::PIDAccepted) { - return Status::PIDAccepted; + if ((pidTpc == TrackSelectorPID::NotApplicable || pidTpc == TrackSelectorPID::Conditional) && pidTof == TrackSelectorPID::Accepted) { + return TrackSelectorPID::Accepted; } - if (statusTPC == Status::PIDConditional && statusTOF == Status::PIDConditional) { - return Status::PIDAccepted; + if (pidTpc == TrackSelectorPID::Conditional && pidTof == TrackSelectorPID::Conditional) { + return TrackSelectorPID::Accepted; } - if (statusTPC == Status::PIDRejected || statusTOF == Status::PIDRejected) { - return Status::PIDRejected; + if (pidTpc == TrackSelectorPID::Rejected || pidTof == TrackSelectorPID::Rejected) { + return TrackSelectorPID::Rejected; } - return Status::PIDNotApplicable; // (NotApplicable for one detector) and (NotApplicable or Conditional for the other) + return TrackSelectorPID::NotApplicable; // (NotApplicable for one detector) and (NotApplicable or Conditional for the other) } /// Checks whether a track is identified as electron and rejected as pion by TOF or RICH. /// \param track track - /// \param useTOF switch to use TOF - /// \param useRICH switch to use RICH + /// \param useTof switch to use TOF + /// \param useRich switch to use RICH /// \return true if track is selected by TOF or RICH /// \note Ported from https://github.com/feisenhu/ALICE3-LoI-LMee/blob/main/efficiency/macros/anaEEstudy.cxx template - bool isElectronAndNotPion(const T& track, bool useTOF = true, bool useRICH = true) - { - bool isSelTOF = false; - bool isSelRICH = false; - bool hasRICH = track.richId() > -1; - bool hasTOF = isValidTrackPIDTOF(track); - auto nSigmaTOFEl = track.tofNSigmaEl(); - auto nSigmaTOFPi = track.tofNSigmaPi(); - auto nSigmaRICHEl = hasRICH ? track.rich().richNsigmaEl() : -1000.; - auto nSigmaRICHPi = hasRICH ? track.rich().richNsigmaPi() : -1000.; + bool isElectronAndNotPion(const T& track, bool useTof = true, bool useRich = true) + { + bool isSelTof = false; + bool isSelRich = false; + bool hasRich = track.richId() > -1; + bool hasTof = isValidForTof(track); + auto nSigmaTofEl = track.tofNSigmaEl(); + auto nSigmaTofPi = track.tofNSigmaPi(); + auto nSigmaRichEl = hasRich ? track.rich().richNsigmaEl() : -1000.; + auto nSigmaRichPi = hasRich ? track.rich().richNsigmaPi() : -1000.; auto p = track.p(); // TOF - if (useTOF && hasTOF && (p < 0.6)) { - if (p > 0.4 && hasRICH) { - if ((std::abs(nSigmaTOFEl) < mNSigmaTOFMax) && (std::abs(nSigmaRICHEl) < mNSigmaRICHMax)) { - isSelTOF = true; // is selected as electron by TOF and RICH + if (useTof && hasTof && (p < 0.6)) { + if (p > 0.4 && hasRich) { + if ((std::abs(nSigmaTofEl) < mNSigmaTofMax) && (std::abs(nSigmaRichEl) < mNSigmaRichMax)) { + isSelTof = true; // is selected as electron by TOF and RICH } } else if (p <= 0.4) { - if (std::abs(nSigmaTOFEl) < mNSigmaTOFMax) { - isSelTOF = true; // is selected as electron by TOF + if (std::abs(nSigmaTofEl) < mNSigmaTofMax) { + isSelTof = true; // is selected as electron by TOF } } else { - isSelTOF = false; // This is rejecting all the heavier particles which do not have a RICH signal in the p area of 0.4-0.6 GeV/c + isSelTof = false; // This is rejecting all the heavier particles which do not have a RICH signal in the p area of 0.4-0.6 GeV/c } - if (std::abs(nSigmaTOFPi) < mNSigmaTOFMax) { - isSelTOF = false; // is selected as pion by TOF + if (std::abs(nSigmaTofPi) < mNSigmaTofMax) { + isSelTof = false; // is selected as pion by TOF } } else { - isSelTOF = false; + isSelTof = false; } // RICH - if (useRICH && hasRICH) { - if (std::abs(nSigmaRICHEl) < mNSigmaRICHMax) { - isSelRICH = true; // is selected as electron by RICH + if (useRich && hasRich) { + if (std::abs(nSigmaRichEl) < mNSigmaRichMax) { + isSelRich = true; // is selected as electron by RICH } - if ((std::abs(nSigmaRICHPi) < mNSigmaRICHMax) && (p > 1.0) && (p < 2.0)) { - isSelRICH = false; // is selected as pion by RICH + if ((std::abs(nSigmaRichPi) < mNSigmaRichMax) && (p > 1.0) && (p < 2.0)) { + isSelRich = false; // is selected as pion by RICH } } else { - isSelRICH = false; + isSelRich = false; } - return isSelRICH || isSelTOF; + return isSelRich || isSelTof; } + // Bayesian + /// Set pT range where Bayes PID is applicable. void setRangePtBayes(float ptMin, float ptMax) { @@ -558,7 +514,7 @@ class TrackSelectorPID /// \param track track /// \return true if track is OK for Bayesian PID template - bool isValidTrackBayesPID(const T& track) + bool isValidForBayes(const T& track) { auto pt = track.pt(); return (mPtBayesMin <= pt && pt <= mPtBayesMax); @@ -568,17 +524,30 @@ class TrackSelectorPID /// \param track track /// \return true if selected species has the highest Bayesian probability template - bool isSelectedTrackBayesPID(const T& track) + bool isSelectedByBayes(const T& track) { // Get index of the most probable species for a given track. - return track.bayesID() == mSpecies; + if constexpr (pdg == kElectron) { + return track.bayesID() == o2::track::PID::Electron; + } else if constexpr (pdg == kMuonMinus) { + return track.bayesID() == o2::track::PID::Muon; + } else if constexpr (pdg == kPiPlus) { + return track.bayesID() == o2::track::PID::Pion; + } else if constexpr (pdg == kKPlus) { + return track.bayesID() == o2::track::PID::Kaon; + } else if constexpr (pdg == kProton) { + return track.bayesID() == o2::track::PID::Proton; + } else { + errorPdg(); + return false; + } } /// Checks if track is compatible with given particle species hypothesis within given Bayesian probability range. /// \param track track /// \return true if track satisfies PID hypothesis for given Bayesian probability range template - bool isSelectedTrackBayesProbPID(const T& track) + bool isSelectedByBayesProb(const T& track) { if (mProbBayesMin < 0.) { // switch off with negative values return true; @@ -586,31 +555,18 @@ class TrackSelectorPID // Get probability for a given particle hypothesis. double prob = 0.; - switch (mPdg) { - case kElectron: { - prob = track.bayesEl(); - break; - } - case kMuonMinus: { - prob = track.bayesMu(); - break; - } - case kPiPlus: { - prob = track.bayesPi(); - break; - } - case kKPlus: { - prob = track.bayesKa(); - break; - } - case kProton: { - prob = track.bayesPr(); - break; - } - default: { - LOGF(error, "ERROR: Bayes PID not implemented for PDG %d", mPdg); - assert(false); - } + if constexpr (pdg == kElectron) { + prob = track.bayesEl(); + } else if constexpr (pdg == kMuonMinus) { + prob = track.bayesMu(); + } else if constexpr (pdg == kPiPlus) { + prob = track.bayesPi(); + } else if constexpr (pdg == kKPlus) { + prob = track.bayesKa(); + } else if constexpr (pdg == kProton) { + prob = track.bayesPr(); + } else { + errorPdg(); } return mProbBayesMin <= prob; @@ -620,16 +576,15 @@ class TrackSelectorPID /// \param track track /// \return Bayesian selection status (see TrackSelectorPID::Status) template - int getStatusTrackBayesPID(const T& track) + TrackSelectorPID::Status statusBayes(const T& track) { - if (isValidTrackBayesPID(track)) { - if (isSelectedTrackBayesPID(track)) { - return Status::PIDAccepted; // accepted - } else { - return Status::PIDRejected; // rejected - } + if (!isValidForBayes(track)) { + return TrackSelectorPID::NotApplicable; + } + if (isSelectedByBayes(track)) { + return TrackSelectorPID::Accepted; } else { - return Status::PIDNotApplicable; // PID not applicable + return TrackSelectorPID::Rejected; } } @@ -637,51 +592,60 @@ class TrackSelectorPID /// \param track track /// \return Bayesian selection status (see TrackSelectorPID::Status) template - int getStatusTrackBayesProbPID(const T& track) + TrackSelectorPID::Status statusBayesProb(const T& track) { - if (isValidTrackBayesPID(track)) { - if (isSelectedTrackBayesProbPID(track)) { - return Status::PIDAccepted; // accepted - } else { - return Status::PIDRejected; // rejected - } + if (!isValidForBayes(track)) { + return TrackSelectorPID::NotApplicable; + } + if (isSelectedByBayesProb(track)) { + return TrackSelectorPID::Accepted; } else { - return Status::PIDNotApplicable; // PID not applicable + return TrackSelectorPID::Rejected; } } private: - uint mPdg = kPiPlus; ///< PDG code of the expected particle - uint mSpecies = o2::track::PID::Pion; ///< Expected species of the track - // TPC - float mPtTPCMin = 0.; ///< minimum pT for TPC PID [GeV/c] - float mPtTPCMax = 100.; ///< maximum pT for TPC PID [GeV/c] - float mNSigmaTPCMin = -3.; ///< minimum number of TPC σ - float mNSigmaTPCMax = 3.; ///< maximum number of TPC σ - float mNSigmaTPCMinCondTOF = 0.; ///< minimum number of TPC σ if combined with TOF - float mNSigmaTPCMaxCondTOF = 0.; ///< maximum number of TPC σ if combined with TOF + float mPtTpcMin = 0.; ///< minimum pT for TPC PID [GeV/c] + float mPtTpcMax = 100.; ///< maximum pT for TPC PID [GeV/c] + float mNSigmaTpcMin = -3.; ///< minimum number of TPC σ + float mNSigmaTpcMax = 3.; ///< maximum number of TPC σ + float mNSigmaTpcMinCondTof = 0.; ///< minimum number of TPC σ if combined with TOF + float mNSigmaTpcMaxCondTof = 0.; ///< maximum number of TPC σ if combined with TOF // TOF - float mPtTOFMin = 0.; ///< minimum pT for TOF PID [GeV/c] - float mPtTOFMax = 100.; ///< maximum pT for TOF PID [GeV/c] - float mNSigmaTOFMin = -3.; ///< minimum number of TOF σ - float mNSigmaTOFMax = 3.; ///< maximum number of TOF σ - float mNSigmaTOFMinCondTPC = 0.; ///< minimum number of TOF σ if combined with TPC - float mNSigmaTOFMaxCondTPC = 0.; ///< maximum number of TOF σ if combined with TPC + float mPtTofMin = 0.; ///< minimum pT for TOF PID [GeV/c] + float mPtTofMax = 100.; ///< maximum pT for TOF PID [GeV/c] + float mNSigmaTofMin = -3.; ///< minimum number of TOF σ + float mNSigmaTofMax = 3.; ///< maximum number of TOF σ + float mNSigmaTofMinCondTpc = 0.; ///< minimum number of TOF σ if combined with TPC + float mNSigmaTofMaxCondTpc = 0.; ///< maximum number of TOF σ if combined with TPC // RICH - float mPtRICHMin = 0.; ///< minimum pT for RICH PID [GeV/c] - float mPtRICHMax = 100.; ///< maximum pT for RICH PID [GeV/c] - float mNSigmaRICHMin = -3.; ///< minimum number of RICH σ - float mNSigmaRICHMax = 3.; ///< maximum number of RICH σ - float mNSigmaRICHMinCondTOF = 0.; ///< minimum number of RICH σ if combined with TOF - float mNSigmaRICHMaxCondTOF = 0.; ///< maximum number of RICH σ if combined with TOF + float mPtRichMin = 0.; ///< minimum pT for RICH PID [GeV/c] + float mPtRichMax = 100.; ///< maximum pT for RICH PID [GeV/c] + float mNSigmaRichMin = -3.; ///< minimum number of RICH σ + float mNSigmaRichMax = 3.; ///< maximum number of RICH σ + float mNSigmaRichMinCondTof = 0.; ///< minimum number of RICH σ if combined with TOF + float mNSigmaRichMaxCondTof = 0.; ///< maximum number of RICH σ if combined with TOF // Bayesian float mPtBayesMin = 0.; ///< minimum pT for Bayesian PID [GeV/c] float mPtBayesMax = 100.; ///< maximum pT for Bayesian PID [GeV/c] - float mProbBayesMin = -1.; ///< minium Bayesian probability [%] + float mProbBayesMin = -1.; ///< minimum Bayesian probability [%] + + /// Throw fatal for unsupported PDG values. + void errorPdg() + { + LOGF(fatal, "Species with PDG code %d not supported", pdg); + } }; +// Predefined types +using TrackSelectorEl = TrackSelectorPidBase; // El +using TrackSelectorMu = TrackSelectorPidBase; // Mu +using TrackSelectorPi = TrackSelectorPidBase; // Pi +using TrackSelectorKa = TrackSelectorPidBase; // Ka +using TrackSelectorPr = TrackSelectorPidBase; // Pr + #endif // COMMON_CORE_TRACKSELECTORPID_H_ diff --git a/Common/Core/aodMerger.cxx b/Common/Core/aodMerger.cxx deleted file mode 100644 index 78164d93882..00000000000 --- a/Common/Core/aodMerger.cxx +++ /dev/null @@ -1,460 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#include -#include -#include -#include - -#include "TSystem.h" -#include "TFile.h" -#include "TTree.h" -#include "TList.h" -#include "TKey.h" -#include "TDirectory.h" -#include "TObjString.h" -#include -#include -#include - -#include "aodMerger.h" - -// AOD merger with correct index rewriting -// No need to know the datamodel because the branch names follow a canonical standard (identified by fIndex) -int main(int argc, char* argv[]) -{ - std::string inputCollection("input.txt"); - std::string outputFileName("AO2D.root"); - long maxDirSize = 100000000; - bool skipNonExistingFiles = false; - bool skipParentFilesList = false; - int verbosity = 2; - int exitCode = 0; // 0: success, >0: failure - - int option_index = 0; - static struct option long_options[] = { - {"input", required_argument, nullptr, 0}, - {"output", required_argument, nullptr, 1}, - {"max-size", required_argument, nullptr, 2}, - {"skip-non-existing-files", no_argument, nullptr, 3}, - {"skip-parent-files-list", no_argument, nullptr, 4}, - {"verbosity", required_argument, nullptr, 5}, - {"help", no_argument, nullptr, 6}, - {nullptr, 0, nullptr, 0}}; - - while (true) { - int c = getopt_long(argc, argv, "", long_options, &option_index); - if (c == -1) { - break; - } else if (c == 0) { - inputCollection = optarg; - } else if (c == 1) { - outputFileName = optarg; - } else if (c == 2) { - maxDirSize = atol(optarg); - } else if (c == 3) { - skipNonExistingFiles = true; - } else if (c == 4) { - skipParentFilesList = true; - } else if (c == 5) { - verbosity = atoi(optarg); - } else if (c == 6) { - printf("AO2D merging tool. Options: \n"); - printf(" --input Contains path to files to be merged. Default: %s\n", inputCollection.c_str()); - printf(" --output Target output ROOT file. Default: %s\n", outputFileName.c_str()); - printf(" --max-size Target directory size. Default: %ld. Set to 0 if file is not self-contained.\n", maxDirSize); - printf(" --skip-non-existing-files Flag to allow skipping of non-existing files in the input list.\n"); - printf(" --skip-parent-files-list Flag to allow skipping the merging of the parent files list.\n"); - printf(" --verbosity Verbosity of output (default: %d).\n", verbosity); - return -1; - } else { - return -2; - } - } - - printf("AOD merger started with:\n"); - printf(" Input file: %s\n", inputCollection.c_str()); - printf(" Output file name: %s\n", outputFileName.c_str()); - printf(" Maximal folder size (uncompressed): %ld\n", maxDirSize); - if (skipNonExistingFiles) { - printf(" WARNING: Skipping non-existing files.\n"); - } - - std::map trees; - std::map sizeCompressed; - std::map sizeUncompressed; - std::map offsets; - std::map unassignedIndexOffset; - - auto outputFile = TFile::Open(outputFileName.c_str(), "RECREATE", "", 501); - TDirectory* outputDir = nullptr; - long currentDirSize = 0; - - std::ifstream in; - in.open(inputCollection); - TString line; - bool connectedToAliEn = false; - TMap* metaData = nullptr; - TMap* parentFiles = nullptr; - int totalMergedDFs = 0; - int mergedDFs = 0; - while (in.good() && exitCode == 0) { - in >> line; - - if (line.Length() == 0) { - continue; - } - - if (line.BeginsWith("alien:") && !connectedToAliEn) { - printf("Connecting to AliEn..."); - TGrid::Connect("alien:"); - connectedToAliEn = true; // Only try once - } - - printf("Processing input file: %s\n", line.Data()); - - auto inputFile = TFile::Open(line); - if (!inputFile) { - printf("Error: Could not open input file %s.\n", line.Data()); - if (skipNonExistingFiles) { - continue; - } else { - printf("Aborting merge!\n"); - exitCode = 1; - break; - } - } - - TList* keyList = inputFile->GetListOfKeys(); - keyList->Sort(); - - for (auto key1 : *keyList) { - if (((TObjString*)key1)->GetString().EqualTo("metaData")) { - auto metaDataCurrentFile = (TMap*)inputFile->Get("metaData"); - if (metaData == nullptr) { - metaData = metaDataCurrentFile; - outputFile->cd(); - metaData->Write("metaData", TObject::kSingleKey); - } else { - for (auto metaDataPair : *metaData) { - auto metaDataKey = ((TPair*)metaDataPair)->Key(); - if (metaDataCurrentFile->Contains(((TObjString*)metaDataKey)->GetString())) { - auto value = (TObjString*)metaData->GetValue(((TObjString*)metaDataKey)->GetString()); - auto valueCurrentFile = (TObjString*)metaDataCurrentFile->GetValue(((TObjString*)metaDataKey)->GetString()); - if (!value->GetString().EqualTo(valueCurrentFile->GetString())) { - printf("WARNING: Metadata differs between input files. Key %s : %s vs. %s\n", ((TObjString*)metaDataKey)->GetString().Data(), - value->GetString().Data(), valueCurrentFile->GetString().Data()); - } - } else { - printf("WARNING: Metadata differs between input files. Key %s is not present in current file\n", ((TObjString*)metaDataKey)->GetString().Data()); - } - } - } - } - - if (((TObjString*)key1)->GetString().EqualTo("parentFiles") && !skipParentFilesList) { - auto parentFilesCurrentFile = (TMap*)inputFile->Get("parentFiles"); - if (parentFiles == nullptr) { - parentFiles = new TMap; - } - for (auto pair : *parentFilesCurrentFile) { - parentFiles->Add(((TPair*)pair)->Key(), ((TPair*)pair)->Value()); - } - delete parentFilesCurrentFile; - } - - if (!((TObjString*)key1)->GetString().BeginsWith("DF_")) { - continue; - } - - auto dfName = ((TObjString*)key1)->GetString().Data(); - - if (verbosity > 0) { - printf(" Processing folder %s\n", dfName); - } - ++mergedDFs; - ++totalMergedDFs; - auto folder = (TDirectoryFile*)inputFile->Get(dfName); - auto treeList = folder->GetListOfKeys(); - - treeList->Sort(); - - // purging keys from duplicates - for (auto i = 0; i < treeList->GetEntries(); ++i) { - TKey* ki = (TKey*)treeList->At(i); - for (int j = i + 1; j < treeList->GetEntries(); ++j) { - TKey* kj = (TKey*)treeList->At(j); - if (std::strcmp(ki->GetName(), kj->GetName()) == 0 && std::strcmp(ki->GetTitle(), kj->GetTitle()) == 0) { - if (ki->GetCycle() < kj->GetCycle()) { - printf(" *** FATAL *** we had ordered the keys, first cycle should be higher, please check"); - exitCode = 5; - } else { - // key is a duplicate, let's remove it - treeList->Remove(kj); - j--; - } - } else { - // we changed key, since they are sorted, we won't have the same anymore - break; - } - } - } - - std::list foundTrees; - - for (auto key2 : *treeList) { - auto treeName = ((TObjString*)key2)->GetString().Data(); - bool found = (std::find(foundTrees.begin(), foundTrees.end(), treeName) != foundTrees.end()); - if (found == true) { - printf(" ***WARNING*** Tree %s was already merged (even if we purged duplicated trees before, so this should not happen), skipping\n", treeName); - continue; - } - foundTrees.push_back(treeName); - - auto inputTree = (TTree*)inputFile->Get(Form("%s/%s", dfName, treeName)); - bool fastCopy = (inputTree->GetTotBytes() > 10000000); // Only do this for large enough trees to avoid that baskets are too small - if (verbosity > 1) { - printf(" Processing tree %s with %lld entries with total size %lld (fast copy: %d)\n", treeName, inputTree->GetEntries(), inputTree->GetTotBytes(), fastCopy); - } - - bool alreadyCopied = false; - if (trees.count(treeName) == 0) { - if (mergedDFs > 1) { - printf(" *** FATAL ***: The tree %s was not in the previous dataframe(s)\n", treeName); - exitCode = 3; - } - - // Connect trees but do not copy entries (using the clone function) unless fast copy is on - // NOTE Basket size etc. are copied in CloneTree() - if (!outputDir) { - outputDir = outputFile->mkdir(dfName); - currentDirSize = 0; - if (verbosity > 0) { - printf("Writing to output folder %s\n", dfName); - } - } - outputDir->cd(); - auto outputTree = inputTree->CloneTree(-1, (fastCopy) ? "fast" : ""); - currentDirSize += outputTree->GetTotBytes(); - alreadyCopied = true; - outputTree->SetAutoFlush(0); - trees[treeName] = outputTree; - } else { - // adjust addresses tree - trees[treeName]->CopyAddresses(inputTree); - } - - auto outputTree = trees[treeName]; - // register index and connect VLA columns - std::vector> indexList; - std::vector vlaPointers; - std::vector indexPointers; - TObjArray* branches = inputTree->GetListOfBranches(); - for (int i = 0; i < branches->GetEntriesFast(); ++i) { - TBranch* br = (TBranch*)branches->UncheckedAt(i); - TString branchName(br->GetName()); - - // detect VLA - if (((TLeaf*)br->GetListOfLeaves()->First())->GetLeafCount() != nullptr) { - int maximum = ((TLeaf*)br->GetListOfLeaves()->First())->GetLeafCount()->GetMaximum(); - - // get type - static TClass* cls; - EDataType type; - br->GetExpectedType(cls, type); - auto typeSize = TDataType::GetDataType(type)->Size(); - - char* buffer = new char[maximum * typeSize]; - memset(buffer, 0, maximum * typeSize); - vlaPointers.push_back(buffer); - if (verbosity > 2) { - printf(" Allocated VLA buffer of length %d with %d bytes each for branch name %s\n", maximum, typeSize, br->GetName()); - } - inputTree->SetBranchAddress(br->GetName(), buffer); - outputTree->SetBranchAddress(br->GetName(), buffer); - - if (branchName.BeginsWith("fIndexArray")) { - for (int i = 0; i < maximum; i++) { - indexList.push_back({reinterpret_cast(buffer + i * typeSize), offsets[getTableName(branchName, treeName)]}); - } - } - } else if (branchName.BeginsWith("fIndexSlice")) { - int* buffer = new int[2]; - memset(buffer, 0, 2 * sizeof(buffer[0])); - vlaPointers.push_back(reinterpret_cast(buffer)); - - inputTree->SetBranchAddress(br->GetName(), buffer); - outputTree->SetBranchAddress(br->GetName(), buffer); - - indexList.push_back({buffer, offsets[getTableName(branchName, treeName)]}); - indexList.push_back({buffer + 1, offsets[getTableName(branchName, treeName)]}); - } else if (branchName.BeginsWith("fIndex") && !branchName.EndsWith("_size")) { - int* buffer = new int; - *buffer = 0; - indexPointers.push_back(buffer); - - inputTree->SetBranchAddress(br->GetName(), buffer); - outputTree->SetBranchAddress(br->GetName(), buffer); - - indexList.push_back({buffer, offsets[getTableName(branchName, treeName)]}); - } - } - - if (indexList.size() > 0) { - auto entries = inputTree->GetEntries(); - int minIndexOffset = unassignedIndexOffset[treeName]; - auto newMinIndexOffset = minIndexOffset; - for (int i = 0; i < entries; i++) { - for (auto& index : indexList) { - *(index.first) = 0; // Any positive number will do, in any case it will not be filled in the output. Otherwise the previous entry is used and manipulated in the following. - } - inputTree->GetEntry(i); - // shift index columns by offset - for (const auto& idx : indexList) { - // if negative, the index is unassigned. In this case, the different unassigned blocks have to get unique negative IDs - if (*(idx.first) < 0) { - *(idx.first) += minIndexOffset; - newMinIndexOffset = std::min(newMinIndexOffset, *(idx.first)); - } else { - *(idx.first) += idx.second; - } - } - if (!alreadyCopied) { - int nbytes = outputTree->Fill(); - if (nbytes > 0) { - currentDirSize += nbytes; - } - } - } - unassignedIndexOffset[treeName] = newMinIndexOffset; - } else if (!alreadyCopied) { - auto nbytes = outputTree->CopyEntries(inputTree, -1, (fastCopy) ? "fast" : ""); - if (nbytes > 0) { - currentDirSize += nbytes; - } - } - - delete inputTree; - - for (auto& buffer : indexPointers) { - delete buffer; - } - for (auto& buffer : vlaPointers) { - delete[] buffer; - } - } - if (exitCode > 0) { - break; - } - - // check if all trees were present - if (mergedDFs > 1) { - for (auto const& tree : trees) { - bool found = (std::find(foundTrees.begin(), foundTrees.end(), tree.first) != foundTrees.end()); - if (found == false) { - printf(" *** FATAL ***: The tree %s was not in the current dataframe\n", tree.first.c_str()); - exitCode = 4; - } - } - } - - // set to -1 to identify not found tables - for (auto& offset : offsets) { - offset.second = -1; - } - - // update offsets - for (auto const& tree : trees) { - offsets[removeVersionSuffix(tree.first.c_str())] = tree.second->GetEntries(); - } - - // check for not found tables - for (auto& offset : offsets) { - if (offset.second < 0) { - if (maxDirSize > 0) { - // if maxDirSize is 0 then we do not merge DFs and this error is not an error actually (e.g. for not self-contained derived data) - printf("ERROR: Index on %s but no tree found\n", offset.first.c_str()); - } - offset.second = 0; - } - } - - if (currentDirSize > maxDirSize) { - if (verbosity > 0) { - printf("Maximum size reached: %ld. Closing folder %s.\n", currentDirSize, dfName); - } - for (auto const& tree : trees) { - // printf("Writing %s\n", tree.first.c_str()); - outputDir->cd(); - tree.second->Write(); - - // stats - sizeCompressed[tree.first] += tree.second->GetZipBytes(); - sizeUncompressed[tree.first] += tree.second->GetTotBytes(); - - delete tree.second; - } - outputDir = nullptr; - trees.clear(); - offsets.clear(); - mergedDFs = 0; - } - } - inputFile->Close(); - } - - if (parentFiles) { - outputFile->cd(); - parentFiles->Write("parentFiles", TObject::kSingleKey); - } - - for (auto const& tree : trees) { - outputDir->cd(); - tree.second->Write(); - - // stats - sizeCompressed[tree.first] += tree.second->GetZipBytes(); - sizeUncompressed[tree.first] += tree.second->GetTotBytes(); - - delete tree.second; - } - - outputFile->Write(); - outputFile->Close(); - - if (totalMergedDFs == 0) { - printf("ERROR: Did not merge a single DF. This does not seem right.\n"); - exitCode = 2; - } - - // in case of failure, remove the incomplete file - if (exitCode != 0) { - printf("Removing incomplete output file %s.\n", outputFile->GetName()); - gSystem->Unlink(outputFile->GetName()); - } else { - printf("AOD merger finished. Size overview follows:\n"); - - uint64_t totalCompressed = 0; - uint64_t totalUncompressed = 0; - for (auto const& tree : sizeCompressed) { - totalCompressed += tree.second; - totalUncompressed += sizeUncompressed[tree.first]; - } - if (totalCompressed > 0 && totalUncompressed > 0) { - for (auto const& tree : sizeCompressed) { - printf(" Tree %20s | Compressed: %12lu (%2.0f%%) | Uncompressed: %12lu (%2.0f%%)\n", tree.first.c_str(), tree.second, 100.0 * tree.second / totalCompressed, sizeUncompressed[tree.first], 100.0 * sizeUncompressed[tree.first] / totalUncompressed); - } - } - } - printf("\n"); - - return exitCode; -} diff --git a/Common/Core/aodMerger.h b/Common/Core/aodMerger.h deleted file mode 100644 index e565272264b..00000000000 --- a/Common/Core/aodMerger.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#include - -const char* removeVersionSuffix(const char* treeName) -{ - // remove version suffix, e.g. O2v0_001 becomes O2v0 - static TString tmp; - tmp = treeName; - if (tmp.First("_") >= 0) { - tmp.Remove(tmp.First("_")); - } - return tmp; -} - -const char* getTableName(const char* branchName, const char* treeName) -{ - // Syntax for branchName: - // fIndex
[_] - // fIndexArray
[_] - // fIndexSlice
[_] - // if
is empty it is a self index and treeName is used as table name - static TString tableName; - tableName = branchName; - if (tableName.BeginsWith("fIndexArray") || tableName.BeginsWith("fIndexSlice")) { - tableName.Remove(0, 11); - } else { - tableName.Remove(0, 6); - } - if (tableName.First("_") >= 0) { - tableName.Remove(tableName.First("_")); - } - if (tableName.Length() == 0) { - return removeVersionSuffix(treeName); - } - tableName.Remove(tableName.Length() - 1); // remove s - tableName.ToLower(); - tableName = "O2" + tableName; - // printf("%s --> %s\n", branchName, tableName.Data()); - return tableName; -} diff --git a/Common/Core/aodThinner.cxx b/Common/Core/aodThinner.cxx deleted file mode 100644 index 6ed8463cae3..00000000000 --- a/Common/Core/aodThinner.cxx +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -#include -#include -#include -#include - -#include "TSystem.h" -#include "TFile.h" -#include "TTree.h" -#include "TList.h" -#include "TKey.h" -#include "TDirectory.h" -#include "TObjString.h" -#include -#include -#include - -#include "aodMerger.h" - -// AOD reduction tool -// Designed for the 2022 pp data with specific selections: -// - Remove all TPC only tracks -// - Remove all V0s which refer to any removed track -// - Remove all cascade which refer to any removed V0 -// - Remove all ambiguous track entries which point to a track with collision -// - Adjust all indices -int main(int argc, char* argv[]) -{ - std::string inputFileName("AO2D.root"); - std::string outputFileName("AO2D_thinned.root"); - int exitCode = 0; // 0: success, >0: failure - - int option_index = 1; - static struct option long_options[] = { - {"input", required_argument, nullptr, 0}, - {"output", required_argument, nullptr, 1}, - {"help", no_argument, nullptr, 2}, - {nullptr, 0, nullptr, 0}}; - - while (true) { - int c = getopt_long(argc, argv, "", long_options, &option_index); - if (c == -1) { - break; - } else if (c == 0) { - inputFileName = optarg; - } else if (c == 1) { - outputFileName = optarg; - } else if (c == 2) { - printf("AO2D thinning tool. Options: \n"); - printf(" --input Contains input file path to the file to be thinned. Default: %s\n", inputFileName.c_str()); - printf(" --output Target output ROOT file. Default: %s\n", outputFileName.c_str()); - return -1; - } else { - return -2; - } - } - - printf("AOD reduction started with:\n"); - printf(" Input file: %s\n", inputFileName.c_str()); - printf(" Ouput file name: %s\n", outputFileName.c_str()); - - auto outputFile = TFile::Open(outputFileName.c_str(), "RECREATE", "", 501); - TDirectory* outputDir = nullptr; - - if (inputFileName.find("alien:") == 0) { - printf("Connecting to AliEn..."); - TGrid::Connect("alien:"); - } - - auto inputFile = TFile::Open(inputFileName.c_str()); - if (!inputFile) { - printf("Error: Could not open input file %s.\n", inputFileName.c_str()); - return 1; - } - - TList* keyList = inputFile->GetListOfKeys(); - keyList->Sort(); - - for (auto key1 : *keyList) { - if (((TObjString*)key1)->GetString().EqualTo("metaData")) { - auto metaData = (TMap*)inputFile->Get("metaData"); - outputFile->cd(); - metaData->Write("metaData", TObject::kSingleKey); - } - - if (((TObjString*)key1)->GetString().EqualTo("parentFiles")) { - auto parentFiles = (TMap*)inputFile->Get("parentFiles"); - outputFile->cd(); - parentFiles->Write("parentFiles", TObject::kSingleKey); - } - - if (!((TObjString*)key1)->GetString().BeginsWith("DF_")) { - continue; - } - - auto dfName = ((TObjString*)key1)->GetString().Data(); - - printf(" Processing folder %s\n", dfName); - auto folder = (TDirectoryFile*)inputFile->Get(dfName); - auto treeList = folder->GetListOfKeys(); - treeList->Sort(); - - // purging keys from duplicates - for (auto i = 0; i < treeList->GetEntries(); ++i) { - TKey* ki = (TKey*)treeList->At(i); - for (int j = i + 1; j < treeList->GetEntries(); ++j) { - TKey* kj = (TKey*)treeList->At(j); - if (std::strcmp(ki->GetName(), kj->GetName()) == 0 && std::strcmp(ki->GetTitle(), kj->GetTitle()) == 0) { - if (ki->GetCycle() < kj->GetCycle()) { - printf(" *** FATAL *** we had ordered the keys, first cycle should be higher, please check"); - exitCode = 5; - } else { - // key is a duplicate, let's remove it - treeList->Remove(kj); - j--; - } - } else { - // we changed key, since they are sorted, we won't have the same anymore - break; - } - } - } - - // Certain order needed in order to populate vectors of skipped entries - auto v0Entry = (TObject*)treeList->FindObject("O2v0_001"); - treeList->Remove(v0Entry); - treeList->AddFirst(v0Entry); - - // Prepare maps for track skimming - auto trackExtraTree = (TTree*)inputFile->Get(Form("%s/%s", dfName, "O2trackextra")); // for example we can use this line to access the track table - if (trackExtraTree == nullptr) { - printf("O2trackextra table not found\n"); - exitCode = 6; - break; - } - auto track_iu = (TTree*)inputFile->Get(Form("%s/%s", dfName, "O2track_iu")); - if (track_iu == nullptr) { - printf("O2track_iu table not found\n"); - exitCode = 7; - break; - } - auto v0s = (TTree*)inputFile->Get(Form("%s/%s", dfName, "O2v0_001")); - if (v0s == nullptr) { - printf("O2v0_001 table not found\n"); - exitCode = 8; - break; - } - - std::vector acceptedTracks(trackExtraTree->GetEntries(), -1); - std::vector hasCollision(trackExtraTree->GetEntries(), false); - std::vector keepV0s(v0s->GetEntries(), -1); - - uint8_t tpcNClsFindable = 0; - uint8_t ITSClusterMap = 0; - uint8_t TRDPattern = 0; - float_t TOFChi2 = 0; - // char16_t fTPCNClsFindableMinusFound = 0; - trackExtraTree->SetBranchAddress("fTPCNClsFindable", &tpcNClsFindable); - trackExtraTree->SetBranchAddress("fITSClusterMap", &ITSClusterMap); - trackExtraTree->SetBranchAddress("fTRDPattern", &TRDPattern); - trackExtraTree->SetBranchAddress("fTOFChi2", &TOFChi2); - // trackExtraTree->SetBranchAddress("fTPCNClsFindableMinusFound", &fTPCNClsFindableMinusFound); - - int fIndexCollisions = 0; - track_iu->SetBranchAddress("fIndexCollisions", &fIndexCollisions); - - // loop over all tracks - auto entries = trackExtraTree->GetEntries(); - int counter = 0; - for (int i = 0; i < entries; i++) { - trackExtraTree->GetEntry(i); - track_iu->GetEntry(i); - - // Remove TPC only tracks - if (tpcNClsFindable > 0. && ITSClusterMap == 0 && TRDPattern == 0 && TOFChi2 < -1.) { - counter++; - } else { - acceptedTracks[i] = i - counter; - } - hasCollision[i] = (fIndexCollisions >= 0); - } - - for (auto key2 : *treeList) { - auto treeName = ((TObjString*)key2)->GetString().Data(); - - auto inputTree = (TTree*)inputFile->Get(Form("%s/%s", dfName, treeName)); - printf(" Processing tree %s with %lld entries with total size %lld\n", treeName, inputTree->GetEntries(), inputTree->GetTotBytes()); - - // Connect trees but do not copy entries (using the clone function) - // NOTE Basket size etc. are copied in CloneTree() - if (!outputDir) { - outputDir = outputFile->mkdir(dfName); - printf("Writing to output folder %s\n", dfName); - } - outputDir->cd(); - auto outputTree = inputTree->CloneTree(0); - outputTree->SetAutoFlush(0); - - std::vector indexList; - std::vector vlaPointers; - std::vector indexPointers; - TObjArray* branches = inputTree->GetListOfBranches(); - for (int i = 0; i < branches->GetEntriesFast(); ++i) { - TBranch* br = (TBranch*)branches->UncheckedAt(i); - TString branchName(br->GetName()); - TString tableName(getTableName(branchName, treeName)); - // register index of track index ONLY - if (!tableName.EqualTo("O2track")) { - continue; - } - // detect VLA - if (((TLeaf*)br->GetListOfLeaves()->First())->GetLeafCount() != nullptr) { - printf(" *** FATAL ***: VLA detection is not supported\n"); - exitCode = 9; - } else if (branchName.BeginsWith("fIndexSlice")) { - int* buffer = new int[2]; - memset(buffer, 0, 2 * sizeof(buffer[0])); - vlaPointers.push_back(reinterpret_cast(buffer)); - inputTree->SetBranchAddress(br->GetName(), buffer); - outputTree->SetBranchAddress(br->GetName(), buffer); - - indexList.push_back(buffer); - indexList.push_back(buffer + 1); - } else if (branchName.BeginsWith("fIndex") && !branchName.EndsWith("_size")) { - int* buffer = new int; - *buffer = 0; - indexPointers.push_back(buffer); - - inputTree->SetBranchAddress(br->GetName(), buffer); - outputTree->SetBranchAddress(br->GetName(), buffer); - - indexList.push_back(buffer); - } - } - - bool processingTracks = memcmp(treeName, "O2track", 7) == 0; // matches any of the track tables - bool processingCascades = memcmp(treeName, "O2cascade", 9) == 0; - bool processingV0s = memcmp(treeName, "O2v0", 4) == 0; - bool processingAmbiguousTracks = memcmp(treeName, "O2ambiguoustrack", 16) == 0; - - auto indexV0s = -1; - if (processingCascades) { - inputTree->SetBranchAddress("fIndexV0s", &indexV0s); - outputTree->SetBranchAddress("fIndexV0s", &indexV0s); - } - - auto entries = inputTree->GetEntries(); - for (int i = 0; i < entries; i++) { - inputTree->GetEntry(i); - bool fillThisEntry = true; - // Special case for Tracks, TracksExtra, TracksCov - if (processingTracks) { - if (acceptedTracks[i] < 0) { - fillThisEntry = false; - } - } else { - // Other table than Tracks* --> reassign indices to Tracks - for (const auto& idx : indexList) { - int oldTrackIndex = *idx; - - // if negative, the index is unassigned. - if (oldTrackIndex >= 0) { - if (acceptedTracks[oldTrackIndex] < 0) { - fillThisEntry = false; - } else { - *idx = acceptedTracks[oldTrackIndex]; - } - } - } - } - - // Reassign v0 index of cascades - if (processingCascades) { - if (keepV0s[indexV0s] < 0) { - fillThisEntry = false; - } else { - indexV0s = keepV0s[indexV0s]; - } - } - - // Keep only tracks which have no collision, see O2-3601 - if (processingAmbiguousTracks) { - if (hasCollision[i]) { - fillThisEntry = false; - } - } - - if (fillThisEntry) { - outputTree->Fill(); - if (processingV0s) { - keepV0s[i] = outputTree->GetEntries() - 1; - } - } - } - - if (entries != outputTree->GetEntries()) { - printf(" Reduced from %lld to %lld entries\n", entries, outputTree->GetEntries()); - } - - delete inputTree; - - for (auto& buffer : indexPointers) { - delete buffer; - } - for (auto& buffer : vlaPointers) { - delete[] buffer; - } - - outputDir->cd(); - outputTree->Write(); - delete outputTree; - } - if (exitCode > 0) { - break; - } - - outputDir = nullptr; - } - inputFile->Close(); - - outputFile->Write(); - outputFile->Close(); - - // in case of failure, remove the incomplete file - if (exitCode != 0) { - printf("Removing incomplete output file %s.\n", outputFile->GetName()); - gSystem->Unlink(outputFile->GetName()); - } - - printf("End of AOD thinning.\n"); - - return exitCode; -} diff --git a/Common/DataModel/CMakeLists.txt b/Common/DataModel/CMakeLists.txt index e5d1c58eb1b..d76bdc9c850 100644 --- a/Common/DataModel/CMakeLists.txt +++ b/Common/DataModel/CMakeLists.txt @@ -17,4 +17,8 @@ o2physics_add_header_only_library(DataModel Multiplicity.h PIDResponse.h CollisionAssociationTables.h - TrackSelectionTables.h) + TrackSelectionTables.h + McCollisionExtra.h + EvtPlanes.h + Qvectors.h + MftmchMatchingML.h) diff --git a/Common/DataModel/Centrality.h b/Common/DataModel/Centrality.h index 3c2b6f6ddaf..f89e6b23e71 100644 --- a/Common/DataModel/Centrality.h +++ b/Common/DataModel/Centrality.h @@ -8,8 +8,8 @@ // 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 O2_ANALYSIS_CENTRALITY_H_ -#define O2_ANALYSIS_CENTRALITY_H_ +#ifndef COMMON_DATAMODEL_CENTRALITY_H_ +#define COMMON_DATAMODEL_CENTRALITY_H_ #include "Framework/AnalysisDataModel.h" @@ -18,6 +18,7 @@ namespace o2::aod namespace cent { DECLARE_SOA_COLUMN(CentRun2V0M, centRun2V0M, float); //! Run2 Centrality percentile estimated from V0C+V0A multiplicities +DECLARE_SOA_COLUMN(CentRun2V0A, centRun2V0A, float); //! Run2 Centrality percentile estimated from V0A multiplicities DECLARE_SOA_COLUMN(CentRun2SPDTracklets, centRun2SPDTracklets, float); //! Run2 centrality percentile estimated from SPD tracklets multiplicity DECLARE_SOA_COLUMN(CentRun2SPDClusters, centRun2SPDClusters, float); //! Run2 centrality percentile estimated from SPD clusters multiplicity DECLARE_SOA_COLUMN(CentRun2CL0, centRun2CL0, float); //! Run2 centrality percentile estimated from CL0 multiplicity @@ -30,6 +31,7 @@ DECLARE_SOA_COLUMN(CentFDDM, centFDDM, float); //! Run3 DECLARE_SOA_COLUMN(CentNTPV, centNTPV, float); //! Run3 centrality percentile estimated from the number of tracks contributing to the PV } // namespace cent DECLARE_SOA_TABLE(CentRun2V0Ms, "AOD", "CENTRUN2V0M", cent::CentRun2V0M); //! Run2 V0M estimated centrality table +DECLARE_SOA_TABLE(CentRun2V0As, "AOD", "CENTRUN2V0A", cent::CentRun2V0A); //! Run2 V0A estimated centrality table DECLARE_SOA_TABLE(CentRun2SPDTrks, "AOD", "CENTRUN2SPDTRK", cent::CentRun2SPDTracklets); //! Run2 SPD tracklets estimated centrality table DECLARE_SOA_TABLE(CentRun2SPDClss, "AOD", "CENTRUN2SPDCLS", cent::CentRun2SPDClusters); //! Run2 SPD clusters estimated centrality table DECLARE_SOA_TABLE(CentRun2CL0s, "AOD", "CENTRUN2CL0", cent::CentRun2CL0); //! Run2 CL0 estimated centrality table @@ -41,6 +43,7 @@ DECLARE_SOA_TABLE(CentFT0Cs, "AOD", "CENTFT0C", cent::CentFT0C); DECLARE_SOA_TABLE(CentFDDMs, "AOD", "CENTFDDM", cent::CentFDDM); //! Run3 FDDM estimated centrality table DECLARE_SOA_TABLE(CentNTPVs, "AOD", "CENTNTPV", cent::CentNTPV); //! Run3 NTPV estimated centrality table using CentRun2V0M = CentRun2V0Ms::iterator; +using CentRun2V0A = CentRun2V0As::iterator; using CentRun2SPDTrk = CentRun2SPDTrks::iterator; using CentRun2SPDCls = CentRun2SPDClss::iterator; using CentRun2CL0 = CentRun2CL0s::iterator; @@ -53,4 +56,4 @@ using CentFDDM = CentFDDMs::iterator; using CentNTPV = CentNTPVs::iterator; } // namespace o2::aod -#endif // O2_ANALYSIS_CENTRALITY_H_ +#endif // COMMON_DATAMODEL_CENTRALITY_H_ diff --git a/Common/DataModel/EventSelection.h b/Common/DataModel/EventSelection.h index 6f6cb4a1a2d..4d81f0ee9da 100644 --- a/Common/DataModel/EventSelection.h +++ b/Common/DataModel/EventSelection.h @@ -43,23 +43,10 @@ enum Run2EventCuts { kTRDHEE // Offline TRD single-electron-in-EMCAL-acceptance trigger decision }; -// collision-joinable event selection decisions namespace evsel { -DECLARE_SOA_BITMAP_COLUMN(Alias, alias, 32); -DECLARE_SOA_BITMAP_COLUMN(Selection, selection, 64); -DECLARE_SOA_COLUMN(BBV0A, bbV0A, bool); //! Beam-beam time in V0A -DECLARE_SOA_COLUMN(BBV0C, bbV0C, bool); //! Beam-beam time in V0C -DECLARE_SOA_COLUMN(BGV0A, bgV0A, bool); //! Beam-gas time in V0A -DECLARE_SOA_COLUMN(BGV0C, bgV0C, bool); //! Beam-gas time in V0C -DECLARE_SOA_COLUMN(BBFDA, bbFDA, bool); //! Beam-beam time in FDA -DECLARE_SOA_COLUMN(BBFDC, bbFDC, bool); //! Beam-beam time in FDC -DECLARE_SOA_COLUMN(BGFDA, bgFDA, bool); //! Beam-gas time in FDA -DECLARE_SOA_COLUMN(BGFDC, bgFDC, bool); //! Beam-gas time in FDC -DECLARE_SOA_COLUMN(MultRingV0A, multRingV0A, float[5]); //! V0A multiplicity per ring (4 rings in run2, 5 rings in run3) -DECLARE_SOA_COLUMN(MultRingV0C, multRingV0C, float[4]); //! V0C multiplicity per ring (4 rings in run2) -DECLARE_SOA_COLUMN(SpdClusters, spdClusters, uint32_t); //! Number of SPD clusters in two layers -DECLARE_SOA_COLUMN(NTracklets, nTracklets, int); //! Tracklet multiplicity +DECLARE_SOA_BITMAP_COLUMN(Alias, alias, 32); //! Bitmask of fired trigger aliases (see TriggerAliases.h for definitions) +DECLARE_SOA_BITMAP_COLUMN(Selection, selection, 64); //! Bitmask of selection flags (see EventSelectionParams.h for definitions) DECLARE_SOA_COLUMN(Sel7, sel7, bool); //! Event selection decision based on V0A & V0C DECLARE_SOA_COLUMN(Sel8, sel8, bool); //! Event selection decision based on TVX DECLARE_SOA_INDEX_COLUMN_FULL(FoundBC, foundBC, int, BCs, "_foundBC"); //! BC entry index in BCs table (-1 if doesn't exist) @@ -68,20 +55,16 @@ DECLARE_SOA_INDEX_COLUMN_FULL(FoundFV0, foundFV0, int, FV0As, "_foundFV0"); //! DECLARE_SOA_INDEX_COLUMN_FULL(FoundFDD, foundFDD, int, FDDs, "_foundFDD"); //! FDD entry index in FDDs table (-1 if doesn't exist) DECLARE_SOA_INDEX_COLUMN_FULL(FoundZDC, foundZDC, int, Zdcs, "_foundZDC"); //! ZDC entry index in ZDCs table (-1 if doesn't exist) } // namespace evsel -DECLARE_SOA_TABLE(EvSels, "AOD", "EVSEL", //! - evsel::Alias, evsel::Selection, - evsel::BBV0A, evsel::BBV0C, evsel::BGV0A, evsel::BGV0C, - evsel::BBFDA, evsel::BBFDC, evsel::BGFDA, evsel::BGFDC, - evsel::MultRingV0A, evsel::MultRingV0C, evsel::SpdClusters, evsel::NTracklets, - evsel::Sel7, evsel::Sel8, evsel::FoundBCId, evsel::FoundFT0Id, evsel::FoundFV0Id, evsel::FoundFDDId, evsel::FoundZDCId); -using EvSel = EvSels::iterator; +// bc-joinable event selection decisions DECLARE_SOA_TABLE(BcSels, "AOD", "BCSEL", //! - evsel::Alias, evsel::Selection, - evsel::BBV0A, evsel::BBV0C, evsel::BGV0A, evsel::BGV0C, - evsel::BBFDA, evsel::BBFDC, evsel::BGFDA, evsel::BGFDC, - evsel::MultRingV0A, evsel::MultRingV0C, evsel::SpdClusters, evsel::FoundFT0Id, evsel::FoundFV0Id, evsel::FoundFDDId, evsel::FoundZDCId); + evsel::Alias, evsel::Selection, evsel::FoundFT0Id, evsel::FoundFV0Id, evsel::FoundFDDId, evsel::FoundZDCId); using BcSel = BcSels::iterator; + +// collision-joinable event selection decisions +DECLARE_SOA_TABLE(EvSels, "AOD", "EVSEL", //! + evsel::Alias, evsel::Selection, evsel::Sel7, evsel::Sel8, evsel::FoundBCId, evsel::FoundFT0Id, evsel::FoundFV0Id, evsel::FoundFDDId, evsel::FoundZDCId); +using EvSel = EvSels::iterator; } // namespace o2::aod #endif // COMMON_DATAMODEL_EVENTSELECTION_H_ diff --git a/Common/DataModel/EvtPlanes.h b/Common/DataModel/EvtPlanes.h new file mode 100644 index 00000000000..a6ebb3c1dae --- /dev/null +++ b/Common/DataModel/EvtPlanes.h @@ -0,0 +1,58 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file EvtPlanes.h +/// \author Cindy Mordasini +/// \author Anna Önnerstad +/// +/// \brief Declaration of the table for the (un)corrected Q-vectors for the event plane +/// determination. +/// + +#ifndef COMMON_DATAMODEL_EVTPLANES_H_ +#define COMMON_DATAMODEL_EVTPLANES_H_ + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace ep +{ +DECLARE_SOA_COLUMN(Cent, cent, float); //! Centrality percentile. +DECLARE_SOA_COLUMN(EvtPlUncor, evtPlUncor, float); +DECLARE_SOA_COLUMN(EvtPlRectr, evtPlRectr, float); +DECLARE_SOA_COLUMN(EvtPlTwist, evtPlTwist, float); +DECLARE_SOA_COLUMN(EvtPlFinal, evtPlFinal, float); + +DECLARE_SOA_COLUMN(EvtPlBPosUncor, evtPlBPosUncor, float); +DECLARE_SOA_COLUMN(EvtPlBPosRectr, evtPlBPosRectr, float); +DECLARE_SOA_COLUMN(EvtPlBPosTwist, evtPlBPosTwist, float); +DECLARE_SOA_COLUMN(EvtPlBPosFinal, evtPlBPosFinal, float); + +DECLARE_SOA_COLUMN(EvtPlBNegUncor, evtPlBNegUncor, float); +DECLARE_SOA_COLUMN(EvtPlBNegRectr, evtPlBNegRectr, float); +DECLARE_SOA_COLUMN(EvtPlBNegTwist, evtPlBNegTwist, float); +DECLARE_SOA_COLUMN(EvtPlBNegFinal, evtPlBNegFinal, float); + +DECLARE_SOA_COLUMN(NTrkBPos, nTrkBPos, int); +DECLARE_SOA_COLUMN(NTrkBNeg, nTrkBNeg, int); +} // namespace ep +DECLARE_SOA_TABLE(EvtPlanes, "AOD", "EVTPLANES", //! Table with all event planes. + ep::Cent, + ep::EvtPlUncor, ep::EvtPlRectr, ep::EvtPlTwist, ep::EvtPlFinal, + ep::EvtPlBPosUncor, ep::EvtPlBPosRectr, ep::EvtPlBPosTwist, ep::EvtPlBPosFinal, + ep::EvtPlBNegUncor, ep::EvtPlBNegRectr, ep::EvtPlBNegTwist, ep::EvtPlBNegFinal, + ep::NTrkBPos, ep::NTrkBNeg); +using EvtPlane = EvtPlanes::iterator; +} // namespace o2::aod + +#endif // COMMON_DATAMODEL_EVTPLANES_H_ diff --git a/PWGLF/DataModel/LFQATables.h b/Common/DataModel/McCollisionExtra.h similarity index 78% rename from PWGLF/DataModel/LFQATables.h rename to Common/DataModel/McCollisionExtra.h index fb1b490a98e..80eff3e9c55 100644 --- a/PWGLF/DataModel/LFQATables.h +++ b/Common/DataModel/McCollisionExtra.h @@ -11,8 +11,8 @@ // Helper tables to correlate collisions if needed -#ifndef PWGLF_DATAMODEL_LFQATABLES_H_ -#define PWGLF_DATAMODEL_LFQATABLES_H_ +#ifndef COMMON_DATAMODEL_MCCOLLISIONEXTRA_H_ +#define COMMON_DATAMODEL_MCCOLLISIONEXTRA_H_ #include #include "Framework/AnalysisDataModel.h" @@ -21,11 +21,11 @@ namespace o2::aod { namespace mccollisionprop { -DECLARE_SOA_COLUMN(HasRecoCollision, hasRecoCollision, int); //! stores N times this PV was recoed +DECLARE_SOA_COLUMN(NumRecoCollision, numRecoCollision, int); //! stores N times this PV was recoed DECLARE_SOA_COLUMN(BestCollisionIndex, bestCollisionIndex, int); //! stores N times this PV was recoed } // namespace mccollisionprop DECLARE_SOA_TABLE(McCollsExtra, "AOD", "MCCOLLSEXTRA", - mccollisionprop::HasRecoCollision, mccollisionprop::BestCollisionIndex); + mccollisionprop::NumRecoCollision, mccollisionprop::BestCollisionIndex); } // namespace o2::aod -#endif // PWGLF_DATAMODEL_LFQATABLES_H_ \ No newline at end of file +#endif // COMMON_DATAMODEL_MCCOLLISIONEXTRA_H_ \ No newline at end of file diff --git a/Common/DataModel/MftmchMatchingML.h b/Common/DataModel/MftmchMatchingML.h new file mode 100644 index 00000000000..f243411f3b7 --- /dev/null +++ b/Common/DataModel/MftmchMatchingML.h @@ -0,0 +1,55 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef COMMON_DATAMODEL_MFTMCHMATCHINGML_H_ +#define COMMON_DATAMODEL_MFTMCHMATCHINGML_H_ + +#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/TrackSelectionTables.h" + +namespace o2::aod +{ +DECLARE_SOA_TABLE(FwdTracksML, "AOD", "FWDTRACKML", + o2::soa::Index<>, + fwdtrack::CollisionId, + fwdtrack::TrackType, + fwdtrack::X, + fwdtrack::Y, + fwdtrack::Z, + fwdtrack::Phi, + fwdtrack::Tgl, + fwdtrack::Signed1Pt, + fwdtrack::NClusters, + fwdtrack::PDca, + fwdtrack::RAtAbsorberEnd, + fwdtrack::Px, + fwdtrack::Py, + fwdtrack::Pz, + fwdtrack::Sign, + fwdtrack::Chi2, + fwdtrack::Chi2MatchMCHMID, + fwdtrack::Chi2MatchMCHMFT, + fwdtrack::MatchScoreMCHMFT, + fwdtrack::MFTTrackId, + fwdtrack::MCHTrackId, + fwdtrack::MCHBitMap, + fwdtrack::MIDBitMap, + fwdtrack::MIDBoards, + fwdtrack::TrackTime, + fwdtrack::TrackTimeRes, + fwdtrack::Eta, + fwdtrack::Pt, + fwdtrack::P, + fwdtrack::FwdDcaX, + fwdtrack::FwdDcaY); +} // namespace o2::aod + +#endif // COMMON_DATAMODEL_MFTMCHMATCHINGML_H_ diff --git a/Common/DataModel/Multiplicity.h b/Common/DataModel/Multiplicity.h index 960af4176d7..a5f78c98044 100644 --- a/Common/DataModel/Multiplicity.h +++ b/Common/DataModel/Multiplicity.h @@ -36,23 +36,61 @@ DECLARE_SOA_COLUMN(MultTPC, multTPC, int); DECLARE_SOA_COLUMN(MultNTracksPV, multNTracksPV, int); DECLARE_SOA_COLUMN(MultNTracksPVeta1, multNTracksPVeta1, int); DECLARE_SOA_COLUMN(MultNTracksPVetaHalf, multNTracksPVetaHalf, int); +DECLARE_SOA_DYNAMIC_COLUMN(IsInelGt0, isInelGt0, //! is INEL > 0 + [](int multPveta1) -> bool { return multPveta1 > 0; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsInelGt1, isInelGt1, //! is INEL > 1 + [](int multPveta1) -> bool { return multPveta1 > 1; }); + +// complementary / MultsExtra table +DECLARE_SOA_COLUMN(MultPVTotalContributors, multPVTotalContributors, float); //! +DECLARE_SOA_COLUMN(MultPVChi2, multPVChi2, float); //! +DECLARE_SOA_COLUMN(MultCollisionTimeRes, multCollisionTimeRes, float); //! +DECLARE_SOA_COLUMN(MultRunNumber, multRunNumber, int); //! +DECLARE_SOA_COLUMN(MultPVz, multPVz, float); //! +DECLARE_SOA_COLUMN(MultSel8, multSel8, bool); //! + +DECLARE_SOA_COLUMN(MultNTracksHasITS, multNTracksHasITS, int); //! +DECLARE_SOA_COLUMN(MultNTracksHasTPC, multNTracksHasTPC, int); //! +DECLARE_SOA_COLUMN(MultNTracksHasTOF, multNTracksHasTOF, int); //! +DECLARE_SOA_COLUMN(MultNTracksHasTRD, multNTracksHasTRD, int); //! + +// further QA +DECLARE_SOA_COLUMN(MultNTracksITSOnly, multNTracksITSOnly, int); //! +DECLARE_SOA_COLUMN(MultNTracksTPCOnly, multNTracksTPCOnly, int); //! +DECLARE_SOA_COLUMN(MultNTracksITSTPC, multNTracksITSTPC, int); //! + +DECLARE_SOA_COLUMN(BCNumber, bcNumber, int); //! } // namespace mult -DECLARE_SOA_TABLE(Mults, "AOD", "MULT", //! +DECLARE_SOA_TABLE(FV0Mults, "AOD", "FV0MULT", //! Multiplicity with the FV0 detector mult::MultFV0A, mult::MultFV0C, + mult::MultFV0M); +DECLARE_SOA_TABLE(FT0Mults, "AOD", "FT0MULT", //! Multiplicity with the FT0 detector mult::MultFT0A, mult::MultFT0C, + mult::MultFT0M); +DECLARE_SOA_TABLE(FDDMults, "AOD", "FDDMULT", //! Multiplicity with the FDD detector mult::MultFDDA, mult::MultFDDC, - mult::MultZNA, mult::MultZNC, - mult::MultFV0M, - mult::MultFT0M, - mult::MultFDDM, + mult::MultFDDM); +DECLARE_SOA_TABLE(ZDCMults, "AOD", "ZDCMULT", //! Multiplicity with the ZDC detector + mult::MultZNA, mult::MultZNC); +DECLARE_SOA_TABLE(BarrelMults, "AOD", "BARRELMULT", //! Multiplicity in the barrel mult::MultTracklets, mult::MultTPC, mult::MultNTracksPV, mult::MultNTracksPVeta1, - mult::MultNTracksPVetaHalf); + mult::MultNTracksPVetaHalf, + mult::IsInelGt0, + mult::IsInelGt1); +using Mults = soa::Join; using Mult = Mults::iterator; +// for QA purposes +DECLARE_SOA_TABLE(MultsExtra, "AOD", "MULTEXTRA", //! + mult::MultPVTotalContributors, mult::MultPVChi2, mult::MultCollisionTimeRes, mult::MultRunNumber, mult::MultPVz, mult::MultSel8, + mult::MultNTracksHasITS, mult::MultNTracksHasTPC, mult::MultNTracksHasTOF, mult::MultNTracksHasTRD, + mult::MultNTracksITSOnly, mult::MultNTracksTPCOnly, mult::MultNTracksITSTPC, mult::BCNumber); +using MultExtra = MultsExtra::iterator; + namespace multZeq { DECLARE_SOA_COLUMN(MultZeqFV0A, multZeqFV0A, float); //! @@ -68,6 +106,29 @@ DECLARE_SOA_TABLE(MultZeqs, "AOD", "MULTZEQ", //! multZeq::MultZeqFDDA, multZeq::MultZeqFDDC, multZeq::MultZeqNTracksPV); using MultZeq = MultZeqs::iterator; + +namespace multBC +{ +DECLARE_SOA_COLUMN(MultBCFT0A, multBCFT0A, float); //! +DECLARE_SOA_COLUMN(MultBCFT0C, multBCFT0C, float); //! +DECLARE_SOA_COLUMN(MultBCFV0A, multBCFV0A, float); //! +DECLARE_SOA_COLUMN(MultBCTVX, multBCTVX, bool); //! +DECLARE_SOA_COLUMN(MultBCFV0OrA, multBCFV0OrA, bool); //! +DECLARE_SOA_COLUMN(MultBCV0triggerBits, multBCV0triggerBits, uint8_t); //! +DECLARE_SOA_COLUMN(MultBCTriggerMask, multBCTriggerMask, uint64_t); //! CTP trigger mask +DECLARE_SOA_COLUMN(MultBCColliding, multBCColliding, bool); //! CTP trigger mask +} // namespace multBC +DECLARE_SOA_TABLE(MultsBC, "AOD", "MULTBC", //! + multBC::MultBCFT0A, + multBC::MultBCFT0C, + multBC::MultBCFV0A, + multBC::MultBCTVX, + multBC::MultBCFV0OrA, + multBC::MultBCV0triggerBits, + multBC::MultBCTriggerMask, + multBC::MultBCColliding); +using MultBC = MultsBC::iterator; + } // namespace o2::aod #endif // O2_ANALYSIS_MULTIPLICITY_H_ diff --git a/Common/DataModel/Qvectors.h b/Common/DataModel/Qvectors.h new file mode 100644 index 00000000000..8c0b05a40c1 --- /dev/null +++ b/Common/DataModel/Qvectors.h @@ -0,0 +1,73 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file Qvectors.h +/// \author Cindy Mordasini +/// \author Anna Önnerstad +/// +/// \brief Declaration of the table for the (un)corrected Q-vectors for the event plane +/// determination. +/// + +#ifndef COMMON_DATAMODEL_QVECTORS_H_ +#define COMMON_DATAMODEL_QVECTORS_H_ + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace qvec +{ +DECLARE_SOA_COLUMN(Cent, cent, float); //! Centrality percentile. +DECLARE_SOA_COLUMN(CentBin, centBin, int); +DECLARE_SOA_COLUMN(QvecUncorRe, qvecUncorRe, float); +DECLARE_SOA_COLUMN(QvecUncorIm, qvecUncorIm, float); +DECLARE_SOA_COLUMN(QvecRectrRe, qvecRectrRe, float); +DECLARE_SOA_COLUMN(QvecRectrIm, qvecRectrIm, float); +DECLARE_SOA_COLUMN(QvecTwistRe, qvecTwistRe, float); +DECLARE_SOA_COLUMN(QvecTwistIm, qvecTwistIm, float); +DECLARE_SOA_COLUMN(QvecFinalRe, qvecFinalRe, float); +DECLARE_SOA_COLUMN(QvecFinalIm, qvecFinalIm, float); +DECLARE_SOA_COLUMN(QvecBPosUncorRe, qvecBPosUncorRe, float); +DECLARE_SOA_COLUMN(QvecBPosUncorIm, qvecBPosUncorIm, float); +DECLARE_SOA_COLUMN(QvecBPosRectrRe, qvecBPosRectrRe, float); +DECLARE_SOA_COLUMN(QvecBPosRectrIm, qvecBPosRectrIm, float); +DECLARE_SOA_COLUMN(QvecBPosTwistRe, qvecBPosTwistRe, float); +DECLARE_SOA_COLUMN(QvecBPosTwistIm, qvecBPosTwistIm, float); +DECLARE_SOA_COLUMN(QvecBPosFinalRe, qvecBPosFinalRe, float); +DECLARE_SOA_COLUMN(QvecBPosFinalIm, qvecBPosFinalIm, float); +DECLARE_SOA_COLUMN(QvecBNegUncorRe, qvecBNegUncorRe, float); +DECLARE_SOA_COLUMN(QvecBNegUncorIm, qvecBNegUncorIm, float); +DECLARE_SOA_COLUMN(QvecBNegRectrRe, qvecBNegRectrRe, float); +DECLARE_SOA_COLUMN(QvecBNegRectrIm, qvecBNegRectrIm, float); +DECLARE_SOA_COLUMN(QvecBNegTwistRe, qvecBNegTwistRe, float); +DECLARE_SOA_COLUMN(QvecBNegTwistIm, qvecBNegTwistIm, float); +DECLARE_SOA_COLUMN(QvecBNegFinalRe, qvecBNegFinalRe, float); +DECLARE_SOA_COLUMN(QvecBNegFinalIm, qvecBNegFinalIm, float); +DECLARE_SOA_COLUMN(NTrkBPos, nTrkBPos, int); +DECLARE_SOA_COLUMN(NTrkBNeg, nTrkBNeg, int); +/// NOTE: Add here Qx,Qy for other systems. +} // namespace qvec + +DECLARE_SOA_TABLE(Qvectors, "AOD", "QVECTORS", //! Table with all Qvectors. + qvec::Cent, qvec::CentBin, + qvec::QvecUncorRe, qvec::QvecUncorIm, qvec::QvecRectrRe, qvec::QvecRectrIm, + qvec::QvecTwistRe, qvec::QvecTwistIm, qvec::QvecFinalRe, qvec::QvecFinalIm, + qvec::QvecBPosUncorRe, qvec::QvecBPosUncorIm, qvec::QvecBPosRectrRe, qvec::QvecBPosRectrIm, + qvec::QvecBPosTwistRe, qvec::QvecBPosTwistIm, qvec::QvecBPosFinalRe, qvec::QvecBPosFinalIm, + qvec::QvecBNegUncorRe, qvec::QvecBNegUncorIm, qvec::QvecBNegRectrRe, qvec::QvecBNegRectrIm, + qvec::QvecBNegTwistRe, qvec::QvecBNegTwistIm, qvec::QvecBNegFinalRe, qvec::QvecBNegFinalIm, + qvec::NTrkBPos, qvec::NTrkBNeg); +using Qvector = Qvectors::iterator; +} // namespace o2::aod + +#endif // COMMON_DATAMODEL_QVECTORS_H_ diff --git a/Common/DataModel/TrackSelectionTables.h b/Common/DataModel/TrackSelectionTables.h index 8515cc6f688..cc27e06bfe7 100644 --- a/Common/DataModel/TrackSelectionTables.h +++ b/Common/DataModel/TrackSelectionTables.h @@ -50,8 +50,9 @@ struct TrackSelectionFlags { static constexpr flagtype kDCAxy = 1 << 13; static constexpr flagtype kDCAz = 1 << 14; // Combo masks - static constexpr flagtype kQualityTracks = kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits; static constexpr flagtype kQualityTracksITS = kTrackType | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits; + static constexpr flagtype kQualityTracksTPC = kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit; + static constexpr flagtype kQualityTracks = kTrackType | kQualityTracksITS | kQualityTracksTPC; static constexpr flagtype kQualityTracksWoTPCCluster = kQualityTracksITS | kTPCChi2NDF | kTPCRefit; static constexpr flagtype kPrimaryTracks = kGoldenChi2 | kDCAxy | kDCAz; static constexpr flagtype kInAcceptanceTracks = kPtRange | kEtaRange; @@ -72,7 +73,7 @@ struct TrackSelectionFlags { } }; -#define requireTrackCutInFilter(mask) ((aod::track::trackCutFlag & aod::track::mask) == aod::track::mask) +#define requireTrackCutInFilter(mask) ((o2::aod::track::trackCutFlag & o2::aod::track::mask) == o2::aod::track::mask) #define requireQualityTracksInFilter() requireTrackCutInFilter(TrackSelectionFlags::kQualityTracks) #define requireQualityTracksITSInFilter() requireTrackCutInFilter(TrackSelectionFlags::kQualityTracksITS) #define requirePrimaryTracksInFilter() requireTrackCutInFilter(TrackSelectionFlags::kPrimaryTracks) @@ -82,7 +83,7 @@ struct TrackSelectionFlags { #define requireGlobalTrackWoPtEtaInFilter() requireTrackCutInFilter(TrackSelectionFlags::kGlobalTrackWoPtEta) #define requireGlobalTrackWoDCAInFilter() requireTrackCutInFilter(TrackSelectionFlags::kGlobalTrackWoDCA) #define requireGlobalTrackWoDCATPCClusterInFilter() requireTrackCutInFilter(TrackSelectionFlags::kGlobalTrackWoDCATPCCluster) -#define requireTrackWithinBeamPipe (nabs(aod::track::x) < o2::constants::geom::XBeamPipeOuterRef) +#define requireTrackWithinBeamPipe (nabs(o2::aod::track::x) < o2::constants::geom::XBeamPipeOuterRef) // Columns to store track filter decisions DECLARE_SOA_COLUMN(IsGlobalTrackSDD, isGlobalTrackSDD, uint8_t); //! @@ -103,6 +104,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(CheckFlag, checkFlag, // Combo selections DECLARE_DYN_TRKSEL_COLUMN(IsQualityTrack, isQualityTrack, TrackSelectionFlags::kQualityTracks); //! Passed the combined track cut: kQualityTracks DECLARE_DYN_TRKSEL_COLUMN(IsQualityTrackITS, isQualityTrackITS, TrackSelectionFlags::kQualityTracksITS); //! Passed the combined track cut: kQualityTracksITS +DECLARE_DYN_TRKSEL_COLUMN(IsQualityTrackTPC, isQualityTrackTPC, TrackSelectionFlags::kQualityTracksTPC); //! Passed the combined track cut: kQualityTracksTPC DECLARE_DYN_TRKSEL_COLUMN(IsPrimaryTrack, isPrimaryTrack, TrackSelectionFlags::kPrimaryTracks); //! Passed the combined track cut: kPrimaryTracks DECLARE_DYN_TRKSEL_COLUMN(IsInAcceptanceTrack, isInAcceptanceTrack, TrackSelectionFlags::kInAcceptanceTracks); //! Passed the combined track cut: kInAcceptanceTracks DECLARE_DYN_TRKSEL_COLUMN(IsGlobalTrack, isGlobalTrack, TrackSelectionFlags::kGlobalTrack); //! Passed the combined track cut: kGlobalTrack @@ -155,6 +157,7 @@ DECLARE_SOA_TABLE(TrackSelection, "AOD", "TRACKSELECTION", //! Information on th track::TrackCutFlagFb5, track::IsQualityTrack, track::IsQualityTrackITS, + track::IsQualityTrackTPC, track::IsPrimaryTrack, track::IsInAcceptanceTrack, track::IsGlobalTrack, diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index de833e7bab2..31f8329609f 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -31,6 +31,11 @@ o2physics_add_dpl_workflow(multiplicity-table PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(multiplicity-extra-table + SOURCES multiplicityExtraTable.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(centrality-table SOURCES centralityTable.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -66,6 +71,11 @@ o2physics_add_dpl_workflow(mc-converter PUBLIC_LINK_LIBRARIES COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(tracks-extra-converter + SOURCES tracksExtraConverter.cxx + PUBLIC_LINK_LIBRARIES + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(fdd-converter SOURCES fddConverter.cxx PUBLIC_LINK_LIBRARIES @@ -76,6 +86,11 @@ o2physics_add_dpl_workflow(collision-converter PUBLIC_LINK_LIBRARIES COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(bc-converter + SOURCES bcConverter.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(calo-clusters SOURCES caloClusterProducer.cxx PUBLIC_LINK_LIBRARIES O2::DataFormatsPHOS O2::PHOSBase O2::PHOSReconstruction O2Physics::DataModel @@ -104,7 +119,44 @@ o2physics_add_dpl_workflow(zdc-converter PUBLIC_LINK_LIBRARIES COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(hmpid-converter + SOURCES hmpConverter.cxx + PUBLIC_LINK_LIBRARIES + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(fwdtrack-to-collision-associator SOURCES fwdtrackToCollisionAssociator.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(mccollisionextra + SOURCES mcCollsExtra.cxx + PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(qvector-table + SOURCES qVectorsTable.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2Physics::AnalysisCore + O2::DetectorsCommonDataFormats + O2Physics::DataModel + O2::CCDB + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(evtplane-table + SOURCES evtPlanesTable.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2Physics::AnalysisCore + O2::DetectorsCommonDataFormats + O2Physics::DataModel + O2::CCDB + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(mftmchmatchingml + SOURCES mftmchMatchingML.cxx + PUBLIC_LINK_LIBRARIES O2::Framework + O2Physics::AnalysisCore + ONNXRuntime::ONNXRuntime + O2::CCDB O2Physics::MLCore + O2::ReconstructionDataFormats + COMPONENT_NAME Analysis) diff --git a/Common/TableProducer/PID/CMakeLists.txt b/Common/TableProducer/PID/CMakeLists.txt index 16c41e6e209..29491b7c8cd 100644 --- a/Common/TableProducer/PID/CMakeLists.txt +++ b/Common/TableProducer/PID/CMakeLists.txt @@ -50,11 +50,6 @@ o2physics_add_dpl_workflow(pid-tpc-full # HMPID -o2physics_add_dpl_workflow(pid-hmpid-qa - SOURCES qaHMPID.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - # BAYES o2physics_add_dpl_workflow(pid-bayes diff --git a/Common/TableProducer/PID/pidTOFBase.h b/Common/TableProducer/PID/pidTOFBase.h index d85b22d240f..d8556f95432 100644 --- a/Common/TableProducer/PID/pidTOFBase.h +++ b/Common/TableProducer/PID/pidTOFBase.h @@ -26,11 +26,6 @@ #include "PID/PIDTOF.h" #include "Common/DataModel/PIDResponse.h" -using namespace o2; -using namespace o2::track; -using namespace o2::framework; -using namespace o2::framework::expressions; - static constexpr int nSpecies = 9; static constexpr int nParameters = 1; static const std::vector particleNames{"El", "Mu", "Pi", "Ka", "Pr", "De", "Tr", "He", "Al"}; diff --git a/Common/TableProducer/PID/pidTPC.cxx b/Common/TableProducer/PID/pidTPC.cxx index 489b2aa49fd..9c93b38a989 100644 --- a/Common/TableProducer/PID/pidTPC.cxx +++ b/Common/TableProducer/PID/pidTPC.cxx @@ -69,8 +69,7 @@ struct tpcPid { Produces tablePIDAl; // TPC PID Response - o2::pid::tpc::Response response; - o2::pid::tpc::Response* responseptr = nullptr; + o2::pid::tpc::Response* response; // Network correction for TPC PID response OnnxModel network; @@ -83,10 +82,12 @@ struct tpcPid { Configurable paramfile{"param-file", "", "Path to the parametrization object, if empty the parametrization is not taken from file"}; Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPath{"ccdbPath", "Analysis/PID/TPC/Response", "Path of the TPC parametrization on the CCDB"}; + Configurable recoPass{"recoPass", "", "Reconstruction pass name for CCDB query (automatically takes latest object for timestamp if blank)"}; Configurable ccdbTimestamp{"ccdb-timestamp", 0, "timestamp of the object used to query in CCDB the detector response. Exceptions: -1 gets the latest object, 0 gets the run dependent timestamp"}; // Parameters for loading network from a file / downloading the file Configurable useNetworkCorrection{"useNetworkCorrection", 0, "(bool) Wether or not to use the network correction for the TPC dE/dx signal"}; Configurable autofetchNetworks{"autofetchNetworks", 1, "(bool) Automatically fetches networks from CCDB for the correct run number"}; + Configurable skipTPCOnly{"skipTPCOnly", false, "Flag to skip TPC only tracks (faster but affects the analyses that use TPC only tracks)"}; Configurable networkPathLocally{"networkPathLocally", "network.onnx", "(std::string) Path to the local .onnx file. If autofetching is enabled, then this is where the files will be downloaded"}; Configurable enableNetworkOptimizations{"enableNetworkOptimizations", 1, "(bool) If the neural network correction is used, this enables GraphOptimizationLevel::ORT_ENABLE_EXTENDED in the ONNX session"}; Configurable networkPathCCDB{"networkPathCCDB", "Analysis/PID/TPC/ML", "Path on CCDB"}; @@ -107,6 +108,7 @@ struct tpcPid { void init(o2::framework::InitContext& initContext) { + response = new o2::pid::tpc::Response(); // Checking the tables are requested in the workflow and enabling them auto enableFlag = [&](const std::string particle, Configurable& flag) { enableFlagIfTableRequired(initContext, "pidTPC" + particle, flag); @@ -121,34 +123,47 @@ struct tpcPid { enableFlag("He", pidHe); enableFlag("Al", pidAl); + // Initialise metadata object for CCDB calls + if (recoPass.value == "") { + LOGP(info, "Reco pass not specified; CCDB will take latest available object"); + } else { + LOGP(info, "CCDB object will be requested for reconstruction pass {}", recoPass.value); + metadata["RecoPassName"] = recoPass.value; + } + /// TPC PID Response const TString fname = paramfile.value; if (fname != "") { // Loading the parametrization from file LOGP(info, "Loading TPC response from file {}", fname); try { std::unique_ptr f(TFile::Open(fname, "READ")); - f->GetObject("Response", responseptr); - response.SetParameters(responseptr); + f->GetObject("Response", response); } catch (...) { LOGF(fatal, "Loading the TPC PID Response from file {} failed!", fname); } + response->PrintAll(); } else { useCCDBParam = true; const std::string path = ccdbPath.value; const auto time = ccdbTimestamp.value; ccdb->setURL(url.value); - + ccdb->setFatalWhenNull(false); // manual fallback in case ccdb entry empty ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); if (time != 0) { - LOGP(info, "Initialising TPC PID response for fixed timestamp {}:", time); + LOGP(info, "Initialising TPC PID response for fixed timestamp {} and reco pass {}:", time, recoPass.value); ccdb->setTimestamp(time); - response.SetParameters(ccdb->getForTimeStamp(path, time)); - } else { - LOGP(info, "Initialising default TPC PID response:"); + response = ccdb->getSpecific(path, time, metadata); + if (!response) { + LOGF(warning, "Unable to find TPC parametrisation for specified pass name - falling back to latest object"); + response = ccdb->getForTimeStamp(path, time); + if (!response) { + LOGF(fatal, "Unable to find any TPC object corresponding to timestamp {}!", time); + } + } + response->PrintAll(); } - response.PrintAll(); } /// Neural network init for TPC PID @@ -187,17 +202,19 @@ struct tpcPid { } } + Partition notTPCStandaloneTracks = ((aod::track::itsClusterMap > (uint8_t)0) || (aod::track::trdPattern > (uint8_t)0) || (aod::track::tofExpMom > 0.f && aod::track::tofChi2 > 0.f)); // To count number of tracks for use in NN array + Partition tracksWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0); + void process(Coll const& collisions, Trks const& tracks, aod::BCsWithTimestamps const&) { - const uint64_t tracks_size = tracks.size(); - - auto reserveTable = [&tracks_size](const Configurable& flag, auto& table) { + const uint64_t outTable_size = tracks.size(); + auto reserveTable = [&outTable_size](const Configurable& flag, auto& table) { if (flag.value != 1) { return; } - table.reserve(tracks_size); + table.reserve(outTable_size); }; // Prepare memory for enabled tables reserveTable(pidEl, tablePIDEl); @@ -211,12 +228,30 @@ struct tpcPid { reserveTable(pidAl, tablePIDAl); std::vector network_prediction; - const float nNclNormalization = response.GetNClNormalization(); + const uint64_t tracksForNet_size = (skipTPCOnly) ? notTPCStandaloneTracks.size() : tracksWithTPC.size(); if (useNetworkCorrection) { auto start_network_total = std::chrono::high_resolution_clock::now(); if (autofetchNetworks) { auto bc = collisions.iteratorAt(0).bc_as(); + // Initialise correct TPC response object before NN setup (for NCl normalisation) + if (useCCDBParam && ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0 + if (recoPass.value == "") { + LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp()); + } else { + LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); + } + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); + if (!response) { + LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", recoPass.value); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + if (!response) { + LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); + } + } + response->PrintAll(); + } + if (bc.timestamp() < network.getValidityFrom() || bc.timestamp() > network.getValidityUntil()) { // fetches network only if the runnumbers change LOG(info) << "Fetching network for timestamp: " << bc.timestamp(); bool retrieveSuccess = ccdbApi.retrieveBlob(networkPathCCDB.value, ".", metadata, bc.timestamp(), false, networkPathLocally.value); @@ -235,11 +270,11 @@ struct tpcPid { // Defining some network parameters int input_dimensions = network.getNumInputNodes(); int output_dimensions = network.getNumOutputNodes(); - const uint64_t track_prop_size = input_dimensions * tracks_size; - const uint64_t prediction_size = output_dimensions * tracks_size; + const uint64_t track_prop_size = input_dimensions * tracksForNet_size; + const uint64_t prediction_size = output_dimensions * tracksForNet_size; network_prediction = std::vector(prediction_size * 9); // For each mass hypotheses - + const float nNclNormalization = response->GetNClNormalization(); float duration_network = 0; std::vector track_properties(track_prop_size); @@ -250,6 +285,14 @@ struct tpcPid { // Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector for (int i = 0; i < 9; i++) { // Loop over particle number for which network correction is used for (auto const& trk : tracks) { + if (!trk.hasTPC()) { + continue; + } + if (skipTPCOnly) { + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { + continue; + } + } track_properties[counter_track_props] = trk.tpcInnerParam(); track_properties[counter_track_props + 1] = trk.tgl(); track_properties[counter_track_props + 2] = trk.signed1Pt(); @@ -275,45 +318,74 @@ struct tpcPid { track_properties.clear(); auto stop_network_total = std::chrono::high_resolution_clock::now(); - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << duration_network / (tracks_size * 9) << "ns ; Total time (eval ONNX): " << duration_network / 1000000000 << " s"; - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / (tracks_size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << duration_network / (tracksForNet_size * 9) << "ns ; Total time (eval ONNX): " << duration_network / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / (tracksForNet_size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / 1000000000 << " s"; } - int lastCollisionId = -1; // Last collision ID analysed uint64_t count_tracks = 0; for (auto const& trk : tracks) { // Loop on Tracks - if (useCCDBParam && ccdbTimestamp.value == 0 && trk.has_collision() && trk.collisionId() != lastCollisionId) { // Updating parametrization only if the initial timestamp is 0 - lastCollisionId = trk.collisionId(); + if (trk.has_collision()) { const auto& bc = collisions.iteratorAt(trk.collisionId()).bc_as(); - response.SetParameters(ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp())); + if (useCCDBParam && ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0 + if (recoPass.value == "") { + LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp()); + } else { + LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); + } + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); + if (!response) { + LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", recoPass.value); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + if (!response) { + LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); + } + } + response->PrintAll(); + } } // Check and fill enabled tables - auto makeTable = [&trk, &collisions, &network_prediction, &count_tracks, &tracks_size, this](const Configurable& flag, auto& table, const o2::track::PID::ID pid) { + auto makeTable = [&trk, &collisions, &network_prediction, &count_tracks, &tracksForNet_size, this](const Configurable& flag, auto& table, const o2::track::PID::ID pid) { if (flag.value != 1) { return; } + if (!trk.hasTPC()) { + table(aod::pidtpc_tiny::binning::underflowBin); + return; + } + if (skipTPCOnly) { + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { + table(aod::pidtpc_tiny::binning::underflowBin); + return; + } + } + auto expSignal = response->GetExpectedSignal(trk, pid); + auto expSigma = response->GetExpectedSigma(collisions.iteratorAt(trk.collisionId()), trk, pid); + if (expSignal < 0. || expSigma < 0.) { // skip if expected signal invalid + table(aod::pidtpc_tiny::binning::underflowBin); + return; + } if (useNetworkCorrection) { // Here comes the application of the network. The output--dimensions of the network dtermine the application: 1: mean, 2: sigma, 3: sigma asymmetric // For now only the option 2: sigma will be used. The other options are kept if there would be demand later on if (network.getNumOutputNodes() == 1) { - aod::pidutils::packInTable((trk.tpcSignal() - network_prediction[count_tracks + tracks_size * pid] * response.GetExpectedSignal(trk, pid)) / response.GetExpectedSigma(collisions.iteratorAt(trk.collisionId()), trk, pid), table); + aod::pidutils::packInTable((trk.tpcSignal() - network_prediction[count_tracks + tracksForNet_size * pid] * expSignal) / expSigma, table); } else if (network.getNumOutputNodes() == 2) { - aod::pidutils::packInTable((trk.tpcSignal() / response.GetExpectedSignal(trk, pid) - network_prediction[2 * (count_tracks + tracks_size * pid)]) / (network_prediction[2 * (count_tracks + tracks_size * pid) + 1] - network_prediction[2 * (count_tracks + tracks_size * pid)]), table); + aod::pidutils::packInTable((trk.tpcSignal() / expSignal - network_prediction[2 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[2 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[2 * (count_tracks + tracksForNet_size * pid)]), table); } else if (network.getNumOutputNodes() == 3) { - if (trk.tpcSignal() / response.GetExpectedSignal(trk, pid) >= network_prediction[3 * (count_tracks + tracks_size * pid)]) { - aod::pidutils::packInTable((trk.tpcSignal() / response.GetExpectedSignal(trk, pid) - network_prediction[3 * (count_tracks + tracks_size * pid)]) / (network_prediction[3 * (count_tracks + tracks_size * pid) + 1] - network_prediction[3 * (count_tracks + tracks_size * pid)]), table); + if (trk.tpcSignal() / expSignal >= network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) { + aod::pidutils::packInTable((trk.tpcSignal() / expSignal - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]), table); } else { - aod::pidutils::packInTable((trk.tpcSignal() / response.GetExpectedSignal(trk, pid) - network_prediction[3 * (count_tracks + tracks_size * pid)]) / (network_prediction[3 * (count_tracks + tracks_size * pid)] - network_prediction[3 * (count_tracks + tracks_size * pid) + 2]), table); + aod::pidutils::packInTable((trk.tpcSignal() / expSignal - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[3 * (count_tracks + tracksForNet_size * pid)] - network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 2]), table); } } else { LOGF(fatal, "Network output-dimensions incompatible!"); } } else { - aod::pidutils::packInTable(response.GetNumberOfSigma(collisions.iteratorAt(trk.collisionId()), trk, pid), table); + aod::pidutils::packInTable(response->GetNumberOfSigma(collisions.iteratorAt(trk.collisionId()), trk, pid), table); } }; @@ -327,7 +399,9 @@ struct tpcPid { makeTable(pidHe, tablePIDHe, o2::track::PID::Helium3); makeTable(pidAl, tablePIDAl, o2::track::PID::Alpha); - count_tracks++; + if (trk.hasTPC() && (!skipTPCOnly || trk.hasITS() || trk.hasTRD() || trk.hasTOF())) { + count_tracks++; // Increment network track counter only if (not skipping TPConly) or (is not TPConly) + } } } }; diff --git a/Common/TableProducer/PID/pidTPCBase.h b/Common/TableProducer/PID/pidTPCBase.h index 1255d9d6344..6d22dabb63d 100644 --- a/Common/TableProducer/PID/pidTPCBase.h +++ b/Common/TableProducer/PID/pidTPCBase.h @@ -21,11 +21,6 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -using namespace o2; -using namespace o2::track; -using namespace o2::framework; -using namespace o2::framework::expressions; - namespace o2::aod { diff --git a/Common/TableProducer/PID/pidTPCFull.cxx b/Common/TableProducer/PID/pidTPCFull.cxx index 699a1c8776d..91181a30dd2 100644 --- a/Common/TableProducer/PID/pidTPCFull.cxx +++ b/Common/TableProducer/PID/pidTPCFull.cxx @@ -69,8 +69,7 @@ struct tpcPidFull { Produces tablePIDAl; // TPC PID Response - o2::pid::tpc::Response response; - o2::pid::tpc::Response* responseptr = nullptr; + o2::pid::tpc::Response* response; // Network correction for TPC PID response OnnxModel network; @@ -83,10 +82,12 @@ struct tpcPidFull { Configurable paramfile{"param-file", "", "Path to the parametrization object, if empty the parametrization is not taken from file"}; Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPath{"ccdbPath", "Analysis/PID/TPC/Response", "Path of the TPC parametrization on the CCDB"}; + Configurable recoPass{"recoPass", "", "Reconstruction pass name for CCDB query (automatically takes latest object for timestamp if blank)"}; Configurable ccdbTimestamp{"ccdb-timestamp", 0, "timestamp of the object used to query in CCDB the detector response. Exceptions: -1 gets the latest object, 0 gets the run dependent timestamp"}; // Parameters for loading network from a file / downloading the file Configurable useNetworkCorrection{"useNetworkCorrection", 0, "(bool) Wether or not to use the network correction for the TPC dE/dx signal"}; Configurable autofetchNetworks{"autofetchNetworks", 1, "(bool) Automatically fetches networks from CCDB for the correct run number"}; + Configurable skipTPCOnly{"skipTPCOnly", false, "Flag to skip TPC only tracks (faster but affects the analyses that use TPC only tracks)"}; Configurable networkPathLocally{"networkPathLocally", "network.onnx", "(std::string) Path to the local .onnx file. If autofetching is enabled, then this is where the files will be downloaded"}; Configurable networkPathCCDB{"networkPathCCDB", "Analysis/PID/TPC/ML", "Path on CCDB"}; Configurable enableNetworkOptimizations{"enableNetworkOptimizations", 1, "(bool) If the neural network correction is used, this enables GraphOptimizationLevel::ORT_ENABLE_EXTENDED in the ONNX session"}; @@ -107,6 +108,7 @@ struct tpcPidFull { void init(o2::framework::InitContext& initContext) { + response = new o2::pid::tpc::Response(); // Checking the tables are requested in the workflow and enabling them auto enableFlag = [&](const std::string particle, Configurable& flag) { enableFlagIfTableRequired(initContext, "pidTPCFull" + particle, flag); @@ -121,34 +123,47 @@ struct tpcPidFull { enableFlag("He", pidHe); enableFlag("Al", pidAl); + // Initialise metadata object for CCDB calls + if (recoPass.value == "") { + LOGP(info, "Reco pass not specified; CCDB will take latest available object"); + } else { + LOGP(info, "CCDB object will be requested for reconstruction pass {}", recoPass.value); + metadata["RecoPassName"] = recoPass.value; + } + /// TPC PID Response const TString fname = paramfile.value; if (fname != "") { // Loading the parametrization from file LOGP(info, "Loading TPC response from file {}", fname); try { std::unique_ptr f(TFile::Open(fname, "READ")); - f->GetObject("Response", responseptr); - response.SetParameters(responseptr); + f->GetObject("Response", response); } catch (...) { LOGF(fatal, "Loading the TPC PID Response from file {} failed!", fname); } + response->PrintAll(); } else { useCCDBParam = true; const std::string path = ccdbPath.value; const auto time = ccdbTimestamp.value; ccdb->setURL(url.value); - + ccdb->setFatalWhenNull(false); // manual fallback in case ccdb entry empty ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); if (time != 0) { - LOGP(info, "Initialising TPC PID response for fixed timestamp {}:", time); + LOGP(info, "Initialising TPC PID response for fixed timestamp {} and reco pass {}:", time, recoPass.value); ccdb->setTimestamp(time); - response.SetParameters(ccdb->getForTimeStamp(path, time)); - } else { - LOGP(info, "Initialising default TPC PID response:"); + response = ccdb->getSpecific(path, time, metadata); + if (!response) { + LOGF(warning, "Unable to find TPC parametrisation for specified pass name - falling back to latest object"); + response = ccdb->getForTimeStamp(path, time); + if (!response) { + LOGF(fatal, "Unable to find any TPC object corresponding to timestamp {}!", time); + } + } + response->PrintAll(); } - response.PrintAll(); } /// Neural network init for TPC PID @@ -156,6 +171,7 @@ struct tpcPidFull { if (!useNetworkCorrection) { return; } else { + /// CCDB and auto-fetching ccdbApi.init(url); if (!autofetchNetworks) { @@ -187,17 +203,19 @@ struct tpcPidFull { } } + Partition notTPCStandaloneTracks = (aod::track::tpcNClsFindable > (uint8_t)0) && ((aod::track::itsClusterMap > (uint8_t)0) || (aod::track::trdPattern > (uint8_t)0) || (aod::track::tofExpMom > 0.f && aod::track::tofChi2 > 0.f)); // To count number of tracks for use in NN array + Partition tracksWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0); + void process(Coll const& collisions, Trks const& tracks, aod::BCsWithTimestamps const&) { - const uint64_t tracks_size = tracks.size(); - - auto reserveTable = [&tracks_size](const Configurable& flag, auto& table) { + const uint64_t outTable_size = tracks.size(); + auto reserveTable = [&outTable_size](const Configurable& flag, auto& table) { if (flag.value != 1) { return; } - table.reserve(tracks_size); + table.reserve(outTable_size); }; // Prepare memory for enabled tables reserveTable(pidEl, tablePIDEl); @@ -211,11 +229,31 @@ struct tpcPidFull { reserveTable(pidAl, tablePIDAl); std::vector network_prediction; + const uint64_t tracksForNet_size = (skipTPCOnly) ? notTPCStandaloneTracks.size() : tracksWithTPC.size(); if (useNetworkCorrection) { + auto start_network_total = std::chrono::high_resolution_clock::now(); if (autofetchNetworks) { auto bc = collisions.iteratorAt(0).bc_as(); + // Initialise correct TPC response object before NN setup (for NCl normalisation) + if (useCCDBParam && ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0 + if (recoPass.value == "") { + LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp()); + } else { + LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); + } + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); + if (!response) { + LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", recoPass.value); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + if (!response) { + LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); + } + } + response->PrintAll(); + } + if (bc.timestamp() < network.getValidityFrom() || bc.timestamp() > network.getValidityUntil()) { // fetches network only if the runnumbers change LOG(info) << "Fetching network for timestamp: " << bc.timestamp(); bool retrieveSuccess = ccdbApi.retrieveBlob(networkPathCCDB.value, ".", metadata, bc.timestamp(), false, networkPathLocally.value); @@ -233,11 +271,11 @@ struct tpcPidFull { // Defining some network parameters int input_dimensions = network.getNumInputNodes(); int output_dimensions = network.getNumOutputNodes(); - const uint64_t track_prop_size = input_dimensions * tracks_size; - const uint64_t prediction_size = output_dimensions * tracks_size; + const uint64_t track_prop_size = input_dimensions * tracksForNet_size; + const uint64_t prediction_size = output_dimensions * tracksForNet_size; network_prediction = std::vector(prediction_size * 9); // For each mass hypotheses - const float nNclNormalization = response.GetNClNormalization(); + const float nNclNormalization = response->GetNClNormalization(); float duration_network = 0; std::vector track_properties(track_prop_size); @@ -248,6 +286,14 @@ struct tpcPidFull { // Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector for (int i = 0; i < 9; i++) { // Loop over particle number for which network correction is used for (auto const& trk : tracks) { + if (!trk.hasTPC()) { + continue; + } + if (skipTPCOnly) { + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { + continue; + } + } track_properties[counter_track_props] = trk.tpcInnerParam(); track_properties[counter_track_props + 1] = trk.tgl(); track_properties[counter_track_props + 2] = trk.signed1Pt(); @@ -273,50 +319,79 @@ struct tpcPidFull { track_properties.clear(); auto stop_network_total = std::chrono::high_resolution_clock::now(); - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << duration_network / (tracks_size * 9) << "ns ; Total time (eval ONNX): " << duration_network / 1000000000 << " s"; - LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / (tracks_size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << duration_network / (tracksForNet_size * 9) << "ns ; Total time (eval ONNX): " << duration_network / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / (tracksForNet_size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / 1000000000 << " s"; } - int lastCollisionId = -1; // Last collision ID analysed uint64_t count_tracks = 0; for (auto const& trk : tracks) { // Loop on Tracks - if (useCCDBParam && ccdbTimestamp.value == 0 && trk.has_collision() && trk.collisionId() != lastCollisionId) { // Updating parametrization only if the initial timestamp is 0 - lastCollisionId = trk.collisionId(); + if (trk.has_collision()) { const auto& bc = collisions.iteratorAt(trk.collisionId()).bc_as(); - response.SetParameters(ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp())); + if (useCCDBParam && ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0 + if (recoPass.value == "") { + LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp()); + } else { + LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value); + } + response = ccdb->getSpecific(ccdbPath.value, bc.timestamp(), metadata); + if (!response) { + LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", recoPass.value); + response = ccdb->getForTimeStamp(ccdbPath.value, bc.timestamp()); + if (!response) { + LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); + } + } + response->PrintAll(); + } } // Check and fill enabled tables - auto makeTable = [&trk, &collisions, &network_prediction, &count_tracks, &tracks_size, this](const Configurable& flag, auto& table, const o2::track::PID::ID pid) { + auto makeTable = [&trk, &collisions, &network_prediction, &count_tracks, &tracksForNet_size, this](const Configurable& flag, auto& table, const o2::track::PID::ID pid) { if (flag.value != 1) { return; } + if (!trk.hasTPC()) { + table(-999.f, -999.f); + return; + } + if (skipTPCOnly) { + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { + table(-999.f, -999.f); + return; + } + } + auto expSignal = response->GetExpectedSignal(trk, pid); + auto expSigma = response->GetExpectedSigma(collisions.iteratorAt(trk.collisionId()), trk, pid); + if (expSignal < 0. || expSigma < 0.) { // skip if expected signal invalid + table(-999.f, -999.f); + return; + } if (useNetworkCorrection) { // Here comes the application of the network. The output--dimensions of the network dtermine the application: 1: mean, 2: sigma, 3: sigma asymmetric // For now only the option 2: sigma will be used. The other options are kept if there would be demand later on if (network.getNumOutputNodes() == 1) { - table(response.GetExpectedSigma(collisions.iteratorAt(trk.collisionId()), trk, pid), - (trk.tpcSignal() - network_prediction[count_tracks + tracks_size * pid] * response.GetExpectedSignal(trk, pid)) / response.GetExpectedSigma(collisions.iteratorAt(trk.collisionId()), trk, pid)); + table(expSigma, + (trk.tpcSignal() - network_prediction[count_tracks + tracksForNet_size * pid] * expSignal) / expSigma); } else if (network.getNumOutputNodes() == 2) { - table((network_prediction[2 * (count_tracks + tracks_size * pid) + 1] - network_prediction[2 * (count_tracks + tracks_size * pid)]) * response.GetExpectedSignal(trk, pid), - (trk.tpcSignal() / response.GetExpectedSignal(trk, pid) - network_prediction[2 * (count_tracks + tracks_size * pid)]) / (network_prediction[2 * (count_tracks + tracks_size * pid) + 1] - network_prediction[2 * (count_tracks + tracks_size * pid)])); + table((network_prediction[2 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[2 * (count_tracks + tracksForNet_size * pid)]) * expSignal, + (trk.tpcSignal() / expSignal - network_prediction[2 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[2 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[2 * (count_tracks + tracksForNet_size * pid)])); } else if (network.getNumOutputNodes() == 3) { - if (trk.tpcSignal() / response.GetExpectedSignal(trk, pid) >= network_prediction[3 * (count_tracks + tracks_size * pid)]) { - table((network_prediction[3 * (count_tracks + tracks_size * pid) + 1] - network_prediction[3 * (count_tracks + tracks_size * pid)]) * response.GetExpectedSignal(trk, pid), - (trk.tpcSignal() / response.GetExpectedSignal(trk, pid) - network_prediction[3 * (count_tracks + tracks_size * pid)]) / (network_prediction[3 * (count_tracks + tracks_size * pid) + 1] - network_prediction[3 * (count_tracks + tracks_size * pid)])); + if (trk.tpcSignal() / expSignal >= network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) { + table((network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) * expSignal, + (trk.tpcSignal() / expSignal - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[3 * (count_tracks + tracksForNet_size * pid)])); } else { - table((network_prediction[3 * (count_tracks + tracks_size * pid)] - network_prediction[3 * (count_tracks + tracks_size * pid) + 2]) * response.GetExpectedSignal(trk, pid), - (trk.tpcSignal() / response.GetExpectedSignal(trk, pid) - network_prediction[3 * (count_tracks + tracks_size * pid)]) / (network_prediction[3 * (count_tracks + tracks_size * pid)] - network_prediction[3 * (count_tracks + tracks_size * pid) + 2])); + table((network_prediction[3 * (count_tracks + tracksForNet_size * pid)] - network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 2]) * expSignal, + (trk.tpcSignal() / expSignal - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[3 * (count_tracks + tracksForNet_size * pid)] - network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 2])); } } else { LOGF(fatal, "Network output-dimensions incompatible!"); } } else { - table(response.GetExpectedSigma(collisions.iteratorAt(trk.collisionId()), trk, pid), - response.GetNumberOfSigma(collisions.iteratorAt(trk.collisionId()), trk, pid)); + table(expSigma, + response->GetNumberOfSigma(collisions.iteratorAt(trk.collisionId()), trk, pid)); } }; @@ -330,7 +405,9 @@ struct tpcPidFull { makeTable(pidHe, tablePIDHe, o2::track::PID::Helium3); makeTable(pidAl, tablePIDAl, o2::track::PID::Alpha); - count_tracks++; + if (trk.hasTPC() && (!skipTPCOnly || trk.hasITS() || trk.hasTRD() || trk.hasTOF())) { + count_tracks++; // Increment network track counter only if track has TPC, and (not skipping TPConly) or (is not TPConly) + } } } }; diff --git a/Common/TableProducer/bcConverter.cxx b/Common/TableProducer/bcConverter.cxx new file mode 100644 index 00000000000..54f9a90aa8b --- /dev/null +++ b/Common/TableProducer/bcConverter.cxx @@ -0,0 +1,36 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" + +using namespace o2; +using namespace o2::framework; + +// Converts bc_000 into bc_001 +struct bcConverter { + Produces bc_001; + + void process(aod::BCs_000 const& bcTable) + { + for (auto& bc : bcTable) { + constexpr uint64_t lEmptyTriggerInputs = 0; + bc_001(bc.runNumber(), bc.globalBC(), bc.triggerMask(), lEmptyTriggerInputs); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/Common/TableProducer/centralityTable.cxx b/Common/TableProducer/centralityTable.cxx index e7242a3ae73..46cf0c76556 100644 --- a/Common/TableProducer/centralityTable.cxx +++ b/Common/TableProducer/centralityTable.cxx @@ -12,21 +12,22 @@ /// \file centrality.cxx /// \brief Task to produce the centrality tables associated to each of the required centrality estimators +#include +#include +#include #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/RunningWorkflowInfo.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" -#include -#include -#include using namespace o2; using namespace o2::framework; struct CentralityTable { Produces centRun2V0M; + Produces centRun2V0A; Produces centRun2SPDTracklets; Produces centRun2SPDClusters; Produces centRun2CL0; @@ -39,7 +40,8 @@ struct CentralityTable { Produces centNTPV; Service ccdb; - Configurable estRun2V0M{"estRun2V0M", -1, {"Produces centrality percentiles using V0 multiplicity. -1: auto, 0: don't, 1: yes. Default: auto (-1)"}}; + Configurable estRun2V0M{"estRun2V0M", -1, {"Produces centrality percentiles using total V0 multiplicity. -1: auto, 0: don't, 1: yes. Default: auto (-1)"}}; + Configurable estRun2V0A{"estRun2V0A", -1, {"Produces centrality percentiles using V0A multiplicity. -1: auto, 0: don't, 1: yes. Default: auto (-1)"}}; Configurable estRun2SPDTrklets{"estRun2SPDtks", -1, {"Produces Run2 centrality percentiles using SPD tracklets multiplicity. -1: auto, 0: don't, 1: yes. Default: auto (-1)"}}; Configurable estRun2SPDClusters{"estRun2SPDcls", -1, {"Produces Run2 centrality percentiles using SPD clusters multiplicity. -1: auto, 0: don't, 1: yes. Default: auto (-1)"}}; Configurable estRun2CL0{"estRun2CL0", -1, {"Produces Run2 centrality percentiles using CL0 multiplicity. -1: auto, 0: don't, 1: yes. Default: auto (-1)"}}; @@ -54,6 +56,7 @@ struct CentralityTable { Configurable ccdbPath{"ccdbpath", "Centrality/Estimators", "The CCDB path for centrality/multiplicity information"}; Configurable genName{"genname", "", "Genearator name: HIJING, PYTHIA8, ... Default: \"\""}; Configurable doNotCrashOnNull{"doNotCrashOnNull", false, {"Option to not crash on null and instead fill required tables with dummy info"}}; + Configurable embedINELgtZEROselection{"embedINELgtZEROselection", false, {"Option to do percentile 100.5 if not INELgtZERO"}}; int mRunNumber; struct tagRun2V0MCalibration { @@ -64,6 +67,11 @@ struct CentralityTable { TH1* mhVtxAmpCorrV0C = nullptr; TH1* mhMultSelCalib = nullptr; } Run2V0MInfo; + struct tagRun2V0ACalibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorrV0A = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2V0AInfo; struct tagRun2SPDTrackletsCalibration { bool mCalibrationStored = false; TH1* mhVtxAmpCorr = nullptr; @@ -91,7 +99,7 @@ struct CentralityTable { TH1* mhMultSelCalib = nullptr; float mMCScalePars[6] = {0.0}; TFormula* mMCScale = nullptr; - calibrationInfo(std::string name) + explicit calibrationInfo(std::string name) : name(name), mCalibrationStored(false), mhMultSelCalib(nullptr), @@ -135,6 +143,7 @@ struct CentralityTable { } }; enable("Run2V0M", estRun2V0M); + enable("Run2V0A", estRun2V0A); enable("Run2SPDTrk", estRun2SPDTrklets); enable("Run2SPDCls", estRun2SPDClusters); enable("Run2CL0", estRun2CL0); @@ -165,17 +174,18 @@ struct CentralityTable { TList* callst = ccdb->getForTimeStamp(ccdbPath, bc.timestamp()); Run2V0MInfo.mCalibrationStored = false; + Run2V0AInfo.mCalibrationStored = false; Run2SPDTksInfo.mCalibrationStored = false; Run2SPDClsInfo.mCalibrationStored = false; Run2CL0Info.mCalibrationStored = false; Run2CL1Info.mCalibrationStored = false; if (callst != nullptr) { auto getccdb = [callst](const char* ccdbhname) { - TH1* h = (TH1*)callst->FindObject(ccdbhname); + TH1* h = reinterpret_cast(callst->FindObject(ccdbhname)); return h; }; auto getformulaccdb = [callst](const char* ccdbhname) { - TFormula* f = (TFormula*)callst->FindObject(ccdbhname); + TFormula* f = reinterpret_cast(callst->FindObject(ccdbhname)); return f; }; if (estRun2V0M == 1) { @@ -184,7 +194,7 @@ struct CentralityTable { Run2V0MInfo.mhVtxAmpCorrV0C = getccdb("hVtx_fAmplitude_V0C_Normalized"); Run2V0MInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0M"); Run2V0MInfo.mMCScale = getformulaccdb(TString::Format("%s-V0M", genName->c_str()).Data()); - if ((Run2V0MInfo.mhVtxAmpCorrV0A != nullptr) and (Run2V0MInfo.mhVtxAmpCorrV0C != nullptr) and (Run2V0MInfo.mhMultSelCalib != nullptr)) { + if ((Run2V0MInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0MInfo.mhVtxAmpCorrV0C != nullptr) && (Run2V0MInfo.mhMultSelCalib != nullptr)) { if (genName->length() != 0) { if (Run2V0MInfo.mMCScale != nullptr) { for (int ixpar = 0; ixpar < 6; ++ixpar) { @@ -199,11 +209,21 @@ struct CentralityTable { LOGF(fatal, "Calibration information from V0M for run %d corrupted", bc.runNumber()); } } + if (estRun2V0A == 1) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2V0AInfo.mhVtxAmpCorrV0A = getccdb("hVtx_fAmplitude_V0A_Normalized"); + Run2V0AInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0A"); + if ((Run2V0AInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0AInfo.mhMultSelCalib != nullptr)) { + Run2V0AInfo.mCalibrationStored = true; + } else { + LOGF(fatal, "Calibration information from V0A for run %d corrupted", bc.runNumber()); + } + } if (estRun2SPDTrklets == 1) { LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); Run2SPDTksInfo.mhVtxAmpCorr = getccdb("hVtx_fnTracklets_Normalized"); Run2SPDTksInfo.mhMultSelCalib = getccdb("hMultSelCalib_SPDTracklets"); - if ((Run2SPDTksInfo.mhVtxAmpCorr != nullptr) and (Run2SPDTksInfo.mhMultSelCalib != nullptr)) { + if ((Run2SPDTksInfo.mhVtxAmpCorr != nullptr) && (Run2SPDTksInfo.mhMultSelCalib != nullptr)) { Run2SPDTksInfo.mCalibrationStored = true; } else { LOGF(fatal, "Calibration information from SPD tracklets for run %d corrupted", bc.runNumber()); @@ -214,7 +234,7 @@ struct CentralityTable { Run2SPDClsInfo.mhVtxAmpCorrCL0 = getccdb("hVtx_fnSPDClusters0_Normalized"); Run2SPDClsInfo.mhVtxAmpCorrCL1 = getccdb("hVtx_fnSPDClusters1_Normalized"); Run2SPDClsInfo.mhMultSelCalib = getccdb("hMultSelCalib_SPDClusters"); - if ((Run2SPDClsInfo.mhVtxAmpCorrCL0 != nullptr) and (Run2SPDClsInfo.mhVtxAmpCorrCL1 != nullptr) and (Run2SPDClsInfo.mhMultSelCalib != nullptr)) { + if ((Run2SPDClsInfo.mhVtxAmpCorrCL0 != nullptr) && (Run2SPDClsInfo.mhVtxAmpCorrCL1 != nullptr) && (Run2SPDClsInfo.mhMultSelCalib != nullptr)) { Run2SPDClsInfo.mCalibrationStored = true; } else { LOGF(fatal, "Calibration information from SPD clusters for run %d corrupted", bc.runNumber()); @@ -224,7 +244,7 @@ struct CentralityTable { LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); Run2CL0Info.mhVtxAmpCorr = getccdb("hVtx_fnSPDClusters0_Normalized"); Run2CL0Info.mhMultSelCalib = getccdb("hMultSelCalib_CL0"); - if ((Run2CL0Info.mhVtxAmpCorr != nullptr) and (Run2CL0Info.mhMultSelCalib != nullptr)) { + if ((Run2CL0Info.mhVtxAmpCorr != nullptr) && (Run2CL0Info.mhMultSelCalib != nullptr)) { Run2CL0Info.mCalibrationStored = true; } else { LOGF(fatal, "Calibration information from CL0 multiplicity for run %d corrupted", bc.runNumber()); @@ -234,13 +254,13 @@ struct CentralityTable { LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); Run2CL1Info.mhVtxAmpCorr = getccdb("hVtx_fnSPDClusters1_Normalized"); Run2CL1Info.mhMultSelCalib = getccdb("hMultSelCalib_CL1"); - if ((Run2CL1Info.mhVtxAmpCorr != nullptr) and (Run2CL1Info.mhMultSelCalib != nullptr)) { + if ((Run2CL1Info.mhVtxAmpCorr != nullptr) && (Run2CL1Info.mhMultSelCalib != nullptr)) { Run2CL1Info.mCalibrationStored = true; } else { LOGF(fatal, "Calibration information from CL1 multiplicity for run %d corrupted", bc.runNumber()); } } - if (Run2V0MInfo.mCalibrationStored or Run2SPDTksInfo.mCalibrationStored or Run2SPDClsInfo.mCalibrationStored or Run2CL0Info.mCalibrationStored or Run2CL1Info.mCalibrationStored) { + if (Run2V0MInfo.mCalibrationStored || Run2V0AInfo.mCalibrationStored || Run2SPDTksInfo.mCalibrationStored || Run2SPDClsInfo.mCalibrationStored || Run2CL0Info.mCalibrationStored || Run2CL1Info.mCalibrationStored) { mRunNumber = bc.runNumber(); } } else { @@ -274,6 +294,16 @@ struct CentralityTable { // fill centrality columns centRun2V0M(cV0M); } + if (estRun2V0A == 1) { + float cV0A = 105.0f; + if (Run2V0AInfo.mCalibrationStored) { + float v0a = collision.multFV0A() * Run2V0AInfo.mhVtxAmpCorrV0A->GetBinContent(Run2V0AInfo.mhVtxAmpCorrV0A->FindFixBin(collision.posZ())); + cV0A = Run2V0AInfo.mhMultSelCalib->GetBinContent(Run2V0AInfo.mhMultSelCalib->FindFixBin(v0a)); + } + LOGF(debug, "centRun2V0A=%.0f", cV0A); + // fill centrality columns + centRun2V0A(cV0A); + } if (estRun2SPDTrklets == 1) { float cSPD = 105.0f; if (Run2SPDTksInfo.mCalibrationStored) { @@ -353,8 +383,8 @@ struct CentralityTable { if (callst != nullptr) { LOGF(info, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); auto getccdb = [callst, bc](struct calibrationInfo& estimator, const Configurable generatorName) { // TODO: to consider the name inside the estimator structure - estimator.mhMultSelCalib = (TH1*)callst->FindObject(TString::Format("hCalibZeq%s", estimator.name.c_str()).Data()); - estimator.mMCScale = (TFormula*)callst->FindObject(TString::Format("%s-%s", generatorName->c_str(), estimator.name.c_str()).Data()); + estimator.mhMultSelCalib = reinterpret_cast(callst->FindObject(TString::Format("hCalibZeq%s", estimator.name.c_str()).Data())); + estimator.mMCScale = reinterpret_cast(callst->FindObject(TString::Format("%s-%s", generatorName->c_str(), estimator.name.c_str()).Data())); if (estimator.mhMultSelCalib != nullptr) { if (generatorName->length() != 0) { if (estimator.mMCScale != nullptr) { @@ -399,7 +429,7 @@ struct CentralityTable { } } - auto populateTable = [](auto& table, struct calibrationInfo& estimator, float multiplicity) { + auto populateTable = [](auto& table, struct calibrationInfo& estimator, float multiplicity, bool assignOutOfRange) { auto scaleMC = [](float x, float pars[6]) { return pow(((pars[0] + pars[1] * pow(x, pars[2])) - pars[3]) / pars[4], 1.0f / pars[5]); }; @@ -412,28 +442,31 @@ struct CentralityTable { LOGF(debug, "Unscaled %s multiplicity: %f, scaled %s multiplicity: %f", estimator.name.c_str(), multiplicity, estimator.name.c_str(), scaledMultiplicity); } percentile = estimator.mhMultSelCalib->GetBinContent(estimator.mhMultSelCalib->FindFixBin(scaledMultiplicity)); + if (assignOutOfRange) + percentile = 100.5f; } LOGF(debug, "%s centrality/multiplicity percentile = %.0f for a zvtx eq %s value %.0f", estimator.name.c_str(), percentile, estimator.name.c_str(), scaledMultiplicity); table(percentile); }; if (estFV0A == 1) { - populateTable(centFV0A, FV0AInfo, collision.multZeqFV0A()); + populateTable(centFV0A, FV0AInfo, collision.multZeqFV0A(), collision.multNTracksPVeta1() < 1 && embedINELgtZEROselection); + } else { } if (estFT0M == 1) { - populateTable(centFT0M, FT0MInfo, collision.multZeqFT0A() + collision.multZeqFT0C()); + populateTable(centFT0M, FT0MInfo, collision.multZeqFT0A() + collision.multZeqFT0C(), collision.multNTracksPVeta1() < 1 && embedINELgtZEROselection); } if (estFT0A == 1) { - populateTable(centFT0A, FT0AInfo, collision.multZeqFT0A()); + populateTable(centFT0A, FT0AInfo, collision.multZeqFT0A(), collision.multNTracksPVeta1() < 1 && embedINELgtZEROselection); } if (estFT0C == 1) { - populateTable(centFT0C, FT0CInfo, collision.multZeqFT0C()); + populateTable(centFT0C, FT0CInfo, collision.multZeqFT0C(), collision.multNTracksPVeta1() < 1 && embedINELgtZEROselection); } if (estFDDM == 1) { - populateTable(centFDDM, FDDMInfo, collision.multZeqFDDA() + collision.multZeqFDDC()); + populateTable(centFDDM, FDDMInfo, collision.multZeqFDDA() + collision.multZeqFDDC(), collision.multNTracksPVeta1() < 1 && embedINELgtZEROselection); } if (estNTPV == 1) { - populateTable(centNTPV, NTPVInfo, collision.multZeqNTracksPV()); + populateTable(centNTPV, NTPVInfo, collision.multZeqNTracksPV(), collision.multNTracksPVeta1() < 1 && embedINELgtZEROselection); } } } diff --git a/Common/TableProducer/eventSelection.cxx b/Common/TableProducer/eventSelection.cxx index bb7a6233935..4f390f6856a 100644 --- a/Common/TableProducer/eventSelection.cxx +++ b/Common/TableProducer/eventSelection.cxx @@ -10,9 +10,6 @@ // or submit itself to any jurisdiction. #include "Framework/ConfigParamSpec.h" -using namespace o2; -using namespace o2::framework; - #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -24,12 +21,17 @@ using namespace o2::framework; #include "Framework/HistogramRegistry.h" #include "DataFormatsFT0/Digit.h" #include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPECSObject.h" #include "TH1D.h" -using namespace evsel; + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::evsel; using BCsWithRun2InfosTimestampsAndMatches = soa::Join; using BCsWithRun3Matchings = soa::Join; -using BCsWithBcSels = soa::Join; +using BCsWithBcSelsRun2 = soa::Join; +using BCsWithBcSelsRun3 = soa::Join; using FullTracksIU = soa::Join; struct BcSelectionTask { @@ -46,6 +48,13 @@ struct BcSelectionTask { ccdb->setLocalObjectValidityChecking(); histos.add("hCounterTVX", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterTCE", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZEM", "", kTH1D, {{1, 0., 1.}}); + histos.add("hCounterZNC", "", kTH1D, {{1, 0., 1.}}); + histos.add("hLumiTVX", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); + histos.add("hLumiTCE", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); + histos.add("hLumiZEM", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); + histos.add("hLumiZNC", ";;Luminosity, 1/#mub", kTH1D, {{1, 0., 1.}}); } void processRun2( @@ -92,35 +101,23 @@ struct BcSelectionTask { LOGF(debug, "timeFDA=%f timeFDC=%f", timeFDA, timeFDC); LOGF(debug, "timeT0A=%f timeT0C=%f", timeT0A, timeT0C); - // applying timing selections - bool bbV0A = timeV0A > par->fV0ABBlower && timeV0A < par->fV0ABBupper; - bool bbV0C = timeV0C > par->fV0CBBlower && timeV0C < par->fV0CBBupper; - bool bbFDA = timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper; - bool bbFDC = timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper; - bool bgV0A = timeV0A > par->fV0ABGlower && timeV0A < par->fV0ABGupper; - bool bgV0C = timeV0C > par->fV0CBGlower && timeV0C < par->fV0CBGupper; - bool bgFDA = timeFDA > par->fFDABGlower && timeFDA < par->fFDABGupper; - bool bgFDC = timeFDC > par->fFDCBGlower && timeFDC < par->fFDCBGupper; - float znSum = timeZNA + timeZNC; - float znDif = timeZNA - timeZNC; - // fill time-based selection criteria uint64_t selection{0}; - selection |= bbV0A ? BIT(kIsBBV0A) : 0; - selection |= bbV0C ? BIT(kIsBBV0C) : 0; - selection |= bbFDA ? BIT(kIsBBFDA) : 0; - selection |= bbFDC ? BIT(kIsBBFDC) : 0; - selection |= !bgV0A ? BIT(kNoBGV0A) : 0; - selection |= !bgV0C ? BIT(kNoBGV0C) : 0; - selection |= !bgFDA ? BIT(kNoBGFDA) : 0; - selection |= !bgFDC ? BIT(kNoBGFDC) : 0; + selection |= timeV0A > par->fV0ABBlower && timeV0A < par->fV0ABBupper ? BIT(kIsBBV0A) : 0; + selection |= timeV0C > par->fV0CBBlower && timeV0C < par->fV0CBBupper ? BIT(kIsBBV0C) : 0; + selection |= timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper ? BIT(kIsBBFDA) : 0; + selection |= timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper ? BIT(kIsBBFDC) : 0; + selection |= !(timeV0A > par->fV0ABGlower && timeV0A < par->fV0ABGupper) ? BIT(kNoBGV0A) : 0; + selection |= !(timeV0C > par->fV0CBGlower && timeV0C < par->fV0CBGupper) ? BIT(kNoBGV0C) : 0; + selection |= !(timeFDA > par->fFDABGlower && timeFDA < par->fFDABGupper) ? BIT(kNoBGFDA) : 0; + selection |= !(timeFDC > par->fFDCBGlower && timeFDC < par->fFDCBGupper) ? BIT(kNoBGFDC) : 0; selection |= (timeT0A > par->fT0ABBlower && timeT0A < par->fT0ABBupper) ? BIT(kIsBBT0A) : 0; selection |= (timeT0C > par->fT0CBBlower && timeT0C < par->fT0CBBupper) ? BIT(kIsBBT0C) : 0; selection |= (timeZNA > par->fZNABBlower && timeZNA < par->fZNABBupper) ? BIT(kIsBBZNA) : 0; selection |= (timeZNC > par->fZNCBBlower && timeZNC < par->fZNCBBupper) ? BIT(kIsBBZNC) : 0; selection |= !(fabs(timeZNA) > par->fZNABGlower && fabs(timeZNA) < par->fZNABGupper) ? BIT(kNoBGZNA) : 0; selection |= !(fabs(timeZNC) > par->fZNCBGlower && fabs(timeZNC) < par->fZNCBGupper) ? BIT(kNoBGZNC) : 0; - selection |= (pow((znSum - par->fZNSumMean) / par->fZNSumSigma, 2) + pow((znDif - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(kIsBBZAC) : 0; + selection |= (pow((timeZNA + timeZNC - par->fZNSumMean) / par->fZNSumSigma, 2) + pow((timeZNA - timeZNC - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(kIsBBZAC) : 0; // Calculate V0 multiplicity per ring float multRingV0A[5] = {0.}; @@ -142,7 +139,6 @@ struct BcSelectionTask { multFV0C += bc.fv0c().amplitude()[i]; } } - uint32_t spdClusters = bc.spdClustersL0() + bc.spdClustersL1(); // Calculate pileup and background related selection flags // V0A0 excluded from online V0A charge sum => excluding also from offline sum for consistency @@ -155,10 +151,11 @@ struct BcSelectionTask { selection |= (onV0M > par->fV0MOnVsOfA + par->fV0MOnVsOfB * ofV0M) ? BIT(kNoV0MOnVsOfPileup) : 0; selection |= (onSPD > par->fSPDOnVsOfA + par->fSPDOnVsOfB * ofSPD) ? BIT(kNoSPDOnVsOfPileup) : 0; selection |= (multRingV0C[3] > par->fV0CasymA + par->fV0CasymB * multV0C012) ? BIT(kNoV0Casymmetry) : 0; + selection |= (TESTBIT(selection, kIsBBV0A) || TESTBIT(selection, kIsBBV0C) || ofSPD) ? BIT(kIsINT1) : 0; + selection |= (bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex) : 0) ? BIT(kIsTriggerTVX) : 0; // copy remaining selection decisions from eventCuts uint32_t eventCuts = bc.eventCuts(); - selection |= (eventCuts & 1 << aod::kTimeRangeCut) ? BIT(kIsGoodTimeRange) : 0; selection |= (eventCuts & 1 << aod::kIncompleteDAQ) ? BIT(kNoIncompleteDAQ) : 0; selection |= !(eventCuts & 1 << aod::kIsTPCLaserWarmUp) ? BIT(kNoTPCLaserWarmUp) : 0; @@ -169,8 +166,6 @@ struct BcSelectionTask { selection |= (eventCuts & 1 << aod::kPileupInMultBins) ? BIT(kNoPileupInMultBins) : 0; selection |= (eventCuts & 1 << aod::kPileUpMV) ? BIT(kNoPileupMV) : 0; selection |= (eventCuts & 1 << aod::kTPCPileUp) ? BIT(kNoPileupTPC) : 0; - selection |= (bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex) : 0) ? BIT(kIsTriggerTVX) : 0; - selection |= (bbV0A || bbV0C || ofSPD) ? BIT(kIsINT1) : 0; int32_t foundFT0 = bc.has_ft0() ? bc.ft0().globalIndex() : -1; int32_t foundFV0 = bc.has_fv0a() ? bc.fv0a().globalIndex() : -1; @@ -183,10 +178,7 @@ struct BcSelectionTask { } // Fill bc selection columns - bcsel(alias, selection, - bbV0A, bbV0C, bgV0A, bgV0C, - bbFDA, bbFDC, bgFDA, bgFDC, - multRingV0A, multRingV0C, spdClusters, foundFT0, foundFV0, foundFDD, foundZDC); + bcsel(alias, selection, foundFT0, foundFV0, foundFDD, foundZDC); } } PROCESS_SWITCH(BcSelectionTask, processRun2, "Process Run2 event selection", true); @@ -207,14 +199,14 @@ struct BcSelectionTask { int triggerBcShift = confTriggerBcShift; if (confTriggerBcShift == 999) { int run = bcs.iteratorAt(0).runNumber(); - triggerBcShift = (run <= 526766 || (run >= 526886 && run <= 527237) || (run >= 527259 && run <= 527518) || run == 527523 || run == 527734) ? 0 : 294; + triggerBcShift = (run <= 526766 || (run >= 526886 && run <= 527237) || (run >= 527259 && run <= 527518) || run == 527523 || run == 527734 || run >= 534091) ? 0 : 294; } for (auto bc : bcs) { EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); TriggerAliases* aliases = ccdb->getForTimeStamp("EventSelection/TriggerAliases", bc.timestamp()); uint32_t alias{0}; - // workaround for pp2022 apass2-apass3 (trigger info is shifted by -294 bcs) + // workaround for pp2022 (trigger info is shifted by -294 bcs) int32_t triggerBcId = mapGlobalBCtoBcId[bc.globalBC() + triggerBcShift]; if (triggerBcId) { auto triggerBc = bcs.iteratorAt(triggerBcId); @@ -240,8 +232,6 @@ struct BcSelectionTask { float timeT0CBG = -999.f; float timeFDABG = -999.f; float timeFDCBG = -999.f; - float znSum = timeZNA + timeZNC; - float znDif = timeZNA - timeZNC; uint64_t globalBC = bc.globalBC(); // move to previous bcs to check beam-gas in FT0, FV0 and FDD @@ -266,68 +256,67 @@ struct BcSelectionTask { // move back to initial position bc.moveByIndex(backwardMoveCount); - // applying timing selections - bool bbV0A = timeV0A > par->fV0ABBlower && timeV0A < par->fV0ABBupper; - bool bbFDA = timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper; - bool bbFDC = timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper; - bool bgV0A = timeV0ABG > par->fV0ABGlower && timeV0ABG < par->fV0ABGupper; - bool bgFDA = timeFDABG > par->fFDABGlower && timeFDABG < par->fFDABGupper; - bool bgFDC = timeFDCBG > par->fFDCBGlower && timeFDCBG < par->fFDCBGupper; - bool bgT0A = timeT0ABG > par->fT0ABGlower && timeT0ABG < par->fT0ABGupper; - bool bgT0C = timeT0CBG > par->fT0CBGlower && timeT0CBG < par->fT0CBGupper; - bool bbV0C = 0; - bool bgV0C = 0; - // fill time-based selection criteria uint64_t selection{0}; - selection |= bbV0A ? BIT(kIsBBV0A) : 0; - selection |= bbFDA ? BIT(kIsBBFDA) : 0; - selection |= bbFDC ? BIT(kIsBBFDC) : 0; - selection |= !bgV0A ? BIT(kNoBGV0A) : 0; - selection |= !bgFDA ? BIT(kNoBGFDA) : 0; - selection |= !bgFDC ? BIT(kNoBGFDC) : 0; - selection |= !bgT0A ? BIT(kNoBGT0A) : 0; - selection |= !bgT0C ? BIT(kNoBGT0C) : 0; + selection |= timeV0A > par->fV0ABBlower && timeV0A < par->fV0ABBupper ? BIT(kIsBBV0A) : 0; + selection |= timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper ? BIT(kIsBBFDA) : 0; + selection |= timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper ? BIT(kIsBBFDC) : 0; + selection |= !(timeV0ABG > par->fV0ABGlower && timeV0ABG < par->fV0ABGupper) ? BIT(kNoBGV0A) : 0; + selection |= !(timeFDABG > par->fFDABGlower && timeFDABG < par->fFDABGupper) ? BIT(kNoBGFDA) : 0; + selection |= !(timeFDCBG > par->fFDCBGlower && timeFDCBG < par->fFDCBGupper) ? BIT(kNoBGFDC) : 0; + selection |= !(timeT0ABG > par->fT0ABGlower && timeT0ABG < par->fT0ABGupper) ? BIT(kNoBGT0A) : 0; + selection |= !(timeT0CBG > par->fT0CBGlower && timeT0CBG < par->fT0CBGupper) ? BIT(kNoBGT0C) : 0; selection |= (timeT0A > par->fT0ABBlower && timeT0A < par->fT0ABBupper) ? BIT(kIsBBT0A) : 0; selection |= (timeT0C > par->fT0CBBlower && timeT0C < par->fT0CBBupper) ? BIT(kIsBBT0C) : 0; selection |= (timeZNA > par->fZNABBlower && timeZNA < par->fZNABBupper) ? BIT(kIsBBZNA) : 0; selection |= (timeZNC > par->fZNCBBlower && timeZNC < par->fZNCBBupper) ? BIT(kIsBBZNC) : 0; - selection |= (pow((znSum - par->fZNSumMean) / par->fZNSumSigma, 2) + pow((znDif - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(kIsBBZAC) : 0; + selection |= (pow((timeZNA + timeZNC - par->fZNSumMean) / par->fZNSumSigma, 2) + pow((timeZNA - timeZNC - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(kIsBBZAC) : 0; selection |= !(fabs(timeZNA) > par->fZNABGlower && fabs(timeZNA) < par->fZNABGupper) ? BIT(kNoBGZNA) : 0; selection |= !(fabs(timeZNC) > par->fZNCBGlower && fabs(timeZNC) < par->fZNCBGupper) ? BIT(kNoBGZNC) : 0; selection |= (bc.has_ft0() ? (bc.ft0().triggerMask() & BIT(o2::ft0::Triggers::bitVertex)) > 0 : 0) ? BIT(kIsTriggerTVX) : 0; - // Calculate V0 multiplicity per ring - float multRingV0A[5] = {0.}; - float multRingV0C[4] = {0.}; - if (bc.has_fv0a()) { - for (unsigned int i = 0; i < bc.fv0a().amplitude().size(); ++i) { - int ring = bc.fv0a().channel()[i] / 8; - if (ring == 5) { - ring = 4; // Outermost ring has 16 channels - } - multRingV0A[ring] += bc.fv0a().amplitude()[i]; - } - } - - uint32_t spdClusters = 0; - int32_t foundFT0 = bc.has_ft0() ? bc.ft0().globalIndex() : -1; int32_t foundFV0 = bc.has_fv0a() ? bc.fv0a().globalIndex() : -1; int32_t foundFDD = bc.has_fdd() ? bc.fdd().globalIndex() : -1; int32_t foundZDC = bc.has_zdc() ? bc.zdc().globalIndex() : -1; - LOGP(debug, "foundFT0={}\n", foundFT0); + LOGP(debug, "foundFT0={}", foundFT0); + + // Temporary workaround to get visible cross section. TODO: store run-by-run visible cross sections in CCDB + int run = bc.runNumber(); + const char* srun = Form("%d", run); + auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", bc.timestamp()); + int beamZ1 = grplhcif->getBeamZ(o2::constants::lhc::BeamA); + int beamZ2 = grplhcif->getBeamZ(o2::constants::lhc::BeamC); + bool isPP = beamZ1 == 1 && beamZ2 == 1; + bool injectionEnergy = (run >= 500000 && run <= 520099) || (run >= 534133 && run <= 534468); + // Cross sections in ub. Using dummy -1 if lumi estimator is not reliable + float csTVX = isPP ? (injectionEnergy ? 0.0355e6 : 0.0594e6) : -1.; + float csTCE = isPP ? -1. : 10.36e6; + float csZEM = isPP ? -1. : 415.2e6; + float csZNC = isPP ? -1. : 214.5e6; // Fill TVX (T0 vertex) counters if (TESTBIT(selection, kIsTriggerTVX)) { - histos.get(HIST("hCounterTVX"))->Fill(Form("%d", bc.runNumber()), 1); + histos.get(HIST("hCounterTVX"))->Fill(srun, 1); + histos.get(HIST("hLumiTVX"))->Fill(srun, 1. / csTVX); + } + // Fill counters and lumi histograms for Pb-Pb lumi monitoring + // TODO: introduce pileup correction + if (bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitCen) : 0) { + histos.get(HIST("hCounterTCE"))->Fill(srun, 1); + histos.get(HIST("hLumiTCE"))->Fill(srun, 1. / csTCE); + } + if (TESTBIT(selection, kIsBBZNA) || TESTBIT(selection, kIsBBZNC)) { + histos.get(HIST("hCounterZEM"))->Fill(srun, 1); + histos.get(HIST("hLumiZEM"))->Fill(srun, 1. / csZEM); + } + if (TESTBIT(selection, kIsBBZNC)) { + histos.get(HIST("hCounterZNC"))->Fill(srun, 1); + histos.get(HIST("hLumiZNC"))->Fill(srun, 1. / csZNC); } // Fill bc selection columns - bcsel(alias, selection, - bbV0A, bbV0C, bgV0A, bgV0C, - bbFDA, bbFDC, bgFDA, bgFDC, - multRingV0A, multRingV0C, spdClusters, foundFT0, foundFV0, foundFDD, foundZDC); + bcsel(alias, selection, foundFT0, foundFV0, foundFDD, foundZDC); } } PROCESS_SWITCH(BcSelectionTask, processRun3, "Process Run3 event selection", false); @@ -378,9 +367,9 @@ struct EventSelectionTask { evsel.reserve(collisions.size()); } - void processRun2(aod::Collision const& col, BCsWithBcSels const& bcs, aod::Tracks const& tracks) + void processRun2(aod::Collision const& col, BCsWithBcSelsRun2 const& bcs, aod::Tracks const& tracks, aod::FV0Cs const&) { - auto bc = col.bc_as(); + auto bc = col.bc_as(); EventSelectionParams* par = ccdb->getForTimeStamp("EventSelection/EventSelectionParams", bc.timestamp()); bool* applySelection = par->GetSelection(muonSelection); if (isMC) { @@ -403,35 +392,24 @@ struct EventSelectionTask { // copy selection decisions from bcsel table uint64_t selection = bc.selection_raw(); - // copy multiplicity per ring and calculate V0C012 multiplicity - float multRingV0A[5] = {0.}; + // calculate V0C012 multiplicity float multRingV0C[4] = {0.}; - for (int i = 0; i < 5; i++) { - multRingV0A[i] = bc.multRingV0A()[i]; - } - for (int i = 0; i < 4; i++) { - multRingV0C[i] = bc.multRingV0C()[i]; + if (bc.has_fv0c()) { + for (unsigned int i = 0; i < bc.fv0c().amplitude().size(); ++i) { + int ring = bc.fv0c().channel()[i] / 8; + multRingV0C[ring] += bc.fv0c().amplitude()[i]; + } } - float multV0C012 = bc.multRingV0C()[0] + bc.multRingV0C()[1] + bc.multRingV0C()[2]; + float multV0C012 = multRingV0C[0] + multRingV0C[1] + multRingV0C[2]; // applying selections depending on the number of tracklets auto trackletsGrouped = tracklets->sliceByCached(aod::track::collisionId, col.globalIndex(), cache); int nTkl = trackletsGrouped.size(); + int spdClusters = bc.spdClustersL0() + bc.spdClustersL1(); - uint32_t spdClusters = bc.spdClusters(); selection |= (spdClusters < par->fSPDClsVsTklA + nTkl * par->fSPDClsVsTklB) ? BIT(kNoSPDClsVsTklBG) : 0; selection |= !(nTkl < 6 && multV0C012 > par->fV0C012vsTklA + nTkl * par->fV0C012vsTklB) ? BIT(kNoV0C012vsTklBG) : 0; - // copy beam-beam and beam-gas flags from bcsel table - bool bbV0A = bc.bbV0A(); - bool bbV0C = bc.bbV0C(); - bool bgV0A = bc.bgV0A(); - bool bgV0C = bc.bgV0C(); - bool bbFDA = bc.bbFDA(); - bool bbFDC = bc.bbFDC(); - bool bgFDA = bc.bgFDA(); - bool bgFDC = bc.bgFDC(); - // apply int7-like selections bool sel7 = 1; for (int i = 0; i < kNsel; i++) { @@ -439,7 +417,7 @@ struct EventSelectionTask { } // TODO introduce array of sel[0]... sel[8] or similar? - bool sel8 = bc.selection_bit(kIsBBT0A) & bc.selection_bit(kIsBBT0C); // TODO apply other cuts for sel8 + bool sel8 = bc.selection_bit(kIsBBT0A) && bc.selection_bit(kIsBBT0C); // TODO apply other cuts for sel8 bool sel1 = bc.selection_bit(kIsINT1); sel1 &= bc.selection_bit(kNoBGV0A); sel1 &= bc.selection_bit(kNoBGV0C); @@ -457,16 +435,12 @@ struct EventSelectionTask { } } - evsel(alias, selection, - bbV0A, bbV0C, bgV0A, bgV0C, - bbFDA, bbFDC, bgFDA, bgFDC, - multRingV0A, multRingV0C, spdClusters, nTkl, sel7, sel8, - foundBC, foundFT0, foundFV0, foundFDD, foundZDC); + evsel(alias, selection, sel7, sel8, foundBC, foundFT0, foundFV0, foundFDD, foundZDC); } PROCESS_SWITCH(EventSelectionTask, processRun2, "Process Run2 event selection", true); Preslice perCollision = aod::track::collisionId; - void processRun3(aod::Collisions const& cols, FullTracksIU const& tracks, BCsWithBcSels const& bcs) + void processRun3(aod::Collisions const& cols, FullTracksIU const& tracks, BCsWithBcSelsRun3 const& bcs) { int run = bcs.iteratorAt(0).runNumber(); // extract bc pattern from CCDB for data or anchored MC only @@ -495,8 +469,23 @@ struct EventSelectionTask { } } + // protection against empty FT0 maps + if (mapGlobalBcWithTOR.size() == 0 || mapGlobalBcWithTVX.size() == 0) { + LOGP(error, "FT0 table is empty or corrupted. Filling evsel table with dummy values"); + for (auto& col : cols) { + auto bc = col.bc_as(); + int32_t foundBC = bc.globalIndex(); + int32_t foundFT0 = bc.foundFT0Id(); + int32_t foundFV0 = bc.foundFV0Id(); + int32_t foundFDD = bc.foundFDDId(); + int32_t foundZDC = bc.foundZDCId(); + evsel(bc.alias_raw(), bc.selection_raw(), kFALSE, kFALSE, foundBC, foundFT0, foundFV0, foundFDD, foundZDC); + } + return; + } + for (auto& col : cols) { - auto bc = col.bc_as(); + auto bc = col.bc_as(); int64_t meanBC = bc.globalBC(); const double bcNS = o2::constants::lhc::LHCBunchSpacingNS; int64_t deltaBC = std::ceil(col.collisionTimeRes() / bcNS * 4); @@ -565,26 +554,6 @@ struct EventSelectionTask { // copy selection decisions from bcsel table uint64_t selection = bc.selection_raw(); - // copy multiplicity per ring - float multRingV0A[5] = {0.}; - float multRingV0C[4] = {0.}; - for (int i = 0; i < 5; i++) { - multRingV0A[i] = bc.multRingV0A()[i]; - } - - int nTkl = 0; - uint32_t spdClusters = 0; - - // copy beam-beam and beam-gas flags from bcsel table - bool bbV0A = bc.bbV0A(); - bool bbV0C = bc.bbV0C(); - bool bgV0A = bc.bgV0A(); - bool bgV0C = bc.bgV0C(); - bool bbFDA = bc.bbFDA(); - bool bbFDC = bc.bbFDC(); - bool bgFDA = bc.bgFDA(); - bool bgFDC = bc.bgFDC(); - // apply int7-like selections bool sel7 = 0; @@ -599,11 +568,7 @@ struct EventSelectionTask { histos.get(HIST("hColCounterAcc"))->Fill(Form("%d", bc.runNumber()), 1); } - evsel(alias, selection, - bbV0A, bbV0C, bgV0A, bgV0C, - bbFDA, bbFDC, bgFDA, bgFDC, - multRingV0A, multRingV0C, spdClusters, nTkl, sel7, sel8, - foundBC, foundFT0, foundFV0, foundFDD, foundZDC); + evsel(alias, selection, sel7, sel8, foundBC, foundFT0, foundFV0, foundFDD, foundZDC); } } PROCESS_SWITCH(EventSelectionTask, processRun3, "Process Run3 event selection", false); diff --git a/Common/TableProducer/evtPlanesTable.cxx b/Common/TableProducer/evtPlanesTable.cxx new file mode 100644 index 00000000000..0440f1b17dc --- /dev/null +++ b/Common/TableProducer/evtPlanesTable.cxx @@ -0,0 +1,108 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file evtPlanesTable.cxx +/// \author Cindy Mordasini +/// \author Anna Önnerstad +/// +/// \brief Task calculating the Q-vectors for each collision in a bunch crossing +/// (with or without corrections) and save the results in a dedicated table. +/// + +// C++/ROOT includes. +#include +#include +#include +#include +#include + +// o2Physics includes. +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/StaticFor.h" + +#include "Common/Core/EventPlaneHelper.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" + +#include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/EvtPlanes.h" + +// o2 includes. +#include "CCDB/BasicCCDBManager.h" +#include "DetectorsCommonDataFormats/AlignParam.h" + +using namespace o2; +using namespace o2::framework; + +struct evtPlanesTable { + // Table. + Produces evPlane; + + // Histogram registry for the output QA figures and list of centrality classes for it. + // Objects are NOT saved in alphabetical orders, and registry names are NOT saved + // as TDirectoryFile. + HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + // Helper variables. + EventPlaneHelper helperEP; + + void init(InitContext const&) + { + } // void init(InitContext const&) + + void process(aod::Qvector const& qVec) + { + // Get the centrality bin, and fill the centrality distribution. + int centBin = helperEP.GetCentBin(qVec.cent()); + if (centBin < 0 || centBin > 8) { + return; + } + // Calculate the event plane for each detector, then save them in the + // corresponding distribution. The order is the same as in detNames[]. + // TODO: Update the calculation of the event plane for the central barrel. + + float evtPlane[4]; + float evtPlaneBPos[4]; + float evtPlaneBNeg[4]; + + evtPlane[0] = helperEP.GetEventPlane(qVec.qvecUncorRe(), qVec.qvecUncorIm()); + evtPlane[1] = helperEP.GetEventPlane(qVec.qvecRectrRe(), qVec.qvecRectrIm()); + evtPlane[2] = helperEP.GetEventPlane(qVec.qvecTwistRe(), qVec.qvecTwistIm()); + evtPlane[3] = helperEP.GetEventPlane(qVec.qvecFinalRe(), qVec.qvecFinalIm()); + + evtPlaneBPos[0] = helperEP.GetEventPlane(qVec.qvecBPosUncorRe(), qVec.qvecBPosUncorIm()); + evtPlaneBPos[1] = helperEP.GetEventPlane(qVec.qvecBPosRectrRe(), qVec.qvecBPosRectrIm()); + evtPlaneBPos[2] = helperEP.GetEventPlane(qVec.qvecBPosTwistRe(), qVec.qvecBPosTwistIm()); + evtPlaneBPos[3] = helperEP.GetEventPlane(qVec.qvecBPosFinalRe(), qVec.qvecBPosFinalIm()); + + evtPlaneBNeg[0] = helperEP.GetEventPlane(qVec.qvecBNegUncorRe(), qVec.qvecBNegUncorIm()); + evtPlaneBNeg[1] = helperEP.GetEventPlane(qVec.qvecBNegRectrRe(), qVec.qvecBNegRectrIm()); + evtPlaneBNeg[2] = helperEP.GetEventPlane(qVec.qvecBNegTwistRe(), qVec.qvecBNegTwistIm()); + evtPlaneBNeg[3] = helperEP.GetEventPlane(qVec.qvecBNegFinalRe(), qVec.qvecBNegFinalIm()); + + // Fill the columns of the evtPlane table. + evPlane(qVec.cent(), + evtPlane[0], evtPlane[1], evtPlane[2], evtPlane[3], + evtPlaneBPos[0], evtPlaneBPos[1], evtPlaneBPos[2], evtPlaneBPos[3], + evtPlaneBNeg[0], evtPlaneBNeg[1], evtPlaneBNeg[2], evtPlaneBNeg[3], + qVec.nTrkBPos(), qVec.nTrkBNeg()); + } // void process(aod::Qvector const& qVec) +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Common/TableProducer/fwdtrackToCollisionAssociator.cxx b/Common/TableProducer/fwdtrackToCollisionAssociator.cxx index 4528a381028..0478b69b12d 100644 --- a/Common/TableProducer/fwdtrackToCollisionAssociator.cxx +++ b/Common/TableProducer/fwdtrackToCollisionAssociator.cxx @@ -37,6 +37,7 @@ struct FwdTrackToCollisionAssociation { Configurable timeMargin{"timeMargin", 0.f, "time margin in ns added to uncertainty because of uncalibrated TPC"}; Configurable includeUnassigned{"includeUnassigned", false, "consider also tracks which are not assigned to any collision"}; Configurable fillTableOfCollIdsPerTrack{"fillTableOfCollIdsPerTrack", false, "fill additional table with vector of collision ids per track"}; + Configurable bcWindowForOneSigma{"bcWindowForOneSigma", 115, "BC window to be multiplied by the number of sigmas to define maximum window to be considered"}; CollisionAssociation collisionAssociator; diff --git a/Common/TableProducer/hmpConverter.cxx b/Common/TableProducer/hmpConverter.cxx new file mode 100644 index 00000000000..da4eeeb7bca --- /dev/null +++ b/Common/TableProducer/hmpConverter.cxx @@ -0,0 +1,62 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// HMPID converter to new format +// to be used with Run 2 converted data and older AO2Ds + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" + +using namespace o2; +using namespace o2::framework; + +struct hmpConverter { + Produces HMPID_001; + + void process(aod::HMPID_000 const& hmpLegacy, aod::Tracks const&) + { + for (auto& hmpData : hmpLegacy) { + + float phots[] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0.}; + auto trackid = hmpData.trackId(); + auto hmpidSignal = hmpData.hmpidSignal(); + auto hmpidXTrack = -999.; // dummy + auto hmpidYTrack = -999.; // dummy + auto hmpidXMip = -999.; // dummy + auto hmpidYMip = -999.; // dummy + auto hmpidNPhotons = hmpData.hmpidNPhotons(); + auto hmpidQMip = hmpData.hmpidQMip(); + auto hmpidClusSize = -999; // dummy + auto hmpidMom = -999; // dummy + auto hmpidPhotsCharge = phots; + + HMPID_001(trackid, + hmpidSignal, + hmpidXTrack, + hmpidYTrack, + hmpidXMip, + hmpidYMip, + hmpidNPhotons, + hmpidQMip, + hmpidClusSize, + hmpidMom, + hmpidPhotsCharge); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGLF/Tasks/QC/mcCollisionExtra.cxx b/Common/TableProducer/mcCollsExtra.cxx similarity index 98% rename from PWGLF/Tasks/QC/mcCollisionExtra.cxx rename to Common/TableProducer/mcCollsExtra.cxx index b63a054b86d..a642bf9d209 100644 --- a/PWGLF/Tasks/QC/mcCollisionExtra.cxx +++ b/Common/TableProducer/mcCollsExtra.cxx @@ -16,10 +16,10 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFQATables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" diff --git a/Common/TableProducer/mftmchMatchingML.cxx b/Common/TableProducer/mftmchMatchingML.cxx new file mode 100644 index 00000000000..eb632e1a060 --- /dev/null +++ b/Common/TableProducer/mftmchMatchingML.cxx @@ -0,0 +1,232 @@ +// Copyright 2020-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. + +#include +#include +#include +#include +#include +#include "Common/DataModel/MftmchMatchingML.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/trackUtilities.h" +#include "Common/Core/TrackSelection.h" +#include "ReconstructionDataFormats/TrackFwd.h" +#include "Math/SMatrix.h" +#include "DetectorsBase/Propagator.h" +#include "MFTTracking/Tracker.h" +#include "MCHTracking/TrackParam.h" +#include "MCHTracking/TrackExtrap.h" +#include "GlobalTracking/MatchGlobalFwd.h" +#include "CCDB/CcdbApi.h" +#include "Tools/ML/model.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::ml; +using o2::globaltracking::MatchingFunc_t; +using o2::track::TrackParCovFwd; +using o2::track::TrackParFwd; +using SMatrix55 = ROOT::Math::SMatrix>; +using SMatrix5 = ROOT::Math::SVector; + +struct mftmchMatchingML { + Produces fwdtrackml; + + float etalow = -4; + float etaup = -2.5; + float pDCAcutrAtBsorberEndlow1 = 17.6; + float pDCAcutrAtBsorberEndup1 = 26.5; + float pDCAcutrAtBsorberEndlow2 = 26.5; + float pDCAcutrAtBsorberEndup2 = 89.5; + float pDCAcutdcaup1 = 594; + float pDCAcutdcaup2 = 324; + float chi2up = 1000000; + float chi2MatchMCHMIDup = 1000000; + + Filter etaFilter = ((etalow < aod::fwdtrack::eta) && (etaup < aod::fwdtrack::eta)); + Filter pDcaFilter = (((pDCAcutrAtBsorberEndlow1 < aod::fwdtrack::rAtAbsorberEnd) && (aod::fwdtrack::rAtAbsorberEnd < pDCAcutrAtBsorberEndup1) && (aod::fwdtrack::pDca < pDCAcutdcaup1)) || ((pDCAcutrAtBsorberEndlow2 < aod::fwdtrack::rAtAbsorberEnd) && (aod::fwdtrack::rAtAbsorberEnd < pDCAcutrAtBsorberEndup2) && (aod::fwdtrack::pDca < pDCAcutdcaup2))); + Filter chi2Filter = (aod::fwdtrack::chi2 < chi2up); + Filter chi2MatchFilter = (aod::fwdtrack::chi2MatchMCHMID < chi2MatchMCHMIDup); + + Configurable cfgCCDBURL{"ccdb-url", "http://ccdb-test.cern.ch:8080", "URL of the CCDB repository"}; + Configurable cfgModelDir{"ccdb-path", "Users/m/mooya/models", "base path to the ONNX models"}; + Configurable cfgModelName{"ccdb-file", "model_LHC22o.onnx", "name of ONNX model file"}; + Configurable cfgThrScore{"threshold-score", 0.5, "Threshold value for matching score"}; + + Ort::Env env{ORT_LOGGING_LEVEL_WARNING, "model-explorer"}; + Ort::SessionOptions session_options; + std::shared_ptr onnx_session = nullptr; + OnnxModel model; + + template + std::vector getVariables(F const& fwdtrack, M const& mfttrack) + { + + static constexpr Double_t MatchingPlaneZ = -77.5; + + // propagate muontrack to matching position + double muonchi2 = fwdtrack.chi2(); + SMatrix5 muonpars(fwdtrack.x(), fwdtrack.y(), fwdtrack.phi(), fwdtrack.tgl(), fwdtrack.signed1Pt()); + std::vector muonv1; + SMatrix55 muoncovs(muonv1.begin(), muonv1.end()); + o2::track::TrackParCovFwd muonpars1{fwdtrack.z(), muonpars, muoncovs, muonchi2}; + muonpars1.propagateToZlinear(MatchingPlaneZ); + + // propagate mfttrack to matching position + double mftchi2 = mfttrack.chi2(); + SMatrix5 mftpars(mfttrack.x(), mfttrack.y(), mfttrack.phi(), mfttrack.tgl(), mfttrack.signed1Pt()); + std::vector mftv1; + SMatrix55 mftcovs(mftv1.begin(), mftv1.end()); + o2::track::TrackParCovFwd mftpars1{mfttrack.z(), mftpars, mftcovs, mftchi2}; + mftpars1.propagateToZlinear(MatchingPlaneZ); + + Float_t MFT_X = mftpars1.getX(); + Float_t MFT_Y = mftpars1.getY(); + Float_t MFT_Phi = mftpars1.getPhi(); + Float_t MFT_Tanl = mftpars1.getTanl(); + + Float_t MCH_X = muonpars1.getX(); + Float_t MCH_Y = muonpars1.getY(); + Float_t MCH_Phi = muonpars1.getPhi(); + Float_t MCH_Tanl = muonpars1.getTanl(); + + Float_t Ratio_X = MFT_X / MCH_X; + Float_t Ratio_Y = MFT_Y / MCH_Y; + Float_t Ratio_Phi = MFT_Phi / MCH_Phi; + Float_t Ratio_Tanl = MFT_Tanl / MCH_Tanl; + + Float_t Delta_X = MFT_X - MCH_X; + Float_t Delta_Y = MFT_Y - MCH_Y; + Float_t Delta_Phi = MFT_Phi - MCH_Phi; + Float_t Delta_Tanl = MFT_Tanl - MCH_Tanl; + + Float_t Delta_XY = sqrt(Delta_X * Delta_X + Delta_Y * Delta_Y); + + std::vector input_tensor_values{ + MFT_X, + MFT_Y, + MFT_Phi, + MFT_Tanl, + MCH_X, + MCH_Y, + MCH_Phi, + MCH_Tanl, + Delta_XY, + Delta_X, + Delta_Y, + Delta_Phi, + Delta_Tanl, + Ratio_X, + Ratio_Y, + Ratio_Phi, + Ratio_Tanl, + }; + return input_tensor_values; + } + + template + double matchONNX(F const& fwdtrack, M const& mfttrack) + { + std::vector input_names; + std::vector> input_shapes; + std::vector output_names; + std::vector> output_shapes; + + input_names = onnx_session->GetInputNames(); + input_shapes = onnx_session->GetInputShapes(); + output_names = onnx_session->GetOutputNames(); + output_shapes = onnx_session->GetOutputShapes(); + + auto input_shape = input_shapes[0]; + input_shape[0] = 1; + + std::vector input_tensor_values; + input_tensor_values = getVariables(fwdtrack, mfttrack); + + if (input_tensor_values[8] < 3) { + std::vector input_tensors; + input_tensors.push_back(Ort::Experimental::Value::CreateTensor(input_tensor_values.data(), input_tensor_values.size(), input_shape)); + + std::vector output_tensors = onnx_session->Run(input_names, input_tensors, output_names); + + const float* output_value = output_tensors[0].GetTensorData(); + + auto score = output_value[0]; + + return score; + } else { + auto score = 0; + return score; + } + }; + + void init(o2::framework::InitContext&) + { + o2::ccdb::CcdbApi ccdbApi; + std::map metadata; + + ccdbApi.init(cfgCCDBURL); + // retrieving onnx file from ccdb + std::string modelFile = cfgModelDir.value; + bool retrieveSuccess = ccdbApi.retrieveBlob(modelFile, ".", metadata, 1642502592629, false, cfgModelName.value); + + // start session + if (retrieveSuccess) { + std::map headers = ccdbApi.retrieveHeaders(modelFile, metadata, -1); + LOG(info) << "Network file downloaded from: " << modelFile << " to: " + << "." + << "/" << cfgModelName.value; + model.initModel(cfgModelName, false, 1, strtoul(headers["Valid-From"].c_str(), NULL, 0), strtoul(headers["Valid-Until"].c_str(), NULL, 0)); + onnx_session = model.getSession(); + } else { + LOG(info) << "Failed to retrieve Network file"; + } + } + + void process(aod::Collisions::iterator const& collision, soa::Filtered const& fwdtracks, aod::MFTTracks const& mfttracks) + { + for (auto& [fwdtrack, mfttrack] : combinations(CombinationsFullIndexPolicy(fwdtracks, mfttracks))) { + + if (fwdtrack.trackType() == aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { + double result = matchONNX(fwdtrack, mfttrack); + if (result > cfgThrScore) { + double mftchi2 = mfttrack.chi2(); + SMatrix5 mftpars(mfttrack.x(), mfttrack.y(), mfttrack.phi(), mfttrack.tgl(), mfttrack.signed1Pt()); + std::vector mftv1; + SMatrix55 mftcovs(mftv1.begin(), mftv1.end()); + o2::track::TrackParCovFwd mftpars1{mfttrack.z(), mftpars, mftcovs, mftchi2}; + mftpars1.propagateToZlinear(collision.posZ()); + + float dcaX = (mftpars1.getX() - collision.posX()); + float dcaY = (mftpars1.getY() - collision.posY()); + double px = fwdtrack.p() * sin(M_PI / 2 - atan(mfttrack.tgl())) * cos(mfttrack.phi()); + double py = fwdtrack.p() * sin(M_PI / 2 - atan(mfttrack.tgl())) * sin(mfttrack.phi()); + double pz = fwdtrack.p() * cos(M_PI / 2 - atan(mfttrack.tgl())); + fwdtrackml(fwdtrack.collisionId(), 0, mfttrack.x(), mfttrack.y(), mfttrack.z(), mfttrack.phi(), mfttrack.tgl(), fwdtrack.sign() / std::sqrt(std::pow(px, 2) + std::pow(py, 2)), fwdtrack.nClusters(), -1, -1, -1, -1, -1, result, mfttrack.globalIndex(), fwdtrack.globalIndex(), fwdtrack.mchBitMap(), fwdtrack.midBitMap(), fwdtrack.midBoards(), mfttrack.trackTime(), mfttrack.trackTimeRes(), mfttrack.eta(), std::sqrt(std::pow(px, 2) + std::pow(py, 2)), std::sqrt(std::pow(px, 2) + std::pow(py, 2) + std::pow(pz, 2)), dcaX, dcaY); + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Common/TableProducer/multiplicityExtraTable.cxx b/Common/TableProducer/multiplicityExtraTable.cxx new file mode 100644 index 00000000000..729d90fa8c4 --- /dev/null +++ b/Common/TableProducer/multiplicityExtraTable.cxx @@ -0,0 +1,120 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#include "Framework/ConfigParamSpec.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "DataFormatsFIT/Triggers.h" +#include "TableHelper.h" + +#include "CCDB/CcdbApi.h" +#include "CommonDataFormat/BunchFilling.h" +#include +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using BCPattern = std::bitset; +const int nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; + +struct MultiplicityExtraTable { + Produces multBC; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + BCPattern CollidingBunch; + + int newRunNumber = -999; + int oldRunNumber = -999; + + void init(InitContext& context) + { + ccdbApi.init("http://alice-ccdb.cern.ch"); + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + + using BCsWithRun3Matchings = soa::Join; + + void process(BCsWithRun3Matchings::iterator const& bc, aod::FV0As const&, aod::FT0s const& ft0s, aod::FDDs const&) + { + bool Tvx = false; + bool isFV0OrA = false; + float multFT0C = 0.f; + float multFT0A = 0.f; + float multFV0A = 0.f; + uint8_t multFV0TriggerBits = 0; + uint64_t multBCTriggerMask = bc.triggerMask(); + + // initialize - from Arvind + newRunNumber = bc.runNumber(); + int localBC = bc.globalBC() % nBCsPerOrbit; + + if (newRunNumber != oldRunNumber) { + uint64_t ts{}; + std::map metadataRCT, headers; + headers = ccdbApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", newRunNumber), metadataRCT, -1); + ts = atol(headers["SOR"].c_str()); + + LOG(info) << " newRunNumber " << newRunNumber << " time stamp " << ts; + oldRunNumber = newRunNumber; + std::map mapMetadata; + std::map mapHeader; + auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", ts); + CollidingBunch = grplhcif->getBunchFilling().getBCPattern(); + for (int i = 0; i < (int)CollidingBunch.size(); i++) { + if (CollidingBunch.test(i)) { + LOG(info) << i << " "; + } + } + } // new run number + + bool collidingBC = CollidingBunch.test(localBC); + + if (bc.has_ft0()) { + auto ft0 = bc.ft0(); + std::bitset<8> triggers = ft0.triggerMask(); + Tvx = triggers[o2::fit::Triggers::bitVertex]; + multFV0TriggerBits = static_cast(triggers.to_ulong()); + + // calculate T0 charge + for (auto amplitude : ft0.amplitudeA()) { + multFT0A += amplitude; + } + for (auto amplitude : ft0.amplitudeC()) { + multFT0C += amplitude; + } + + if (bc.has_fv0a()) { + auto fv0 = bc.fv0a(); + std::bitset<8> fV0Triggers = fv0.triggerMask(); + + for (auto amplitude : fv0.amplitude()) { + multFV0A += amplitude; + } + isFV0OrA = fV0Triggers[o2::fit::Triggers::bitA]; + } // fv0 + } + + multBC(multFT0A, multFT0C, multFV0A, Tvx, isFV0OrA, multFV0TriggerBits, multBCTriggerMask, collidingBC); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"multiplicity-extra-table"})}; +} diff --git a/Common/TableProducer/multiplicityTable.cxx b/Common/TableProducer/multiplicityTable.cxx index fa4a4c09031..3a217b046b8 100644 --- a/Common/TableProducer/multiplicityTable.cxx +++ b/Common/TableProducer/multiplicityTable.cxx @@ -19,11 +19,19 @@ using namespace o2::framework; #include #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "TableHelper.h" #include "iostream" +#define bitcheck(var, nbit) ((var) & (1 << (nbit))) + struct MultiplicityTableTaskIndexed { SliceCache cache; - Produces mult; + Produces multFV0; + Produces multFT0; + Produces multFDD; + Produces multZDC; + Produces multBarrel; + Produces multExtra; Produces multzeq; // For vertex-Z corrections in calibration @@ -37,8 +45,12 @@ struct MultiplicityTableTaskIndexed { Preslice perCol = aod::track::collisionId; Preslice perColIU = aod::track::collisionId; + using BCsWithRun3Matchings = soa::Join; + // Configurable Configurable doVertexZeq{"doVertexZeq", 1, "if 1: do vertex Z eq mult table"}; + Configurable populateMultExtra{"populateMultExtra", true, "if 1: populate table with some extra QA information"}; + Configurable fractionOfEvents{"fractionOfEvents", 2.0, "Fractions of events to keep in case the QA is used"}; int mRunNumber; bool lCalibLoaded; @@ -50,14 +62,31 @@ struct MultiplicityTableTaskIndexed { TProfile* hVtxZFDDC; TProfile* hVtxZNTracks; + unsigned int randomSeed = 0; void init(InitContext& context) { + randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); if (doprocessRun2 == false && doprocessRun3 == false) { LOGF(fatal, "Neither processRun2 nor processRun3 enabled. Please choose one."); } if (doprocessRun2 == true && doprocessRun3 == true) { LOGF(fatal, "Cannot enable processRun2 and processRun3 at the same time. Please choose one."); } + if (fractionOfEvents <= 1.f && isTableRequiredInWorkflow(context, "FV0Mults")) { + LOG(fatal) << "Cannot have a fraction of events <= 1 and multiplicity table consumed."; + } + if (fractionOfEvents <= 1.f && isTableRequiredInWorkflow(context, "FT0Mults")) { + LOG(fatal) << "Cannot have a fraction of events <= 1 and multiplicity table consumed."; + } + if (fractionOfEvents <= 1.f && isTableRequiredInWorkflow(context, "FDDMults")) { + LOG(fatal) << "Cannot have a fraction of events <= 1 and multiplicity table consumed."; + } + if (fractionOfEvents <= 1.f && isTableRequiredInWorkflow(context, "ZDCMults")) { + LOG(fatal) << "Cannot have a fraction of events <= 1 and multiplicity table consumed."; + } + if (fractionOfEvents <= 1.f && isTableRequiredInWorkflow(context, "BarrelMults")) { + LOG(fatal) << "Cannot have a fraction of events <= 1 and multiplicity table consumed."; + } mRunNumber = 0; lCalibLoaded = false; @@ -76,12 +105,12 @@ struct MultiplicityTableTaskIndexed { } void processRun2(aod::Run2MatchedSparse::iterator const& collision, - Run2Tracks const& tracksExtra, + Run2Tracks const&, aod::BCs const&, aod::Zdcs const&, - aod::FV0As const& fv0as, + aod::FV0As const&, aod::FV0Cs const& fv0cs, - aod::FT0s const& ft0s) + aod::FT0s const&) { float multFV0A = 0.f; float multFV0C = 0.f; @@ -126,35 +155,48 @@ struct MultiplicityTableTaskIndexed { } LOGF(debug, "multFV0A=%5.0f multFV0C=%5.0f multFT0A=%5.0f multFT0C=%5.0f multFDDA=%5.0f multFDDC=%5.0f multZNA=%6.0f multZNC=%6.0f multTracklets=%i multTPC=%i", multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTPC); - mult(multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTPC, multNContribs, multNContribsEta1, multNContribsEtaHalf); + multFV0(multFV0A, multFV0C); + multFT0(multFT0A, multFT0C); + multFDD(multFDDA, multFDDC); + multZDC(multZNA, multZNC); + multBarrel(multTracklets, multTPC, multNContribs, multNContribsEta1, multNContribsEtaHalf); } - PROCESS_SWITCH(MultiplicityTableTaskIndexed, processRun2, "Produce Run 2 multiplicity tables", true); + PROCESS_SWITCH(MultiplicityTableTaskIndexed, processRun2, "Produce Run 2 multiplicity tables", false); using Run3Tracks = soa::Join; Partition tracksIUWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0); + Partition pvAllContribTracksIU = ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); Partition pvContribTracksIU = (nabs(aod::track::eta) < 0.8f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); Partition pvContribTracksIUEta1 = (nabs(aod::track::eta) < 1.0f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); Partition pvContribTracksIUEtaHalf = (nabs(aod::track::eta) < 0.5f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); void processRun3(soa::Join const& collisions, - Run3Tracks const& tracksExtra, - soa::Join const& bcs, - aod::Zdcs const& zdcs, - aod::FV0As const& fv0as, - aod::FT0s const& ft0s, - aod::FDDs const& fdds) + Run3Tracks const&, + BCsWithRun3Matchings const&, + aod::Zdcs const&, + aod::FV0As const&, + aod::FT0s const&, + aod::FDDs const&) { // reserve memory - mult.reserve(collisions.size()); + multFV0.reserve(collisions.size()); + multFT0.reserve(collisions.size()); + multFDD.reserve(collisions.size()); + multZDC.reserve(collisions.size()); + multBarrel.reserve(collisions.size()); multzeq.reserve(collisions.size()); for (auto const& collision : collisions) { + if ((fractionOfEvents < 1.f) && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > fractionOfEvents) { // Skip events that are not sampled (only for the QA) + return; + } + float multFV0A = 0.f; float multFV0C = 0.f; float multFT0A = 0.f; float multFT0C = 0.f; float multFDDA = 0.f; float multFDDC = 0.f; - float multZNA = 0.f; - float multZNC = 0.f; + float multZNA = -1.f; + float multZNC = -1.f; int multTracklets = 0; float multZeqFV0A = 0.f; @@ -165,6 +207,7 @@ struct MultiplicityTableTaskIndexed { float multZeqNContribs = 0.f; auto tracksGrouped = tracksIUWithTPC->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto pvAllContribsGrouped = pvAllContribTracksIU->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto pvContribsGrouped = pvContribTracksIU->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto pvContribsEta1Grouped = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto pvContribsEtaHalfGrouped = pvContribTracksIUEtaHalf->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); @@ -174,7 +217,7 @@ struct MultiplicityTableTaskIndexed { int multNContribsEtaHalf = pvContribsEtaHalfGrouped.size(); /* check the previous run number */ - auto bc = collision.bc_as>(); + const auto& bc = collision.bc_as(); if (doVertexZeq > 0) { if (bc.runNumber() != mRunNumber) { mRunNumber = bc.runNumber(); // mark this run as at least tried @@ -198,6 +241,11 @@ struct MultiplicityTableTaskIndexed { } } } + if (bc.has_zdc()) { + multZNA = bc.zdc().amplitudeZNA(); + multZNC = bc.zdc().amplitudeZNC(); + } + // using FT0 row index from event selection task if (collision.has_foundFT0()) { auto ft0 = collision.foundFT0(); @@ -235,11 +283,42 @@ struct MultiplicityTableTaskIndexed { } LOGF(debug, "multFV0A=%5.0f multFV0C=%5.0f multFT0A=%5.0f multFT0C=%5.0f multFDDA=%5.0f multFDDC=%5.0f multZNA=%6.0f multZNC=%6.0f multTracklets=%i multTPC=%i", multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTPC); - mult(multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTPC, multNContribs, multNContribsEta1, multNContribsEtaHalf); + multFV0(multFV0A, multFV0C); + multFT0(multFT0A, multFT0C); + multFDD(multFDDA, multFDDC); + multZDC(multZNA, multZNC); + multBarrel(multTracklets, multTPC, multNContribs, multNContribsEta1, multNContribsEtaHalf); multzeq(multZeqFV0A, multZeqFT0A, multZeqFT0C, multZeqFDDA, multZeqFDDC, multZeqNContribs); + + if (populateMultExtra) { + int nHasITS = 0, nHasTPC = 0, nHasTOF = 0, nHasTRD = 0; + int nITSonly = 0, nTPConly = 0, nITSTPC = 0; + for (auto track : pvAllContribsGrouped) { + if (track.hasITS()) { + nHasITS++; + if (track.hasTPC()) + nITSTPC++; + if (!track.hasTPC() && !track.hasTOF() && !track.hasTRD()) + nITSonly++; + } + if (track.hasTPC()) { + nHasTPC++; + if (!track.hasITS() && !track.hasTOF() && !track.hasTRD()) + nTPConly++; + } + if (track.hasTOF()) + nHasTOF++; + if (track.hasTRD()) + nHasTRD++; + }; + + int bcNumber = bc.globalBC() % 3564; + + multExtra(static_cast(collision.numContrib()), collision.chi2(), collision.collisionTimeRes(), mRunNumber, collision.posZ(), collision.sel8(), nHasITS, nHasTPC, nHasTOF, nHasTRD, nITSonly, nTPConly, nITSTPC, bcNumber); + } } } - PROCESS_SWITCH(MultiplicityTableTaskIndexed, processRun3, "Produce Run 3 multiplicity tables", false); + PROCESS_SWITCH(MultiplicityTableTaskIndexed, processRun3, "Produce Run 3 multiplicity tables", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/Common/TableProducer/qVectorsTable.cxx b/Common/TableProducer/qVectorsTable.cxx new file mode 100644 index 00000000000..442739f4462 --- /dev/null +++ b/Common/TableProducer/qVectorsTable.cxx @@ -0,0 +1,407 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file qVectorsTable.cxx +/// \author Cindy Mordasini +/// \author Anna Önnerstad +/// +/// \brief Task calculating the Q-vectors for each collision in a bunch crossing +/// (with or without corrections) and save the results in a dedicated table. +/// + +// C++/ROOT includes. +#include +#include +#include +#include +#include + +// o2Physics includes. +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/EventPlaneHelper.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" + +#include "Common/DataModel/Qvectors.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +// o2 includes. +#include "CCDB/BasicCCDBManager.h" +#include "DetectorsCommonDataFormats/AlignParam.h" + +using namespace o2; +using namespace o2::framework; + +using MyCollisions = soa::Join; + +using MyTracks = soa::Join; + +struct qVectorsTable { + // Configurables. + struct : ConfigurableGroup { + Configurable cfgURL{"cfgURL", + "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; + Configurable nolaterthan{"ccdb-no-later-than", + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), + "Latest acceptable timestamp of creation for the object"}; + } cfgCcdbParam; + + Configurable cfgCentEsti{"cfgCentEsti", + 2, "Centrality estimator (Run3): 0 = FT0M, 1 = FT0A, 2 = FT0C, 3 = FV0A"}; + + Configurable cfgMultName{"cfgDetName", "FT0C", "The name of detector to be analyzed, available systems: FT0A, FT0C, FV0A, TPCF, TPCB"}; + + // LOKI: We have here all centrality estimators for Run 3 (except FDDM and NTPV), + // but the Q-vectors are calculated only for some of them. + // FIXME: 6 correction factors for each centrality and 8 centrality intervals are hard-coded. + + Configurable> cfgCorr{"cfgCorr", std::vector{0.0}, "Correction constants for detector"}; + Configurable> cfgBPosCorr{"cfgBPosCorr", std::vector{0.0}, "Correction constants for positive TPC tracks"}; + Configurable> cfgBNegCorr{"cfgBNegCorr", std::vector{0.0}, "Correction constants for negative TPC tracks"}; + + Configurable cfgMinPtOnTPC{"cfgMinPtOnTPC", 0.15, "minimum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"}; + Configurable cfgMaxPtOnTPC{"cfgMaxPtOnTPC", 5., "maximum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"}; + + // Table. + Produces qVector; + + // Enable access to the CCDB for the offset and correction constants and save them + // in dedicated variables. + Service ccdb; + std::vector* offsetFT0; + std::vector* offsetFV0; + + // Variables for other classes. + EventPlaneHelper helperEP; + + HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + void init(InitContext const&) + { + // Setup the access to the CCDB objects of interest. + ccdb->setURL(cfgCcdbParam.cfgURL); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(cfgCcdbParam.nolaterthan.value); + + LOGF(info, "Getting alignment offsets from the CCDB..."); + offsetFT0 = ccdb->getForTimeStamp>("FT0/Calib/Align", + cfgCcdbParam.nolaterthan.value); + offsetFV0 = ccdb->getForTimeStamp>("FV0/Calib/Align", + cfgCcdbParam.nolaterthan.value); + + // Get the offset values for the different parts of FIT. + if (offsetFT0 != nullptr) { + // FT0 has vector size 2: one element for A side, one for C side. + helperEP.SetOffsetFT0A((*offsetFT0)[0].getX(), (*offsetFT0)[0].getY()); + helperEP.SetOffsetFT0C((*offsetFT0)[1].getX(), (*offsetFT0)[1].getY()); + } else { + LOGF(fatal, "Could not get the alignment parameters for FT0."); + } + + if (offsetFV0 != nullptr) { + // FV0 has vector size 2: one element for left side, one for right side. + helperEP.SetOffsetFV0left((*offsetFV0)[0].getX(), (*offsetFV0)[0].getY()); + helperEP.SetOffsetFV0right((*offsetFV0)[1].getX(), (*offsetFV0)[1].getY()); + } else { + LOGF(fatal, "Could not get the alignment parameters for FV0."); + } + + if (cfgCorr->size() < 48) { + LOGF(fatal, "No proper correction factor assigned"); + } + if (cfgBPosCorr->size() < 48) { + LOGF(fatal, "No proper correction factor assigned"); + } + if (cfgBNegCorr->size() < 48) { + LOGF(fatal, "No proper correction factor assigned"); + } + //|| cfgBPosCent.size() != 48 || cfgBNegCent.size() != 48) { + /* // Debug printing. + printf("Offset for FT0A: x = %.3f y = %.3f\n", (*offsetFT0)[0].getX(), (*offsetFT0)[0].getY()); + printf("Offset for FT0C: x = %.3f y = %.3f\n", (*offsetFT0)[1].getX(), (*offsetFT0)[1].getY()); + printf("Offset for FV0-left: x = %.3f y = %.3f\n", (*offsetFV0)[0].getX(), (*offsetFV0)[0].getY()); + printf("Offset for FV0-right: x = %.3f y = %.3f\n", (*offsetFV0)[1].getX(), (*offsetFV0)[1].getY()); + */ + + // LOKI: If we need to access the corrections from the CCDB, insert that here. + // In the meantime, call upon the external files with all the configurables. + + AxisSpec axisPt = {40, 0.0, 4.0}; + AxisSpec axisEta = {32, -0.8, 0.8}; + AxisSpec axisPhi = {32, -TMath::Pi(), TMath::Pi()}; + AxisSpec axixCent = {20, 0, 100}; + + histosQA.add("ChTracks", "", {HistType::kTHnSparseF, {axisPt, axisEta, axisPhi, axixCent}}); + } + + template + bool SelTrack(const TrackType track) + { + if (track.pt() < cfgMinPtOnTPC) + return false; + if (track.pt() > cfgMaxPtOnTPC) + return false; + if (!track.passedITSNCls()) + return false; + if (!track.passedITSChi2NDF()) + return false; + if (!track.passedITSHits()) + return false; + if (!track.passedITSNCls()) + return false; + if (!track.passedTPCCrossedRowsOverNCls()) + return false; + if (!track.passedTPCChi2NDF()) + return false; + if (!track.passedDCAxy()) + return false; + if (!track.passedDCAz()) + return false; + + return true; + } + + void process(MyCollisions::iterator const& coll, aod::FT0s const& ft0s, aod::FV0As const& fv0s, MyTracks const& tracks) //, aod::FV0Cs const&) + // void process(MyCollisions::iterator const& coll, aod::FT0s const& ft0s, aod::FV0As const& fv0s) + { + // Get the centrality value for all subscribed estimators and takes the one + // corresponding to cfgCentEsti. Reject also the events with invalid values. + // NOTE: centFDDM and centNTPV not implemented as it makes the compilation crashes... + float centAllEstim[4] = { + coll.centFT0M(), coll.centFT0A(), coll.centFT0C(), + coll.centFV0A()}; + float cent = centAllEstim[cfgCentEsti]; + if (cent < 0. || cent > 100.) { + return; + } + + // Calculate the Q-vectors values for this event. + // TODO: Add here qVect for other detectors,... + float qVectFT0A[2] = {0.}; // Real and imaginary parts of the Q-vector in FT0A. + float qVectFT0C[2] = {0.}; // Real and imaginary parts of the Q-vector in FT0C. + float qVectFV0A[2] = {0.}; // Real and imaginary parts of the Q-vector in FV0A. + + float qVectBPos[2] = {0.}; + float qVectBNeg[2] = {0.}; + + TComplex QvecDet(0); // Complex value of the Q-vector for any detector. + double sumAmplDet = 0.; // Sum of the amplitudes of all non-dead channels in any detector. + + /// First check if the collision has a found FT0. If yes, calculate the + /// Q-vectors for FT0A and FT0C (both real and imaginary parts). If no, + /// attribute dummy values to the corresponding qVect. + if (coll.has_foundFT0()) { + auto ft0 = coll.foundFT0(); + + // Iterate over the non-dead channels for FT0-A to get the total Q-vector + // and sum of amplitudes. + for (std::size_t iChA = 0; iChA < ft0.channelA().size(); iChA++) { + // Get first the corresponding amplitude. + float ampl = ft0.amplitudeA()[iChA]; + + // Update the Q-vector and sum of amplitudes using the helper function. + // LOKI: Note this assumes nHarmo = 2!! Likely generalise in the future. + helperEP.SumQvectors(0, iChA, ampl, QvecDet, sumAmplDet); + } // Go to the next channel iChA. + + // Set the Qvectors for FT0A with the normalised Q-vector values if the sum of + // amplitudes is non-zero. Otherwise, set it to a dummy 999. + if (sumAmplDet > 1e-8) { + QvecDet /= sumAmplDet; + qVectFT0A[0] = QvecDet.Re(); + qVectFT0A[1] = QvecDet.Im(); + // printf("qVectFT0A[0] = %.2f ; qVectFT0A[1] = %.2f \n", qVectFT0A[0], qVectFT0A[1]); // Debug printing. + } else { + qVectFT0A[0] = 999.; + qVectFT0A[1] = 999.; + } + + // Repeat the procedure with FT0-C for the found FT0. + // Start by resetting to zero the intermediate quantities. + QvecDet = TComplex(0., 0.); + sumAmplDet = 0; + for (std::size_t iChC = 0; iChC < ft0.channelC().size(); iChC++) { + // iChC ranging from 0 to max 112. We need to add 96 (= max channels in FT0-A) + // to ensure a proper channel number in FT0 as a whole. + float ampl = ft0.amplitudeC()[iChC]; + helperEP.SumQvectors(0, iChC + 96, ampl, QvecDet, sumAmplDet); + } + + if (sumAmplDet > 1e-8) { + QvecDet /= sumAmplDet; + qVectFT0C[0] = QvecDet.Re(); + qVectFT0C[1] = QvecDet.Im(); + // printf("qVectFT0C[0] = %.2f ; qVectFT0C[1] = %.2f \n", qVectFT0C[0], qVectFT0C[1]); // Debug printing. + } else { + qVectFT0C[0] = 999.; + qVectFT0C[1] = 999.; + } + } else { + qVectFT0A[0] = -999.; + qVectFT0A[1] = -999.; + qVectFT0C[0] = -999.; + qVectFT0C[1] = -999.; + } + + /// Repeat the procedure for FV0 if one has been found for this collision. + /// Again reset the intermediate quantities to zero. + QvecDet = TComplex(0., 0.); + sumAmplDet = 0; + if (coll.has_foundFV0()) { + auto fv0 = coll.foundFV0(); + + for (std::size_t iCh = 0; iCh < fv0.channel().size(); iCh++) { + float ampl = fv0.amplitude()[iCh]; + helperEP.SumQvectors(1, iCh, ampl, QvecDet, sumAmplDet); + } + + if (sumAmplDet > 1e-8) { + QvecDet /= sumAmplDet; + qVectFV0A[0] = QvecDet.Re(); + qVectFV0A[1] = QvecDet.Im(); + // printf("qVectFV0[0] = %.2f ; qVectFV0[1] = %.2f \n", qVectFV0[0], qVectFV0[1]); // Debug printing. + } else { + qVectFV0A[0] = 999.; + qVectFV0A[1] = 999.; + } + } else { + qVectFV0A[0] = -999.; + qVectFV0A[1] = -999.; + } + + qVectBPos[0] = 0.; + qVectBPos[1] = 0.; + qVectBNeg[0] = 0.; + qVectBNeg[1] = 0.; + + int nTrkBPos = 0; + int nTrkBNeg = 0; + for (auto& trk : tracks) { + if (!SelTrack(trk)) + continue; + histosQA.fill(HIST("ChTracks"), trk.pt(), trk.eta(), trk.phi(), cent); + if (abs(trk.eta()) < 0.1 || abs(trk.eta()) > 0.8) + continue; + if (trk.eta() > 0) { + qVectBPos[0] += trk.pt() * TMath::Cos(2. * trk.phi()) / 20.; + qVectBPos[1] += trk.pt() * TMath::Sin(2. * trk.phi()) / 20.; + nTrkBPos++; + } else if (trk.eta() < 0) { + qVectBNeg[0] += trk.pt() * TMath::Cos(2. * trk.phi()) / 20.; + qVectBNeg[1] += trk.pt() * TMath::Sin(2. * trk.phi()) / 20.; + nTrkBNeg++; + } + } // FIXME: ARBITRARY SCALE FACTOR OF 20 + + /// TODO: Repeat here the procedure for any other Qvector columns. + /// Do not forget to add the configurable for the correction constants. + + // Apply the correction constants (configurable) to the obtained Q-vectors. + // The function needs to be called for each detector/set separately. + // A correction constant set to zero means this correction is not applied. + // LOKI: Each detector must have their own vector of correction constants. + int cBin = helperEP.GetCentBin(cent); + + float qVector_final[2] = {0.}; + if (cfgMultName.value == "FT0A") { + qVector_final[0] = qVectFT0A[0]; + qVector_final[1] = qVectFT0A[1]; + } else if (cfgMultName.value == "FT0C") { + qVector_final[0] = qVectFT0C[0]; + qVector_final[1] = qVectFT0C[1]; + } else if (cfgMultName.value == "FV0A") { + qVector_final[0] = qVectFV0A[0]; + qVector_final[1] = qVectFV0A[1]; + } + + float qVector_uncor[2]; + float qVector_rectr[2]; + float qVector_twist[2]; + + float qVectBPos_uncor[2]; + float qVectBPos_rectr[2]; + float qVectBPos_twist[2]; + float qVectBPos_final[2]; + + float qVectBNeg_uncor[2]; + float qVectBNeg_rectr[2]; + float qVectBNeg_twist[2]; + float qVectBNeg_final[2]; + + for (int i = 0; i < 2; i++) { + qVector_uncor[i] = qVector_final[i]; + qVector_rectr[i] = qVector_final[i]; + qVector_twist[i] = qVector_final[i]; + + qVectBPos_uncor[i] = qVectBPos[i]; + qVectBPos_rectr[i] = qVectBPos[i]; + qVectBPos_twist[i] = qVectBPos[i]; + qVectBPos_final[i] = qVectBPos[i]; + + qVectBNeg_uncor[i] = qVectBNeg[i]; + qVectBNeg_rectr[i] = qVectBNeg[i]; + qVectBNeg_twist[i] = qVectBNeg[i]; + qVectBNeg_final[i] = qVectBNeg[i]; + } + + helperEP.DoRecenter(qVector_rectr[0], qVector_rectr[1], cfgCorr->at(cBin * 6), cfgCorr->at(cBin * 6 + 1)); + + helperEP.DoRecenter(qVector_twist[0], qVector_twist[1], cfgCorr->at(cBin * 6), cfgCorr->at(cBin * 6 + 1)); + helperEP.DoTwist(qVector_twist[0], qVector_twist[1], cfgCorr->at(cBin * 6 + 2), cfgCorr->at(cBin * 6 + 3)); + + helperEP.DoRecenter(qVector_final[0], qVector_final[1], cfgCorr->at(cBin * 6), cfgCorr->at(cBin * 6 + 1)); + helperEP.DoTwist(qVector_final[0], qVector_final[1], cfgCorr->at(cBin * 6 + 2), cfgCorr->at(cBin * 6 + 3)); + helperEP.DoRescale(qVector_final[0], qVector_final[1], cfgCorr->at(cBin * 6 + 4), cfgCorr->at(cBin * 6 + 5)); + + helperEP.DoRecenter(qVectBPos_rectr[0], qVectBPos_rectr[1], cfgBPosCorr->at(cBin * 6), cfgBPosCorr->at(cBin * 6 + 1)); + + helperEP.DoRecenter(qVectBPos_twist[0], qVectBPos_twist[1], cfgBPosCorr->at(cBin * 6), cfgBPosCorr->at(cBin * 6 + 1)); + helperEP.DoTwist(qVectBPos_twist[0], qVectBPos_twist[1], cfgBPosCorr->at(cBin * 6 + 2), cfgBPosCorr->at(cBin * 6 + 3)); + + helperEP.DoRecenter(qVectBPos_final[0], qVectBPos_final[1], cfgBPosCorr->at(cBin * 6), cfgBPosCorr->at(cBin * 6 + 1)); + helperEP.DoTwist(qVectBPos_final[0], qVectBPos_final[1], cfgBPosCorr->at(cBin * 6 + 2), cfgBPosCorr->at(cBin * 6 + 3)); + helperEP.DoRescale(qVectBPos_final[0], qVectBPos_final[1], cfgBPosCorr->at(cBin * 6 + 4), cfgBPosCorr->at(cBin * 6 + 5)); + + helperEP.DoRecenter(qVectBNeg_rectr[0], qVectBNeg_rectr[1], cfgBNegCorr->at(cBin * 6), cfgBNegCorr->at(cBin * 6 + 1)); + + helperEP.DoRecenter(qVectBNeg_twist[0], qVectBNeg_twist[1], cfgBNegCorr->at(cBin * 6), cfgBNegCorr->at(cBin * 6 + 1)); + helperEP.DoTwist(qVectBNeg_twist[0], qVectBNeg_twist[1], cfgBNegCorr->at(cBin * 6 + 2), cfgBNegCorr->at(cBin * 6 + 3)); + + helperEP.DoRecenter(qVectBNeg_final[0], qVectBNeg_final[1], cfgBNegCorr->at(cBin * 6), cfgBNegCorr->at(cBin * 6 + 1)); + helperEP.DoTwist(qVectBNeg_final[0], qVectBNeg_final[1], cfgBNegCorr->at(cBin * 6 + 2), cfgBNegCorr->at(cBin * 6 + 3)); + helperEP.DoRescale(qVectBNeg_final[0], qVectBNeg_final[1], cfgBNegCorr->at(cBin * 6 + 4), cfgBNegCorr->at(cBin * 6 + 5)); + + // Fill the columns of the Qvectors table. + qVector(cent, cBin, + qVector_uncor[0], qVector_uncor[1], qVector_rectr[0], qVector_rectr[1], + qVector_twist[0], qVector_twist[1], qVector_final[0], qVector_final[1], + qVectBPos_uncor[0], qVectBPos_uncor[1], qVectBPos_rectr[0], qVectBPos_rectr[1], + qVectBPos_twist[0], qVectBPos_twist[1], qVectBPos_final[0], qVectBPos_final[1], + qVectBNeg_uncor[0], qVectBNeg_uncor[1], qVectBNeg_rectr[0], qVectBNeg_rectr[1], + qVectBNeg_twist[0], qVectBNeg_twist[1], qVectBNeg_final[0], qVectBNeg_final[1], + nTrkBPos, nTrkBNeg); + } // End process. +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Common/TableProducer/trackToCollisionAssociator.cxx b/Common/TableProducer/trackToCollisionAssociator.cxx index b39d9f31f32..62d90edaa9f 100644 --- a/Common/TableProducer/trackToCollisionAssociator.cxx +++ b/Common/TableProducer/trackToCollisionAssociator.cxx @@ -38,6 +38,7 @@ struct TrackToCollisionAssociation { Configurable usePVAssociation{"usePVAssociation", true, "if the track is a PV contributor, use the collision time for it"}; Configurable includeUnassigned{"includeUnassigned", false, "consider also tracks which are not assigned to any collision"}; Configurable fillTableOfCollIdsPerTrack{"fillTableOfCollIdsPerTrack", false, "fill additional table with vector of collision ids per track"}; + Configurable bcWindowForOneSigma{"bcWindowForOneSigma", 60, "BC window to be multiplied by the number of sigmas to define maximum window to be considered"}; CollisionAssociation collisionAssociator; @@ -61,6 +62,7 @@ struct TrackToCollisionAssociation { collisionAssociator.setUsePvAssociation(usePVAssociation); collisionAssociator.setIncludeUnassigned(includeUnassigned); collisionAssociator.setFillTableOfCollIdsPerTrack(fillTableOfCollIdsPerTrack); + collisionAssociator.setBcWindow(bcWindowForOneSigma); } void processAssocWithTime(Collisions const& collisions, TracksWithSel const& tracksUnfiltered, TracksWithSelFilter const& tracks, AmbiguousTracks const& ambiguousTracks, BCs const& bcs) diff --git a/Common/TableProducer/tracksExtraConverter.cxx b/Common/TableProducer/tracksExtraConverter.cxx new file mode 100644 index 00000000000..b097cb7c4a3 --- /dev/null +++ b/Common/TableProducer/tracksExtraConverter.cxx @@ -0,0 +1,78 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file tracksExtraConverter.cxx +/// \brief Converts TracksExtra table from version 000 to 001 + +/// This task allows for the conversion of the TracksExtra table from version 000 to 001. +/// The conversion is needed because the table has been extended with the ITSClusterSize column +/// and the ITSClusterMap column is evaluated dynamically from it. +/// In the converter a dummy ITSClusterSize column is filled with overflows if a hit in the layer is present + +/// \author F.Mazzaschi + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" + +using namespace o2; +using namespace o2::framework; + +struct TracksExtraConverter { + Produces tracksExtra_001; + void process(aod::TracksExtra_000 const& tracksExtra_000) + { + + for (const auto& track0 : tracksExtra_000) { + + uint32_t itsClusterSizes = 0; + for (int layer = 0; layer < 7; layer++) { + if (track0.itsClusterMap() & (1 << layer)) { + itsClusterSizes |= (0xf << (layer * 4)); + } + } + + tracksExtra_001(track0.tpcInnerParam(), + track0.flags(), + itsClusterSizes, + track0.tpcNClsFindable(), + track0.tpcNClsFindableMinusFound(), + track0.tpcNClsFindableMinusCrossedRows(), + track0.tpcNClsShared(), + track0.trdPattern(), + track0.itsChi2NCl(), + track0.tpcChi2NCl(), + track0.trdChi2(), + track0.tofChi2(), + track0.tpcSignal(), + track0.trdSignal(), + track0.length(), + track0.tofExpMom(), + track0.trackEtaEmcal(), + track0.trackPhiEmcal(), + track0.trackTime(), + track0.trackTimeRes()); + } + } +}; + +/// Spawn the extended table for TracksExtra001 to avoid the call to the internal spawner and a consequent circular dependency +struct TracksExtraSpawner { + Spawns tracksExtra_001; +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + }; +} diff --git a/Common/TableProducer/trackselection.cxx b/Common/TableProducer/trackselection.cxx index 73ceb14fdb2..7ae8930de17 100644 --- a/Common/TableProducer/trackselection.cxx +++ b/Common/TableProducer/trackselection.cxx @@ -24,6 +24,7 @@ #include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/trackUtilities.h" +#include "TableHelper.h" using namespace o2; using namespace o2::framework; @@ -37,7 +38,8 @@ using namespace o2::framework::expressions; struct TrackSelectionTask { // FIXME: this will be removed once we can get this via meta data Configurable isRun3{"isRun3", false, "temp option to enable run3 mode"}; - Configurable produceFBextendedTable{"produceFBextendedTable", false, "option to produce table with FB selection information"}; + Configurable produceTable{"produceTable", -1, "option to produce the standard table table with the track selection. -1 autosetup, 0 dislabled, 1 enabled"}; + Configurable produceFBextendedTable{"produceFBextendedTable", -1, "option to produce table with FB selection information. -1 autosetup, 0 dislabled, 1 enabled"}; Configurable compatibilityIU{"compatibilityIU", false, "compatibility option to allow the processing of tracks before the introduction of IU tracks"}; Configurable itsMatching{"itsMatching", 0, "condition for ITS matching (0: Run2 SPD kAny, 1: Run3ITSibAny, 2: Run3ITSallAny, 3: Run3ITSall7Layers)"}; Configurable dcaSetup{"dcaSetup", 0, "dca setup: (0: default, 1: ppPass3)"}; @@ -56,8 +58,13 @@ struct TrackSelectionTask { TrackSelection filtBit4; TrackSelection filtBit5; - void init(InitContext&) + void init(InitContext& initContext) { + // Check which tables are used + enableFlagIfTableRequired(initContext, "TrackSelection", produceTable); + enableFlagIfTableRequired(initContext, "TrackSelectionExtension", produceFBextendedTable); + + // Set up the track cuts switch (itsMatching) { case 0: // Run 2 SPD kAny @@ -70,22 +77,22 @@ struct TrackSelectionTask { case 1: // Run 3 kAny on 3 IB layers of ITS if (isRun3) { - LOG(info) << "setting up globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny);"; - globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny); + LOG(info) << "setting up getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, " << dcaSetup.value << ");"; + globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, dcaSetup.value); break; } case 2: // Run 3 kAny on all 7 layers of ITS if (isRun3) { - LOG(info) << "setting up globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSallAny);"; - globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSallAny); + LOG(info) << "setting up getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSallAny, " << dcaSetup.value << ");"; + globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSallAny, dcaSetup.value); break; } case 3: // Run 3 kAll on all 7 layers of ITS if (isRun3) { - LOG(info) << "setting up globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers);"; - globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers); + LOG(info) << "setting up getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers, " << dcaSetup.value << ");"; + globalTracks = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers, dcaSetup.value); break; } default: @@ -120,27 +127,35 @@ struct TrackSelectionTask { void process(soa::Join const& tracks) { - filterTable.reserve(tracks.size()); - if (produceFBextendedTable) { + if (produceTable == 1) { + filterTable.reserve(tracks.size()); + } + if (produceFBextendedTable == 1) { filterTableDetail.reserve(tracks.size()); } + if (produceTable == 0 && produceFBextendedTable == 0) { + return; + } if (isRun3) { for (auto& track : tracks) { - o2::aod::track::TrackSelectionFlags::flagtype trackflagGlob = globalTracks.IsSelectedMask(track); - o2::aod::track::TrackSelectionFlags::flagtype trackflagFB1 = filtBit1.IsSelectedMask(track); - o2::aod::track::TrackSelectionFlags::flagtype trackflagFB2 = filtBit2.IsSelectedMask(track); - // o2::aod::track::TrackSelectionFlags::flagtype trackflagFB3 = filtBit3.IsSelectedMask(track); // only temporarily commented, will be used - // o2::aod::track::TrackSelectionFlags::flagtype trackflagFB4 = filtBit4.IsSelectedMask(track); - // o2::aod::track::TrackSelectionFlags::flagtype trackflagFB5 = filtBit5.IsSelectedMask(track); - - filterTable((uint8_t)0, - globalTracks.IsSelectedMask(track), - filtBit1.IsSelected(track), - filtBit2.IsSelected(track), - filtBit3.IsSelected(track), - filtBit4.IsSelected(track), - filtBit5.IsSelected(track)); - if (produceFBextendedTable) { + + if (produceTable == 1) { + filterTable((uint8_t)0, + globalTracks.IsSelectedMask(track), + filtBit1.IsSelected(track), + filtBit2.IsSelected(track), + filtBit3.IsSelected(track), + filtBit4.IsSelected(track), + filtBit5.IsSelected(track)); + } + if (produceFBextendedTable == 1) { + o2::aod::track::TrackSelectionFlags::flagtype trackflagGlob = globalTracks.IsSelectedMask(track); + o2::aod::track::TrackSelectionFlags::flagtype trackflagFB1 = filtBit1.IsSelectedMask(track); + o2::aod::track::TrackSelectionFlags::flagtype trackflagFB2 = filtBit2.IsSelectedMask(track); + // o2::aod::track::TrackSelectionFlags::flagtype trackflagFB3 = filtBit3.IsSelectedMask(track); // only temporarily commented, will be used + // o2::aod::track::TrackSelectionFlags::flagtype trackflagFB4 = filtBit4.IsSelectedMask(track); + // o2::aod::track::TrackSelectionFlags::flagtype trackflagFB5 = filtBit5.IsSelectedMask(track); + filterTableDetail(o2::aod::track::TrackSelectionFlags::checkFlag(trackflagGlob, o2::aod::track::TrackSelectionFlags::kTrackType), o2::aod::track::TrackSelectionFlags::checkFlag(trackflagGlob, o2::aod::track::TrackSelectionFlags::kPtRange), o2::aod::track::TrackSelectionFlags::checkFlag(trackflagGlob, o2::aod::track::TrackSelectionFlags::kEtaRange), @@ -165,14 +180,16 @@ struct TrackSelectionTask { for (auto& track : tracks) { o2::aod::track::TrackSelectionFlags::flagtype trackflagGlob = globalTracks.IsSelectedMask(track); - filterTable((uint8_t)globalTracksSDD.IsSelected(track), - globalTracks.IsSelectedMask(track), - filtBit1.IsSelected(track), - filtBit2.IsSelected(track), - filtBit3.IsSelected(track), - filtBit4.IsSelected(track), - filtBit5.IsSelected(track)); - if (produceFBextendedTable) { + if (produceTable == 1) { + filterTable((uint8_t)globalTracksSDD.IsSelected(track), + globalTracks.IsSelectedMask(track), + filtBit1.IsSelected(track), + filtBit2.IsSelected(track), + filtBit3.IsSelected(track), + filtBit4.IsSelected(track), + filtBit5.IsSelected(track)); + } + if (produceFBextendedTable == 1) { filterTableDetail(o2::aod::track::TrackSelectionFlags::checkFlag(trackflagGlob, o2::aod::track::TrackSelectionFlags::kTrackType), o2::aod::track::TrackSelectionFlags::checkFlag(trackflagGlob, o2::aod::track::TrackSelectionFlags::kPtRange), o2::aod::track::TrackSelectionFlags::checkFlag(trackflagGlob, o2::aod::track::TrackSelectionFlags::kEtaRange), diff --git a/Common/Tasks/CMakeLists.txt b/Common/Tasks/CMakeLists.txt index 66c0a370181..9ba918032d9 100644 --- a/Common/Tasks/CMakeLists.txt +++ b/Common/Tasks/CMakeLists.txt @@ -24,16 +24,16 @@ o2physics_add_dpl_workflow(integrationtest PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(integrationtestccdb + SOURCES integrationTestCCDB.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(validation SOURCES validation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(event-selection-qa - SOURCES eventSelectionQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(multiplicity-qa SOURCES multiplicityQa.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase @@ -68,3 +68,13 @@ o2physics_add_dpl_workflow(qa-cpv SOURCES cpvQa.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(qvectors-correction + SOURCES qVectorsCorrection.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(evtplanes-resolution + SOURCES evtPlanesResolution.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Common/Tasks/centralityQa.cxx b/Common/Tasks/centralityQa.cxx index 93382b0e762..9e39194415c 100644 --- a/Common/Tasks/centralityQa.cxx +++ b/Common/Tasks/centralityQa.cxx @@ -23,6 +23,7 @@ struct CentralityQa { Configurable nBins{"nBins", 1050, "number of bins"}; Configurable INELgtZERO{"INELgtZERO", 1, "0 - no, 1 - yes"}; OutputObj hCentRun2V0M{TH1F("hCentRun2V0M", "V0M", nBins, 0, 105.)}; + OutputObj hCentRun2V0A{TH1F("hCentRun2V0A", "V0A", nBins, 0, 105.)}; OutputObj hCentRun2SPDTks{TH1F("hCentRun2SPDTks", "SPD Tracklets", nBins, 0, 105.)}; OutputObj hCentRun2SPDCls{TH1F("hCentRun2SPDCls", "SPD Clusters", nBins, 0, 105.)}; OutputObj hCentRun2CL0{TH1F("hCentRun2CL0", "CL0", nBins, 0, 105.)}; @@ -86,6 +87,23 @@ struct CentralityQa { } PROCESS_SWITCH(CentralityQa, processRun2PbPb, "Process with Run2 CL0 and CL1 multiplicities centrality/multiplicity estimation", false); + void processRun2PPb(soa::Join::iterator const& col) + { + if (!col.alias_bit(kINT7)) { + return; + } + if (!col.sel7()) { + return; + } + if (INELgtZERO && col.multNTracksPVeta1() < 1) { + return; + } + LOGF(debug, "centV0A=%.0f", col.centRun2V0A()); + // fill centrality histos + hCentRun2V0A->Fill(col.centRun2V0A()); + } + PROCESS_SWITCH(CentralityQa, processRun2PPb, "Process with Run2 V0A multiplicitY centrality/multiplicity estimation", false); + void processRun3_FV0A(soa::Join::iterator const& col) { if (INELgtZERO && col.multNTracksPVeta1() < 1) { diff --git a/Common/Tasks/evtPlanesResolution.cxx b/Common/Tasks/evtPlanesResolution.cxx new file mode 100644 index 00000000000..358d4f8fb55 --- /dev/null +++ b/Common/Tasks/evtPlanesResolution.cxx @@ -0,0 +1,155 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file evtPlanesResolution.cxx +/// \author Cindy Mordasini +/// \author Anna Önnerstad +/// +/// \brief ... +/// + +// C++/ROOT includes. +#include +#include +#include +#include +#include +#include +#include + +// o2Physics includes. +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StaticFor.h" + +#include "Common/DataModel/EvtPlanes.h" +#include "Common/Core/EventPlaneHelper.h" + +// o2 includes. + +using namespace o2; +using namespace o2::framework; + +namespace ep +{ +static constexpr std::string_view centClasses[] = { + "Centrality_0-5/", "Centrality_5-10/", "Centrality_10-20/", "Centrality_20-30/", + "Centrality_30-40/", "Centrality_40-50/", "Centrality_50-60/", "Centrality_60-80/"}; +} // namespace ep + +struct evtPlanesResolution { + // Configurables. + + // Histogram registry for the output QA figures and list of centrality classes for it. + // Objects are NOT saved in alphabetical orders, and registry names are NOT saved + // as TDirectoryFile. + HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + // Helper variables. + EventPlaneHelper helperEP; + + Configurable cfgMinTPCTracks{"cfgMinTPCTracks", 20, "minimum TPC tracks participating in Q-vector reconstruction"}; + + void init(InitContext const&) + { + // Fill the registry with the needed objects. + const AxisSpec axisEvtPl{360, -constants::math::PI, constants::math::PI}; + + histosQA.add("Centrality_0-5/histEvtPlUncor", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlRectr", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlTwist", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlFinal", "", {HistType::kTH1F, {axisEvtPl}}); + + histosQA.add("Centrality_0-5/histEvtPlBPosUncor", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlBPosRectr", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlBPosTwist", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlBPosFinal", "", {HistType::kTH1F, {axisEvtPl}}); + + histosQA.add("Centrality_0-5/histEvtPlBNegUncor", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlBNegRectr", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlBNegTwist", "", {HistType::kTH1F, {axisEvtPl}}); + histosQA.add("Centrality_0-5/histEvtPlBNegFinal", "", {HistType::kTH1F, {axisEvtPl}}); + + histosQA.add("Centrality_0-5/histEvtPlResolution", "", {HistType::kTH1F, {axisEvtPl}}); + + for (int iBin = 1; iBin < 8; iBin++) { + histosQA.addClone("Centrality_0-5/", ep::centClasses[iBin].data()); + } + } // End void init(InitContext const&) + + template + void fillHistosEvtPl(const T& vec) + { + if (vec.nTrkBPos() < cfgMinTPCTracks || vec.nTrkBNeg() < cfgMinTPCTracks) + return; + + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlUncor"), vec.evtPlUncor()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlRectr"), vec.evtPlRectr()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlTwist"), vec.evtPlTwist()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlFinal"), vec.evtPlFinal()); + + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlBPosUncor"), vec.evtPlBPosUncor()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlBPosRectr"), vec.evtPlBPosRectr()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlBPosTwist"), vec.evtPlBPosTwist()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlBPosFinal"), vec.evtPlBPosFinal()); + + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlBNegUncor"), vec.evtPlBNegUncor()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlBNegRectr"), vec.evtPlBNegRectr()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlBNegTwist"), vec.evtPlBNegTwist()); + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlBNegFinal"), vec.evtPlBNegFinal()); + + histosQA.fill(HIST(ep::centClasses[cBin]) + HIST("histEvtPlResolution"), + std::sqrt(std::cos(2 * (vec.evtPlFinal() - vec.evtPlBPosFinal())) * std::cos(2 * (vec.evtPlFinal() - vec.evtPlBNegFinal())) / + std::cos(2 * (vec.evtPlBPosFinal() - vec.evtPlBNegFinal())))); + } + + void process(aod::EvtPlane const& evPl) + { + int centBin = helperEP.GetCentBin(evPl.cent()); + switch (centBin) { + case 0: + fillHistosEvtPl<0>(evPl); + break; + case 1: + fillHistosEvtPl<1>(evPl); + break; + case 2: + fillHistosEvtPl<2>(evPl); + break; + case 3: + fillHistosEvtPl<3>(evPl); + break; + case 4: + fillHistosEvtPl<4>(evPl); + break; + case 5: + fillHistosEvtPl<5>(evPl); + break; + case 6: + fillHistosEvtPl<6>(evPl); + break; + case 7: + fillHistosEvtPl<7>(evPl); + break; + } // End switch(centBin) + } // End void process(...) +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Common/Tasks/ft0Qa.cxx b/Common/Tasks/ft0Qa.cxx index 82fe8009624..cf5ff2805f2 100644 --- a/Common/Tasks/ft0Qa.cxx +++ b/Common/Tasks/ft0Qa.cxx @@ -10,45 +10,69 @@ // or submit itself to any jurisdiction. #include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include "DataFormatsFT0/Digit.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" #include "TH1F.h" #include "TH2F.h" -#include "DataFormatsFT0/Digit.h" using namespace o2; using namespace o2::framework; +using BCsWithRun3Matchings = soa::Join; + struct ft0QaTask { // Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; Configurable selection{"selection", 0, "trigger: 0 - no sel, 8 - sel8"}; - Configurable isLowFlux{"isLowFlux", 1, "1 - low flux (pp, pPb), 0 - high flux (PbPb)"}; + Configurable isLowFlux{"isLowFlux", 1, + "1 - low flux (pp, pPb), 0 - high flux (PbPb)"}; - HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry histos{ + "Histos", + {}, + OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { const AxisSpec axisTime{500, -5., 5., "collision time (ns)"}; - const AxisSpec axisColTimeRes{isLowFlux ? 500 : 2000, -0.5, 0.5, "(T0A - T0C)/2 (ns)"}; + const AxisSpec axisColTimeRes{isLowFlux ? 500 : 2000, -0.5, 0.5, + "(T0A - T0C)/2 (ns)"}; const AxisSpec axisVertex{300, -30., 30.}; - const AxisSpec axisAmpT0A{isLowFlux ? 500 : 2000, 0., isLowFlux ? 500. : 2000., "T0A amplitude (# ADC channels)"}; - const AxisSpec axisAmpT0C{isLowFlux ? 500 : 2000, 0., isLowFlux ? 500. : 2000., "T0C amplitude (# ADC channels)"}; - - const AxisSpec axisMultT0A{isLowFlux ? 10000 : 200000, 0., isLowFlux ? 10000. : 200000., "T0A multiplicity (# ADC channels)"}; - const AxisSpec axisMultT0C{isLowFlux ? 2000 : 70000, 0., isLowFlux ? 2000. : 70000., "T0C multiplicity (# ADC channels)"}; - const AxisSpec axisMultT0AC{isLowFlux ? 12000 : 27000, 0., isLowFlux ? 12000. : 270000., "T0AC multiplicity (# ADC channels)"}; - const AxisSpec axisMultV0A{isLowFlux ? 40000 : 200000, 0., isLowFlux ? 40000. : 200000., "V0A multiplicity (# ADC channels)"}; - - const AxisSpec axisNcontrib{isLowFlux ? 150 : 4500, 0., isLowFlux ? 150. : 4500., "# contributors"}; - - // FT0 time + const AxisSpec axisAmpT0A{isLowFlux ? 500 : 2000, 0., + isLowFlux ? 500. : 2000., + "T0A amplitude (# ADC channels)"}; + const AxisSpec axisAmpT0C{isLowFlux ? 500 : 2000, 0., + isLowFlux ? 500. : 2000., + "T0C amplitude (# ADC channels)"}; + + const AxisSpec axisMultT0A{isLowFlux ? 10000 : 200000, 0., + isLowFlux ? 10000. : 200000., + "T0A multiplicity (# ADC channels)"}; + const AxisSpec axisMultT0C{isLowFlux ? 2000 : 70000, 0., + isLowFlux ? 2000. : 70000., + "T0C multiplicity (# ADC channels)"}; + const AxisSpec axisMultT0AC{isLowFlux ? 12000 : 27000, 0., + isLowFlux ? 12000. : 270000., + "T0AC multiplicity (# ADC channels)"}; + const AxisSpec axisMultV0A{isLowFlux ? 40000 : 200000, 0., + isLowFlux ? 40000. : 200000., + "V0A multiplicity (# ADC channels)"}; + + const AxisSpec axisNcontrib{isLowFlux ? 150 : 4500, 0., + isLowFlux ? 150. : 4500., "# contributors"}; + + const AxisSpec axisCounter{2, 0.5, 1.5, ""}; + + // Collisions task + // FT0 time histos.add("hT0A", "T0A;T0A time (ns);counts", kTH1F, {axisTime}); histos.add("hT0C", "T0C;T0C time (ns);counts", kTH1F, {axisTime}); histos.add("hT0AC", "T0AC;T0AC time (ns);counts", kTH1F, {axisTime}); @@ -56,56 +80,159 @@ struct ft0QaTask { histos.add("hColTime", "", kTH1F, {axisTime}); // FT0 vertex - histos.add("hT0vertex", "FT0 vertex;FT0 vertex (cm);counts", kTH1F, {axisVertex}); + histos.add("hT0vertex", "FT0 vertex;FT0 vertex (cm);counts", kTH1F, + {axisVertex}); histos.add("hPV", "PV;primary vertex (cm);counts", kTH1F, {axisVertex}); - histos.add("hT0vertexDiff", "FT0V - PV;FT0 vertex - PV (cm);counts", kTH1F, {axisVertex}); - histos.add("hVertex_T0_PV", "PV vs. FT0V;FT0 vertex (cm);primary vertex (cm)", kTH2F, {axisVertex, axisVertex}); - histos.add("hVertex_T0_PV_nC20", "PV vs. FT0V;FT0 vertex (cm);primary vertex (cm)", kTH2F, {axisVertex, axisVertex}); - histos.add("hT0vertexDiff_nC20", "FT0V - PV;FT0 vertex - PV (cm);counts", kTH1F, {axisVertex}); - histos.add("hVertex_T0_PV_TVX", "PV vs. FT0V;FT0 vertex (cm);primary vertex (cm)", kTH2F, {axisVertex, axisVertex}); - histos.add("hT0AC_T0Vertex_TVX", "time vs. FT0V;FT0 vertex (cm);T0AC time (ns)", kTH2F, {axisVertex, axisTime}); - - histos.add("hPV_nContrib", "PV vs. Ncontributers;primary vertex (cm);(# contrubutors)", kTH2F, {axisVertex, axisNcontrib}); + histos.add("hT0vertexDiff", "FT0V - PV;FT0 vertex - PV (cm);counts", kTH1F, + {axisVertex}); + histos.add("hVertex_T0_PV", + "PV vs. FT0V;FT0 vertex (cm);primary vertex (cm)", kTH2F, + {axisVertex, axisVertex}); + histos.add("hVertex_T0_PV_nC20", + "PV vs. FT0V;FT0 vertex (cm);primary vertex (cm)", kTH2F, + {axisVertex, axisVertex}); + histos.add("hT0vertexDiff_nC20", "FT0V - PV;FT0 vertex - PV (cm);counts", + kTH1F, {axisVertex}); + histos.add("hVertex_T0_PV_TVX", + "PV vs. FT0V;FT0 vertex (cm);primary vertex (cm)", kTH2F, + {axisVertex, axisVertex}); + histos.add("hT0AC_T0Vertex_TVX", + "time vs. FT0V;FT0 vertex (cm);T0AC time (ns)", kTH2F, + {axisVertex, axisTime}); + + histos.add("hPV_nContrib", + "PV vs. Ncontributers;primary vertex (cm);(# contrubutors)", + kTH2F, {axisVertex, axisNcontrib}); // FT0 amplitude and multiplicity - histos.add("hAmpT0A", "amplitude T0A;#ADC channels;counts", kTH1F, {axisAmpT0A}); - histos.add("hAmpT0C", "amplitude T0C;#ADC channels;counts", kTH1F, {axisAmpT0C}); + histos.add("hAmpT0A", "amplitude T0A;#ADC channels;counts", kTH1F, + {axisAmpT0A}); + histos.add("hAmpT0C", "amplitude T0C;#ADC channels;counts", kTH1F, + {axisAmpT0C}); histos.add("hMultT0A", ";(# ADC channels);counts", kTH1F, {axisMultT0A}); - histos.add("hMultT0AOrA", "OrA trig;(# ADC channels);counts", kTH1F, {axisMultT0A}); - histos.add("hMultT0ATVX", "TVX trig;(# ADC channels);counts", kTH1F, {axisMultT0A}); - histos.add("hMultT0AOrAC", "OrA && OrC trig;(# ADC channels);counts", kTH1F, {axisMultT0A}); - histos.add("hMultT0ACent", "Central trig;(# ADC channels);counts", kTH1F, {axisMultT0A}); - histos.add("hMultT0ASCent", "SemiCentral trig;(# ADC channels);counts", kTH1F, {axisMultT0A}); + histos.add("hMultT0AOrA", "OrA trig;(# ADC channels);counts", kTH1F, + {axisMultT0A}); + histos.add("hMultT0ATVX", "TVX trig;(# ADC channels);counts", kTH1F, + {axisMultT0A}); + histos.add("hMultT0AOrAC", "OrA && OrC trig;(# ADC channels);counts", kTH1F, + {axisMultT0A}); + histos.add("hMultT0ACent", "Central trig;(# ADC channels);counts", kTH1F, + {axisMultT0A}); + histos.add("hMultT0ASCent", "SemiCentral trig;(# ADC channels);counts", + kTH1F, {axisMultT0A}); histos.add("hMultT0C", ";(# ADC channels);counts", kTH1F, {axisMultT0C}); - histos.add("hMultT0COrC", "OrC trig;(# ADC channels);counts", kTH1F, {axisMultT0C}); - histos.add("hMultT0CTVX", "TVX trig;(# ADC channels);counts", kTH1F, {axisMultT0C}); - histos.add("hMultT0COrAC", "OrA && OrC trig;(# ADC channels);counts", kTH1F, {axisMultT0C}); - histos.add("hMultT0CCent", "Central trig;(# ADC channels);counts", kTH1F, {axisMultT0C}); - histos.add("hMultT0CSCent", "SemiCentral trig;(# ADC channels);counts", kTH1F, {axisMultT0C}); + histos.add("hMultT0COrC", "OrC trig;(# ADC channels);counts", kTH1F, + {axisMultT0C}); + histos.add("hMultT0CTVX", "TVX trig;(# ADC channels);counts", kTH1F, + {axisMultT0C}); + histos.add("hMultT0COrAC", "OrA && OrC trig;(# ADC channels);counts", kTH1F, + {axisMultT0C}); + histos.add("hMultT0CCent", "Central trig;(# ADC channels);counts", kTH1F, + {axisMultT0C}); + histos.add("hMultT0CSCent", "SemiCentral trig;(# ADC channels);counts", + kTH1F, {axisMultT0C}); histos.add("hMultT0AC", ";(# ADC channels);counts", kTH1F, {axisMultT0AC}); - histos.add("hMultT0ACTVX", "TVX trig;(# ADC channels);counts", kTH1F, {axisMultT0AC}); - histos.add("hMultT0ACOrAC", "OrA && OrC trig;(# ADC channels);counts", kTH1F, {axisMultT0AC}); - histos.add("hMultT0ACCent", "Central trig;(# ADC channels);counts", kTH1F, {axisMultT0AC}); - histos.add("hMultT0ACSCent", "SemiCentral trig;(# ADC channels);counts", kTH1F, {axisMultT0AC}); + histos.add("hMultT0ACTVX", "TVX trig;(# ADC channels);counts", kTH1F, + {axisMultT0AC}); + histos.add("hMultT0ACOrAC", "OrA && OrC trig;(# ADC channels);counts", + kTH1F, {axisMultT0AC}); + histos.add("hMultT0ACCent", "Central trig;(# ADC channels);counts", kTH1F, + {axisMultT0AC}); + histos.add("hMultT0ACSCent", "SemiCentral trig;(# ADC channels);counts", + kTH1F, {axisMultT0AC}); // Number of contributers to PV for FT0 triggers histos.add("hContrib", ";(# contrubutors);counts", kTH1F, {axisNcontrib}); - histos.add("hContribOrAC", "Ncontributers with T0AC;(# contrubutors);counts", kTH1F, {axisNcontrib}); - histos.add("hContribOrA", "Ncontributers with T0A;(# contrubutors);counts", kTH1F, {axisNcontrib}); - histos.add("hContribOrC", "Ncontributers with T0C;(# contrubutors);counts", kTH1F, {axisNcontrib}); - histos.add("hContribTVX", "Ncontributers with TVX;(# contrubutors);counts", kTH1F, {axisNcontrib}); - histos.add("hContribCent", "Ncontributers with bitCen;(# contrubutors);counts", kTH1F, {axisNcontrib}); - histos.add("hContribSemiCent", "Ncontributers with bitSCen;(# contrubutors);counts", kTH1F, {axisNcontrib}); + histos.add("hContribOrAC", + "Ncontributers with T0AC;(# contrubutors);counts", kTH1F, + {axisNcontrib}); + histos.add("hContribOrA", "Ncontributers with T0A;(# contrubutors);counts", + kTH1F, {axisNcontrib}); + histos.add("hContribOrC", "Ncontributers with T0C;(# contrubutors);counts", + kTH1F, {axisNcontrib}); + histos.add("hContribTVX", "Ncontributers with TVX;(# contrubutors);counts", + kTH1F, {axisNcontrib}); + histos.add("hContribCent", + "Ncontributers with bitCen;(# contrubutors);counts", kTH1F, + {axisNcontrib}); + histos.add("hContribSemiCent", + "Ncontributers with bitSCen;(# contrubutors);counts", kTH1F, + {axisNcontrib}); // FV0 histos.add("hContribV0", "Ncontributers with V0A", kTH1F, {axisNcontrib}); - histos.add("hT0V0time", "T0A vs V0 time;V0 time (ns);T0A time (ns)", kTH2F, {axisTime, axisTime}); + histos.add("hT0V0time", "T0A vs V0 time;V0 time (ns);T0A time (ns)", kTH2F, + {axisTime, axisTime}); + + //_______________________________________________________________________________________________________________________ + // BC task + + histos.add("hBcCounterAll", "", kTH1F, {axisCounter}); + histos.add("hBcCounterFT0", "", kTH1F, {axisCounter}); + histos.add("hBcCounterTVX", "", kTH1F, {axisCounter}); + + histos.add("hBcT0A", "T0A;T0A time (ns);counts", kTH1F, {axisTime}); + histos.add("hBcT0C", "T0C;T0C time (ns);counts", kTH1F, {axisTime}); + histos.add("hBcT0AC", "T0AC;T0AC time (ns);counts", kTH1F, {axisTime}); + histos.add("hBcT0ACdiff", "(T0A -T0C)/2;(T0A -T0C)/2 (ns);counts", kTH1F, + {axisColTimeRes}); + + histos.add("hBcT0ATVX", "T0A TVX;T0A time (ns);counts", kTH1F, {axisTime}); + histos.add("hBcT0CTVX", "T0C TVX;T0C time (ns);counts", kTH1F, {axisTime}); + histos.add("hBcT0ACTVX", "T0AC TVX;T0AC time (ns);counts", kTH1F, + {axisTime}); + histos.add("hBcT0ACdiffTVX", "(T0A -T0C)/2;(T0A -T0C)/2 (ns);counts", kTH1F, + {axisColTimeRes}); + + // FT0 amplitude and multiplicity + histos.add("hBcAmpT0A", "amplitude T0A;#ADC channels;counts", kTH1F, + {axisAmpT0A}); + histos.add("hBcAmpT0C", "amplitude T0C;#ADC channels;counts", kTH1F, + {axisAmpT0C}); + + histos.add("hBcMultT0A", ";(# ADC channels);counts", kTH1F, {axisMultT0A}); + histos.add("hBcMultT0AOrA", "OrA trig;(# ADC channels);counts", kTH1F, + {axisMultT0A}); + histos.add("hBcMultT0ATVX", "TVX trig;(# ADC channels);counts", kTH1F, + {axisMultT0A}); + histos.add("hBcMultT0AOrAC", "OrA && OrC trig;(# ADC channels);counts", + kTH1F, {axisMultT0A}); + histos.add("hBcMultT0ACent", "Central trig;(# ADC channels);counts", kTH1F, + {axisMultT0A}); + histos.add("hBcMultT0ASCent", "SemiCentral trig;(# ADC channels);counts", + kTH1F, {axisMultT0A}); + + histos.add("hBcMultT0C", ";(# ADC channels);counts", kTH1F, {axisMultT0C}); + histos.add("hBcMultT0COrC", "OrC trig;(# ADC channels);counts", kTH1F, + {axisMultT0C}); + histos.add("hBcMultT0CTVX", "TVX trig;(# ADC channels);counts", kTH1F, + {axisMultT0C}); + histos.add("hBcMultT0COrAC", "OrA && OrC trig;(# ADC channels);counts", + kTH1F, {axisMultT0C}); + histos.add("hBcMultT0CCent", "Central trig;(# ADC channels);counts", kTH1F, + {axisMultT0C}); + histos.add("hBcMultT0CSCent", "SemiCentral trig;(# ADC channels);counts", + kTH1F, {axisMultT0C}); + + histos.add("hBcMultT0AC", ";(# ADC channels);counts", kTH1F, + {axisMultT0AC}); + histos.add("hBcMultT0ACTVX", "TVX trig;(# ADC channels);counts", kTH1F, + {axisMultT0AC}); + histos.add("hBcMultT0ACOrAC", "OrA && OrC trig;(# ADC channels);counts", + kTH1F, {axisMultT0AC}); + histos.add("hBcMultT0ACCent", "Central trig;(# ADC channels);counts", kTH1F, + {axisMultT0AC}); + histos.add("hBcMultT0ACSCent", "SemiCentral trig;(# ADC channels);counts", + kTH1F, {axisMultT0AC}); } - void process(soa::Join::iterator const& collision, aod::FT0s const& ft0s, aod::FV0As const& fv0s) + void + processCollisions(soa::Join::iterator const& collision, + aod::FT0s const& ft0s, aod::FV0As const& fv0s) { if (selection == 8 && !collision.sel8()) { @@ -241,7 +368,8 @@ struct ft0QaTask { if (nContrib > 20) { histos.fill(HIST("hVertex_T0_PV_nC20"), ft0.posZ(), collision.posZ()); - histos.fill(HIST("hT0vertexDiff_nC20"), ft0.posZ() - collision.posZ()); + histos.fill(HIST("hT0vertexDiff_nC20"), + ft0.posZ() - collision.posZ()); } if (tvx) { @@ -264,13 +392,129 @@ struct ft0QaTask { } } // end of if (collision.has_foundFV0()) - } // end of process() + } // end of processCollsions() + + PROCESS_SWITCH(ft0QaTask, processCollisions, "per-collision analysis", true); + + // soa::Join::iterator const &collision, + // aod::FT0s const &ft0s, aod::FV0As const &fv0s + + void processBCs(BCsWithRun3Matchings::iterator const& bc, aod::FV0As const&, + aod::FT0s const&) + { + + histos.fill(HIST("hBcCounterAll"), 1); + + float multFV0A = 0.f; + float multFT0A = 0.f; + float multFT0C = 0.f; + float multFT0M = 0.f; + + float timeA = -999.0; + float timeC = -999.0; + float timeAC = -999.0; + float timeACdiff = -999.0; + + bool ora = false; + bool orc = false; + bool tvx = false; + bool cent = false; + bool semicent = false; + + if (bc.has_ft0()) { + + histos.fill(HIST("hBcCounterFT0"), 1); + auto ft0 = bc.ft0(); + + std::bitset<8> triggers = ft0.triggerMask(); + ora = triggers[o2::ft0::Triggers::bitA]; + orc = triggers[o2::ft0::Triggers::bitC]; + tvx = triggers[o2::ft0::Triggers::bitVertex]; + cent = triggers[o2::ft0::Triggers::bitCen]; + semicent = triggers[o2::ft0::Triggers::bitSCen]; + + for (auto amplitude : ft0.amplitudeA()) { + multFT0A += amplitude; + histos.fill(HIST("hBcAmpT0A"), amplitude); + } + for (auto amplitude : ft0.amplitudeC()) { + multFT0C += amplitude; + histos.fill(HIST("hBcAmpT0C"), amplitude); + } + + multFT0M = multFT0A + multFT0C; + + // Multiplicities (no triggers) + + histos.fill(HIST("hBcMultT0A"), multFT0A); + histos.fill(HIST("hBcMultT0C"), multFT0C); + + histos.fill(HIST("hBcMultT0AC"), multFT0M); + + timeA = ft0.timeA(); + timeC = ft0.timeC(); + timeAC = (ft0.timeA() + ft0.timeC()) / 2; + timeACdiff = (ft0.timeA() - ft0.timeC()) / 2; + + if (ora) { + histos.fill(HIST("hBcMultT0AOrA"), multFT0A); + + histos.fill(HIST("hBcT0A"), timeA); + } + + if (orc) { + histos.fill(HIST("hBcMultT0COrC"), multFT0C); + + histos.fill(HIST("hBcT0C"), timeC); + } + + if (ora && orc) { + histos.fill(HIST("hBcMultT0AOrAC"), multFT0A); + histos.fill(HIST("hBcMultT0COrAC"), multFT0C); + histos.fill(HIST("hBcMultT0ACOrAC"), multFT0M); + + histos.fill(HIST("hBcT0AC"), timeAC); + histos.fill(HIST("hBcT0ACdiff"), timeACdiff); + } + + if (tvx) { + // continue; + histos.fill(HIST("hBcCounterTVX"), 1); + histos.fill(HIST("hBcMultT0ACTVX"), multFT0M); + histos.fill(HIST("hBcMultT0ATVX"), multFT0A); + histos.fill(HIST("hBcMultT0CTVX"), multFT0C); + + histos.fill(HIST("hBcT0ATVX"), timeA); + histos.fill(HIST("hBcT0CTVX"), timeC); + histos.fill(HIST("hBcT0ACTVX"), timeAC); + histos.fill(HIST("hBcT0ACdiffTVX"), timeACdiff); + } + + if (cent) { + histos.fill(HIST("hBcMultT0ACent"), multFT0A); + histos.fill(HIST("hBcMultT0CCent"), multFT0C); + histos.fill(HIST("hBcMultT0ACCent"), multFT0M); + } + + if (semicent) { + histos.fill(HIST("hBcMultT0ASCent"), multFT0A); + histos.fill(HIST("hBcMultT0CSCent"), multFT0C); + histos.fill(HIST("hBcMultT0ACSCent"), multFT0M); + } + } + + if (bc.has_fv0a()) { + auto fv0a = bc.fv0a(); + for (auto amplitude : fv0a.amplitude()) { + multFV0A += amplitude; + } + } + } + PROCESS_SWITCH(ft0QaTask, processBCs, "per-BC analysis", true); }; // end of struct -WorkflowSpec - defineDataProcessing(ConfigContext const& cfgc) +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"ft0-qa"})}; + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"ft0-qa"})}; } diff --git a/Common/Tasks/integrationTestCCDB.cxx b/Common/Tasks/integrationTestCCDB.cxx new file mode 100644 index 00000000000..9a75683b8f8 --- /dev/null +++ b/Common/Tasks/integrationTestCCDB.cxx @@ -0,0 +1,129 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// Integration tester for CCDB access +// This task is meant to attempt accessing typical CCDB objects +// but to do no actual analysis. It will then allow for systematic +// studies of CCDB access performance for the various objects it queries. +// +// The task allows for some basic configuration of which CCDB objects +// are to be queried (from B field to material LUT and others). +// For now: magnetic field is required, matlut is optional +// +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/trackUtilities.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +#include "Framework/runDataProcessing.h" + +struct integrationTestCCDB { + // this is anyway what this is all about + Service ccdb; + + Configurable loadMatLut{"loadMatLut", true, "load material look-up table"}; + + // CCDB paths for access + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + o2::base::MatLayerCylSet* lut; + + int mRunNumber; + + void initMagneticFieldCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + LOG(info) << "Starting MagField initialization..."; + + float d_bz = 0.0f; // to store value for printouts only, unused + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = bc.runNumber(); + + // Known magnetic field + float magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Finished MagField init! Magnetic field set in Propagator Instance for inspection: " << magneticField; + } + + void init(InitContext& context) + { + lut = 0x0; + const AxisSpec axis{1, 0.0f, 1.0f, ""}; + histos.add("hDFs", "hDFs", HistType::kTH1F, {axis}); + } + + void process(aod::BCsWithTimestamps const& bcs) + { + mRunNumber = 0; + + auto bc = bcs.begin(); // first element + histos.fill(HIST("hDFs"), 0.5f); + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + if (loadMatLut && !lut) { + LOG(info) << "Loading material LUT..."; + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + LOG(info) << "Material LUT successfully loaded!"; + LOG(info) << "Material LUT min R: " << lut->getRMin() << " max R: " << lut->getRMax(); + } + initMagneticFieldCCDB(bc); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Common/Tasks/multiplicityQa.cxx b/Common/Tasks/multiplicityQa.cxx index 6e144ae4180..3efd57063fd 100644 --- a/Common/Tasks/multiplicityQa.cxx +++ b/Common/Tasks/multiplicityQa.cxx @@ -25,8 +25,10 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/EventSelection.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "TH1F.h" #include "TH2F.h" @@ -36,61 +38,40 @@ using namespace o2::framework; using BCsWithRun3Matchings = soa::Join; struct MultiplicityQa { - //Raw multiplicities + // Raw multiplicities HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; Configurable selection{"sel", 7, "trigger: 7 - sel7, 8 - sel8"}; Configurable vtxZsel{"vtxZsel", 10, "max vertex Z (cm)"}; - Configurable INELgtZERO{"INELgtZERO", 1, "0 - no, 1 - yes"}; - - Configurable NBinsMultFV0{"NBinsMultFV0", 1000, "N bins FV0"}; - Configurable NBinsMultFT0{"NBinsMultFT0", 1000, "N bins FT0"}; - Configurable NBinsMultFT0A{"NBinsMultFT0A", 1000, "N bins FT0A"}; - Configurable NBinsMultFT0C{"NBinsMultFT0C", 1000, "N bins FT0C"}; - Configurable NBinsMultFDD{"NBinsMultFDD", 1000, "N bins FDD"}; - Configurable NBinsMultNTracks{"NBinsMultNTracks", 1000, "N bins Ntracks"}; - - Configurable NBinsMultFV02d{"NBinsMultFV02d", 100, "N bins FV0 in 2D"}; - Configurable NBinsMultFT02d{"NBinsMultFT02d", 100, "N bins FT0 in 2D"}; - Configurable NBinsMultFT0A2d{"NBinsMultFT0A2d", 100, "N bins FT0A in 2D"}; - Configurable NBinsMultFT0C2d{"NBinsMultFT0C2d", 100, "N bins FT0C in 2D"}; - Configurable NBinsMultFDD2d{"NBinsMultFDD2d", 100, "N bins FDD in 2D"}; - Configurable NBinsMultNTracks2d{"NBinsMultNTracks2d", 100, "N bins Ntracks in 2D"}; - Configurable NBinsNContributors{"NBinsNContributors", 100, "N bins Ntracks in 2D"}; - - Configurable MaxMultFV0{"MaxMultFV0", 20000, "Max FV0 signal"}; - Configurable MaxMultFT0{"MaxMultFT0", 10000, "Max FT0 signal"}; - Configurable MaxMultFT0A{"MaxMultFT0A", 10000, "Max FT0A signal"}; - Configurable MaxMultFT0C{"MaxMultFT0C", 10000, "Max FT0C signal"}; - Configurable MaxMultFDD{"MaxMultFDD", 10000, "Max FDD signal"}; - Configurable MaxMultNTracks{"MaxMultNTracks", 1000, "Max Ntracks"}; - Configurable MaxNContributors{"MaxNContributors", 200, "Max NContributors"}; - Configurable NBinsVertexZ{"NBinsVertexZ", 400, "max vertex Z (cm)"}; + Configurable INELgtZERO{"INELgtZERO", true, "0 - no, 1 - yes"}; + Configurable do2Dplots{"do2Dplots", false, "0 - no, 1 - yes"}; + + ConfigurableAxis axisMultFV0{"axisMultFV0", {10000, 0, 500000}, "FV0 amplitude"}; + ConfigurableAxis axisMultFT0{"axisMultFT0", {10000, 0, 40000}, "FT0 amplitude"}; + ConfigurableAxis axisMultFT0A{"axisMultFT0A", {10000, 0, 30000}, "FT0A amplitude"}; + ConfigurableAxis axisMultFT0C{"axisMultFT0C", {10000, 0, 10000}, "FT0C amplitude"}; + ConfigurableAxis axisMultFDD{"axisMultFDD", {1000, 0, 4000}, "FDD amplitude"}; + ConfigurableAxis axisMultNTracks{"axisMultNTracks", {500, 0, 500}, "N_{tracks}"}; + ConfigurableAxis axisVertexZ{"axisVertexZ", {60, -15, 15}, "Vertex z (cm)"}; + + ConfigurableAxis axisContributors{"axisContributors", {100, -0.5f, 99.5f}, "Vertex z (cm)"}; + ConfigurableAxis axisNumberOfPVs{"axisNumberOfPVs", {10, -0.5f, 9.5f}, "Number of reconstructed PVs"}; + ConfigurableAxis axisNchFT0{"axisNchFT0", {500, -0.5f, 499.5f}, "Number of charged particles in FT0 acceptance"}; + Configurable useZeqInProfiles{"useZeqInProfiles", true, "use Z-equalized signals in midrap Nch profiles"}; + // necessary for particle charges + Service pdgDB; + + SliceCache cache; + void init(InitContext&) { const AxisSpec axisEvent{10, 0, 10, "Event counter"}; - const AxisSpec axisMultFV0{(int)NBinsMultFV0, 0, MaxMultFV0, "FV0 total amplitude"}; - const AxisSpec axisMultFT0{(int)NBinsMultFT0, 0, MaxMultFT0, "FT0 total amplitude"}; - const AxisSpec axisMultFT0A{(int)NBinsMultFT0A, 0, MaxMultFT0A, "FT0A total amplitude"}; - const AxisSpec axisMultFT0C{(int)NBinsMultFT0C, 0, MaxMultFT0C, "FT0C total amplitude"}; - const AxisSpec axisMultFDD{(int)NBinsMultFDD, 0, MaxMultFDD, "FDD total amplitude"}; - const AxisSpec axisMultNTracks{(int)NBinsMultNTracks, 0, MaxMultNTracks, "Track counter"}; - - const AxisSpec axisMultFV02d{(int)NBinsMultFV02d, 0, MaxMultFV0, "FV0 total amplitude"}; - const AxisSpec axisMultFT02d{(int)NBinsMultFT02d, 0, MaxMultFT0, "FT0 total amplitude"}; - const AxisSpec axisMultFT0A2d{(int)NBinsMultFT0A2d, 0, MaxMultFT0A, "FT0A total amplitude"}; - const AxisSpec axisMultFT0C2d{(int)NBinsMultFT0C2d, 0, MaxMultFT0C, "FT0C total amplitude"}; - const AxisSpec axisMultFDD2d{(int)NBinsMultFDD2d, 0, MaxMultFDD, "FDD total amplitude"}; - const AxisSpec axisMultNTracks2d{(int)NBinsMultNTracks2d, 0, MaxMultNTracks, "Track counter"}; - - const AxisSpec axisVertexZ{(int)NBinsVertexZ, -20, 20, "Vertex Z (cm)"}; - const AxisSpec axisContributorsTRD{(int)NBinsNContributors, -0.5f, MaxNContributors - 0.5f, "N_{contribs}^{TRD}"}; - const AxisSpec axisContributorsTOF{(int)NBinsNContributors, -0.5f, MaxNContributors - 0.5f, "N_{contribs}^{TOF}"}; - - //Base histograms + + // Base histograms histos.add("multiplicityQa/hEventCounter", "Event counter", kTH1D, {axisEvent}); + histos.add("multiplicityQa/hRawFV0", "Raw FV0", kTH1D, {axisMultFV0}); histos.add("multiplicityQa/hRawFT0", "Raw FT0", kTH1D, {axisMultFT0}); histos.add("multiplicityQa/hRawFT0A", "Raw FT0A", kTH1D, {axisMultFT0A}); @@ -119,15 +100,42 @@ struct MultiplicityQa { histos.add("multiplicityQa/hVtxZFDDC", "Av FDDC vs vertex Z", kTProfile, {axisVertexZ}); histos.add("multiplicityQa/hVtxZNTracksPV", "Av NTracks vs vertex Z", kTProfile, {axisVertexZ}); - // profiles of track contributors - histos.add("multiplicityQa/hNchProfileFV0", "FV0", kTH2F, {axisMultFV02d, axisMultNTracks2d}); - histos.add("multiplicityQa/hNchProfileFT0", "FT0", kTH2F, {axisMultFT02d, axisMultNTracks2d}); - histos.add("multiplicityQa/hNchProfileFT0A", "FT0A", kTH2F, {axisMultFT0A2d, axisMultNTracks2d}); - histos.add("multiplicityQa/hNchProfileFT0C", "FT0C", kTH2F, {axisMultFT0C2d, axisMultNTracks2d}); - histos.add("multiplicityQa/hNchProfileFDD", "FDD", kTH2F, {axisMultFDD2d, axisMultNTracks2d}); + // two-dimensional histograms + if (do2Dplots) { + histos.add("multiplicityQa/h2dNchVsFV0", "FV0", kTH2F, {axisMultFV0, axisMultNTracks}); + histos.add("multiplicityQa/h2dNchVsFT0", "FT0", kTH2F, {axisMultFT0, axisMultNTracks}); + histos.add("multiplicityQa/h2dNchVsFT0A", "FT0A", kTH2F, {axisMultFT0A, axisMultNTracks}); + histos.add("multiplicityQa/h2dNchVsFT0C", "FT0C", kTH2F, {axisMultFT0C, axisMultNTracks}); + histos.add("multiplicityQa/h2dNchVsFDD", "FDD", kTH2F, {axisMultFDD, axisMultNTracks}); + + histos.add("multiplicityQa/h2dPVsVsFV0", "FV0", kTH2F, {axisMultFV0, axisNumberOfPVs}); + histos.add("multiplicityQa/h2dPVsVsFT0", "FT0", kTH2F, {axisMultFT0, axisNumberOfPVs}); + histos.add("multiplicityQa/h2dPVsVsFT0A", "FT0A", kTH2F, {axisMultFT0A, axisNumberOfPVs}); + histos.add("multiplicityQa/h2dPVsVsFT0C", "FT0C", kTH2F, {axisMultFT0C, axisNumberOfPVs}); + histos.add("multiplicityQa/h2dPVsVsFDD", "FDD", kTH2F, {axisMultFDD, axisNumberOfPVs}); + + // correlate T0 and V0 + histos.add("multiplicityQa/h2dFT0VsFV0", "FDD", kTH2F, {axisMultFV0, axisMultFT0}); + } + + if (doprocessMCCollisions) { + histos.add("multiplicityQa/h2dPVsVsNchT0M", "N(PV) vs Nch(FT0)", kTH2F, {axisNchFT0, axisNumberOfPVs}); + histos.add("multiplicityQa/h2dNtracksVsNchT0M", "N(tracks) vs Nch(FT0)", kTH2F, {axisNchFT0, axisMultNTracks}); + histos.add("multiplicityQa/h2dFT0MVsNchT0M", "FT0M sig vs Nch(FT0)", kTH2F, {axisNchFT0, axisMultFT0}); + } // Contributors correlation - histos.add("h2dNContribCorrAll", "h2dNContribCorrAll", kTH2D, {axisContributorsTRD, axisContributorsTOF}); + histos.add("h2dNContribCorrAll", "h2dNContribCorrAll", kTH2D, {axisContributors, axisContributors}); + + if (doprocessFIT) { + histos.add("multiplicityQa/hIsolatedFT0A", "isolated FT0A", kTH1D, {axisMultFT0}); + histos.add("multiplicityQa/hIsolatedFT0C", "isolated FT0C", kTH1D, {axisMultFT0}); + histos.add("multiplicityQa/hIsolatedFT0M", "isolated FT0M", kTH1D, {axisMultFT0}); + } + + if (doprocessCollisionExtras) { + histos.add("multiplicityQa/h2dITSOnlyVsITSTPC", "h2dITSOnlyVsITSTPC", kTH2D, {axisMultNTracks, axisMultNTracks}); + } } void processCollisions(soa::Join::iterator const& col) @@ -140,7 +148,7 @@ struct MultiplicityQa { if (selection == 8 && !col.sel8()) { return; } - if (selection != 7 && selection != 8) { + if (selection != 7 && selection != 8 && selection >= 0) { LOGF(fatal, "Unknown selection type! Use `--sel 7` or `--sel 8`"); } histos.fill(HIST("multiplicityQa/hEventCounter"), 1.5); @@ -149,7 +157,7 @@ struct MultiplicityQa { } histos.fill(HIST("multiplicityQa/hEventCounter"), 2.5); - //Vertex-Z dependencies, necessary for CCDB objects + // Vertex-Z dependencies, necessary for CCDB objects histos.fill(HIST("multiplicityQa/hVtxZFV0A"), col.posZ(), col.multFV0A()); histos.fill(HIST("multiplicityQa/hVtxZFT0A"), col.posZ(), col.multFT0A()); histos.fill(HIST("multiplicityQa/hVtxZFT0C"), col.posZ(), col.multFT0C()); @@ -165,7 +173,7 @@ struct MultiplicityQa { LOGF(debug, "multFV0A=%5.0f multFV0C=%5.0f multFV0M=%5.0f multFT0A=%5.0f multFT0C=%5.0f multFT0M=%5.0f multFDDA=%5.0f multFDDC=%5.0f", col.multFV0A(), col.multFV0C(), col.multFV0M(), col.multFT0A(), col.multFT0C(), col.multFT0M(), col.multFDDA(), col.multFDDC()); - //Raw multiplicities + // Raw multiplicities histos.fill(HIST("multiplicityQa/hRawFV0"), col.multFV0A()); histos.fill(HIST("multiplicityQa/hRawFT0"), col.multFT0M()); histos.fill(HIST("multiplicityQa/hRawFT0A"), col.multFT0A()); @@ -173,7 +181,7 @@ struct MultiplicityQa { histos.fill(HIST("multiplicityQa/hRawFDD"), col.multFDDM()); histos.fill(HIST("multiplicityQa/hRawNTracksPV"), col.multNTracksPV()); - //vertex-Z corrected - FIXME + // vertex-Z corrected - FIXME histos.fill(HIST("multiplicityQa/hZeqFV0"), col.multZeqFV0A()); histos.fill(HIST("multiplicityQa/hZeqFT0"), col.multZeqFT0A() + col.multZeqFT0C()); histos.fill(HIST("multiplicityQa/hZeqFT0A"), col.multZeqFT0A()); @@ -182,21 +190,30 @@ struct MultiplicityQa { histos.fill(HIST("multiplicityQa/hZeqNTracksPV"), col.multZeqNTracksPV()); // Profiles - if (useZeqInProfiles) { - histos.fill(HIST("multiplicityQa/hNchProfileFV0"), col.multZeqFV0A(), col.multZeqNTracksPV()); - histos.fill(HIST("multiplicityQa/hNchProfileFT0"), col.multZeqFT0A() + col.multZeqFT0C(), col.multZeqNTracksPV()); - histos.fill(HIST("multiplicityQa/hNchProfileFT0A"), col.multZeqFT0A(), col.multZeqNTracksPV()); - histos.fill(HIST("multiplicityQa/hNchProfileFT0C"), col.multZeqFT0C(), col.multZeqNTracksPV()); - histos.fill(HIST("multiplicityQa/hNchProfileFDD"), col.multZeqFDDA() + col.multZeqFDDC(), col.multZeqNTracksPV()); - } else { - histos.fill(HIST("multiplicityQa/hNchProfileFV0"), col.multFV0A(), col.multNTracksPV()); - histos.fill(HIST("multiplicityQa/hNchProfileFT0"), col.multFT0A() + col.multFT0C(), col.multNTracksPV()); - histos.fill(HIST("multiplicityQa/hNchProfileFT0A"), col.multFT0A(), col.multNTracksPV()); - histos.fill(HIST("multiplicityQa/hNchProfileFT0C"), col.multFT0C(), col.multNTracksPV()); - histos.fill(HIST("multiplicityQa/hNchProfileFDD"), col.multFDDA() + col.multFDDC(), col.multNTracksPV()); + if (do2Dplots) { + if (useZeqInProfiles) { + histos.fill(HIST("multiplicityQa/h2dNchVsFV0"), col.multZeqFV0A(), col.multZeqNTracksPV()); + histos.fill(HIST("multiplicityQa/h2dNchVsFT0"), col.multZeqFT0A() + col.multZeqFT0C(), col.multZeqNTracksPV()); + histos.fill(HIST("multiplicityQa/h2dNchVsFT0A"), col.multZeqFT0A(), col.multZeqNTracksPV()); + histos.fill(HIST("multiplicityQa/h2dNchVsFT0C"), col.multZeqFT0C(), col.multZeqNTracksPV()); + histos.fill(HIST("multiplicityQa/h2dNchVsFDD"), col.multZeqFDDA() + col.multZeqFDDC(), col.multZeqNTracksPV()); + } else { + histos.fill(HIST("multiplicityQa/h2dNchVsFV0"), col.multFV0A(), col.multNTracksPV()); + histos.fill(HIST("multiplicityQa/h2dNchVsFT0"), col.multFT0A() + col.multFT0C(), col.multNTracksPV()); + histos.fill(HIST("multiplicityQa/h2dNchVsFT0A"), col.multFT0A(), col.multNTracksPV()); + histos.fill(HIST("multiplicityQa/h2dNchVsFT0C"), col.multFT0C(), col.multNTracksPV()); + histos.fill(HIST("multiplicityQa/h2dNchVsFDD"), col.multFDDA() + col.multFDDC(), col.multNTracksPV()); + + // 2d FT0 vs FV0 fill + histos.fill(HIST("multiplicityQa/h2dFT0VsFV0"), col.multFV0A(), col.multFT0A() + col.multFT0C()); + } } } - PROCESS_SWITCH(MultiplicityQa, processCollisions, "per-collision analysis", true); + + void processCollisionExtras(soa::Join::iterator const& col) + { + histos.fill(HIST("multiplicityQa/h2dITSOnlyVsITSTPC"), col.multNTracksITSTPC(), col.multNTracksITSOnly()); + } void processBCs(BCsWithRun3Matchings::iterator const& bc, aod::FV0As const&, @@ -243,7 +260,6 @@ struct MultiplicityQa { histos.fill(HIST("multiplicityQa/hPerBCRawFT0C"), multFT0C); histos.fill(HIST("multiplicityQa/hPerBCRawFDD"), multFDDA + multFDDC); } - PROCESS_SWITCH(MultiplicityQa, processBCs, "per-BC analysis", true); void processCollisionsPVChecks(soa::Join::iterator const& col, soa::Join const& tracks) { @@ -277,7 +293,131 @@ struct MultiplicityQa { } histos.fill(HIST("h2dNContribCorrAll"), NcontribsTRD, NcontribsTOF); } - PROCESS_SWITCH(MultiplicityQa, processCollisionsPVChecks, "do PV contributors check", true); + + void processCollisionsWithMCInfo(soa::Join::iterator const& col, soa::Join const& mcCollisions) + { + if (selection == 7 && !col.sel7()) { + return; + } + + if (selection == 8 && !col.sel8()) { + return; + } + if (INELgtZERO && col.multNTracksPVeta1() < 1) { + return; + } + if (fabs(col.posZ()) > vtxZsel) { + return; + } + + // verify that PV has collision + if (!col.has_mcCollision()) + return; + + auto mcCollision = col.mcCollision_as>(); + if (mcCollision.numRecoCollision() < 1) + return; // total paranoia mode: on + + // Profiles + if (useZeqInProfiles && do2Dplots) { + histos.fill(HIST("multiplicityQa/h2dPVsVsFV0"), col.multZeqFV0A(), mcCollision.numRecoCollision()); + histos.fill(HIST("multiplicityQa/h2dPVsVsFT0"), col.multZeqFT0A() + col.multZeqFT0C(), mcCollision.numRecoCollision()); + histos.fill(HIST("multiplicityQa/h2dPVsVsFT0A"), col.multZeqFT0A(), mcCollision.numRecoCollision()); + histos.fill(HIST("multiplicityQa/h2dPVsVsFT0C"), col.multZeqFT0C(), mcCollision.numRecoCollision()); + histos.fill(HIST("multiplicityQa/h2dPVsVsFDD"), col.multZeqFDDA() + col.multZeqFDDC(), mcCollision.numRecoCollision()); + } else { + histos.fill(HIST("multiplicityQa/h2dPVsVsFV0"), col.multFV0A(), mcCollision.numRecoCollision()); + histos.fill(HIST("multiplicityQa/h2dPVsVsFT0"), col.multFT0A() + col.multFT0C(), mcCollision.numRecoCollision()); + histos.fill(HIST("multiplicityQa/h2dPVsVsFT0A"), col.multFT0A(), mcCollision.numRecoCollision()); + histos.fill(HIST("multiplicityQa/h2dPVsVsFT0C"), col.multFT0C(), mcCollision.numRecoCollision()); + histos.fill(HIST("multiplicityQa/h2dPVsVsFDD"), col.multFDDA() + col.multFDDC(), mcCollision.numRecoCollision()); + } + } + + Preslice perCol = aod::track::collisionId; + Preslice perColIU = aod::track::collisionId; + + using Run3Tracks = soa::Join; + Partition pvContribTracksIUEta1 = (nabs(aod::track::eta) < 1.0f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); + + void processMCCollisions(soa::Join::iterator const& mcCollision, aod::McParticles const& mcParticles, soa::SmallGroups> const& collisions, Run3Tracks const&) + { + // This process function is to be used to loop over MC collisions and + // --- understand the properties of PV finding versus true multiplicity + // --- understand the correlation between true multiplicity and reconstructed multiplicity + // --- Nota bene: further work separating the midrapidity response and the forward/midrapidity Nch correlation to be done + + // step zero: particle counting! + // FITFT0:-3.3<η<-2.1,3.5<η<4.9 + // FITFV0:2.2<η<5.0 + // FITFDD:-6.9<η<-4.9,4.7<η<6.3 + + uint16_t nchFT0 = 0; + bool conditionINELgtZERO = false; + + for (auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + const auto& pdgInfo = pdgDB->GetParticle(mcParticle.pdgCode()); + if (!pdgInfo) { + continue; + } + if (pdgInfo->Charge() == 0) { + continue; + } + if (fabs(mcParticle.eta()) < 1.0f) { + conditionINELgtZERO = true; + } + if (mcParticle.eta() < -3.3 || mcParticle.eta() > 4.9 || (mcParticle.eta() > -2.1 && mcParticle.eta() < 3.5)) { + continue; // select on T0M Nch region + } + nchFT0++; // increment + } + if (!conditionINELgtZERO && INELgtZERO) + return; + + // Ingredient one: PV finding versus true multiplicity + histos.fill(HIST("multiplicityQa/h2dPVsVsNchT0M"), nchFT0, mcCollision.numRecoCollision()); + + // Ingredient two: true multiplicity vs reco multiplicity + // important: reco multiplicity of which collision, exactly? + // to be understood - could study first and second collision separately + int biggestNContribs = -1; + uint16_t ntracks = 0; + float biggestFT0 = 0.0f; + for (auto& collision : collisions) { + if (biggestNContribs < collision.numContrib()) { + biggestNContribs = collision.numContrib(); + auto tracksGrouped = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + ntracks = tracksGrouped.size(); + if (useZeqInProfiles) { + biggestFT0 = collision.multFT0A() + collision.multFT0C(); + } else { + biggestFT0 = collision.multZeqFT0A() + collision.multZeqFT0C(); + } + } + } + histos.fill(HIST("multiplicityQa/h2dNtracksVsNchT0M"), nchFT0, ntracks); + histos.fill(HIST("multiplicityQa/h2dFT0MVsNchT0M"), nchFT0, biggestFT0); + } + + void processFIT(aod::MultsBC const& multsdebug) + { + for (auto& mult : multsdebug) { + histos.fill(HIST("multiplicityQa/hIsolatedFT0A"), mult.multBCFT0A()); + histos.fill(HIST("multiplicityQa/hIsolatedFT0C"), mult.multBCFT0C()); + histos.fill(HIST("multiplicityQa/hIsolatedFT0M"), mult.multBCFT0A() + mult.multBCFT0C()); + } + } + + PROCESS_SWITCH(MultiplicityQa, processCollisions, "per-collision analysis", true); + PROCESS_SWITCH(MultiplicityQa, processCollisionExtras, "per-collision analysis, extra QA", false); + PROCESS_SWITCH(MultiplicityQa, processBCs, "per-BC analysis", false); + PROCESS_SWITCH(MultiplicityQa, processCollisionsPVChecks, "do PV contributors check", false); + PROCESS_SWITCH(MultiplicityQa, processCollisionsWithMCInfo, "analyse collisions + correlate with MC info", false); + PROCESS_SWITCH(MultiplicityQa, processMCCollisions, "analyse MC collisions", false); + PROCESS_SWITCH(MultiplicityQa, processFIT, "analyse FIT table", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/Common/Tasks/propagatorQa.cxx b/Common/Tasks/propagatorQa.cxx index be6cf5dee2d..822214cfef3 100644 --- a/Common/Tasks/propagatorQa.cxx +++ b/Common/Tasks/propagatorQa.cxx @@ -438,6 +438,38 @@ struct propagatorQa { } } PROCESS_SWITCH(propagatorQa, processData, "process data", false); + + void processMatLUTTest(aod::Collision const& collision, soa::Join const& tracks, soa::Join const& tracksIU, aod::BCsWithTimestamps const&) + { + /* check the previous run number */ + auto bc = collision.bc_as(); + initCCDB(bc); + gpu::gpustd::array dcaInfo; + + for (auto& trackIU : tracksIU) { + if (trackIU.tpcNClsFound() < minTPCClustersRequired) + continue; // skip if not enough TPC clusters + + if (trackIU.trackType() != aod::track::TrackIU && trackIU.x() > maxXtoConsider) + continue; // skip if not track IU or if beyong the max X to be considered + + o2::track::TrackParCov trackParCov = getTrackParCov(trackIU); + + dcaInfo[0] = 999; + dcaInfo[1] = 999; + + // Recalculate the propagation with this instance of the matLUT + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCov, maxPropagStep, matCorr, &dcaInfo); + + auto track = tracks.iteratorAt(trackIU.globalIndex() - tracksIU.offset()); + + histos.fill(HIST("hDeltaTanLambdaVsPt"), track.tgl(), track.tgl() - trackParCov.getTgl()); + histos.fill(HIST("hDeltaPtVsPt"), track.pt(), track.pt() - trackParCov.getPt()); + histos.fill(HIST("hDeltaDCAs"), track.dcaXY() - dcaInfo[0]); + histos.fill(HIST("hDeltaDCAsVsPt"), track.pt(), track.dcaXY() - dcaInfo[0]); + } + } + PROCESS_SWITCH(propagatorQa, processMatLUTTest, "process mat lut test", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/Common/Tasks/qVectorsCorrection.cxx b/Common/Tasks/qVectorsCorrection.cxx new file mode 100644 index 00000000000..ee77c90d20c --- /dev/null +++ b/Common/Tasks/qVectorsCorrection.cxx @@ -0,0 +1,163 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file qVectorsCorrection.cxx +/// \author Cindy Mordasini +/// \author Anna Önnerstad +/// +/// \brief ... +/// + +// C++/ROOT includes. +#include +#include +#include +#include +#include +#include +#include + +// o2Physics includes. +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StaticFor.h" + +#include "Common/DataModel/Qvectors.h" +#include "Common/Core/EventPlaneHelper.h" + +// o2 includes. + +using namespace o2; +using namespace o2::framework; + +namespace qV +{ +static constexpr std::string_view centClasses[8] = { + "Centrality_0-5/", "Centrality_5-10/", "Centrality_10-20/", "Centrality_20-30/", + "Centrality_30-40/", "Centrality_40-50/", "Centrality_50-60/", "Centrality_60-80/"}; +} // namespace qV + +struct qVectorsCorrection { + // No correction = recenter, recentered Qvectors = twist, twisted Qvectors = rescale. + // NOTE: As of no, the twist gets both twist and rescale correction constants. + + // Histogram registry for the output QA figures and list of centrality classes for it. + // Objects are NOT saved in alphabetical orders, and registry names are NOT saved + // as TDirectoryFile. + HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + // Helper variables. + EventPlaneHelper helperEP; + + void init(InitContext const&) + { + // Fill the registry with the needed objects. + const AxisSpec axisCent{110, 0., 110.}; + const AxisSpec axisQvec{1000, -5, 5}; + const AxisSpec axisConst{12, 0., 12.}; // 4 constants x 3 detectors. + + histosQA.add("histCentFull", "Centrality distribution for valid events", + HistType::kTH1F, {axisCent}); + + histosQA.add("Centrality_0-5/histCent", "Centrality distribution", + HistType::kTH1F, {axisCent}); + + histosQA.add("Centrality_0-5/histQvecUncor", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecRectr", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecTwist", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecFinal", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + + histosQA.add("Centrality_0-5/histQvecBPosUncor", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecBPosRectr", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecBPosTwist", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecBPosFinal", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + + histosQA.add("Centrality_0-5/histQvecBNegUncor", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecBNegRectr", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecBNegTwist", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + histosQA.add("Centrality_0-5/histQvecBNegFinal", "", {HistType::kTH2F, {axisQvec, axisQvec}}); + + for (int iBin = 1; iBin < 8; iBin++) { + histosQA.addClone("Centrality_0-5/", qV::centClasses[iBin].data()); + } + + } // End void init(InitContext const&) + + // Definition of all the needed template functions. + template + void fillHistosQvec(const T& vec) + { + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histCent"), vec.cent()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histCent"), vec.cent()); + + // Fill the (Qx,Qy) distributions for each detector, after removing dummy values. + /// NOTE: FV0 (and FT0C?) are not fully implemented yet + /// --> Values are just dummy placeholders. + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecUncor"), vec.qvecUncorRe(), vec.qvecUncorIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecRectr"), vec.qvecRectrRe(), vec.qvecRectrIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecTwist"), vec.qvecTwistRe(), vec.qvecTwistIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecFinal"), vec.qvecFinalRe(), vec.qvecFinalIm()); + + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecBPosUncor"), vec.qvecBPosUncorRe(), vec.qvecBPosUncorIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecBPosRectr"), vec.qvecBPosRectrRe(), vec.qvecBPosRectrIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecBPosTwist"), vec.qvecBPosTwistRe(), vec.qvecBPosTwistIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecBPosFinal"), vec.qvecBPosFinalRe(), vec.qvecBPosFinalIm()); + + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecBNegUncor"), vec.qvecBNegUncorRe(), vec.qvecBNegUncorIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecBNegRectr"), vec.qvecBNegRectrRe(), vec.qvecBNegRectrIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecBNegTwist"), vec.qvecBNegTwistRe(), vec.qvecBNegTwistIm()); + histosQA.fill(HIST(qV::centClasses[cBin]) + HIST("histQvecBNegFinal"), vec.qvecBNegFinalRe(), vec.qvecBNegFinalIm()); + } + + void process(aod::Qvector const& qVec) + { + // Get the centrality bin, and fill the centrality QA histograms. + int centBin = helperEP.GetCentBin(qVec.cent()); + histosQA.fill(HIST("histCentFull"), qVec.cent()); + switch (centBin) { // LOKI: See if we can replace that with a const something like below. + case 0: + fillHistosQvec<0>(qVec); + break; + case 1: + fillHistosQvec<1>(qVec); + break; + case 2: + fillHistosQvec<2>(qVec); + break; + case 3: + fillHistosQvec<3>(qVec); + break; + case 4: + fillHistosQvec<4>(qVec); + break; + case 5: + fillHistosQvec<5>(qVec); + break; + case 6: + fillHistosQvec<6>(qVec); + break; + case 7: + fillHistosQvec<7>(qVec); + break; + } // End switch(centBin) + } // End void process(...) +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Common/Tools/Multiplicity/multCalibrator.cxx b/Common/Tools/Multiplicity/multCalibrator.cxx index 9f34fa6fbaa..2c898370156 100644 --- a/Common/Tools/Multiplicity/multCalibrator.cxx +++ b/Common/Tools/Multiplicity/multCalibrator.cxx @@ -27,6 +27,8 @@ #include "TArrayF.h" #include "multCalibrator.h" +using namespace std; + const TString multCalibrator::fCentEstimName[kNCentEstim] = { "RawV0M", "RawT0M", "RawFDD", "RawNTracks", "ZeqV0M", "ZeqT0M", "ZeqFDD", "ZeqNTracks"}; diff --git a/Common/Tools/Multiplicity/multCalibrator.h b/Common/Tools/Multiplicity/multCalibrator.h index 671116b211c..b5c618bdc3d 100644 --- a/Common/Tools/Multiplicity/multCalibrator.h +++ b/Common/Tools/Multiplicity/multCalibrator.h @@ -20,11 +20,10 @@ #define MULTCALIBRATOR_H #include -#include "TNamed.h" -#include "TH1D.h" #include -using namespace std; +#include "TNamed.h" +#include "TH1D.h" class multCalibrator : public TNamed { @@ -47,7 +46,7 @@ class multCalibrator : public TNamed void SetBoundaries(Long_t lNB, Double_t* lB) { if (lNB < 2 || lNB > 1e+6) { - cout << "Please make sure you are using a reasonable number of boundaries!" << endl; + std::cout << "Please make sure you are using a reasonable number of boundaries!" << std::endl; lNB = -1; } lDesiredBoundaries = lB; diff --git a/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx b/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx index 2b472bec0db..112983de9ea 100644 --- a/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx +++ b/Common/Tools/Multiplicity/multGlauberNBDFitter.cxx @@ -34,6 +34,8 @@ #include "TProfile.h" #include "TFitResult.h" +using namespace std; + ClassImp(multGlauberNBDFitter); multGlauberNBDFitter::multGlauberNBDFitter() : TNamed(), @@ -49,6 +51,7 @@ multGlauberNBDFitter::multGlauberNBDFitter() : TNamed(), fNNpNcPairs(-1), fMaxNpNcPairs(1000000), fMu(45), + fdMu(0.0), fk(1.5), ff(0.8), fnorm(100), @@ -74,6 +77,12 @@ multGlauberNBDFitter::multGlauberNBDFitter() : TNamed(), fGlauberNBD->SetParameter(1, fk); fGlauberNBD->SetParameter(2, ff); fGlauberNBD->SetParameter(3, fnorm); + + fGlauberNBD->SetParName(0, "mu"); + fGlauberNBD->SetParName(1, "k"); + fGlauberNBD->SetParName(2, "f"); + fGlauberNBD->SetParName(3, "norm"); + fGlauberNBD->SetParName(4, "dMu/dNanc"); } multGlauberNBDFitter::multGlauberNBDFitter(const char* name, const char* title) : TNamed(name, title), @@ -89,6 +98,7 @@ multGlauberNBDFitter::multGlauberNBDFitter(const char* name, const char* title) fNNpNcPairs(-1), fMaxNpNcPairs(1000000), fMu(45), + fdMu(0.0), fk(1.5), ff(0.8), fnorm(100), @@ -109,11 +119,17 @@ multGlauberNBDFitter::multGlauberNBDFitter(const char* name, const char* title) //master function fGlauberNBD = new TF1("fGlauberNBD", this, &multGlauberNBDFitter::ProbDistrib, - 0, 50000, 4, "multGlauberNBDFitter", "ProbDistrib"); + 0, 50000, 5, "multGlauberNBDFitter", "ProbDistrib"); fGlauberNBD->SetParameter(0, fMu); fGlauberNBD->SetParameter(1, fk); fGlauberNBD->SetParameter(2, ff); fGlauberNBD->SetParameter(3, fnorm); + + fGlauberNBD->SetParName(0, "mu"); + fGlauberNBD->SetParName(1, "k"); + fGlauberNBD->SetParName(2, "f"); + fGlauberNBD->SetParName(3, "norm"); + fGlauberNBD->SetParName(4, "dMu/dNanc"); } //________________________________________________________________ multGlauberNBDFitter::~multGlauberNBDFitter() @@ -183,7 +199,8 @@ Double_t multGlauberNBDFitter::ProbDistrib(Double_t* x, Double_t* par) Double_t lNancestorCount = fhNanc->GetBinContent(iNanc); //if(lNancestorCount<1e-12&&lNancestors>10) break; - Double_t lThisMu = (((Double_t)lNancestors)) * par[0]; + // allow for variable mu in case requested + Double_t lThisMu = (((Double_t)lNancestors)) * (par[0] + par[4] * lNancestors); Double_t lThisk = (((Double_t)lNancestors)) * par[1]; Double_t lpval = TMath::Power(1.0 + lThisMu / lThisk, -1); fNBD->SetParameter(1, lThisk); diff --git a/Common/Tools/Multiplicity/multGlauberNBDFitter.h b/Common/Tools/Multiplicity/multGlauberNBDFitter.h index 04c16e4df0d..ed93c49fc6b 100644 --- a/Common/Tools/Multiplicity/multGlauberNBDFitter.h +++ b/Common/Tools/Multiplicity/multGlauberNBDFitter.h @@ -20,7 +20,6 @@ #include "TH2.h" #include "TProfile.h" -using namespace std; class multGlauberNBDFitter : public TNamed { @@ -108,6 +107,7 @@ class multGlauberNBDFitter : public TNamed //The actual output: mu, k, f, norm Double_t fMu; + Double_t fdMu; // variable mu option Double_t fk; Double_t ff; Double_t fnorm; diff --git a/Common/Tools/Multiplicity/multMCCalibrator.cxx b/Common/Tools/Multiplicity/multMCCalibrator.cxx index dad0a32d31e..5b490daf77d 100644 --- a/Common/Tools/Multiplicity/multMCCalibrator.cxx +++ b/Common/Tools/Multiplicity/multMCCalibrator.cxx @@ -29,6 +29,8 @@ #include "multCalibrator.h" #include "multMCCalibrator.h" +using namespace std; + multMCCalibrator::multMCCalibrator() : TNamed(), fDataInputFileName("AnalysisResults.root"), fSimInputFileName("AnalysisResultsMC.root"), diff --git a/Common/Tools/Multiplicity/multMCCalibrator.h b/Common/Tools/Multiplicity/multMCCalibrator.h index 09e028f331d..f88bddf98c3 100644 --- a/Common/Tools/Multiplicity/multMCCalibrator.h +++ b/Common/Tools/Multiplicity/multMCCalibrator.h @@ -26,8 +26,6 @@ #include "TProfile.h" #include -using namespace std; - class multMCCalibrator : public TNamed { diff --git a/Common/Tools/handleParamBase.h b/Common/Tools/handleParamBase.h index 501a7a0a859..072038a7b4a 100644 --- a/Common/Tools/handleParamBase.h +++ b/Common/Tools/handleParamBase.h @@ -16,6 +16,11 @@ /// \brief Header file with utilities for handling PID parametrization on CCDB /// +#ifndef COMMON_TOOLS_HANDLEPARAMBASE_H_ +#define COMMON_TOOLS_HANDLEPARAMBASE_H_ + +#include +#include #include "CCDB/CcdbApi.h" #include #include "Framework/Logger.h" @@ -27,19 +32,19 @@ bpo::variables_map arguments; // Command line arguments o2::ccdb::CcdbApi api; // Global CCDB api unsigned int minRunNumber = 0; // Starting run validity unsigned int maxRunNumber = minRunNumber; // Ending run validity -long ccdbTimestamp = 0; // Timestamp used for the retrieval -long validityStart = 0; // Initial validity for the object -long validityStop = 0; // End validity for the object +int64_t ccdbTimestamp = 0; // Timestamp used for the retrieval +int64_t validityStart = 0; // Initial validity for the object +int64_t validityStop = 0; // End validity for the object std::string timeStampToHReadble(time_t rawtime) { if (rawtime < 0) { return std::string(" latest"); } - struct tm* dt; + struct tm* dt = new tm(); char buffer[30]; rawtime /= 1000; - dt = localtime(&rawtime); + localtime_r(&rawtime, dt); strftime(buffer, sizeof(buffer), "%H:%M %d-%m %Y", dt); return std::string(buffer); } @@ -61,9 +66,9 @@ void setStandardOpt(bpo::options_description& options) "dryrun,D", bpo::value()->default_value(1), "Dryrun mode")( "url,u", bpo::value()->default_value("http://alice-ccdb.cern.ch"), "URL of the CCDB database e.g. http://ccdb-test.cern.ch:8080 or http://alice-ccdb.cern.ch")( "rct-path", bpo::value()->default_value("RCT/Info/RunInformation"), "path to the ccdb RCT objects for the SOR/EOR timestamps")( - "start,s", bpo::value()->default_value(0), "Start timestamp of object validity. If 0 and min-runnumber != 0 it will be set to the run SOR")( - "stop,S", bpo::value()->default_value(0), "Stop timestamp of object validity. If 0 and max-runnumber != 0 it will be set to the run EOR")( - "timestamp,T", bpo::value()->default_value(-1), "Timestamp of the object to retrieve, used in alternative to the run number")( + "start,s", bpo::value()->default_value(0), "Start timestamp of object validity. If 0 and min-runnumber != 0 it will be set to the run SOR")( + "stop,S", bpo::value()->default_value(0), "Stop timestamp of object validity. If 0 and max-runnumber != 0 it will be set to the run EOR")( + "timestamp,T", bpo::value()->default_value(-1), "Timestamp of the object to retrieve, used in alternative to the run number")( "min-runnumber,r", bpo::value()->default_value(0), "Starting run number validity (included) corresponding to the parametrization")( "max-runnumber,R", bpo::value()->default_value(0), "Ending run number validity (included) corresponding to the parametrization. If not specified coincides with min-runnumber")( "delete-previous,delete_previous,d", bpo::value()->default_value(0), "Flag to delete previous versions of converter objects in the CCDB before uploading the new one so as to avoid proliferation on CCDB")( @@ -75,9 +80,10 @@ void setStandardOpt(bpo::options_description& options) template T* retrieveFromCCDB(const std::string path, - const long timestamp) + const int64_t timestamp, + std::map metadata) { - std::map metadata, headers; + std::map headers; LOG(info) << "Object " << path << " for timestamp " << timestamp << " -> " << timeStampToHReadble(timestamp); headers = api.retrieveHeaders(path, metadata, timestamp); LOG(info) << headers.size() << " HEADERS:"; @@ -92,11 +98,19 @@ T* retrieveFromCCDB(const std::string path, return obj; } +template +T* retrieveFromCCDB(const std::string path, + const int64_t timestamp) +{ + std::map metadata; + return retrieveFromCCDB(path, timestamp, metadata); +} + template void storeOnCCDB(const std::string& path, const std::map& metadata, - const long& start, - const long& stop, + const int64_t& start, + const int64_t& stop, const T* obj) { const auto dryrun = arguments["dryrun"].as(); @@ -111,13 +125,13 @@ void storeOnCCDB(const std::string& path, } } -void setupTimestamps(long& timestamp, - long& start, - long& stop) +void setupTimestamps(int64_t& timestamp, + int64_t& start, + int64_t& stop) { - ccdbTimestamp = arguments["timestamp"].as(); - validityStart = arguments["start"].as(); - validityStop = arguments["stop"].as(); + ccdbTimestamp = arguments["timestamp"].as(); + validityStart = arguments["start"].as(); + validityStop = arguments["stop"].as(); minRunNumber = arguments["min-runnumber"].as(); auto mrun = arguments["max-runnumber"].as(); maxRunNumber = mrun > 0 ? mrun : minRunNumber; @@ -125,7 +139,7 @@ void setupTimestamps(long& timestamp, LOG(fatal) << "Cannot have `min-runnumber` " << minRunNumber << " > `max-runnumber`" << maxRunNumber; } - auto getSOREOR = [&](const unsigned int runnumber, long& sor, long& eor) { + auto getSOREOR = [&](const unsigned int runnumber, int64_t& sor, int64_t& eor) { std::map metadata, headers; const auto rct_path = arguments["rct-path"].as(); const std::string run_path = Form("%s/%i", rct_path.data(), runnumber); @@ -144,7 +158,7 @@ void setupTimestamps(long& timestamp, }; if (minRunNumber != 0) { - long SOR = 0, EOR = 0; + int64_t SOR = 0, EOR = 0; getSOREOR(minRunNumber, SOR, EOR); timestamp = SOR; // timestamp of the SOR in ms LOG(info) << "Setting timestamp of object from run number " << minRunNumber << ": " << validityStart << " -> " << timeStampToHReadble(validityStart); @@ -167,3 +181,5 @@ void setupTimestamps(long& timestamp, validityStop = 4108971600000; } } + +#endif // COMMON_TOOLS_HANDLEPARAMBASE_H_ diff --git a/Common/Tools/handleParamTPCResponse.cxx b/Common/Tools/handleParamTPCResponse.cxx index d7430dd9c46..64741503fae 100644 --- a/Common/Tools/handleParamTPCResponse.cxx +++ b/Common/Tools/handleParamTPCResponse.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include "TFile.h" #include "Common/Core/PID/TPCPIDResponse.h" #include "handleParamBase.h" @@ -29,6 +30,10 @@ bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv "ccdb-path,c", bpo::value()->default_value("Analysis/PID/TPC"), "CCDB path for storage/retrieval")( "objname,n", bpo::value()->default_value("Response"), "Object name to be stored in file")( "inobjname", bpo::value()->default_value("Response"), "Object name to be read from file in 'push' mode")( + "recopass", bpo::value()->default_value(""), "Reconstruction pass name")( + "period", bpo::value()->default_value(""), "Period name")( + "jiraticket", bpo::value()->default_value(""), "JIRA ticket")( + "comment", bpo::value()->default_value(""), "Comment for metadata")( "bb0", bpo::value()->default_value(0.03209809958934784f), "Bethe-Bloch parameter 0")( "bb1", bpo::value()->default_value(19.9768009185791f), "Bethe-Bloch parameter 1")( "bb2", bpo::value()->default_value(2.5266601063857674e-16f), "Bethe-Bloch parameter 2")( @@ -81,6 +86,10 @@ int main(int argc, char* argv[]) const std::string inFilename = arguments["read-from-file"].as(); const std::string objname = arguments["objname"].as(); const std::string inobjname = arguments["inobjname"].as(); + const std::string recopass = arguments["recopass"].as(); + const std::string periodname = arguments["period"].as(); + const std::string jiraticket = arguments["jiraticket"].as(); + const std::string comment = arguments["comment"].as(); const float bb0 = arguments["bb0"].as(); const float bb1 = arguments["bb1"].as(); @@ -147,10 +156,9 @@ int main(int argc, char* argv[]) LOG(info) << "Reading existing TPCPIDResponse object " << objname << " from " << inFilename << ":"; tpc->PrintAll(); return 0; - } - else if (optMode.compare("write") == 0 || optMode.compare("push") == 0) // Create new object to write to local file or push to CCDB - { + } else if (optMode.compare("write") == 0 || optMode.compare("push") == 0) { // Create new object to write to local file or push to CCDB + if (!inFilename.empty()) { // Read from existing file to push to CCDB LOG(info) << "Reading from existing file to write to CCDB:"; TFile fin(inFilename.data(), "READ"); @@ -158,11 +166,13 @@ int main(int argc, char* argv[]) LOG(error) << "Input file " << inFilename << " could not be read"; return 1; } + tpc = fin.Get(inobjname.c_str()); if (!tpc) { LOG(error) << "Object with name " << objname << " could not be found in file " << inFilename; return 1; } + tpc->PrintAll(); } else { // Create new object if file not specified LOG(info) << "Creating new TPCPIDResponse object with defined parameters:"; @@ -178,6 +188,7 @@ int main(int argc, char* argv[]) tpc->SetUseDefaultResolutionParam(useDefaultParam); tpc->PrintAll(); } + if (optMode.compare("write") == 0) { if (outFilename.empty()) { LOG(error) << "'write' mode specified, but no output filename. Quitting"; @@ -199,20 +210,76 @@ int main(int argc, char* argv[]) if (optMode.compare("push") == 0) { LOG(info) << "Attempting to push object to CCDB"; - std::map metadata; + + // Sanity check: Request confirmation if any of recoPass, period name, comment, jira not specified + int missingPass = 0, missingPeriod = 0, missingComment = 0, missingJira = 0; + if (recopass.empty()) { + missingPass = 1; + } else { + metadata["RecoPassName"] = recopass; + } + + if (periodname.empty()) { + missingPeriod = 1; + } else { + metadata["LPMProductionTag"] = periodname; + } + + if (comment.empty()) { + missingComment = 1; + } else { + metadata["Comment"] = comment; + } + if (jiraticket.empty()) { + missingJira = 1; + } else { + metadata["JIRA"] = jiraticket; + } + + if (missingPass || missingPeriod || missingComment || missingJira) { + LOG(info) << "WARNING: Attempting to push an object with missing metadata elements:"; + if (missingPass) + LOG(info) << "\t- Pass name"; + if (missingPeriod) + LOG(info) << "\t- Period name"; + if (missingComment) + LOG(info) << "\t- Comment"; + if (missingJira) + LOG(info) << "\t- JIRA ticket"; + + // Request interactive confirmation to upload + LOG(info) << "Continue with object upload anyway? (Y/n)"; + std::string confirm; + std::cin >> confirm; + if (boost::iequals(confirm.substr(0, 1), "y")) { + LOG(info) << "Continuing with object upload"; + } else { + LOG(info) << "Aborting upload"; + return 1; + } + } + + // Fill metadata map for start/end run number if (minRunNumber != 0) { metadata["min-runnumber"] = Form("%i", minRunNumber); metadata["max-runnumber"] = Form("%i", maxRunNumber); } + storeOnCCDB(pathCCDB + "/" + objname, metadata, validityStart, validityStop, tpc); } - } - - else if (optMode.compare("pull") == 0) { // pull existing from CCDB; write out to file if requested - LOG(info) << "Attempting to pull object from CCDB (" << urlCCDB << "): " << pathCCDB << "/" << objname; - tpc = retrieveFromCCDB(pathCCDB + "/" + objname, ccdbTimestamp); + } else if (optMode.compare("pull") == 0) { // pull existing from CCDB; write out to file if requested + LOG(info) << "Attempting to pull object from CCDB (" << urlCCDB << "): " << pathCCDB << "/" << objname << (recopass.empty() ? "" : "/recoPass=" + recopass); + std::map metadata; + if (!recopass.empty()) { + metadata["RecoPassName"] = recopass; + } + tpc = retrieveFromCCDB(pathCCDB + "/" + objname, ccdbTimestamp, metadata); + if (!tpc) { + LOG(error) << "No CCDB object found with requested parameters"; + return 1; + } tpc->PrintAll(); if (!outFilename.empty()) { @@ -228,9 +295,7 @@ int main(int argc, char* argv[]) LOG(info) << "File successfully written"; } return 0; - } - - else { + } else { LOG(error) << "Invalid mode specified! (must be 'read', 'write', 'pull' or 'push')"; return 1; } diff --git a/DPG/Tasks/AOTEvent/CMakeLists.txt b/DPG/Tasks/AOTEvent/CMakeLists.txt new file mode 100644 index 00000000000..18ff8a6e5bc --- /dev/null +++ b/DPG/Tasks/AOTEvent/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2physics_add_dpl_workflow(event-selection-qa + SOURCES eventSelectionQa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase + COMPONENT_NAME Analysis) diff --git a/Common/Tasks/eventSelectionQa.cxx b/DPG/Tasks/AOTEvent/eventSelectionQa.cxx similarity index 97% rename from Common/Tasks/eventSelectionQa.cxx rename to DPG/Tasks/AOTEvent/eventSelectionQa.cxx index b4e26fd13cd..7131b919f6b 100644 --- a/Common/Tasks/eventSelectionQa.cxx +++ b/DPG/Tasks/AOTEvent/eventSelectionQa.cxx @@ -21,14 +21,16 @@ #include "DataFormatsParameters/GRPECSObject.h" #include "TH1F.h" #include "TH2F.h" + using namespace o2::framework; using namespace o2; -using namespace evsel; +using namespace o2::aod::evsel; using BCsRun2 = soa::Join; using BCsRun3 = soa::Join; using ColEvSels = soa::Join; using FullTracksIU = soa::Join; + struct EventSelectionQaTask { Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; Configurable nGlobalBCs{"nGlobalBCs", 100000, "number of global bcs"}; @@ -51,6 +53,9 @@ struct EventSelectionQaTask { std::bitset bcPatternC; std::bitset bcPatternB; + SliceCache cache; + Partition tracklets = (aod::track::trackType == static_cast(o2::aod::track::TrackTypeEnum::Run2Tracklet)); + void init(InitContext&) { minGlobalBC = uint64_t(minOrbit) * 3564; @@ -81,7 +86,7 @@ struct EventSelectionQaTask { const AxisSpec axisTimeSum{100, -10., 10., ""}; const AxisSpec axisGlobalBCs{nGlobalBCs, 0., static_cast(nGlobalBCs), ""}; const AxisSpec axisBCs{nBCsPerOrbit, 0., static_cast(nBCsPerOrbit), ""}; - const AxisSpec axisNcontrib{200, 0., isLowFlux ? 200. : 4500., "n contributors"}; + const AxisSpec axisNcontrib{200, 0., isLowFlux ? 200. : 7000., "n contributors"}; const AxisSpec axisEta{100, -1., 1., "track #eta"}; const AxisSpec axisColTimeRes{1500, 0., 1500., "collision time resolution (ns)"}; const AxisSpec axisBcDif{600, -300., 300., "collision bc difference"}; @@ -299,7 +304,7 @@ struct EventSelectionQaTask { // collision-based event selection qa for (auto& col : cols) { - bool sel1 = col.selection_bit(kIsINT1) & col.selection_bit(kNoBGV0A) & col.selection_bit(kNoBGV0C) & col.selection_bit(kNoTPCLaserWarmUp) & col.selection_bit(kNoTPCHVdip); + bool sel1 = col.selection_bit(kIsINT1) && col.selection_bit(kNoBGV0A) && col.selection_bit(kNoBGV0C) && col.selection_bit(kNoTPCLaserWarmUp) && col.selection_bit(kNoTPCHVdip); for (int iAlias = 0; iAlias < kNaliases; iAlias++) { if (!col.alias_bit(iAlias)) { @@ -345,6 +350,27 @@ struct EventSelectionQaTask { histos.fill(HIST("hBcFDD"), localBC); } + // Calculate V0 multiplicity per ring + float multRingV0A[5] = {0.}; + float multRingV0C[4] = {0.}; + float multV0A = 0; + float multV0C = 0; + if (bc.has_fv0a()) { + for (unsigned int i = 0; i < bc.fv0a().amplitude().size(); ++i) { + int ring = bc.fv0a().channel()[i] / 8; + multRingV0A[ring] += bc.fv0a().amplitude()[i]; + multV0A += bc.fv0a().amplitude()[i]; + } + } + + if (bc.has_fv0c()) { + for (unsigned int i = 0; i < bc.fv0c().amplitude().size(); ++i) { + int ring = bc.fv0c().channel()[i] / 8; + multRingV0C[ring] += bc.fv0c().amplitude()[i]; + multV0C += bc.fv0c().amplitude()[i]; + } + } + float timeZNA = bc.has_zdc() ? bc.zdc().timeZNA() : -999.f; float timeZNC = bc.has_zdc() ? bc.zdc().timeZNC() : -999.f; float timeV0A = bc.has_fv0a() ? bc.fv0a().time() : -999.f; @@ -357,15 +383,15 @@ struct EventSelectionQaTask { float znDif = timeZNA - timeZNC; float ofSPD = bc.spdFiredChipsL0() + bc.spdFiredChipsL1(); float onSPD = bc.spdFiredFastOrL0() + bc.spdFiredFastOrL1(); - float multV0A = col.multRingV0A()[0] + col.multRingV0A()[1] + col.multRingV0A()[2] + col.multRingV0A()[3]; - float multV0C = col.multRingV0C()[0] + col.multRingV0C()[1] + col.multRingV0C()[2] + col.multRingV0C()[3]; float multV0M = multV0A + multV0C; - float multRingV0C3 = col.multRingV0C()[3]; + float multRingV0C3 = multRingV0C[3]; float multRingV0C012 = multV0C - multRingV0C3; float onV0M = bc.v0TriggerChargeA() + bc.v0TriggerChargeC(); - float ofV0M = multV0A + multV0C - col.multRingV0A()[0]; - int nTracklets = col.nTracklets(); - int spdClusters = col.spdClusters(); + float ofV0M = multV0A + multV0C - multRingV0A[0]; + int spdClusters = bc.spdClustersL0() + bc.spdClustersL1(); + + auto trackletsGrouped = tracklets->sliceByCached(aod::track::collisionId, col.globalIndex(), cache); + int nTracklets = trackletsGrouped.size(); float multT0A = 0; float multT0C = 0; @@ -545,7 +571,7 @@ struct EventSelectionQaTask { double minSec = floor(tsSOR / 1000.); double maxSec = ceil(tsEOR / 1000.); const AxisSpec axisSeconds{static_cast(maxSec - minSec), minSec, maxSec, "seconds"}; - const AxisSpec axisBcDif{200, -100., 100., "collision bc difference"}; + const AxisSpec axisBcDif{600, -300., 300., "bc difference"}; histos.add("hSecondsTVXvsBcDif", "", kTH2F, {axisSeconds, axisBcDif}); histos.add("hSecondsTVXvsBcDifAll", "", kTH2F, {axisSeconds, axisBcDif}); } diff --git a/DPG/Tasks/AOTTrack/PID/CMakeLists.txt b/DPG/Tasks/AOTTrack/PID/CMakeLists.txt index 51eb8aae663..25af2fe083f 100644 --- a/DPG/Tasks/AOTTrack/PID/CMakeLists.txt +++ b/DPG/Tasks/AOTTrack/PID/CMakeLists.txt @@ -53,3 +53,10 @@ o2physics_add_dpl_workflow(pid-tpc-qa-mc SOURCES qaPIDTPCMC.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +## HMPID +#o2physics_add_dpl_workflow(pid-hmpid-qa +# SOURCES qaHMPID.cxx +# PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore +# COMPONENT_NAME Analysis) + diff --git a/Common/TableProducer/PID/qaHMPID.cxx b/DPG/Tasks/AOTTrack/PID/qaHMPID.cxx similarity index 92% rename from Common/TableProducer/PID/qaHMPID.cxx rename to DPG/Tasks/AOTTrack/PID/qaHMPID.cxx index fa484e11bab..f7eb7ce817a 100644 --- a/Common/TableProducer/PID/qaHMPID.cxx +++ b/DPG/Tasks/AOTTrack/PID/qaHMPID.cxx @@ -16,14 +16,12 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/TrackSelectionTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct pidHMPIDQA { +struct pidHmpidQa { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable nBinsP{"nBinsP", 500, "Number of momentum bins"}; Configurable minP{"minP", 0.01f, "Minimum momentum plotted (GeV/c)"}; @@ -74,8 +72,4 @@ struct pidHMPIDQA { } }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfg) -{ - WorkflowSpec workflow{adaptAnalysisTask(cfg, TaskName{"pidHMPID-qa"})}; - return workflow; -} +WorkflowSpec defineDataProcessing(ConfigContext const& cfg) { return WorkflowSpec{adaptAnalysisTask(cfg)}; } diff --git a/DPG/Tasks/AOTTrack/PID/qaPIDTOFBeta.cxx b/DPG/Tasks/AOTTrack/PID/qaPIDTOFBeta.cxx index b5506467cc5..dc44dee5798 100644 --- a/DPG/Tasks/AOTTrack/PID/qaPIDTOFBeta.cxx +++ b/DPG/Tasks/AOTTrack/PID/qaPIDTOFBeta.cxx @@ -25,6 +25,10 @@ #include "Common/DataModel/FT0Corrected.h" #include "Common/TableProducer/PID/pidTOFBase.h" +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + /// Task to produce the TOF Beta QA plots struct tofPidBetaQa { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; diff --git a/DPG/Tasks/AOTTrack/PID/qaPIDTOFEvTime.cxx b/DPG/Tasks/AOTTrack/PID/qaPIDTOFEvTime.cxx index d1286f8fbea..c70e69c5c75 100644 --- a/DPG/Tasks/AOTTrack/PID/qaPIDTOFEvTime.cxx +++ b/DPG/Tasks/AOTTrack/PID/qaPIDTOFEvTime.cxx @@ -28,6 +28,9 @@ #include "Common/TableProducer/PID/pidTOFBase.h" #include "Framework/runDataProcessing.h" +using namespace o2; +using namespace o2::framework; + struct tofPidCollisionTimeQa { ConfigurableAxis evTimeBins{"evTimeBins", {1000, -1000.f, 1000.f}, "Binning for the event time"}; ConfigurableAxis evTimeDeltaBins{"evTimeDeltaBins", {1000, -1000.f, 1000.f}, "Binning for the delta between event times"}; @@ -312,7 +315,7 @@ struct tofPidCollisionTimeQa { const float& massT0C = collision.t0CCorrectedValid() ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaT0C) : 999.f; const float& massT0AC = collision.t0ACValid() ? o2::pid::tof::TOFMass::GetTOFMass(trk, betaT0AC) : 999.f; - const float& deltaPi = trk.tofSignal() - trk.tofEvTime() - o2::pid::tof::ExpTimes::GetExpectedSignal(trk); + const float& deltaPi = trk.tofSignal() - trk.tofEvTime() - o2::pid::tof::ExpTimes::GetExpectedSignal(trk); histos.fill(HIST("tofbeta/inclusive"), trk.p(), trk.beta()); histos.fill(HIST("tofmass/inclusive"), trk.p(), trk.mass()); diff --git a/DPG/Tasks/AOTTrack/PID/qaPIDTOFMC.cxx b/DPG/Tasks/AOTTrack/PID/qaPIDTOFMC.cxx index 680ba69c088..ccea57b2a1d 100644 --- a/DPG/Tasks/AOTTrack/PID/qaPIDTOFMC.cxx +++ b/DPG/Tasks/AOTTrack/PID/qaPIDTOFMC.cxx @@ -206,16 +206,16 @@ struct pidTOFTaskQAMC { Configurable doHe{"doHe", 0, "Process helium3"}; Configurable doAl{"doAl", 0, "Process alpha"}; ConfigurableAxis binsPt{"binsPt", {2000, 0.f, 20.f}, "Binning of the pT axis"}; - ConfigurableAxis binsNsigma{"binsNsigma", {2000, -30.f, 30.f}, "Binning of the NSigma axis"}; + ConfigurableAxis binsNsigma{"binsNsigma", {2000, -50.f, 50.f}, "Binning of the NSigma axis"}; ConfigurableAxis binsSignal{"binsSignal", {6000, 0, 2000}, "Binning of the TPC signal axis"}; ConfigurableAxis binsLength{"binsLength", {1000, 0, 3000}, "Binning of the Length axis"}; ConfigurableAxis binsEta{"binsEta", {100, -4, 4}, "Binning of the Eta axis"}; Configurable minEta{"minEta", -0.8, "Minimum eta in range"}; Configurable maxEta{"maxEta", 0.8, "Maximum eta in range"}; Configurable nMinNumberOfContributors{"nMinNumberOfContributors", 2, "Minimum required number of contributors to the vertex"}; - Configurable logAxis{"logAxis", 1, "Flag to use a logarithmic pT axis, in this case the pT limits are the expontents"}; + Configurable logAxis{"logAxis", 0, "Flag to use a logarithmic pT axis, in this case the pT limits are the expontents"}; // TODO: support log axis - template + template void addParticleHistos(const AxisSpec& ptAxis, const AxisSpec& pAxis, const AxisSpec& signalAxis) { switch (mcID) { @@ -270,7 +270,7 @@ struct pidTOFTaskQAMC { const AxisSpec lengthAxis{binsLength, "Track length (cm)"}; const AxisSpec etaAxis{binsEta, "#it{#eta}"}; - const AxisSpec nSigmaAxis{binsNsigma, Form("N_{#sigma}^{TOF}(%s)", pT[massID])}; + const AxisSpec nSigmaAxis{binsNsigma, Form("N_{#sigma}^{TOF}(%s)", pT[mcID])}; // Particle info histos.add(hparticlept[mcID].data(), "", kTH1F, {pAxis}); @@ -285,22 +285,84 @@ struct pidTOFTaskQAMC { // NSigma histos.add(hnsigma[mcID].data(), pT[mcID], HistType::kTH2F, {ptAxis, nSigmaAxis}); - histos.add(hnsigmaMC[mcID * Np + massID].data(), Form("True %s", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); + histos.add(hsignalMC[mcID].data(), pT[mcID], HistType::kTH2F, {pAxis, signalAxis}); + if (!checkPrimaries) { return; } + histos.add(hnsigmaprm[mcID].data(), Form("Primary %s", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); histos.add(hnsigmastr[mcID].data(), Form("Secondary %s from decay", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); histos.add(hnsigmamat[mcID].data(), Form("Secondary %s from material", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); - histos.add(hnsigmaMCprm[mcID * Np + massID].data(), Form("True Primary %s", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); - histos.add(hnsigmaMCstr[mcID * Np + massID].data(), Form("True Secondary %s from decay", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); - histos.add(hnsigmaMCmat[mcID * Np + massID].data(), Form("True Secondary %s from material", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); histos.add(hsignalMCprm[mcID].data(), Form("Primary %s", pT[mcID]), HistType::kTH2F, {pAxis, signalAxis}); histos.add(hsignalMCstr[mcID].data(), Form("Secondary %s from decay", pT[mcID]), HistType::kTH2F, {pAxis, signalAxis}); histos.add(hsignalMCmat[mcID].data(), Form("Secondary %s from material", pT[mcID]), HistType::kTH2F, {pAxis, signalAxis}); } + template + void addParticleMCHistos(const AxisSpec& ptAxis, const AxisSpec& pAxis, const AxisSpec& signalAxis) + { + switch (mcID) { + case 0: + if (!doEl) { + return; + } + break; + case 1: + if (!doMu) { + return; + } + break; + case 2: + if (!doPi) { + return; + } + break; + case 3: + if (!doKa) { + return; + } + break; + case 4: + if (!doPr) { + return; + } + break; + case 5: + if (!doDe) { + return; + } + break; + case 6: + if (!doTr) { + return; + } + break; + case 7: + if (!doHe) { + return; + } + break; + case 8: + if (!doAl) { + return; + } + break; + default: + LOG(fatal) << "Can't interpret index"; + } + + const AxisSpec nSigmaAxis{binsNsigma, Form("N_{#sigma}^{TOF}(%s)", pT[massID])}; + + histos.add(hnsigmaMC[mcID * Np + massID].data(), Form("True %s", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); + if (checkPrimaries) { + histos.add(hnsigmaMCprm[mcID * Np + massID].data(), Form("True Primary %s", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); + histos.add(hnsigmaMCstr[mcID * Np + massID].data(), Form("True Secondary %s from decay", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); + histos.add(hnsigmaMCmat[mcID * Np + massID].data(), Form("True Secondary %s from material", pT[mcID]), HistType::kTH2F, {ptAxis, nSigmaAxis}); + } + } + void init(o2::framework::InitContext&) { AxisSpec pAxis{binsPt, "#it{p} (GeV/#it{c})"}; @@ -317,15 +379,21 @@ struct pidTOFTaskQAMC { static_for<0, 8>([&](auto i) { static_for<0, 8>([&](auto j) { - addParticleHistos(ptAxis, pAxis, betaAxis); + addParticleMCHistos(ptAxis, pAxis, betaAxis); }); + addParticleHistos(ptAxis, pAxis, betaAxis); }); histos.add("event/tofbeta", "All", HistType::kTH2F, {pAxis, betaAxis}); if (checkPrimaries) { histos.add("event/tofbetaPrm", "Primaries", HistType::kTH2F, {pAxis, betaAxis}); - histos.add("event/tofbetaSec", "Secondaries", HistType::kTH2F, {pAxis, betaAxis}); + // histos.add("event/tofbetaSec", "Secondaries", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("event/tofbetaStr", "Secondaries from weak decays", HistType::kTH2F, {pAxis, betaAxis}); + histos.add("event/tofbetaMat", "Secondaries from material", HistType::kTH2F, {pAxis, betaAxis}); } + // Print output histograms statistics + LOG(info) << "Size of the histograms in qaPIDTOFMC"; + histos.print(); } template @@ -408,7 +476,6 @@ struct pidTOFTaskQAMC { template void fillTrackInfoForPdg(const T& track, const TT& particle) { - switch (mcID) { case 0: if (!doEl) { @@ -504,18 +571,105 @@ struct pidTOFTaskQAMC { // PID info histos.fill(HIST(hsignalMC[mcID]), track.p(), track.beta()); - histos.fill(HIST(hnsigmaMC[mcID]), track.pt(), nsigma); - if (!particle.isPhysicalPrimary()) { - if (particle.getProcess() == 4) { - histos.fill(HIST(hsignalMCstr[mcID]), track.p(), track.beta()); - histos.fill(HIST(hnsigmaMCstr[mcID]), track.pt(), nsigma); + if (checkPrimaries) { + if (!particle.isPhysicalPrimary()) { + if (particle.getProcess() == 4) { + histos.fill(HIST(hsignalMCstr[mcID]), track.p(), track.beta()); + } else { + histos.fill(HIST(hsignalMCmat[mcID]), track.p(), track.beta()); + } + } else { + histos.fill(HIST(hsignalMCprm[mcID]), track.p(), track.beta()); + } + } + } + + template + void fillPIDInfoForPdg(const T& track, const TT& particle) + { + switch (mcID) { + case 0: + if (!doEl) { + return; + } + break; + case 1: + if (!doMu) { + return; + } + break; + case 2: + if (!doPi) { + return; + } + break; + case 3: + if (!doKa) { + return; + } + break; + case 4: + if (!doPr) { + return; + } + break; + case 5: + if (!doDe) { + return; + } + break; + case 6: + if (!doTr) { + return; + } + break; + case 7: + if (!doHe) { + return; + } + break; + case 8: + if (!doAl) { + return; + } + break; + default: + LOG(fatal) << "Can't interpret index"; + } + + switch (pdgSign.value) { + case 0: + if (abs(particle.pdgCode()) != PDGs[mcID]) { + return; + } + break; + case 1: + if (particle.pdgCode() != PDGs[mcID]) { + return; + } + break; + case 2: + if (particle.pdgCode() != -PDGs[mcID]) { + return; + } + break; + default: + LOG(fatal) << "Can't interpret pdgSign"; + } + + const float nsigmaMassID = o2::aod::pidutils::tofNSigma(track); + + histos.fill(HIST(hnsigmaMC[mcID * Np + massID]), track.pt(), nsigmaMassID); + if (checkPrimaries) { + if (!particle.isPhysicalPrimary()) { + if (particle.getProcess() == 4) { + histos.fill(HIST(hnsigmaMCstr[mcID * Np + massID]), track.pt(), nsigmaMassID); + } else { + histos.fill(HIST(hnsigmaMCmat[mcID * Np + massID]), track.pt(), nsigmaMassID); + } } else { - histos.fill(HIST(hsignalMCmat[mcID]), track.p(), track.beta()); - histos.fill(HIST(hnsigmaMCmat[mcID]), track.pt(), nsigma); + histos.fill(HIST(hnsigmaMCprm[mcID * Np + massID]), track.pt(), nsigmaMassID); } - } else { - histos.fill(HIST(hsignalMCprm[mcID]), track.p(), track.beta()); - histos.fill(HIST(hnsigmaMCprm[mcID]), track.pt(), nsigma); } } @@ -568,25 +722,31 @@ struct pidTOFTaskQAMC { const auto& particle = t.mcParticle(); - if (!particle.isPhysicalPrimary()) { - if (particle.getProcess() == 4) { - histos.fill(HIST("event/tpcsignalStr"), t.tpcInnerParam(), t.tpcSignal()); + if (checkPrimaries) { + if (!particle.isPhysicalPrimary()) { + // histos.fill(HIST("event/tofbetaSec"), t.p(), t.beta()); + if (particle.getProcess() == 4) { + histos.fill(HIST("event/tofbetaStr"), t.tpcInnerParam(), t.tpcSignal()); + } else { + histos.fill(HIST("event/tofbetaMat"), t.tpcInnerParam(), t.tpcSignal()); + } } else { - histos.fill(HIST("event/tpcsignalMat"), t.tpcInnerParam(), t.tpcSignal()); + histos.fill(HIST("event/tofbetaPrm"), t.p(), t.beta()); } - } else { - histos.fill(HIST("event/tpcsignalPrm"), t.tpcInnerParam(), t.tpcSignal()); } // Fill with PDG codes static_for<0, 8>([&](auto i) { + static_for<0, 8>([&](auto j) { + fillPIDInfoForPdg(t, particle); + }); fillTrackInfoForPdg(t, particle); }); - } + } // track loop histos.fill(HIST("event/T0"), nTracksWithTOF, collisionTime_ps); histos.fill(HIST("event/vertexz"), collision.posZ()); - } - } + } // collision loop + } // process() }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/DPG/Tasks/AOTTrack/PID/qaPIDTPCSignal.cxx b/DPG/Tasks/AOTTrack/PID/qaPIDTPCSignal.cxx index f3d9901cb9b..35d1c3b728a 100644 --- a/DPG/Tasks/AOTTrack/PID/qaPIDTPCSignal.cxx +++ b/DPG/Tasks/AOTTrack/PID/qaPIDTPCSignal.cxx @@ -33,15 +33,20 @@ struct tpcPidQaSignal { Configurable logAxis{"logAxis", 1, "Flag to use a log momentum axis"}; Configurable nBinsP{"nBinsP", 3000, "Number of bins for the momentum"}; + Configurable runPerRunOutput{"runPerRunOutput", false, "Flag to produce run by run output for e.g. lite calibration purposes"}; + Configurable fractionOfEvents{"fractionOfEvents", 0.1f, "Downsampling factor for the events for derived data"}; Configurable minP{"minP", 0.01, "Minimum momentum in range"}; Configurable maxP{"maxP", 20, "Maximum momentum in range"}; ConfigurableAxis dEdxBins{"dEdxBins", {5000, 0.f, 5000.f}, "Binning in dE/dx"}; - Configurable applyEvSel{"applyEvSel", 2, "Flag to apply event selection cut: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"}; Configurable minTPCNcls{"minTPCNcls", 0.f, "Minimum number or TPC Clusters for tracks"}; Configurable minNClsCrossedRows{"minNClsCrossedRows", 70.f, "Minimum number or TPC crossed rows for tracks"}; + std::shared_ptr hdedx; + int lastRun = -1; + unsigned int randomSeed = 0; void init(o2::framework::InitContext&) { + randomSeed = static_cast(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); const AxisSpec vtxZAxis{100, -20, 20, "Vtx_{z} (cm)"}; AxisSpec pAxis{nBinsP, minP, maxP, "#it{p}/|Z| (GeV/#it{c})"}; if (logAxis) { @@ -57,7 +62,7 @@ struct tpcPidQaSignal { h->GetXaxis()->SetBinLabel(3, "Passed vtx Z"); histos.add("event/vertexz", "", kTH1D, {vtxZAxis}); - histos.add("event/tpcsignal", "", kTH3F, {pAxis, dedxAxis, chargeAxis}); + hdedx = histos.add("event/tpcsignal", "", kTH3D, {pAxis, dedxAxis, chargeAxis}); LOG(info) << "QA PID TPC histograms:"; histos.print(); } @@ -67,8 +72,12 @@ struct tpcPidQaSignal { Filter trackFilterTPC = ((aod::track::tpcChi2NCl < 4.f)); using TrackCandidates = soa::Join; void processEvSel(soa::Join::iterator const& collision, - soa::Filtered const& tracks) + soa::Filtered const& tracks, + aod::BCs const&) { + if (fractionOfEvents < 1.f && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > fractionOfEvents) { // Skip events that are not sampled + return; + } histos.fill(HIST("event/evsel"), 1); if (!collision.sel8()) { @@ -99,7 +108,18 @@ struct tpcPidQaSignal { if (t.tpcNClsCrossedRows() < minNClsCrossedRows) { continue; } - histos.fill(HIST("event/tpcsignal"), t.tpcInnerParam(), t.tpcSignal(), t.sign()); + + if (runPerRunOutput.value == true && lastRun != collision.bc().runNumber()) { + lastRun = collision.bc().runNumber(); + AxisSpec pAxis{nBinsP, minP, maxP, "#it{p}/|Z| (GeV/#it{c})"}; + if (logAxis) { + pAxis.makeLogarithmic(); + } + const AxisSpec dedxAxis{dEdxBins, "d#it{E}/d#it{x} Arb. units"}; + const AxisSpec chargeAxis{2, -2.f, 2.f, "Charge"}; + hdedx = histos.add(Form("Run%i/tpcsignal", lastRun), "", kTH3D, {pAxis, dedxAxis, chargeAxis}); + } + hdedx->Fill(t.tpcInnerParam(), t.tpcSignal(), t.sign()); } } PROCESS_SWITCH(tpcPidQaSignal, processEvSel, "Process with event selection", false); @@ -107,6 +127,9 @@ struct tpcPidQaSignal { void processNoEvSel(aod::Collision const& collision, soa::Filtered const& tracks) { + if (fractionOfEvents < 1.f && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > fractionOfEvents) { // Skip events that are not sampled + return; + } histos.fill(HIST("event/evsel"), 1); histos.fill(HIST("event/evsel"), 2); diff --git a/DPG/Tasks/AOTTrack/qaEfficiency.cxx b/DPG/Tasks/AOTTrack/qaEfficiency.cxx index 27327e9ff6d..a8e345ab5e9 100644 --- a/DPG/Tasks/AOTTrack/qaEfficiency.cxx +++ b/DPG/Tasks/AOTTrack/qaEfficiency.cxx @@ -42,6 +42,7 @@ struct QaEfficiency { static constexpr int PDGs[nSpecies] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton, 1000010020, 1000010030, 1000020030, 1000020040}; // Track/particle selection Configurable noFakesHits{"noFakesHits", false, "Flag to reject tracks that have fake hits"}; + Configurable skipEventsWithoutTPCTracks{"skipEventsWithoutTPCTracks", false, "Flag to reject events that have no tracks reconstructed in the TPC"}; Configurable maxProdRadius{"maxProdRadius", 9999.f, "Maximum production radius of the particle under study"}; // Charge selection Configurable doPositivePDG{"doPositivePDG", false, "Flag to fill histograms for positive PDG codes."}; @@ -79,6 +80,8 @@ struct QaEfficiency { Configurable requireITS{"requireITS", true, "Additional cut on the ITS requirement"}; Configurable requireTPC{"requireTPC", true, "Additional cut on the TPC requirement"}; Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable minITScl{"minITScl", 4, "Additional cut on the ITS cluster"}; + Configurable doPVContributorCut{"doPVContributorCut", false, "Select tracks used for primary vertex recostruction (isPVContributor)"}; Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.f, "Additional cut on the minimum number of crossed rows in the TPC"}; Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.8f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 4.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; @@ -182,6 +185,12 @@ struct QaEfficiency { "MC/el/neg_pdg/pt/prm/its_tpc_tof", "MC/mu/neg_pdg/pt/prm/its_tpc_tof", "MC/pi/neg_pdg/pt/prm/its_tpc_tof", "MC/ka/neg_pdg/pt/prm/its_tpc_tof", "MC/pr/neg_pdg/pt/prm/its_tpc_tof", "MC/de/neg_pdg/pt/prm/its_tpc_tof", "MC/tr/neg_pdg/pt/prm/its_tpc_tof", "MC/he/neg_pdg/pt/prm/its_tpc_tof", "MC/al/neg_pdg/pt/prm/its_tpc_tof"}; + static constexpr std::string_view hPtTrkItsTpcTofPrm[nHistograms] = {"MC/el/pos_pdg/pt/prm/trk/its_tpc_tof", "MC/mu/pos_pdg/pt/prm/trk/its_tpc_tof", "MC/pi/pos_pdg/pt/prm/trk/its_tpc_tof", + "MC/ka/pos_pdg/pt/prm/trk/its_tpc_tof", "MC/pr/pos_pdg/pt/prm/trk/its_tpc_tof", "MC/de/pos_pdg/pt/prm/trk/its_tpc_tof", + "MC/tr/pos_pdg/pt/prm/trk/its_tpc_tof", "MC/he/pos_pdg/pt/prm/trk/its_tpc_tof", "MC/al/pos_pdg/pt/prm/trk/its_tpc_tof", + "MC/el/neg_pdg/pt/prm/trk/its_tpc_tof", "MC/mu/neg_pdg/pt/prm/trk/its_tpc_tof", "MC/pi/neg_pdg/pt/prm/trk/its_tpc_tof", + "MC/ka/neg_pdg/pt/prm/trk/its_tpc_tof", "MC/pr/neg_pdg/pt/prm/trk/its_tpc_tof", "MC/de/neg_pdg/pt/prm/trk/its_tpc_tof", + "MC/tr/neg_pdg/pt/prm/trk/its_tpc_tof", "MC/he/neg_pdg/pt/prm/trk/its_tpc_tof", "MC/al/neg_pdg/pt/prm/trk/its_tpc_tof"}; static constexpr std::string_view hPtGeneratedPrm[nHistograms] = {"MC/el/pos_pdg/pt/prm/generated", "MC/mu/pos_pdg/pt/prm/generated", "MC/pi/pos_pdg/pt/prm/generated", "MC/ka/pos_pdg/pt/prm/generated", "MC/pr/pos_pdg/pt/prm/generated", "MC/de/pos_pdg/pt/prm/generated", "MC/tr/pos_pdg/pt/prm/generated", "MC/he/pos_pdg/pt/prm/generated", "MC/al/pos_pdg/pt/prm/generated", @@ -504,6 +513,7 @@ struct QaEfficiency { registry->add(hPtItsTpcPrm[histogramIndex].data(), "ITS-TPC tracks (primaries) " + tagPt, kTH1F, {axisPt}); registry->add(hPtTrkItsTpcPrm[histogramIndex].data(), "ITS-TPC tracks (reco primaries) " + tagPt, kTH1F, {axisPt}); registry->add(hPtItsTpcTofPrm[histogramIndex].data(), "ITS-TPC-TOF tracks (primaries) " + tagPt, kTH1F, {axisPt}); + registry->add(hPtTrkItsTpcTofPrm[histogramIndex].data(), "ITS-TPC-TOF tracks (reco primaries) " + tagPt, kTH1F, {axisPt}); registry->add(hPtGeneratedPrm[histogramIndex].data(), "Generated (primaries) " + tagPt, kTH1F, {axisPt}); registry->add(hPtItsTpcStr[histogramIndex].data(), "ITS-TPC tracks (from weak decays) " + tagPt, kTH1F, {axisPt}); @@ -609,7 +619,7 @@ struct QaEfficiency { makeEfficiency("TPC_vsPt", HIST(hPtTpc[histogramIndex])); makeEfficiency("ITS-TPC_vsPt", HIST(hPtItsTpc[histogramIndex])); makeEfficiency("ITS-TOF_vsPt", HIST(hPtItsTof[histogramIndex])); - makeEfficiency("Tpc-TOF_vsPt", HIST(hPtTpcTof[histogramIndex])); + makeEfficiency("TPC-TOF_vsPt", HIST(hPtTpcTof[histogramIndex])); makeEfficiency("ITS-TPC-TRD_vsPt", HIST(hPtItsTpcTrd[histogramIndex])); makeEfficiency("ITS-TPC-TOF_vsPt", HIST(hPtItsTpcTof[histogramIndex])); makeEfficiency("ITS-TPC-TRD-TOF_vsPt", HIST(hPtItsTpcTrdTof[histogramIndex])); @@ -619,6 +629,7 @@ struct QaEfficiency { makeEfficiency("ITS-TPC_vsPt_Prm", HIST(hPtItsTpcPrm[histogramIndex])); makeEfficiency("ITS-TPC_vsPt_Prm_Trk", HIST(hPtTrkItsTpcPrm[histogramIndex])); makeEfficiency("ITS-TPC-TOF_vsPt_Prm", HIST(hPtItsTpcTofPrm[histogramIndex])); + makeEfficiency("ITS-TPC-TOF_vsPt_Prm_Trk", HIST(hPtTrkItsTpcTofPrm[histogramIndex])); makeEfficiency("ITS-TPC_vsPt_Str", HIST(hPtItsTpcStr[histogramIndex])); makeEfficiency("ITS-TPC_vsPt_Str_Trk", HIST(hPtTrkItsTpcStr[histogramIndex])); @@ -694,30 +705,31 @@ struct QaEfficiency { h->GetXaxis()->SetBinLabel(12, "passedDCAxy"); h->GetXaxis()->SetBinLabel(13, "passedDCAz"); h->GetXaxis()->SetBinLabel(14, "passedGoldenChi2"); - h->GetXaxis()->SetBinLabel(15, "passedITS (partial)"); - h->GetXaxis()->SetBinLabel(16, "passedTPC (partial)"); - h->GetXaxis()->SetBinLabel(17, "passedTOF (partial)"); + h->GetXaxis()->SetBinLabel(15, "passed isPVContributor"); + h->GetXaxis()->SetBinLabel(16, "passedITS (partial)"); + h->GetXaxis()->SetBinLabel(17, "passedTPC (partial)"); + h->GetXaxis()->SetBinLabel(18, "passedTOF (partial)"); switch (globalTrackSelection) { case 0: - h->GetXaxis()->SetBinLabel(18, "No extra selection"); + h->GetXaxis()->SetBinLabel(19, "No extra selection"); break; case 1: - h->GetXaxis()->SetBinLabel(18, "isGlobalTrack"); + h->GetXaxis()->SetBinLabel(19, "isGlobalTrack"); break; case 2: - h->GetXaxis()->SetBinLabel(18, "isGlobalTrackWoPtEta"); + h->GetXaxis()->SetBinLabel(19, "isGlobalTrackWoPtEta"); break; case 3: - h->GetXaxis()->SetBinLabel(18, "isGlobalTrackWoDCA"); + h->GetXaxis()->SetBinLabel(19, "isGlobalTrackWoDCA"); break; case 4: - h->GetXaxis()->SetBinLabel(18, "isQualityTrack"); + h->GetXaxis()->SetBinLabel(19, "isQualityTrack"); break; case 5: - h->GetXaxis()->SetBinLabel(18, "isInAcceptanceTrack"); + h->GetXaxis()->SetBinLabel(19, "isInAcceptanceTrack"); break; case 6: - h->GetXaxis()->SetBinLabel(18, "customTrackSelection"); + h->GetXaxis()->SetBinLabel(19, "customTrackSelection"); break; default: LOG(fatal) << "Can't interpret track asked selection " << globalTrackSelection; @@ -766,6 +778,18 @@ struct QaEfficiency { }); } + // Efficiencies + TEfficiency* effITSTPCMatchingVsPt = nullptr; + TEfficiency* effTPCITSMatchingVsPt = nullptr; + TEfficiency* effTPCTOFMatchingVsPt = nullptr; + TEfficiency* effTPCTOFMatchingVsP = nullptr; + TEfficiency* effTPCTOFMatchingVsEta = nullptr; + TEfficiency* effTPCTOFMatchingVsPhi = nullptr; + + // 2D + TEfficiency* effTPCTOFMatchingVsPtVsEta = nullptr; + TEfficiency* effTPCTOFMatchingVsPtVsPhi = nullptr; + void initData(const AxisSpec& axisSel) { if (!doprocessData) { @@ -787,10 +811,11 @@ struct QaEfficiency { h->GetXaxis()->SetBinLabel(12, "passedDCAxy"); h->GetXaxis()->SetBinLabel(13, "passedDCAz"); h->GetXaxis()->SetBinLabel(14, "passedGoldenChi2"); - h->GetXaxis()->SetBinLabel(15, "passedITS (partial)"); - h->GetXaxis()->SetBinLabel(16, "passedTPC (partial)"); - h->GetXaxis()->SetBinLabel(17, "passedTOF (partial)"); - h->GetXaxis()->SetBinLabel(18, "Passed globalCut"); + h->GetXaxis()->SetBinLabel(15, "passed isPVContributor"); + h->GetXaxis()->SetBinLabel(16, "passedITS (partial)"); + h->GetXaxis()->SetBinLabel(17, "passedTPC (partial)"); + h->GetXaxis()->SetBinLabel(18, "passedTOF (partial)"); + h->GetXaxis()->SetBinLabel(19, "Passed globalCut"); const TString tagPt = Form("#it{#eta} [%.2f,%.2f] #it{#varphi} [%.2f,%.2f]", etaMin, etaMax, @@ -870,33 +895,52 @@ struct QaEfficiency { listEfficiencyData.setObject(new THashList); if (makeEff) { LOG(debug) << "Making TEfficiency for Data"; - auto makeEfficiency = [&](TString effname, TString efftitle, auto templateHisto) { + auto makeEfficiency = [&](TString effname, TString efftitle, auto templateHisto, TEfficiency*& eff) { TAxis* axis = histos.get(templateHisto)->GetXaxis(); if (axis->IsVariableBinSize()) { - listEfficiencyData->Add(new TEfficiency(effname, efftitle, axis->GetNbins(), axis->GetXbins()->GetArray())); + eff = new TEfficiency(effname, efftitle, axis->GetNbins(), axis->GetXbins()->GetArray()); } else { - listEfficiencyData->Add(new TEfficiency(effname, efftitle, axis->GetNbins(), axis->GetXmin(), axis->GetXmax())); + eff = new TEfficiency(effname, efftitle, axis->GetNbins(), axis->GetXmin(), axis->GetXmax()); } + listEfficiencyData->Add(eff); }; - makeEfficiency("ITSTPCMatchingEfficiencyVsPt", "ITS-TPC M.E. in data " + tagPt + ";#it{p}_{T} (GeV/#it{c});Efficiency", HIST("Data/pos/pt/its_tpc_tof")); - makeEfficiency("TPCTOFMatchingEfficiencyVsPt", "TPC-TOF M.E. in data " + tagPt + ";#it{p}_{T} (GeV/#it{c});Efficiency", HIST("Data/pos/pt/its_tpc_tof")); - makeEfficiency("TPCTOFMatchingEfficiencyVsP", "TPC-TOF M.E. in data " + tagPt + ";#it{p} (GeV/#it{c});Efficiency", HIST("Data/pos/pt/its_tpc_tof")); - makeEfficiency("TPCTOFMatchingEfficiencyVsEta", "TPC-TOF M.E. in data " + tagEta + ";#it{#eta};Efficiency", HIST("Data/pos/eta/its_tpc_tof")); - makeEfficiency("TPCTOFMatchingEfficiencyVsPhi", "TPC-TOF M.E. in data " + tagPhi + ";#it{#varphi} (rad);Efficiency", HIST("Data/pos/phi/its_tpc_tof")); - - auto makeEfficiency2D = [&](TString effname, TString efftitle, auto templateHistoX, auto templateHistoY) { + makeEfficiency("ITSTPCMatchingEfficiencyVsPt", + "ITS-TPC M.E. (ITS-TPC)/ITS in data " + tagPt + ";#it{p}_{T} (GeV/#it{c});Efficiency", HIST("Data/pos/pt/its_tpc_tof"), + effITSTPCMatchingVsPt); + makeEfficiency("TPCITSMatchingEfficiencyVsPt", + "ITS-TPC M.E. (ITS-TPC)/TPC in data " + tagPt + ";#it{p}_{T} (GeV/#it{c});Efficiency", HIST("Data/pos/pt/its_tpc_tof"), + effTPCITSMatchingVsPt); + makeEfficiency("TPCTOFMatchingEfficiencyVsPt", + "TPC-TOF M.E. in data " + tagPt + ";#it{p}_{T} (GeV/#it{c});Efficiency", HIST("Data/pos/pt/its_tpc_tof"), + effTPCTOFMatchingVsPt); + makeEfficiency("TPCTOFMatchingEfficiencyVsP", + "TPC-TOF M.E. in data " + tagPt + ";#it{p} (GeV/#it{c});Efficiency", HIST("Data/pos/pt/its_tpc_tof"), + effTPCTOFMatchingVsP); + makeEfficiency("TPCTOFMatchingEfficiencyVsEta", + "TPC-TOF M.E. in data " + tagEta + ";#it{#eta};Efficiency", HIST("Data/pos/eta/its_tpc_tof"), + effTPCTOFMatchingVsEta); + makeEfficiency("TPCTOFMatchingEfficiencyVsPhi", + "TPC-TOF M.E. in data " + tagPhi + ";#it{#varphi} (rad);Efficiency", HIST("Data/pos/phi/its_tpc_tof"), + effTPCTOFMatchingVsPhi); + + auto makeEfficiency2D = [&](TString effname, TString efftitle, auto templateHistoX, auto templateHistoY, TEfficiency*& eff) { TAxis* axisX = histos.get(templateHistoX)->GetXaxis(); TAxis* axisY = histos.get(templateHistoY)->GetYaxis(); if (axisX->IsVariableBinSize() || axisY->IsVariableBinSize()) { - listEfficiencyData->Add(new TEfficiency(effname, efftitle, axisX->GetNbins(), axisX->GetXbins()->GetArray(), axisY->GetNbins(), axisY->GetXbins()->GetArray())); + eff = new TEfficiency(effname, efftitle, axisX->GetNbins(), axisX->GetXbins()->GetArray(), axisY->GetNbins(), axisY->GetXbins()->GetArray()); } else { - listEfficiencyData->Add(new TEfficiency(effname, efftitle, axisX->GetNbins(), axisX->GetXmin(), axisX->GetXmax(), axisY->GetNbins(), axisY->GetXmin(), axisY->GetXmax())); + eff = new TEfficiency(effname, efftitle, axisX->GetNbins(), axisX->GetXmin(), axisX->GetXmax(), axisY->GetNbins(), axisY->GetXmin(), axisY->GetXmax()); } + listEfficiencyData->Add(eff); }; - makeEfficiency2D("TPCTOFMatchingEfficiencyVsPtVsEta", Form("TPC-TOF M.E. in data #it{#varphi} [%.2f,%.2f];%s;%s;Efficiency", phiMin, phiMax, "#it{p}_{T} (GeV/#it{c})", "#it{#eta}"), HIST("Data/pos/pt/its_tpc_tof"), HIST("Data/pos/eta/its_tpc_tof")); - makeEfficiency2D("TPCTOFMatchingEfficiencyVsPtVsPhi", Form("TPC-TOF M.E. in data #it{#eta} [%.2f,%.2f];%s;%s;Efficiency", etaMin, etaMax, "#it{p}_{T} (GeV/#it{c})", "#it{#varphi} (rad)"), HIST("Data/pos/pt/its_tpc_tof"), HIST("Data/pos/phi/its_tpc_tof")); + makeEfficiency2D("TPCTOFMatchingEfficiencyVsPtVsEta", + Form("TPC-TOF M.E. in data #it{#varphi} [%.2f,%.2f];%s;%s;Efficiency", phiMin, phiMax, "#it{p}_{T} (GeV/#it{c})", "#it{#eta}"), HIST("Data/pos/pt/its_tpc_tof"), HIST("Data/pos/eta/its_tpc_tof"), + effTPCTOFMatchingVsPtVsEta); + makeEfficiency2D("TPCTOFMatchingEfficiencyVsPtVsPhi", + Form("TPC-TOF M.E. in data #it{#eta} [%.2f,%.2f];%s;%s;Efficiency", etaMin, etaMax, "#it{p}_{T} (GeV/#it{c})", "#it{#varphi} (rad)"), HIST("Data/pos/pt/its_tpc_tof"), HIST("Data/pos/phi/its_tpc_tof"), + effTPCTOFMatchingVsPtVsPhi); } } @@ -939,13 +983,31 @@ struct QaEfficiency { doLimits(phiMin, phiMax, phiBins); doLimits(yMin, yMax, yBins); - const AxisSpec axisSel{40, 0.5, 40.5, "Selection"}; - histos.add("eventSelection", "Event Selection", kTH1F, {axisSel}); + histos.add("eventSelection", "Event Selection", kTH1D, {{10, 0.5, 10.5, "Selection"}}); histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(1, "Events read"); - histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(2, "Passed Ev. Sel."); + if (applyEvSel == 0) { + histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(2, "Passed Ev. Sel. (no ev. sel)"); + } else if (applyEvSel == 1) { + histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(2, "Passed Ev. Sel. (sel7)"); + } else if (applyEvSel == 2) { + histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(2, "Passed Ev. Sel. (sel8)"); + } else { + LOG(fatal) << "Can't interpret event selection asked " << applyEvSel << " (0: no event selection, 1: sel7, 2: sel8)"; + } + histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(3, "Passed Contrib."); histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(4, "Passed Position"); + if (doprocessMC) { + histos.add("MC/generatedCollisions", "Generated Collisions", kTH1D, {{10, 0.5, 10.5, "Generated collisions"}}); + histos.get(HIST("MC/generatedCollisions"))->GetXaxis()->SetBinLabel(1, "Gen. coll"); + histos.get(HIST("MC/generatedCollisions"))->GetXaxis()->SetBinLabel(2, "At least 1 reco"); + histos.get(HIST("MC/generatedCollisions"))->GetXaxis()->SetBinLabel(3, "At least 1 TPC track"); + histos.get(HIST("MC/generatedCollisions"))->GetXaxis()->SetBinLabel(4, "Reco. coll."); + histos.get(HIST("MC/generatedCollisions"))->GetXaxis()->SetBinLabel(5, "Reco. good coll."); + } + + const AxisSpec axisSel{40, 0.5, 40.5, "Selection"}; initData(axisSel); initMC(axisSel); @@ -956,6 +1018,7 @@ struct QaEfficiency { customTrackCuts.SetRequireITSRefit(requireITS.value); customTrackCuts.SetRequireTPCRefit(requireTPC.value); customTrackCuts.SetRequireGoldenChi2(requireGoldenChi2.value); + customTrackCuts.SetRequireHitsInITSLayers(minITScl.value, {0, 1, 2, 3, 4, 5, 6}); customTrackCuts.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); customTrackCuts.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); customTrackCuts.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); @@ -1080,6 +1143,7 @@ struct QaEfficiency { h->fill(HIST(hPhiTrkItsTpcPrm[histogramIndex]), track.phi()); if (passedTOF) { h->fill(HIST(hPtItsTpcTofPrm[histogramIndex]), mcParticle.pt()); + h->fill(HIST(hPtTrkItsTpcTofPrm[histogramIndex]), track.pt()); h->fill(HIST(hEtaItsTpcTofPrm[histogramIndex]), mcParticle.eta()); h->fill(HIST(hPhiItsTpcTofPrm[histogramIndex]), mcParticle.phi()); } @@ -1214,7 +1278,7 @@ struct QaEfficiency { doFillEfficiency("TPC_vsPt", HIST(hPtTpc[histogramIndex]), HIST(hPtGenerated[histogramIndex])); doFillEfficiency("ITS-TPC_vsPt", HIST(hPtItsTpc[histogramIndex]), HIST(hPtGenerated[histogramIndex])); doFillEfficiency("ITS-TOF_vsPt", HIST(hPtItsTof[histogramIndex]), HIST(hPtGenerated[histogramIndex])); - doFillEfficiency("Tpc-TOF_vsPt", HIST(hPtTpcTof[histogramIndex]), HIST(hPtGenerated[histogramIndex])); + doFillEfficiency("TPC-TOF_vsPt", HIST(hPtTpcTof[histogramIndex]), HIST(hPtGenerated[histogramIndex])); doFillEfficiency("ITS-TPC-TRD_vsPt", HIST(hPtItsTpcTrd[histogramIndex]), HIST(hPtGenerated[histogramIndex])); doFillEfficiency("ITS-TPC-TOF_vsPt", HIST(hPtItsTpcTof[histogramIndex]), HIST(hPtGenerated[histogramIndex])); doFillEfficiency("ITS-TPC-TRD-TOF_vsPt", HIST(hPtItsTpcTrdTof[histogramIndex]), HIST(hPtGenerated[histogramIndex])); @@ -1224,6 +1288,7 @@ struct QaEfficiency { doFillEfficiency("ITS-TPC_vsPt_Prm", HIST(hPtItsTpcPrm[histogramIndex]), HIST(hPtGeneratedPrm[histogramIndex])); doFillEfficiency("ITS-TPC_vsPt_Prm_Trk", HIST(hPtTrkItsTpcPrm[histogramIndex]), HIST(hPtGeneratedPrm[histogramIndex])); doFillEfficiency("ITS-TPC-TOF_vsPt_Prm", HIST(hPtItsTpcTofPrm[histogramIndex]), HIST(hPtGeneratedPrm[histogramIndex])); + doFillEfficiency("ITS-TPC-TOF_vsPt_Prm_Trk", HIST(hPtTrkItsTpcTofPrm[histogramIndex]), HIST(hPtGeneratedPrm[histogramIndex])); doFillEfficiency("ITS-TPC_vsPt_Str", HIST(hPtItsTpcStr[histogramIndex]), HIST(hPtGeneratedStr[histogramIndex])); doFillEfficiency("ITS-TPC_vsPt_Str_Trk", HIST(hPtTrkItsTpcStr[histogramIndex]), HIST(hPtGeneratedStr[histogramIndex])); @@ -1415,6 +1480,10 @@ struct QaEfficiency { return false; } histos.fill(countingHisto, 14); + if (doPVContributorCut && !track.isPVContributor()) { + return false; + } + histos.fill(countingHisto, 15); passedITS = track.passedITSNCls() && track.passedITSChi2NDF() && @@ -1438,15 +1507,15 @@ struct QaEfficiency { } if (passedITS) { // Partial - histos.fill(countingHisto, 15); + histos.fill(countingHisto, 16); } if (passedTPC) { // Partial - histos.fill(countingHisto, 16); + histos.fill(countingHisto, 17); } if (passedTOF) { // Partial - histos.fill(countingHisto, 17); + histos.fill(countingHisto, 18); } switch (globalTrackSelection) { @@ -1467,7 +1536,7 @@ struct QaEfficiency { default: LOG(fatal) << "Can't interpret track asked selection " << globalTrackSelection; } - histos.fill(countingHisto, 18); + histos.fill(countingHisto, 19); return false; } @@ -1479,14 +1548,37 @@ struct QaEfficiency { o2::soa::Join const& tracks, o2::aod::McParticles const& mcParticles) { + histos.fill(HIST("MC/generatedCollisions"), 1); + if (collisions.size() < 1) { // Skipping MC events that have no reconstructed collisions return; } + histos.fill(HIST("MC/generatedCollisions"), 2); + if (skipEventsWithoutTPCTracks) { + int nTPCTracks = 0; + for (const auto& collision : collisions) { + const auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); + for (const auto& track : groupedTracks) { + if (track.hasTPC()) { + nTPCTracks++; + break; + } + } + } + if (nTPCTracks == 0) { + LOG(info) << "Skipping event with no TPC tracks"; + return; + } + } + histos.fill(HIST("MC/generatedCollisions"), 3); for (const auto& collision : collisions) { + histos.fill(HIST("MC/generatedCollisions"), 4); if (!isCollisionSelected(collision)) { continue; } + histos.fill(HIST("MC/generatedCollisions"), 5); + const auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); // Track loop @@ -1679,15 +1771,18 @@ struct QaEfficiency { if (makeEff) { if (passedITS) { - static_cast(listEfficiencyData->At(0))->Fill(passedTPC, track.pt()); + effITSTPCMatchingVsPt->Fill(passedTPC, track.pt()); + } + if (passedTPC) { + effTPCITSMatchingVsPt->Fill(passedITS, track.pt()); } if (passedITS && passedTPC) { - static_cast(listEfficiencyData->At(1))->Fill(passedTOF, track.pt()); - static_cast(listEfficiencyData->At(2))->Fill(passedTOF, track.p()); - static_cast(listEfficiencyData->At(3))->Fill(passedTOF, track.eta()); - static_cast(listEfficiencyData->At(4))->Fill(passedTOF, track.phi()); - static_cast(listEfficiencyData->At(5))->Fill(passedTOF, track.pt(), track.eta()); - static_cast(listEfficiencyData->At(6))->Fill(passedTOF, track.pt(), track.phi()); + effTPCTOFMatchingVsPt->Fill(passedTOF, track.pt()); + effTPCTOFMatchingVsP->Fill(passedTOF, track.p()); + effTPCTOFMatchingVsEta->Fill(passedTOF, track.eta()); + effTPCTOFMatchingVsPhi->Fill(passedTOF, track.phi()); + effTPCTOFMatchingVsPtVsEta->Fill(passedTOF, track.pt(), track.eta()); + effTPCTOFMatchingVsPtVsPhi->Fill(passedTOF, track.pt(), track.phi()); } } } @@ -1698,4 +1793,4 @@ struct QaEfficiency { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} +} \ No newline at end of file diff --git a/DPG/Tasks/AOTTrack/qaEventTrack.cxx b/DPG/Tasks/AOTTrack/qaEventTrack.cxx index ac502f48f2e..f0f473b2b8f 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrack.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrack.cxx @@ -81,7 +81,7 @@ struct qaEventTrack { ConfigurableAxis binsVertexPosZ{"binsVertexPosZ", {100, -20., 20.}, ""}; // TODO: do we need this to be configurable? ConfigurableAxis binsVertexPosXY{"binsVertexPosXY", {500, -1., 1.}, ""}; // TODO: do we need this to be configurable? - ConfigurableAxis binsTrackMultiplicity{"binsTrackMultiplcity", {200, 0, 200}, ""}; + ConfigurableAxis binsTrackMultiplicity{"binsTrackMultiplcity", {5000, 0, 5000}, ""}; // TODO: ask if one can have different filters for both process functions Filter trackFilter = (trackSelection.node() == 0) || @@ -133,7 +133,7 @@ struct qaEventTrack { const AxisSpec axisInvPt{100, -10, 10, "1/#it{p}_{T}_{gen} [GeV/c]^{-1}"}; const AxisSpec axisEta{180, -0.9, 0.9, "#it{#eta}"}; const AxisSpec axisPhi{180, 0., 2 * M_PI, "#it{#varphi} [rad]"}; - const AxisSpec axisVertexNumContrib{200, 0, 200, "Number Of contributors to the PV"}; + const AxisSpec axisVertexNumContrib{5000, 0, 5000, "Number Of contributors to the PV"}; const AxisSpec axisVertexPosX{binsVertexPosXY, "X [cm]"}; const AxisSpec axisVertexPosY{binsVertexPosXY, "Y [cm]"}; const AxisSpec axisVertexPosZ{binsVertexPosZ, "Z [cm]"}; @@ -167,6 +167,7 @@ struct qaEventTrack { histos.add("Events/nContribVsFilteredMult", "", kTH2D, {axisVertexNumContrib, axisTrackMultiplicity}); histos.add("Events/nContribVsMult", "", kTH2D, {axisVertexNumContrib, axisTrackMultiplicity}); histos.add("Events/nContribWithTOFvsWithTRD", ";PV contrib. with TOF; PV contrib. with TRD;", kTH2D, {axisVertexNumContrib, axisVertexNumContrib}); + histos.add("Events/nContribAllvsWithTRD", ";PV contrib. all PV contrib. with TRD;", kTH2D, {axisVertexNumContrib, axisVertexNumContrib}); histos.add("Events/vertexChi2", ";#chi^{2}", kTH1D, {{100, 0, 100}}); histos.add("Events/covXX", ";Cov_{xx} [cm^{2}]", kTH1D, {axisVertexCov}); @@ -191,7 +192,11 @@ struct qaEventTrack { trackRecoEffHist->SetBit(TH1::kIsNotW); // kine histograms - histos.add("Tracks/Kine/pt", "#it{p}_{T}", kTH1D, {axisPt}); + histos.add("Tracks/Kine/pt", "#it{p}_{T} (filtered)", kTH1D, {axisPt}); + histos.add("Tracks/Kine/ptFilteredPositive", "positive charge track #it{p}_{T} (filtered)", kTH1D, {axisPt}); + histos.add("Tracks/Kine/ptFilteredNegative", "negative charge track #it{p}_{T} (filtered)", kTH1D, {axisPt}); + histos.add("Tracks/Kine/ptUnfilteredPositive", "positive charge track #it{p}_{T} (unfiltered)", kTH1D, {axisPt}); + histos.add("Tracks/Kine/ptUnfilteredNegative", "negative charge track #it{p}_{T} (unfiltered)", kTH1D, {axisPt}); histos.add("Tracks/Kine/eta", "#eta", kTH1D, {axisEta}); histos.add("Tracks/Kine/phi", "#varphi", kTH1D, {axisPhi}); histos.add("Tracks/Kine/etavsphi", "#eta vs #varphi", kTH2F, {axisEta, axisPhi}); @@ -334,9 +339,15 @@ struct qaEventTrack { h3->GetXaxis()->SetTitle("#eta"); h3->GetYaxis()->SetTitle("# clusters TPC"); h3->GetZaxis()->SetTitle("Vtx. Z [cm]"); + auto h4 = histos.add("Tracks/TPC/tpcNClsFoundVsEtaPhi", "tracks with at least 1 TPC cluster", kTH3D, {axisEta, {165, -0.5, 164.5}, axisPhi}); + h4->GetXaxis()->SetTitle("#eta"); + h4->GetYaxis()->SetTitle("# clusters TPC"); + h4->GetZaxis()->SetTitle("#varphi"); histos.add("Tracks/TPC/tpcNClsShared", "number of shared TPC clusters;# shared clusters TPC", kTH1D, {{165, -0.5, 164.5}}); histos.add("Tracks/TPC/tpcCrossedRows", "number of crossed TPC rows;# crossed rows TPC", kTH1D, {{165, -0.5, 164.5}}); histos.add("Tracks/TPC/tpcFractionSharedCls", "fraction of shared TPC clusters;fraction shared clusters TPC", kTH1D, {{100, 0., 1.}}); + histos.add("Tracks/TPC/tpcNClsSharedVsFilteredTracks", "number of shared TPC clusters vs. filtered tracks", kTH2D, {{165, -0.5, 164.5, "# shared clusters TPC"}, axisTrackMultiplicity}); + histos.add("Tracks/TPC/tpcFractionSharedClsVsFilteredTracks", "fraction of shared TPC clusters vs. filtered tracks", kTH2D, {{100, 0., 1., "fraction shared clusters TPC"}, axisTrackMultiplicity}); histos.add("Tracks/TPC/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {{60, 0.7, 1.3}}); histos.add("Tracks/TPC/tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {{100, 0, 10}}); histos.add("Tracks/TPC/hasTPC", "pt distribution of tracks crossing TPC", kTH1D, {axisPt}); @@ -1315,6 +1326,12 @@ void qaEventTrack::fillRecoHistogramsGroupedTracks(const C& collision, const T& int nPvContrWithTOF = 0; int nPvContrWithTRD = 0; for (const auto& trackUnfiltered : tracksUnfiltered) { + // fill unfiltered track pt + if (trackUnfiltered.sign() > 0) { + histos.fill(HIST("Tracks/Kine/ptUnfilteredPositive"), trackUnfiltered.pt()); + } else { + histos.fill(HIST("Tracks/Kine/ptUnfilteredNegative"), trackUnfiltered.pt()); + } // fill ITS variables int itsNhits = 0; for (unsigned int i = 0; i < 7; i++) { @@ -1345,6 +1362,7 @@ void qaEventTrack::fillRecoHistogramsGroupedTracks(const C& collision, const T& } } histos.fill(HIST("Events/nContribWithTOFvsWithTRD"), nPvContrWithTOF, nPvContrWithTRD); + histos.fill(HIST("Events/nContribAllvsWithTRD"), collision.numContrib(), nPvContrWithTRD); // track related histograms for (const auto& track : tracks) { @@ -1356,6 +1374,11 @@ void qaEventTrack::fillRecoHistogramsGroupedTracks(const C& collision, const T& } // fill kinematic variables histos.fill(HIST("Tracks/Kine/pt"), track.pt()); + if (track.sign() > 0) { + histos.fill(HIST("Tracks/Kine/ptFilteredPositive"), track.pt()); + } else { + histos.fill(HIST("Tracks/Kine/ptFilteredNegative"), track.pt()); + } histos.fill(HIST("Tracks/Kine/eta"), track.eta()); histos.fill(HIST("Tracks/Kine/phi"), track.phi()); histos.fill(HIST("Tracks/Kine/etavsphi"), track.eta(), track.phi()); @@ -1425,10 +1448,13 @@ void qaEventTrack::fillRecoHistogramsGroupedTracks(const C& collision, const T& histos.fill(HIST("Tracks/TPC/tpcNClsFound"), track.tpcNClsFound()); histos.fill(HIST("Tracks/TPC/tpcNClsFoundVsEta"), track.eta(), track.tpcNClsFound()); histos.fill(HIST("Tracks/TPC/tpcNClsFoundVsEtaVtxZ"), track.eta(), track.tpcNClsFound(), collision.posZ()); + histos.fill(HIST("Tracks/TPC/tpcNClsFoundVsEtaPhi"), track.eta(), track.tpcNClsFound(), track.phi()); histos.fill(HIST("Tracks/TPC/tpcNClsShared"), track.tpcNClsShared()); histos.fill(HIST("Tracks/TPC/tpcCrossedRows"), track.tpcNClsCrossedRows()); histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); histos.fill(HIST("Tracks/TPC/tpcFractionSharedCls"), track.tpcFractionSharedCls()); + histos.fill(HIST("Tracks/TPC/tpcNClsSharedVsFilteredTracks"), track.tpcNClsShared(), nFilteredTracks); + histos.fill(HIST("Tracks/TPC/tpcFractionSharedClsVsFilteredTracks"), track.tpcFractionSharedCls(), nFilteredTracks); histos.fill(HIST("Tracks/TPC/tpcChi2NCl"), track.tpcChi2NCl()); if constexpr (IS_MC) { diff --git a/DPG/Tasks/AOTTrack/qaEventTrack.h b/DPG/Tasks/AOTTrack/qaEventTrack.h index 8293cb21bdc..e2230e37c87 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrack.h +++ b/DPG/Tasks/AOTTrack/qaEventTrack.h @@ -30,8 +30,27 @@ namespace dpgcollision { DECLARE_SOA_INDEX_COLUMN(BC, bc); DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); +DECLARE_SOA_COLUMN(IsEventSelected, isEventSelected, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); DECLARE_SOA_COLUMN(NumContrib, numContrib, int); +DECLARE_SOA_COLUMN(NumTracksAll, numTracksAll, int); +DECLARE_SOA_COLUMN(NumTracksFiltered, numTracksFiltered, int); +DECLARE_SOA_COLUMN(GlobalBcInRun, globalBcInRun, uint64_t); +DECLARE_SOA_COLUMN(Ft0PosZ, ft0PosZ, float); +DECLARE_SOA_COLUMN(SignalFT0A, signalFT0A, float); +DECLARE_SOA_COLUMN(SignalFT0C, signalFT0C, float); +DECLARE_SOA_COLUMN(SignalFT0M, signalFT0M, float); +DECLARE_SOA_COLUMN(SignalV0A, signalV0A, float); +DECLARE_SOA_COLUMN(CollIDMC, collIDMC, int); +DECLARE_SOA_COLUMN(PosXMC, posXMC, float); +DECLARE_SOA_COLUMN(PosYMC, posYMC, float); +DECLARE_SOA_COLUMN(PosZMC, posZMC, float); +DECLARE_SOA_COLUMN(CollisionTimeMC, collisionTimeMC, float); +DECLARE_SOA_COLUMN(RecoPVsPerMcColl, recoPVsPerMcColls, int); // from LF MCcollisionExtra +DECLARE_SOA_COLUMN(IsPvHighestContribForMcColl, IsPvHighestContribForMcColls, int); // from LF MCcollisionExtra +DECLARE_SOA_COLUMN(DpgCounterCollision, dpgCounterCollision, int); +DECLARE_SOA_COLUMN(DpgCounterDF, dpgCounterDF, int); +DECLARE_SOA_COLUMN(IsFakeCollision, isFakeCollision, int); } // namespace dpgcollision DECLARE_SOA_TABLE(DPGCollisions, "AOD", "DPGCollisions", //! Table of the DPG collisions @@ -40,6 +59,42 @@ DECLARE_SOA_TABLE(DPGCollisions, "AOD", "DPGCollisions", //! Table of the DPG co dpgcollision::RunNumber, dpgcollision::NumContrib); +DECLARE_SOA_TABLE(DPGCollsBig, "AOD", "DPGCollsBig", //! Big table of the DPG collisions + dpgcollision::IsEventSelected, + dpgcollision::RunNumber, + collision::PosX, + collision::PosY, + collision::PosZ, + collision::CovXX, + collision::CovXY, + collision::CovXZ, + collision::CovYY, + collision::CovYZ, + collision::CovZZ, + dpgcollision::NumContrib, + dpgcollision::NumTracksAll, + dpgcollision::NumTracksFiltered, + collision::Chi2, + dpgcollision::GlobalBcInRun, + dpgcollision::Ft0PosZ, + dpgcollision::SignalFT0A, + dpgcollision::SignalFT0C, + dpgcollision::SignalFT0M, + dpgcollision::SignalV0A, + collision::CollisionTime, + collision::CollisionTimeRes, + dpgcollision::DpgCounterCollision, /// counter to give a unique ID to each collision + dpgcollision::DpgCounterDF, /// counter to give a unique ID to data each dataframe + /// MC info + dpgcollision::CollIDMC, /// unique only if combined with DF counter (dpgcollision::DpgCounterDF) + dpgcollision::PosXMC, + dpgcollision::PosYMC, + dpgcollision::PosZMC, + dpgcollision::CollisionTimeMC, + dpgcollision::IsFakeCollision, /// -1: unknown (data); 0: not fake; 1: fake (== it does not correspond to any MC collision) + dpgcollision::RecoPVsPerMcColl, + dpgcollision::IsPvHighestContribForMcColl); + namespace dpgtrack { DECLARE_SOA_INDEX_COLUMN(DPGCollision, dpgCollision); //! Index to move from track to collision diff --git a/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx b/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx index bbbaf37a37a..6adc2614994 100644 --- a/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx +++ b/DPG/Tasks/AOTTrack/qaEventTrackLiteProducer.cxx @@ -25,8 +25,10 @@ #include "Framework/AnalysisDataModel.h" #include "ReconstructionDataFormats/DCA.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" #include "Common/TableProducer/PID/pidTOFBase.h" @@ -39,6 +41,7 @@ using namespace o2::dataformats; struct qaEventTrackLiteProducer { // Tables to produce Produces tableCollisions; + Produces tableCollsBig; Produces tableTracks; Produces tableRecoParticles; Produces tableNonRecoParticles; @@ -52,6 +55,8 @@ struct qaEventTrackLiteProducer { Configurable selectMaxVtxZ{"selectMaxVtxZ", 100.f, "Derived data option: select collision in a given Z window"}; Configurable targetNumberOfEvents{"targetNumberOfEvents", 10000000, "Derived data option: target number of collisions, if the target is met, future collisions will be skipped"}; Configurable fractionOfSampledEvents{"fractionOfSampledEvents", 1.f, "Derived data option: fraction of events to sample"}; + Configurable storeOnlySinglePvCollsBig{"storeOnlySinglePvCollsBig", false, "Colls. big table (MC): store only reco. PV for single-reconstructed MC collisions"}; + Configurable storeOnlyMultiplePvCollsBig{"storeOnlyMultiplePvCollsBig", false, "Colls. big table (MC): store only reco. PV for multiple-reconstructed MC collisions"}; // options to select only specific tracks Configurable trackSelection{"trackSelection", 1, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; @@ -90,15 +95,25 @@ struct qaEventTrackLiteProducer { ((trackSelection.node() == 5) && requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks)); Preslice perMcCollision = aod::mcparticle::mcCollisionId; - Preslice perRecoCollision = aod::track::collisionId; + Preslice perRecoCollision = aod::track::collisionId; + + int counterColl; + int counterDF; void init(InitContext const&) { - if (doprocessTableData == true && doprocessTableMC == true) { - LOGF(fatal, "Cannot enable processTableData and processTableMC at the same time. Please choose one."); + int howManyProcesses = static_cast(doprocessTableData) + static_cast(doprocessTableMC) + static_cast(doprocessTableDataCollsBig) + static_cast(doprocessTableMCCollsBig); + if (howManyProcesses > 1) { + LOGF(fatal, "%d process functions enabled. Enable only one of them!", howManyProcesses); + } else if (howManyProcesses == 0) { + LOGF(fatal, "No process function enabled. Enable one of them."); } - if (doprocessTableData == false && doprocessTableMC == false) { - LOGF(fatal, "No process function enabled. Enable either processTableData or processTableMC"); + + /// for studies with collision table + counterColl = 0; + counterDF = 0; + if (doprocessTableMCCollsBig && storeOnlySinglePvCollsBig && storeOnlyMultiplePvCollsBig) { + LOGF(fatal, "storeOnlySinglePvCollsBig and storeOnlyMultiplePvCollsBig are both activated. Not possible. Fix the configuration."); } } @@ -278,6 +293,137 @@ struct qaEventTrackLiteProducer { } } } + + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + /// Table filling for offline collision monitoring /// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + using BCsWithRun3Matchings = soa::Join; + using CollsBigTable = soa::Join; + using CollsBigTableMC = soa::Join; + using McCollsWithExtra = soa::Join; + + template + void fillCollsBigTable(COLLS& collisions, MCCOLLS& mcCollisions, TFILT& tracksFiltered, TALL& tracksAll, soa::Join const& bcs, aod::FT0s const& ft0s) + { + if (nTableEventCounter > targetNumberOfEvents) { // Skip events if target is reached + return; + } + for (auto& collision : collisions) { + + if (fractionOfSampledEvents < 1.f && (static_cast(rand()) / static_cast(RAND_MAX)) > fractionOfSampledEvents) { // Skip events that are not sampled + return; + } + nTableEventCounter++; + + const auto tracksFilteredPerColl = tracksFiltered.sliceBy(perRecoCollision, collision.globalIndex()); + const auto tracksAllPerColl = tracksAll.sliceBy(perRecoCollision, collision.globalIndex()); + + const auto& bc = collision.template bc_as(); + int collIDMC = -1; + float posXMC = -9999.; + float posYMC = -9999.; + float posZMC = -9999.; + float collTimeMC = -9999.; + int isFakeCollision = -1; + int recoPVsPerMcColl = -1; // how many reco. PV are associated to this MC collision + int isPvHighestContribForMcColl = -1; // the "best" PV associated to this MC collision, i.e. the one with the highest number of PV contributors + if constexpr (IS_MC) { + if (!collision.has_mcCollision()) { + isFakeCollision = 1; + } else { + isFakeCollision = 0; + const auto& mcCollision = collision.template mcCollision_as(); + collIDMC = mcCollision.globalIndex(); + posXMC = mcCollision.posX(); + posYMC = mcCollision.posY(); + posZMC = mcCollision.posZ(); + collTimeMC = mcCollision.t(); + recoPVsPerMcColl = mcCollision.numRecoCollision(); + isPvHighestContribForMcColl = (mcCollision.bestCollisionIndex() == collision.globalIndex()); + } + + /// MC + /// Decide to fill the table only with the desired collisions + if ((!storeOnlySinglePvCollsBig && !storeOnlyMultiplePvCollsBig) || /// store all collisions + (storeOnlySinglePvCollsBig && recoPVsPerMcColl == 1) || /// store only single-reconstructed collisions + (storeOnlyMultiplePvCollsBig && recoPVsPerMcColl > 1)) /// store only multiple-reconstructed collisions + { + tableCollsBig((isRun3 ? collision.sel8() : collision.sel7()), + bc.runNumber(), + collision.posX(), collision.posY(), collision.posZ(), + collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), + collision.numContrib(), tracksAllPerColl.size(), tracksFilteredPerColl.size(), + collision.chi2(), + bc.globalBC(), + bc.has_ft0() ? bc.ft0().posZ() : -999., + collision.multFT0A(), collision.multFT0C(), collision.multFT0M(), collision.multFV0A(), + collision.collisionTime(), collision.collisionTimeRes(), + counterColl, counterDF, + collIDMC, + posXMC, posYMC, posZMC, + collTimeMC, + isFakeCollision, + recoPVsPerMcColl, isPvHighestContribForMcColl); + } + + } else { + /// DATA + /// Let's fill the table with all the collisions + tableCollsBig((isRun3 ? collision.sel8() : collision.sel7()), + bc.runNumber(), + collision.posX(), collision.posY(), collision.posZ(), + collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), + collision.numContrib(), tracksAllPerColl.size(), tracksFilteredPerColl.size(), + collision.chi2(), + bc.globalBC(), + bc.has_ft0() ? bc.ft0().posZ() : -999., + collision.multFT0A(), collision.multFT0C(), collision.multFT0M(), collision.multFV0A(), + collision.collisionTime(), collision.collisionTimeRes(), + counterColl, counterDF, + collIDMC, + posXMC, posYMC, posZMC, + collTimeMC, + isFakeCollision, + recoPVsPerMcColl, isPvHighestContribForMcColl); + } + + /// update the collision global counter + counterColl++; + } + } + + /// Processing data + void processTableDataCollsBig(CollsBigTable const& collisions, + soa::Filtered const& tracksFiltered, + TrackTableData const& tracksAll, + BCsWithRun3Matchings const& bcs, aod::FT0s const& ft0s) + { + + fillCollsBigTable(collisions, collisions, tracksFiltered, tracksAll, bcs, ft0s); + + /// We are at the end of the process, which is run once per DF + /// Let's update the DF counter + counterDF++; + } + PROCESS_SWITCH(qaEventTrackLiteProducer, processTableDataCollsBig, "Process data for big collision table producing", false); + + /// Processing MC + void processTableMCCollsBig(CollsBigTableMC const& collisions, + McCollsWithExtra const& mcCollisions, + soa::Filtered const& tracksFiltered, + TrackTableData const& tracksAll, + BCsWithRun3Matchings const& bcs, aod::FT0s const& ft0s) + { + + fillCollsBigTable(collisions, mcCollisions, tracksFiltered, tracksAll, bcs, ft0s); + + /// We are at the end of the process, which is run once per DF + /// Let's update the DF counter + counterDF++; + } + PROCESS_SWITCH(qaEventTrackLiteProducer, processTableMCCollsBig, "Process MC for big collision table producing", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/DPG/Tasks/AOTTrack/qaMatchEff.cxx b/DPG/Tasks/AOTTrack/qaMatchEff.cxx index a1d5a916f13..af38f9591ba 100644 --- a/DPG/Tasks/AOTTrack/qaMatchEff.cxx +++ b/DPG/Tasks/AOTTrack/qaMatchEff.cxx @@ -10,7 +10,7 @@ // or submit itself to any jurisdiction. /// \file qaMatchEff.cxx -/// \brief ITS-TPC track matching and prim/sec separation checks +/// \brief ITS-TPC track matching checks, per charge and with PID /// /// \author Rosario Turrisi , INFN-PD /// \author Mattia Faggin , UniTs & INFN-TS @@ -21,36 +21,67 @@ #include "Common/DataModel/EventSelection.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/PIDResponse.h" #include "CommonConstants/MathConstants.h" +#include "CCDB/BasicCCDBManager.h" // #include "Framework/AnalysisTask.h" #include "Framework/RunningWorkflowInfo.h" #include "Framework/runDataProcessing.h" +// +namespace extConfPar +{ +static constexpr int nParDCA = 1; +static constexpr int nParVaDCA = 2; +static const std::vector parClassDCA{"TrVtx"}; +static const std::vector parNameDCA{"dcaXY", "dcaZ"}; +static const float parTableDCA[nParDCA][nParVaDCA]{{9999.f, 99999.f}}; +static constexpr int nParPID = 2; +static constexpr int nParVaPID = 6; +static const std::vector parClassPID{"TPC", "TOF"}; +static const std::vector parNamePID{"nSigPionMin", "nSigPionMax", "nSigKaonMin", "nSigKaonMax", "nSigProtonMin", "nSigProtonMax"}; +static const float parTablePID[nParPID][nParVaPID]{ + {-99999.f, 999999.f, -99999.f, 999999.f, -99999.f, 999999.f}, + {-99999.f, 999999.f, -99999.f, 999999.f, -99999.f, 999999.f}}; +} // namespace extConfPar // // base namespaces using namespace o2; +using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +using namespace extConfPar; +// // struct qaMatchEff { + int lastRunNumber = -1; + bool timeMonitorSetUp = false; + Service ccdb; + using BCsWithTimeStamp = soa::Join; + + Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable enableMonitorVsTime{"enableMonitorVsTime", false, "Enable the storage of ITS-TPC matching efficiency vs. time"}; + Configurable enableTHnSparseMonitorVsTime{"enableTHnSparseMonitorVsTime", false, "Enable the storage of ITS-TPC matching efficiency vs. time"}; // // histogram registry HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // // Track selections Configurable b_useTrackSelections{"b_useTrackSelections", false, "Boolean to switch the track selections on/off."}; + Configurable filterbitTrackSelections{"filterbitTrackSelections", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; // kinematics Configurable ptMinCutInnerWallTPC{"ptMinCutInnerWallTPC", 0.1f, "Minimum transverse momentum calculated at the inner wall of TPC (GeV/c)"}; Configurable ptMinCut{"ptMinCut", 0.1f, "Minimum transverse momentum (GeV/c)"}; Configurable ptMaxCut{"ptMaxCut", 100.f, "Maximum transverse momentum (GeV/c)"}; Configurable etaMinCut{"etaMinCut", -2.0f, "Minimum pseudorapidity"}; Configurable etaMaxCut{"etaMaxCut", 2.0f, "Maximum pseudorapidity"}; - Configurable dcaXYMaxCut{"dcaXYMaxCut", 1000000.0f, "Maximum dcaXY (cm)"}; Configurable b_useTPCinnerWallPt{"b_useTPCinnerWallPt", false, "Boolean to switch the usage of pt calculated at the inner wall of TPC on/off."}; - Configurable b_useTPCinnerWallPtForITS{"b_useTPCinnerWallPtForITS", false, "Boolean to switch the usage of pt calculated at the inner wall of TPC on/off just for ITS-tagged (not TPC tagged) histos."}; + // DCA and PID cuts + Configurable> dcaMaxCut{"dcaMaxCut", {parTableDCA[0], nParDCA, nParVaDCA, parClassDCA, parNameDCA}, "Track DCA cuts"}; + Configurable> nSigmaPID{"nSigmaPID", {parTablePID[0], nParPID, nParVaPID, parClassPID, parNamePID}, "PID nSigma cuts TPC and TOF"}; // TPC Configurable tpcNClusterMin{"tpcNClusterMin", 0, "Minimum number of clusters in TPC"}; Configurable tpcNCrossedRowsMin{"tpcNCrossedRowsMin", 70, "Minimum number of crossed rows in TPC"}; @@ -84,6 +115,12 @@ struct qaMatchEff { // histo axes // ConfigurableAxis ptBins{"ptBins", {100, 0.f, 20.f}, "pT binning"}; + ConfigurableAxis ptBinsVsTime{"ptBinsVsTime", {VARIABLE_WIDTH, 0.1, 0.5, 1.0, 2.0, 5.0}, "pT binning for monitorning vs time"}; + ConfigurableAxis ptInvserseBinsVsTime{"ptInverseBinsVsTime", {VARIABLE_WIDTH, 0, 0.2, 0.5, 1, 2, 10}, "1/pT binning for monitorning vs time"}; + ConfigurableAxis etaBinsVsTime{"etaBinsVsTime", {14, -1.4, 1.4}, "eta binning for monitoring vs time"}; + ConfigurableAxis posZBinsVsTime{"posZBinsVsTime", {2, -100, 100}, "posZ primary vertex binning for monitoring vs time"}; + ConfigurableAxis tpcClstBinsVsTime{"tpcClstBinsVsTime", {40, 0, 160}, "TPC cluster binning for monitoring vs time"}; + ConfigurableAxis itsClstBinsVsTime{"itsClstBinsVsTime", {9, 0, 9}, "ITS cluster binning for monitoring vs time"}; // AxisSpec axisPDG{pdgBins, 0, pdgBins + 1.000, "pdgclass"}; // @@ -116,26 +153,10 @@ struct qaMatchEff { AxisSpec thnTypeAxis{thnType, "0:prim-1:sec-2:matsec"}; AxisSpec thnLabelSignAxis{thnLabelSign, "+/- 1 for part./antipart."}; AxisSpec thnSpecAxis{thnSpec, "particle from MC (1,2,3,4,5 -> e,pi,K,P,other)"}; - // PID stuff - Configurable nSigmaTPCPionMin{"nSigmaTPCPionMin", -99999.f, "Minimum nSigma value in TPC, pion hypothesis"}; - Configurable nSigmaTPCPionMax{"nSigmaTPCPionMax", 99999.f, "Maximum nSigma value in TPC, pion hypothesis"}; - Configurable nSigmaTPCKaonMin{"nSigmaTPCKaonMin", -99999.f, "Minimum nSigma value in TPC, kaon hypothesis"}; - Configurable nSigmaTPCKaonMax{"nSigmaTPCKaonMax", 99999.f, "Maximum nSigma value in TPC, kaon hypothesis"}; - Configurable nSigmaTPCProtonMin{"nSigmaTPCProtonMin", -99999.f, "Minimum nSigma value in TPC, proton hypothesis"}; - Configurable nSigmaTPCProtonMax{"nSigmaTPCProtonMax", 99999.f, "Maximum nSigma value in TPC, proton hypothesis"}; - Configurable nSigmaTOFPionMin{"nSigmaTOFPionMin", -99999.f, "Minimum nSigma value in TOF, pion hypothesis"}; - Configurable nSigmaTOFPionMax{"nSigmaTOFPionMax", 99999.f, "Maximum nSigma value in TOF, pion hypothesis"}; - Configurable nSigmaTOFKaonMin{"nSigmaTOFKaonMin", -99999.f, "Minimum nSigma value in TOF, kaon hypothesis"}; - Configurable nSigmaTOFKaonMax{"nSigmaTOFKaonMax", 99999.f, "Maximum nSigma value in TOF, kaon hypothesis"}; - Configurable nSigmaTOFProtonMin{"nSigmaTOFProtonMin", -99999.f, "Minimum nSigma value in TOF, proton hypothesis"}; - Configurable nSigmaTOFProtonMax{"nSigmaTOFProtonMax", 99999.f, "Maximum nSigma value in TOF, proton hypothesis"}; // // Tracks selection object TrackSelection cutObject; // - // pt calculated at the inner wall of TPC - float trackPtInParamTPC = -1.; - // // do you want pt comparison 2d's ? Configurable makept2d{"makept2d", false, "choose if produce pt reco/TPC derived pt 2dims "}; // @@ -144,8 +165,23 @@ struct qaMatchEff { Configurable isPIDKaonRequired{"isPIDKaonRequired", false, "choose if apply kaon PID"}; Configurable isPIDProtonRequired{"isPIDProtonRequired", false, "choose if apply proton PID"}; // + // limit for z position of primary vertex + Configurable zPrimVtxMax{"zPrimVtxax", 999.f, "Maximum asbolute value of z of primary vertex"}; + // + // + // ****** BE VERY CAREFUL! -- FILTERS !!! ***** + // + Filter zPrimVtxLim = nabs(aod::collision::posZ) < zPrimVtxMax; + Filter trackFilter = (filterbitTrackSelections.node() == 0) || + ((filterbitTrackSelections.node() == 1) && requireGlobalTrackInFilter()) || /// filterbit 4 track selections + tight DCA cuts + ((filterbitTrackSelections.node() == 2) && requireGlobalTrackWoPtEtaInFilter()) || + ((filterbitTrackSelections.node() == 3) && requireGlobalTrackWoDCAInFilter()) || + ((filterbitTrackSelections.node() == 4) && requireQualityTracksInFilter()) || + ((filterbitTrackSelections.node() == 5) && requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks)); + // // - // Init function + // + // Init function // void init(o2::framework::InitContext&) { @@ -158,9 +194,9 @@ struct qaMatchEff { else initData(); - if ((!isitMC && (doprocessMC || doprocessMCNoColl || doprocessTrkIUMC)) || (isitMC && (doprocessData && doprocessDataNoColl && doprocessTrkIUMC))) + if ((!isitMC && (doprocessMCFilteredTracks || doprocessMC || doprocessMCNoColl || doprocessTrkIUMC)) || (isitMC && (doprocessDataFilteredTracks || doprocessData || doprocessDataNoColl || doprocessTrkIUMC))) LOGF(fatal, "Initialization set for MC and processData function flagged (or viceversa)! Fix the configuration."); - if ((doprocessMC && doprocessMCNoColl && doprocessTrkIUMC) || (doprocessData && doprocessDataNoColl && doprocessTrkIUData)) + if ((doprocessMCFilteredTracks && doprocessMC && doprocessMCNoColl && doprocessTrkIUMC) || (doprocessDataFilteredTracks && doprocessData && doprocessDataNoColl && doprocessTrkIUData)) LOGF(fatal, "Cannot process for both without collision tag and with collision tag at the same time! Fix the configuration."); if (doprocessTrkIUMC && makethn) { LOGF(fatal, "No DCA for IU tracks. Put makethn = false."); @@ -174,7 +210,8 @@ struct qaMatchEff { // kinematics cutObject.SetEtaRange(etaMinCut, etaMaxCut); cutObject.SetPtRange(ptMinCut, ptMaxCut); - cutObject.SetMaxDcaXY(dcaXYMaxCut); /// max for dca implementend by hand in isTrackSelectedKineCuts + cutObject.SetMaxDcaXY(dcaMaxCut->get("TrVtx", "dcaXY")); /// max for dca implementend by hand in isTrackSelectedKineCuts + cutObject.SetMaxDcaZ(dcaMaxCut->get("TrVtx", "dcaZ")); /// max for dca implementend by hand in isTrackSelectedKineCuts // TPC cutObject.SetMinNClustersTPC(tpcNClusterMin); cutObject.SetMinNCrossedRowsTPC(tpcNCrossedRowsMin); @@ -217,6 +254,34 @@ struct qaMatchEff { /// control plots histos.add("data/control/itsHitsMatched", "No. of hits vs ITS layer for ITS-TPC matched tracks;layer ITS", kTH2D, {{8, -1.5, 6.5}, {8, -0.5, 7.5, "No. of hits"}}); + histos.add("data/control/zPrimary", "Position of primary vertex along beam axis;z position [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/control/yPrimary", "Position of primary vertex along y axis;y position [cm]", kTH1D, {{200, -0.1, 0.1}}, true); + histos.add("data/control/xPrimary", "Position of primary vertex along x axis;x position [cm]", kTH1D, {{200, -0.1, 0.1}}, true); + histos.add("data/control/chi2Prim", "#chi^2 of primary vertex fit;#chi^2", kTH1D, {{200, 0., 100.0}}, true); + histos.add("data/control/zDCA_tpc", "DCA along z TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/control/xyDCA_tpc", "DCA in x-y plane TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/control/zDCA_tpcits", "DCA along z TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/control/xyDCA_tpcits", "DCA in x-y plane TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + // + histos.add("data/PID/zDCA_tpc_pi", "DCA along z - pions TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/xyDCA_tpc_pi", "DCA in x-y plane - pions TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/zDCA_tpcits_pi", "DCA along z - pions TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/xyDCA_tpcits_pi", "DCA in x-y plane - pions TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + // + histos.add("data/PID/zDCA_tpc_ka", "DCA along z - kaons TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/xyDCA_tpc_ka", "DCA in x-y plane - kaons TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/zDCA_tpcits_ka", "DCA along z - kaons TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/xyDCA_tpcits_ka", "DCA in x-y plane - kaons TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + // + histos.add("data/PID/zDCA_tpc_pr", "DCA along z - protons TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/xyDCA_tpc_pr", "DCA in x-y plane - protons TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/zDCA_tpcits_pr", "DCA along z - protons TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/xyDCA_tpcits_pr", "DCA in x-y plane - protons TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + // + histos.add("data/PID/zDCA_tpc_noid", "DCA along z - no pi/K/P TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/xyDCA_tpc_noid", "DCA in x-y plane - no pi/K/P TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/zDCA_tpcits_noid", "DCA along z - no pi/K/P TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("data/PID/xyDCA_tpcits_noid", "DCA in x-y plane - no pi/K/P TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); /// compare pt's (tracking and innerParamTPC) if (makept2d) { @@ -231,16 +296,12 @@ struct qaMatchEff { // Q/pt histos.add("data/qopthist_tpc", "Q/#it{p}_{T} distribution - data TPC tag", kTH1D, {axisQoPt}, true); - // histos.add("data/qopthist_its", "Q/#it{p}_{T} distribution - data ITS tag", kTH1D, {axisQoPt}, true); histos.add("data/qopthist_tpcits", "Q/#it{p}_{T} distribution - data TPC+ITS tag", kTH1D, {axisQoPt}, true); // pt, phi, eta histos.add("data/pthist_tpc", "#it{p}_{T} distribution - data TPC tag", kTH1D, {axisPt}, true); histos.add("data/etahist_tpc", "#eta distribution - data TPC tag", kTH1D, {axisEta}, true); histos.add("data/phihist_tpc", "#phi distribution - data TPC tag", kTH1D, {axisPhi}, true); - // histos.add("data/pthist_its", "#it{p}_{T} distribution - data ITS tag", kTH1D, {axisPt}, true); - // histos.add("data/etahist_its", "#eta distribution - data ITS tag", kTH1D, {axisEta}, true); - // histos.add("data/phihist_its", "#phi distribution - data ITS tag", kTH1D, {axisPhi}, true); histos.add("data/pthist_tpcits", "#it{p}_{T} distribution - data TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("data/etahist_tpcits", "#eta distribution - data TPC+ITS tag", kTH1D, {axisEta}, true); @@ -250,9 +311,6 @@ struct qaMatchEff { histos.add("data/pthist_toftpc", "#it{p}_{T} distribution - data TOF+TPC tag", kTH1D, {axisPt}, true); histos.add("data/etahist_toftpc", "#eta distribution - data TOF+TPC tag", kTH1D, {axisEta}, true); histos.add("data/phihist_toftpc", "#phi distribution - data TOF+TPC tag", kTH1D, {axisPhi}, true); - histos.add("data/pthist_tofits", "#it{p}_{T} distribution - TOF+data ITS tag", kTH1D, {axisPt}, true); - histos.add("data/etahist_tofits", "#eta distribution - data TOF+ITS tag", kTH1D, {axisEta}, true); - histos.add("data/phihist_tofits", "#phi distribution - data TOF+ITS tag", kTH1D, {axisPhi}, true); histos.add("data/pthist_toftpcits", "#it{p}_{T} distribution - data TOF+TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("data/etahist_toftpcits", "#eta distribution - data TOF+TPC+ITS tag", kTH1D, {axisEta}, true); @@ -264,10 +322,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_pi", "#eta distribution - data TPC tag - pions", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_pi", "#phi distribution - data TPC tag - pions", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_pi", "#it{p}_{T} distribution - data ITS tag - pions", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_pi", "#eta distribution - data ITS tag - pions", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_pi", "#phi distribution - data ITS tag - pions", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_pi", "#it{p}_{T} distribution - data TPC+ITS tag - pions", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_pi", "#eta distribution - data TPC+ITS tag - pions", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_pi", "#phi distribution - data TPC+ITS tag - pions", kTH1D, {axisPhi}, true); @@ -279,6 +333,20 @@ struct qaMatchEff { histos.add("data/PID/pthist_tpcits_pi_PIDTPC_O", "#it{p}_{T} distribution - data TPC+ITS tag - pions PID TPC only", kTH1D, {axisPt}, true); histos.add("data/PID/pthist_tpcits_pi_PIDTOF_O", "#it{p}_{T} distribution - data TPC+ITS tag - pions PID TOF only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_piplus_PIDTPC", "#it{p}_{T} distribution - data TPC+ITS tag - pions+ PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_piplus_PIDTOF", "#it{p}_{T} distribution - data TPC+ITS tag - pions+ PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_piplus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC+ITS tag - pions+ PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_piplus_PIDTPC_O", "#it{p}_{T} distribution - data TPC+ITS tag - pions+ PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_piplus_PIDTOF_O", "#it{p}_{T} distribution - data TPC+ITS tag - pions+ PID TOF only", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_piminus_PIDTPC", "#it{p}_{T} distribution - data TPC+ITS tag - pions- PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_piminus_PIDTOF", "#it{p}_{T} distribution - data TPC+ITS tag - pions- PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_piminus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC+ITS tag - pions- PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_piminus_PIDTPC_O", "#it{p}_{T} distribution - data TPC+ITS tag - pions- PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_piminus_PIDTOF_O", "#it{p}_{T} distribution - data TPC+ITS tag - pions- PID TOF only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_pi_PIDTPC", "#it{p}_{T} distribution - data TPC tag - pions PID w/TPC at least", kTH1D, {axisPt}, true); histos.add("data/PID/pthist_tpc_pi_PIDTOF", "#it{p}_{T} distribution - data TPC tag - pions PID w/TOF at least", kTH1D, {axisPt}, true); histos.add("data/PID/pthist_tpc_pi_PIDTPCTOF", "#it{p}_{T} distribution - data TPC tag - pions PID TPC+TOF", kTH1D, {axisPt}, true); @@ -286,15 +354,25 @@ struct qaMatchEff { histos.add("data/PID/pthist_tpc_pi_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - pions PID TPC only", kTH1D, {axisPt}, true); histos.add("data/PID/pthist_tpc_pi_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - pions PID TOF only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_piplus_PIDTPC", "#it{p}_{T} distribution - data TPC tag - pions+ PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_piplus_PIDTOF", "#it{p}_{T} distribution - data TPC tag - pions+ PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_piplus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC tag - pions+ PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_piplus_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - pions+ PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_piplus_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - pions+ PID TOF only", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_piminus_PIDTPC", "#it{p}_{T} distribution - data TPC tag - pions- PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_piminus_PIDTOF", "#it{p}_{T} distribution - data TPC tag - pions- PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_piminus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC tag - pions- PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_piminus_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - pions- PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_piminus_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - pions- PID TOF only", kTH1D, {axisPt}, true); + // plus histos.add("data/PID/pthist_tpc_piplus", "#it{p}_{T} distribution - data TPC tag - pos. pions", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpc_piplus", "#eta distribution - data TPC tag - pos. pions", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_piplus", "#phi distribution - data TPC tag - pos. pions", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_piplus", "#it{p}_{T} distribution - data ITS tag - pos. pions", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_piplus", "#eta distribution - data ITS tag - pos. pions", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_piplus", "#phi distribution - data ITS tag - pos. pions", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_piplus", "#it{p}_{T} distribution - data TPC+ITS tag - pos. pions", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_piplus", "#eta distribution - data TPC+ITS tag - pos. pions", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_piplus", "#phi distribution - data TPC+ITS tag - pos. pions", kTH1D, {axisPhi}, true); @@ -303,10 +381,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_piminus", "#eta distribution - data TPC tag - neg. pions", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_piminus", "#phi distribution - data TPC tag - neg. pions", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_piminus", "#it{p}_{T} distribution - data ITS tag - neg. pions", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_piminus", "#eta distribution - data ITS tag - neg. pions", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_piminus", "#phi distribution - data ITS tag - neg. pions", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_piminus", "#it{p}_{T} distribution - data TPC+ITS tag - neg. pions", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_piminus", "#eta distribution - data TPC+ITS tag - neg. pions", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_piminus", "#phi distribution - data TPC+ITS tag - neg. pions", kTH1D, {axisPhi}, true); @@ -318,10 +392,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_ka", "#eta distribution - data TPC tag - kaons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_ka", "#phi distribution - data TPC tag - kaons", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_ka", "#it{p}_{T} distribution - data ITS tag - kaons", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_ka", "#eta distribution - data ITS tag - kaons", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_ka", "#phi distribution - data ITS tag - kaons", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_ka", "#it{p}_{T} distribution - data TPC+ITS tag - kaons", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_ka", "#eta distribution - data TPC+ITS tag - kaons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_ka", "#phi distribution - data TPC+ITS tag - kaons", kTH1D, {axisPhi}, true); @@ -340,15 +410,39 @@ struct qaMatchEff { histos.add("data/PID/pthist_tpc_ka_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - kaons PID TPC only", kTH1D, {axisPt}, true); histos.add("data/PID/pthist_tpc_ka_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - kaons PID TOF only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_kaplus_PIDTPC", "#it{p}_{T} distribution - data TPC+ITS tag - kaons+ PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_kaplus_PIDTOF", "#it{p}_{T} distribution - data TPC+ITS tag - kaons+ PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_kaplus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC+ITS tag - kaons+ PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_kaplus_PIDTPC_O", "#it{p}_{T} distribution - data TPC+ITS tag - kaons+ PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_kaplus_PIDTOF_O", "#it{p}_{T} distribution - data TPC+ITS tag - kaons+ PID TOF only", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_kaplus_PIDTPC", "#it{p}_{T} distribution - data TPC tag - kaons+ PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_kaplus_PIDTOF", "#it{p}_{T} distribution - data TPC tag - kaons+ PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_kaplus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC tag - kaons+ PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_kaplus_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - kaons+ PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_kaplus_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - kaons+ PID TOF only", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_kaminus_PIDTPC", "#it{p}_{T} distribution - data TPC+ITS tag - kaons- PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_kaminus_PIDTOF", "#it{p}_{T} distribution - data TPC+ITS tag - kaons- PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_kaminus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC+ITS tag - kaons- PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_kaminus_PIDTPC_O", "#it{p}_{T} distribution - data TPC+ITS tag - kaons- PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_kaminus_PIDTOF_O", "#it{p}_{T} distribution - data TPC+ITS tag - kaons- PID TOF only", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_kaminus_PIDTPC", "#it{p}_{T} distribution - data TPC tag - kaons- PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_kaminus_PIDTOF", "#it{p}_{T} distribution - data TPC tag - kaons- PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_kaminus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC tag - kaons- PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_kaminus_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - kaons- PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_kaminus_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - kaons- PID TOF only", kTH1D, {axisPt}, true); + // plus histos.add("data/PID/pthist_tpc_kaplus", "#it{p}_{T} distribution - data TPC tag - pos. kaons", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpc_kaplus", "#eta distribution - data TPC tag - pos. kaons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_kaplus", "#phi distribution - data TPC tag - pos. kaons", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_kaplus", "#it{p}_{T} distribution - data ITS tag - pos. kaons", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_kaplus", "#eta distribution - data ITS tag - pos. kaons", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_kaplus", "#phi distribution - data ITS tag - pos. kaons", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_kaplus", "#it{p}_{T} distribution - data TPC+ITS tag - pos. kaons", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_kaplus", "#eta distribution - data TPC+ITS tag - pos. kaons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_kaplus", "#phi distribution - data TPC+ITS tag - pos. kaons", kTH1D, {axisPhi}, true); @@ -357,10 +451,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_kaminus", "#eta distribution - data TPC tag - neg. kaons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_kaminus", "#phi distribution - data TPC tag - neg. kaons", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_kaminus", "#it{p}_{T} distribution - data ITS tag - neg. kaons", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_kaminus", "#eta distribution - data ITS tag - neg. kaons", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_kaminus", "#phi distribution - data ITS tag - neg. kaons", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_kaminus", "#it{p}_{T} distribution - data TPC+ITS tag - neg. kaons", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_kaminus", "#eta distribution - data TPC+ITS tag - neg. kaons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_kaminus", "#phi distribution - data TPC+ITS tag - neg. kaons", kTH1D, {axisPhi}, true); @@ -372,10 +462,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_pr", "#eta distribution - data TPC tag - protons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_pr", "#phi distribution - data TPC tag - protons", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_pr", "#it{p}_{T} distribution - data ITS tag - protons", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_pr", "#eta distribution - data ITS tag - protons", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_pr", "#phi distribution - data ITS tag - protons", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_pr", "#it{p}_{T} distribution - data TPC+ITS tag - protons", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_pr", "#eta distribution - data TPC+ITS tag - protons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_pr", "#phi distribution - data TPC+ITS tag - protons", kTH1D, {axisPhi}, true); @@ -394,15 +480,39 @@ struct qaMatchEff { histos.add("data/PID/pthist_tpc_pr_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - protons PID TPC only", kTH1D, {axisPt}, true); histos.add("data/PID/pthist_tpc_pr_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - protons PID TOF only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_prplus_PIDTPC", "#it{p}_{T} distribution - data TPC+ITS tag - protons+ PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_prplus_PIDTOF", "#it{p}_{T} distribution - data TPC+ITS tag - protons+ PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_prplus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC+ITS tag - protons+ PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_prplus_PIDTPC_O", "#it{p}_{T} distribution - data TPC+ITS tag - protons+ PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_prplus_PIDTOF_O", "#it{p}_{T} distribution - data TPC+ITS tag - protons+ PID TOF only", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_prplus_PIDTPC", "#it{p}_{T} distribution - data TPC tag - protons+ PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_prplus_PIDTOF", "#it{p}_{T} distribution - data TPC tag - protons+ PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_prplus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC tag - protons+ PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_prplus_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - protons+ PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_prplus_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - protons+ PID TOF only", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_prminus_PIDTPC", "#it{p}_{T} distribution - data TPC+ITS tag - protons- PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_prminus_PIDTOF", "#it{p}_{T} distribution - data TPC+ITS tag - protons- PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_prminus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC+ITS tag - protons- PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpcits_prminus_PIDTPC_O", "#it{p}_{T} distribution - data TPC+ITS tag - protons- PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpcits_prminus_PIDTOF_O", "#it{p}_{T} distribution - data TPC+ITS tag - protons- PID TOF only", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_prminus_PIDTPC", "#it{p}_{T} distribution - data TPC tag - protons- PID w/TPC at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_prminus_PIDTOF", "#it{p}_{T} distribution - data TPC tag - protons- PID w/TOF at least", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_prminus_PIDTPCTOF", "#it{p}_{T} distribution - data TPC tag - protons- PID TPC+TOF", kTH1D, {axisPt}, true); + + histos.add("data/PID/pthist_tpc_prminus_PIDTPC_O", "#it{p}_{T} distribution - data TPC tag - protons- PID TPC only", kTH1D, {axisPt}, true); + histos.add("data/PID/pthist_tpc_prminus_PIDTOF_O", "#it{p}_{T} distribution - data TPC tag - protons- PID TOF only", kTH1D, {axisPt}, true); + // plus histos.add("data/PID/pthist_tpc_prplus", "#it{p}_{T} distribution - data TPC tag - pos. protons", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpc_prplus", "#eta distribution - data TPC tag - pos. protons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_prplus", "#phi distribution - data TPC tag - pos. protons", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_prplus", "#it{p}_{T} distribution - data ITS tag - pos. protons", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_prplus", "#eta distribution - data ITS tag - pos. protons", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_prplus", "#phi distribution - data ITS tag - pos. protons", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_prplus", "#it{p}_{T} distribution - data TPC+ITS tag - pos. protons", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_prplus", "#eta distribution - data TPC+ITS tag - pos. protons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_prplus", "#phi distribution - data TPC+ITS tag - pos. protons", kTH1D, {axisPhi}, true); @@ -411,10 +521,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_prminus", "#eta distribution - data TPC tag - neg. protons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_prminus", "#phi distribution - data TPC tag - neg. protons", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_prminus", "#it{p}_{T} distribution - data ITS tag - neg. protons", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_prminus", "#eta distribution - data ITS tag - neg. protons", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_prminus", "#phi distribution - data ITS tag - neg. protons", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_prminus", "#it{p}_{T} distribution - data TPC+ITS tag - neg. protons", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_prminus", "#eta distribution - data TPC+ITS tag - neg. protons", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_prminus", "#phi distribution - data TPC+ITS tag - neg. protons ", kTH1D, {axisPhi}, true); @@ -426,10 +532,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_noid", "#eta distribution - data TPC tag - no ident.", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_noid", "#phi distribution - data TPC tag - no ident.", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_noid", "#it{p}_{T} distribution - data ITS tag - no ident.", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_noid", "#eta distribution - data ITS tag - no ident.", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_noid", "#phi distribution - data ITS tag - no ident.", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_noid", "#it{p}_{T} distribution - data TPC+ITS tag - no ident.", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_noid", "#eta distribution - data TPC+ITS tag - no ident.", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_noid", "#phi distribution - data TPC+ITS tag - no ident.", kTH1D, {axisPhi}, true); @@ -438,10 +540,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_noidplus", "#eta distribution - data TPC tag - pos. no ident.", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_noidplus", "#phi distribution - data TPC tag - pos. no ident.", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_noidplus", "#it{p}_{T} distribution - data ITS tag - pos. no ident.", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_noidplus", "#eta distribution - data ITS tag - pos. no ident.", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_noidplus", "#phi distribution - data ITS tag - pos. no ident.", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_noidplus", "#it{p}_{T} distribution - data TPC+ITS tag - pos. no ident.", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_noidplus", "#eta distribution - data TPC+ITS tag - pos. no ident.", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_noidplus", "#phi distribution - data TPC+ITS tag - pos. no ident.", kTH1D, {axisPhi}, true); @@ -450,10 +548,6 @@ struct qaMatchEff { histos.add("data/PID/etahist_tpc_noidminus", "#eta distribution - data TPC tag - neg. no ident.", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpc_noidminus", "#phi distribution - data TPC tag - neg. no ident.", kTH1D, {axisPhi}, true); - // histos.add("data/PID/pthist_its_noidminus", "#it{p}_{T} distribution - data ITS tag - neg. no ident.", kTH1D, {axisPt}, true); - // histos.add("data/PID/etahist_its_noidminus", "#eta distribution - data ITS tag - neg. no ident.", kTH1D, {axisEta}, true); - // histos.add("data/PID/phihist_its_noidminus", "#phi distribution - data ITS tag - neg. no ident.", kTH1D, {axisPhi}, true); - histos.add("data/PID/pthist_tpcits_noidminus", "#it{p}_{T} distribution - data TPC+ITS tag - neg. no ident.", kTH1D, {axisPt}, true); histos.add("data/PID/etahist_tpcits_noidminus", "#eta distribution - data TPC+ITS tag - neg. no ident.", kTH1D, {axisEta}, true); histos.add("data/PID/phihist_tpcits_noidminus", "#phi distribution - data TPC+ITS tag - neg. no ident. ", kTH1D, {axisPhi}, true); @@ -464,10 +558,6 @@ struct qaMatchEff { histos.add("data/etahist_tpc_pos", "#eta distribution - data q>0 TPC tag", kTH1D, {axisEta}, true); histos.add("data/phihist_tpc_pos", "#phi distribution - data q>0 TPC tag", kTH1D, {axisPhi}, true); - // histos.add("data/pthist_its_pos", "#it{p}_{T} distribution - data q>0 ITS tag", kTH1D, {axisPt}, true); - // histos.add("data/etahist_its_pos", "#eta distribution - data q>0 ITS tag", kTH1D, {axisEta}, true); - // histos.add("data/phihist_its_pos", "#phi distribution - data q>0 ITS tag", kTH1D, {axisPhi}, true); - histos.add("data/pthist_tpcits_pos", "#it{p}_{T} distribution - data q>0 TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("data/etahist_tpcits_pos", "#eta distribution - data q>0 TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("data/phihist_tpcits_pos", "#phi distribution - data q>0 TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -476,10 +566,6 @@ struct qaMatchEff { histos.add("data/etahist_tpc_neg", "#eta distribution - data q<0 TPC tag", kTH1D, {axisEta}, true); histos.add("data/phihist_tpc_neg", "#phi distribution - data q<0 TPC tag", kTH1D, {axisPhi}, true); - // histos.add("data/pthist_its_neg", "#it{p}_{T} distribution - data q<0 ITS tag", kTH1D, {axisPt}, true); - // histos.add("data/etahist_its_neg", "#eta distribution - data q<0 ITS tag", kTH1D, {axisEta}, true); - // histos.add("data/phihist_its_neg", "#phi distribution - data q<0 ITS tag", kTH1D, {axisPhi}, true); - histos.add("data/pthist_tpcits_neg", "#it{p}_{T} distribution - data q<0 TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("data/etahist_tpcits_neg", "#eta distribution - data q<0 TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("data/phihist_tpcits_neg", "#phi distribution - data q<0 TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -489,10 +575,6 @@ struct qaMatchEff { histos.add("data/etahist_tpc_05", "#eta distribution - data TPC tag, #it{p}_{T}>0.5", kTH1D, {axisEta}, true); histos.add("data/phihist_tpc_05", "#phi distribution - data TPC tag, #it{p}_{T}>0.5", kTH1D, {axisPhi}, true); - // histos.add("data/pthist_its_05", "#it{p}_{T} distribution - data ITS tag, #it{p}_{T}>0.5", kTH1D, {axisPt}, true); - // histos.add("data/etahist_its_05", "#eta distribution - data ITS tag, #it{p}_{T}>0.5", kTH1D, {axisEta}, true); - // histos.add("data/phihist_its_05", "#phi distribution - data ITS tag, #it{p}_{T}>0.5", kTH1D, {axisPhi}, true); - histos.add("data/pthist_tpcits_05", "#it{p}_{T} distribution - data TPC+ITS tag #it{p}_{T}>0.5", kTH1D, {axisPt}, true); histos.add("data/etahist_tpcits_05", "#eta distribution - data TPC+ITS tag #it{p}_{T}>0.5", kTH1D, {axisEta}, true); histos.add("data/phihist_tpcits_05", "#phi distribution - data TPC+ITS tag #it{p}_{T}>0.5", kTH1D, {axisPhi}, true); @@ -518,6 +600,15 @@ struct qaMatchEff { /// control plots histos.add("MC/control/itsHitsMatched", "No. of hits vs ITS layer for ITS-TPC matched tracks;layer ITS", kTH2D, {{8, -1.5, 6.5}, {8, -0.5, 7.5, "No. of hits"}}); + histos.add("MC/control/zPrimary", "Position of primary vertex along beam axis;z position [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/control/yPrimary", "Position of primary vertex along y axis;y position [cm]", kTH1D, {{200, -0.1, 0.1}}, true); + histos.add("MC/control/xPrimary", "Position of primary vertex along x axis;x position [cm]", kTH1D, {{200, -0.1, 0.1}}, true); + histos.add("MC/control/chi2Prim", "#chi^2 of primary vertex fit;#chi^2", kTH1D, {{200, 0., 100.0}}, true); + histos.add("MC/control/zDCA_tpc", "DCA along z TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/control/xyDCA_tpc", "DCA in x-y plane TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/control/zDCA_tpcits", "DCA along z TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/control/xyDCA_tpcits", "DCA in x-y plane TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + /// compare pt's (tracking and innerParamTPC) if (makept2d) { histos.add("MC/control/ptptconfTPCall", "Tracking pt vs TPC inner wall pt - TPC tag", kTH2D, {{100, 0.0, 10.0, "tracking #it{p}_{T}"}, {100, 0.0, 10.0, "TPC #it{p}_{T}"}}); @@ -531,7 +622,6 @@ struct qaMatchEff { // Q/pt histos.add("MC/qopthist_tpc", "Q/#it{p}_{T} distribution - MC TPC tag", kTH1D, {axisQoPt}, true); - // histos.add("MC/qopthist_its", "Q/#it{p}_{T} distribution - MC ITS tag", kTH1D, {axisQoPt}, true); histos.add("MC/qopthist_tpcits", "Q/#it{p}_{T} distribution - MC TPC+ITS tag", kTH1D, {axisQoPt}, true); // // TOF tag @@ -539,10 +629,6 @@ struct qaMatchEff { histos.add("MC/etahist_toftpc", "#eta distribution - MC TOF+TPC tag", kTH1D, {axisEta}, true); histos.add("MC/phihist_toftpc", "#phi distribution - MC TOF+TPC tag", kTH1D, {axisPhi}, true); - histos.add("MC/pthist_tofits", "#it{p}_{T} distribution - MC TOF+ITS tag", kTH1D, {axisPt}, true); - histos.add("MC/etahist_tofits", "#eta distribution - MC TOF+ITS tag", kTH1D, {axisEta}, true); - histos.add("MC/phihist_tofits", "#phi distribution - MC TOF+ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/pthist_toftpcits", "#it{p}_{T} distribution - MC TOF+TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/etahist_toftpcits", "#eta distribution - MC TOF+TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/phihist_toftpcits", "#phi distribution - MC TOF+TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -552,10 +638,6 @@ struct qaMatchEff { histos.add("MC/etahist_tpc", "#eta distribution - MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/phihist_tpc", "#phi distribution - MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/pthist_its", "#it{p}_{T} distribution - MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/etahist_its", "#eta distribution - MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/phihist_its", "#phi distribution - MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/pthist_tpcits", "#it{p}_{T} distribution - MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/etahist_tpcits", "#eta distribution - MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/phihist_tpcits", "#phi distribution - MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -564,10 +646,6 @@ struct qaMatchEff { histos.add("MC/etahist_tpc_pos", "#eta distribution - MC q>0 TPC tag", kTH1D, {axisEta}, true); histos.add("MC/phihist_tpc_pos", "#phi distribution - MC q>0 TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/pthist_its_pos", "#it{p}_{T} distribution - MC q>0 ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/etahist_its_pos", "#eta distribution - MC q>0 ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/phihist_its_pos", "#phi distribution - MC q>0 ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/pthist_tpcits_pos", "#it{p}_{T} distribution - MC q>0 TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/etahist_tpcits_pos", "#eta distribution - MC q>0 TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/phihist_tpcits_pos", "#phi distribution - MC q>0 TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -576,10 +654,6 @@ struct qaMatchEff { histos.add("MC/etahist_tpc_neg", "#eta distribution - MC q<0 TPC tag", kTH1D, {axisEta}, true); histos.add("MC/phihist_tpc_neg", "#phi distribution - MC q<0 TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/pthist_its_neg", "#it{p}_{T} distribution - MC q<0 ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/etahist_its_neg", "#eta distribution - MC q<0 ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/phihist_its_neg", "#phi distribution - MC q<0 ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/pthist_tpcits_neg", "#it{p}_{T} distribution - MC q<0 TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/etahist_tpcits_neg", "#eta distribution - MC q<0 TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/phihist_tpcits_neg", "#phi distribution - MC q<0 TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -589,65 +663,79 @@ struct qaMatchEff { // Q/pt histos.add("MC/primsec/qopthist_tpc_prim", "Q/#it{p}_{T} distribution - MC prim TPC tag", kTH1D, {axisQoPt}, true); - // histos.add("MC/primsec/qopthist_its_prim", "Q/#it{p}_{T} distribution - MC prim ITS tag", kTH1D, {axisQoPt}, true); histos.add("MC/primsec/qopthist_tpcits_prim", "Q/#it{p}_{T} distribution - MC prim TPC+ITS tag", kTH1D, {axisQoPt}, true); + histos.add("MC/primsec/zDCA_tpc_prim", "DCA along z TPC tag - primaries;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/zDCA_tpcits_prim", "DCA along z TPC+ITS tag - primaries;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + + histos.add("MC/primsec/xyDCA_tpc_prim", "DCA in x-y plane TPC tag - primaries;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/xyDCA_tpcits_prim", "DCA in x-y plane TPC+ITS tag - primaries;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/pthist_tpc_prim", "#it{p}_{T} distribution - MC prim TPC tag", kTH1D, {axisPt}, true); histos.add("MC/primsec/etahist_tpc_prim", "#eta distribution - MC prim TPC tag", kTH1D, {axisEta}, true); histos.add("MC/primsec/phihist_tpc_prim", "#phi distribution - MC prim TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/primsec/pthist_its_prim", "#it{p}_{T} distribution - MC prim ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/primsec/etahist_its_prim", "#eta distribution - MC prim ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/primsec/phihist_its_prim", "#phi distribution - MC prim ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/primsec/pthist_tpcits_prim", "#it{p}_{T} distribution - MC prim TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/primsec/etahist_tpcits_prim", "#eta distribution - MC prim TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/primsec/phihist_tpcits_prim", "#phi distribution - MC prim TPC+ITS tag", kTH1D, {axisPhi}, true); // Q/pt histos.add("MC/primsec/qopthist_tpc_secd", "Q/#it{p}_{T} distribution - MC dec. sec. TPC tag", kTH1D, {axisQoPt}, true); - // histos.add("MC/primsec/qopthist_its_secd", "Q/#it{p}_{T} distribution - MC dec. sec. ITS tag", kTH1D, {axisQoPt}, true); histos.add("MC/primsec/qopthist_tpcits_secd", "Q/#it{p}_{T} distribution - MC dec. sec. TPC+ITS tag", kTH1D, {axisQoPt}, true); + histos.add("MC/primsec/zDCA_tpc_secd", "DCA along z TPC tag - secd;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/zDCA_tpcits_secd", "DCA along z TPC+ITS tag - secd;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + + histos.add("MC/primsec/xyDCA_tpc_secd", "DCA in x-y plane TPC tag - secd;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/xyDCA_tpcits_secd", "DCA in x-y plane TPC+ITS tag - secd;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/pthist_tpc_secd", "#it{p}_{T} distribution - MC dec. sec. TPC tag", kTH1D, {axisPt}, true); histos.add("MC/primsec/etahist_tpc_secd", "#eta distribution - MC dec. sec. TPC tag", kTH1D, {axisEta}, true); histos.add("MC/primsec/phihist_tpc_secd", "#phi distribution - MC dec. sec. TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/primsec/pthist_its_secd", "#it{p}_{T} distribution - MC dec. sec. ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/primsec/etahist_its_secd", "#eta distribution - MC dec. sec. ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/primsec/phihist_its_secd", "#phi distribution - MC dec. sec. ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/primsec/pthist_tpcits_secd", "#it{p}_{T} distribution - MC dec.sec. TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/primsec/etahist_tpcits_secd", "#eta distribution - MC dec. sec. TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/primsec/phihist_tpcits_secd", "#phi distribution - MC dec. sec. TPC+ITS tag", kTH1D, {axisPhi}, true); // Q/pt histos.add("MC/primsec/qopthist_tpc_secm", "Q/#it{p}_{T} distribution - MC mat. sec. TPC tag", kTH1D, {axisQoPt}, true); - // histos.add("MC/primsec/qopthist_its_secm", "Q/#it{p}_{T} distribution - MC mat. sec. ITS tag", kTH1D, {axisQoPt}, true); histos.add("MC/primsec/qopthist_tpcits_secm", "Q/#it{p}_{T} distribution - MC mat. sec. TPC+ITS tag", kTH1D, {axisQoPt}, true); + histos.add("MC/primsec/zDCA_tpc_secm", "DCA along z TPC tag - secm;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/zDCA_tpcits_secm", "DCA along z TPC+ITS tag - secm;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + + histos.add("MC/primsec/xyDCA_tpc_secm", "DCA in x-y plane TPC tag - secm;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/xyDCA_tpcits_secm", "DCA in x-y plane TPC+ITS tag - secm;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/primsec/pthist_tpc_secm", "#it{p}_{T} distribution - MC mat. sec. TPC tag", kTH1D, {axisPt}, true); histos.add("MC/primsec/etahist_tpc_secm", "#eta distribution - MC mat. sec. TPC tag", kTH1D, {axisEta}, true); histos.add("MC/primsec/phihist_tpc_secm", "#phi distribution - MC mat. sec. TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/primsec/pthist_its_secm", "#it{p}_{T} distribution - MC mat. sec. ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/primsec/etahist_its_secm", "#eta distribution - MC mat. sec. ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/primsec/phihist_its_secm", "#phi distribution - MC mat. sec. ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/primsec/pthist_tpcits_secm", "#it{p}_{T} distribution - MC mat.sec. TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/primsec/etahist_tpcits_secm", "#eta distribution - MC mat. sec. TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/primsec/phihist_tpcits_secm", "#phi distribution - MC mat. sec. TPC+ITS tag", kTH1D, {axisPhi}, true); // // pions only // all + histos.add("MC/PID/zDCA_tpc_pi", "DCA along z - pions TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/xyDCA_tpc_pi", "DCA in x-y plane - pions TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/zDCA_tpcits_pi", "DCA along z - pions TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/xyDCA_tpcits_pi", "DCA in x-y plane - pions TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + + histos.add("MC/PID/zDCA_tpc_ka", "DCA along z - kaons TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/xyDCA_tpc_ka", "DCA in x-y plane - kaons TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/zDCA_tpcits_ka", "DCA along z - kaons TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/xyDCA_tpcits_ka", "DCA in x-y plane - kaons TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + + histos.add("MC/PID/zDCA_tpc_pr", "DCA along z - protons TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/xyDCA_tpc_pr", "DCA in x-y plane - protons TPC tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/zDCA_tpcits_pr", "DCA along z - protons TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/xyDCA_tpcits_pr", "DCA in x-y plane - protons TPC+ITS tag;dca [cm]", kTH1D, {{200, -20.0, 20.0}}, true); + histos.add("MC/PID/pthist_tpc_pi", "#it{p}_{T} distribution - #pi MC TPC tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpc_pi", "#eta distribution - #pi MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_pi", "#phi distribution - #pi MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_pi", "#it{p}_{T} distribution - #pi MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_pi", "#eta distribution - #pi MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_pi", "#phi distribution - #pi MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_pi", "#it{p}_{T} distribution - #pi MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_pi", "#eta distribution - #pi MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_pi", "#phi distribution - #pi MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -657,10 +745,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_piplus", "#eta distribution -pos. #pi MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_piplus", "#phi distribution -pos. #pi MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_piplus", "#it{p}_{T} distribution -pos. #pi MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_piplus", "#eta distribution -pos. #pi MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_piplus", "#phi distribution -pos. #pi MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_piplus", "#it{p}_{T} distribution -pos. #pi MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_piplus", "#eta distribution -pos. #pi MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_piplus", "#phi distribution -pos. #pi MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -670,10 +754,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_piminus", "#eta distribution -neg. #pi MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_piminus", "#phi distribution -neg. #pi MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_piminus", "#it{p}_{T} distribution -neg. #pi MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_piminus", "#eta distribution -neg. #pi MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_piminus", "#phi distribution -neg. #pi MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_piminus", "#it{p}_{T} distribution -neg. #pi MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_piminus", "#eta distribution -neg. #pi MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_piminus", "#phi distribution -neg. #pi MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -684,10 +764,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_pi_prim", "#eta distribution - #pi MC prim TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_pi_prim", "#phi distribution - #pi MC prim TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_pi_prim", "#it{p}_{T} distribution - #pi MC prim ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_pi_prim", "#eta distribution - #pi MC prim ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_pi_prim", "#phi distribution - #pi MC prim ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_pi_prim", "#it{p}_{T} distribution - #pi MC prim TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_pi_prim", "#eta distribution - #pi MC prim TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_pi_prim", "#phi distribution - #pi MC prim TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -696,10 +772,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_pi_secd", "#eta distribution - #pi MC dec. sec. TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_pi_secd", "#phi distribution - #pi MC dec. sec. TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_pi_secd", "#it{p}_{T} distribution - #pi MC dec. sec. ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_pi_secd", "#eta distribution - #pi MC dec. sec. ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_pi_secd", "#phi distribution - #pi MC dec. sec. ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_pi_secd", "#it{p}_{T} distribution - #pi MC dec.sec. TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_pi_secd", "#eta distribution - #pi MC dec. sec. TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_pi_secd", "#phi distribution - #pi MC dec. sec. TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -708,24 +780,16 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_pi_secm", "#eta distribution - #pi MC mat. sec. TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_pi_secm", "#phi distribution - #pi MC mat. sec. TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_pi_secm", "#it{p}_{T} distribution - #pi MC mat. sec. ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_pi_secm", "#eta distribution - #pi MC mat. sec. ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_pi_secm", "#phi distribution - #pi MC mat. sec. ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_pi_secm", "#it{p}_{T} distribution - #pi MC mat.sec. TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_pi_secm", "#eta distribution - #pi MC mat. sec. TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_pi_secm", "#phi distribution - #pi MC mat. sec. TPC+ITS tag", kTH1D, {axisPhi}, true); - + // // protons only // all histos.add("MC/PID/pthist_tpc_pr", "#it{p}_{T} distribution - prot MC TPC tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpc_pr", "#eta distribution - prot MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_pr", "#phi distribution - prot MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_pr", "#it{p}_{T} distribution - prot MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_pr", "#eta distribution - prot MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_pr", "#phi distribution - prot MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_pr", "#it{p}_{T} distribution - prot MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_pr", "#eta distribution - prot MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_pr", "#phi distribution - prot MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -734,10 +798,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_prplus", "#eta distribution - pos. prot MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_prplus", "#phi distribution - pos. prot MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_prplus", "#it{p}_{T} distribution - pos. prot MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_prplus", "#eta distribution - pos. prot MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_prplus", "#phi distribution - pos. prot MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_prplus", "#it{p}_{T} distribution - pos. prot MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_prplus", "#eta distribution - pos. prot MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_prplus", "#phi distribution - pos. prot MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -746,10 +806,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_prminus", "#eta distribution - neg. prot MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_prminus", "#phi distribution - neg. prot MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_prminus", "#it{p}_{T} distribution - neg. prot MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_prminus", "#eta distribution - neg. prot MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_prminus", "#phi distribution - neg. prot MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_prminus", "#it{p}_{T} distribution - neg. prot MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_prminus", "#eta distribution - neg. prot MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_prminus", "#phi distribution - neg. prot MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -760,10 +816,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_ka", "#eta distribution - kaons MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_ka", "#phi distribution - kaons MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_ka", "#it{p}_{T} distribution - kaons MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_ka", "#eta distribution - kaons MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_ka", "#phi distribution - kaons MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_ka", "#it{p}_{T} distribution - kaons MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_ka", "#eta distribution - kaons MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_ka", "#phi distribution - kaons MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -773,10 +825,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_kaplus", "#eta distribution - pos. kaons MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_kaplus", "#phi distribution - pos. kaons MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_kaplus", "#it{p}_{T} distribution - pos. kaons MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_kaplus", "#eta distribution - pos. kaons MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_kaplus", "#phi distribution - pos. kaons MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_kaplus", "#it{p}_{T} distribution - pos. kaons MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_kaplus", "#eta distribution - pos. kaons MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_kaplus", "#phi distribution - pos. kaons MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -786,10 +834,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_kaminus", "#eta distribution - neg. kaons MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_kaminus", "#phi distribution - neg. kaons MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_kaminus", "#it{p}_{T} distribution - neg. kaons MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_kaminus", "#eta distribution - neg. kaons MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_kaminus", "#phi distribution - neg. kaons MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_kaminus", "#it{p}_{T} distribution - neg. kaons MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_kaminus", "#eta distribution - neg. kaons MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_kaminus", "#phi distribution - neg. kaons MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -800,10 +844,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_piK", "#eta distribution - #pi+kaons MC TPC tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_piK", "#phi distribution - #pi+kaons MC TPC tag", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_piK", "#it{p}_{T} distribution - #pi+kaons MC ITS tag", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_piK", "#eta distribution - #pi+kaons MC ITS tag", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_piK", "#phi distribution - #pi+kaons MC ITS tag", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_piK", "#it{p}_{T} distribution - #pi+kaons MC TPC+ITS tag", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_piK", "#eta distribution - #pi+kaons MC TPC+ITS tag", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_piK", "#phi distribution - #pi+kaons MC TPC+ITS tag", kTH1D, {axisPhi}, true); @@ -813,10 +853,6 @@ struct qaMatchEff { histos.add("MC/etahist_tpc_05", "#eta distribution - MC TPC tag, #it{p}_{T}>0.5", kTH1D, {axisEta}, true); histos.add("MC/phihist_tpc_05", "#phi distribution - MC TPC tag, #it{p}_{T}>0.5", kTH1D, {axisPhi}, true); - // histos.add("MC/pthist_its_05", "#it{p}_{T} distribution - MC ITS tag, #it{p}_{T}>0.5", kTH1D, {axisPt}, true); - // histos.add("MC/etahist_its_05", "#eta distribution - MC ITS tag, #it{p}_{T}>0.5", kTH1D, {axisEta}, true); - // histos.add("MC/phihist_its_05", "#phi distribution - MC ITS tag, #it{p}_{T}>0.5", kTH1D, {axisPhi}, true); - histos.add("MC/pthist_tpcits_05", "#it{p}_{T} distribution - MC TPC+ITS tag, #it{p}_{T}>0.5", kTH1D, {axisPt}, true); histos.add("MC/etahist_tpcits_05", "#eta distribution - MC TPC+ITS tag, #it{p}_{T}>0.5", kTH1D, {axisEta}, true); histos.add("MC/phihist_tpcits_05", "#phi distribution - MC TPC+ITS tag, #it{p}_{T}>0.5", kTH1D, {axisPhi}, true); @@ -827,10 +863,6 @@ struct qaMatchEff { histos.add("MC/PID/etahist_tpc_nopi", "#eta distribution - MC TPC tag ! prim/secd #pi", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpc_nopi", "#phi distribution - MC TPC tag ! prim/secd #pi", kTH1D, {axisPhi}, true); - // histos.add("MC/PID/pthist_its_nopi", "#it{p}_{T} distribution - MC ITS tag ! prim/secd #pi", kTH1D, {axisPt}, true); - // histos.add("MC/PID/etahist_its_nopi", "#eta distribution - MC ITS tag ! prim/secd #pi", kTH1D, {axisEta}, true); - // histos.add("MC/PID/phihist_its_nopi", "#phi distribution - MC ITS tag ! prim/secd #pi", kTH1D, {axisPhi}, true); - histos.add("MC/PID/pthist_tpcits_nopi", "#it{p}_{T} distribution - MC TPC+ITS tag ! prim/secd #pi", kTH1D, {axisPt}, true); histos.add("MC/PID/etahist_tpcits_nopi", "#eta distribution - MC TPC+ITS tag ! prim/secd #pi", kTH1D, {axisEta}, true); histos.add("MC/PID/phihist_tpcits_nopi", "#phi distribution - MC TPC+ITS tag ! prim/secd #pi", kTH1D, {axisPhi}, true); @@ -846,7 +878,7 @@ struct qaMatchEff { } // end initMC - /// Function calculatind the pt at inner wall of TPC + /// Function calculating the pt at inner wall of TPC template float computePtInParamTPC(T& track) { @@ -872,9 +904,8 @@ struct qaMatchEff { if (!cutObject.IsSelected(track, TrackSelection::TrackCuts::kDCAxy)) return false; // dcaZ selection to simulate the dca cut in QC () - // if ( abs(track.dcaZ()) < sqrt( dcaMaxCut*dcaMaxCut - - // track.dcaXY()*track.dcaXY() ) ) - // return false; + if (abs(track.dcaZ()) > dcaMaxCut->get("TrVtx", "dcaZ")) + return false; return true; } /// Function applying the TPC selections @@ -905,7 +936,27 @@ struct qaMatchEff { return false; return true; } - + // + // + // fill collision control plots + // + template + void fillGeneralHistos(T& coll) + { + if constexpr (IS_MC) { + histos.fill(HIST("MC/control/zPrimary"), coll.posZ()); + histos.fill(HIST("MC/control/yPrimary"), coll.posY()); + histos.fill(HIST("MC/control/xPrimary"), coll.posX()); + histos.fill(HIST("MC/control/chi2Prim"), coll.chi2()); + } else { + histos.fill(HIST("data/control/zPrimary"), coll.posZ()); + histos.fill(HIST("data/control/yPrimary"), coll.posY()); + histos.fill(HIST("data/control/xPrimary"), coll.posX()); + histos.fill(HIST("data/control/chi2Prim"), coll.chi2()); + } + return; + } + // // define global variables int count = 0; int countData = 0; @@ -914,15 +965,20 @@ struct qaMatchEff { int tpPDGCode = 0; std::vector::iterator itr_pdg; float pdg_fill = 0.0; - + // + // + // + /******************************************************************/ + // + // ///////////////////////////////////////////////////// /// Template function to perform the analysis /// ///////////////////////////////////////////////////// - template - void fillHistograms(T& tracks, P& mcParticles) + template + void fillHistograms(T& tracks, P& mcParticles, B const& bcs) { // - float trackPt = 0, ITStrackPt = 0; + float trackPt = 0; //, ITStrackPt = 0; // // float tpcNSigmaPion = -999.f; @@ -970,10 +1026,10 @@ struct qaMatchEff { /// Using pt calculated at the inner wall of TPC /// Caveat: tgl still from tracking: this is not the value of tgl at the /// inner wall of TPC - if (b_useTPCinnerWallPtForITS) - ITStrackPt = tpcinner_pt; - else - ITStrackPt = reco_pt; + // if (b_useTPCinnerWallPtForITS) + // ITStrackPt = tpcinner_pt; + // else + // ITStrackPt = reco_pt; countData++; // @@ -994,23 +1050,23 @@ struct qaMatchEff { const bool trkWTOF = track.hasTOF(); const bool trkWTPC = track.hasTPC(); const bool trkWITS = track.hasITS(); - bool pionPIDwithTPC = (nSigmaTPCPionMin < tpcNSigmaPion && tpcNSigmaPion < nSigmaTPCPionMax); - bool pionPIDwithTOF = (nSigmaTOFPionMin < tofNSigmaPion && tofNSigmaPion < nSigmaTOFPionMax); - bool kaonPIDwithTPC = (nSigmaTPCKaonMin < tpcNSigmaKaon && tpcNSigmaKaon < nSigmaTPCKaonMax); - bool kaonPIDwithTOF = (nSigmaTOFKaonMin < tofNSigmaKaon && tofNSigmaKaon < nSigmaTOFKaonMax); - bool protonPIDwithTPC = (nSigmaTPCProtonMin < tpcNSigmaProton && tpcNSigmaProton < nSigmaTPCProtonMax); - bool protonPIDwithTOF = (nSigmaTOFProtonMin < tofNSigmaProton && tofNSigmaProton < nSigmaTOFProtonMax); + bool pionPIDwithTPC = (nSigmaPID->get("TPC", "nSigPionMin") < tpcNSigmaPion && tpcNSigmaPion < nSigmaPID->get("TPC", "nSigPionMax")); + bool pionPIDwithTOF = (nSigmaPID->get("TOF", "nSigPionMin") < tofNSigmaPion && tofNSigmaPion < nSigmaPID->get("TOF", "nSigPionMax")); + bool kaonPIDwithTPC = (nSigmaPID->get("TPC", "nSigKaonMin") < tpcNSigmaKaon && tpcNSigmaKaon < nSigmaPID->get("TPC", "nSigKaonMax")); + bool kaonPIDwithTOF = (nSigmaPID->get("TOF", "nSigKaonMin") < tofNSigmaKaon && tofNSigmaKaon < nSigmaPID->get("TOF", "nSigKaonMax")); + bool protonPIDwithTPC = (nSigmaPID->get("TPC", "nSigProtonMin") < tpcNSigmaProton && tpcNSigmaProton < nSigmaPID->get("TPC", "nSigProtonMax")); + bool protonPIDwithTOF = (nSigmaPID->get("TOF", "nSigProtonMin") < tofNSigmaProton && tofNSigmaProton < nSigmaPID->get("TOF", "nSigProtonMax")); // isPion bool isPion = false; - if (isPIDPionRequired && nSigmaTPCPionMin < tpcNSigmaPion && tpcNSigmaPion < nSigmaTPCPionMax && ((!trkWTOF) || (nSigmaTOFPionMin < tofNSigmaPion && tofNSigmaPion < nSigmaTOFPionMax))) + if (isPIDPionRequired && pionPIDwithTPC && ((!trkWTOF) || pionPIDwithTOF)) isPion = true; // isKaon bool isKaon = false; - if (isPIDKaonRequired && nSigmaTPCKaonMin < tpcNSigmaKaon && tpcNSigmaKaon < nSigmaTPCKaonMax && ((!trkWTOF) || (nSigmaTOFKaonMin < tofNSigmaKaon && tofNSigmaKaon < nSigmaTOFKaonMax))) + if (isPIDKaonRequired && kaonPIDwithTPC && ((!trkWTOF) || kaonPIDwithTOF)) isKaon = true; // isProton bool isProton = false; - if (isPIDProtonRequired && nSigmaTPCProtonMin < tpcNSigmaProton && tpcNSigmaProton < nSigmaTPCProtonMax && ((!trkWTOF) || (nSigmaTOFProtonMin < tofNSigmaProton && tofNSigmaProton < nSigmaTOFProtonMax))) + if (isPIDProtonRequired && protonPIDwithTPC && ((!trkWTOF) || protonPIDwithTOF)) isProton = true; // int sayPrim = -1, signPDGCode = -2, specind = 0; @@ -1069,150 +1125,13 @@ struct qaMatchEff { } // // all tracks, no conditions - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - if constexpr (IS_MC) { // MC - // pt comparison plot - if (makept2d) { - histos.fill(HIST("MC/control/ptptconfITSall"), reco_pt, tpcinner_pt); - if (!trkWTPC) - histos.fill(HIST("MC/control/ptptconfITSo"), reco_pt, tpcinner_pt); - } - // - histos.get(HIST("MC/qopthist_its"))->Fill(track.signed1Pt()); - histos.get(HIST("MC/pthist_its"))->Fill(ITStrackPt); - histos.get(HIST("MC/phihist_its"))->Fill(track.phi()); - histos.get(HIST("MC/etahist_its"))->Fill(track.eta()); - if (trkWTOF) { - histos.get(HIST("MC/pthist_tofits"))->Fill(ITStrackPt); - histos.get(HIST("MC/phihist_tofits"))->Fill(track.phi()); - histos.get(HIST("MC/etahist_tofits"))->Fill(track.eta()); - } - } else { // DATA - // pt comparison plot - if (makept2d) { - histos.fill(HIST("data/control/ptptconfITSall"), reco_pt, tpcinner_pt); - if (!trkWTPC) - histos.fill(HIST("data/control/ptptconfITSo"), reco_pt, tpcinner_pt); - } - // - histos.get(HIST("data/qopthist_its"))->Fill(track.signed1Pt()); - histos.get(HIST("data/pthist_its"))->Fill(ITStrackPt); - histos.get(HIST("data/phihist_its"))->Fill(track.phi()); - histos.get(HIST("data/etahist_its"))->Fill(track.eta()); - // - // with TOF tag - if (trkWTOF) { - histos.get(HIST("data/pthist_tofits"))->Fill(ITStrackPt); - histos.get(HIST("data/phihist_tofits"))->Fill(track.phi()); - histos.get(HIST("data/etahist_tofits"))->Fill(track.eta()); - } - // - // PID is applied - if (isPion) { - histos.get(HIST("data/PID/pthist_its_pi"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_pi"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_pi"))->Fill(track.eta()); - if (positiveTrack) { - histos.get(HIST("data/PID/pthist_its_piplus"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_piplus"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_piplus"))->Fill(track.eta()); - } else { - histos.get(HIST("data/PID/pthist_its_piminus"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_piminus"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_piminus"))->Fill(track.eta()); - } - } - if(isPIDPionRequired) { - if (pionPIDwithTPC) { - histos.get(HIST("data/PID/pthist_its_pi_PIDTPC"))->Fill(trackPt); - if(!trkWTOF || !pionPIDwithTOF) histos.get(HIST("data/PID/pthist_its_pi_PIDTPC_O"))->Fill(trackPt); - } - if (trkWTOF && pionPIDwithTOF) { - histos.get(HIST("data/PID/pthist_its_pi_PIDTOF"))->Fill(trackPt); - if (!pionPIDwithTPC) histos.get(HIST("data/PID/pthist_its_pi_PIDTOF_O"))->Fill(trackPt); - } - if (pionPIDwithTPC && trkWTOF && pionPIDwithTOF) { - histos.get(HIST("data/PID/pthist_its_pi_PIDTPCTOF"))->Fill(trackPt); - } - } - // end pions - if (isKaon) { - histos.get(HIST("data/PID/pthist_its_ka"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_ka"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_ka"))->Fill(track.eta()); - if (positiveTrack) { - histos.get(HIST("data/PID/pthist_its_kaplus"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_kaplus"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_kaplus"))->Fill(track.eta()); - } else { - histos.get(HIST("data/PID/pthist_its_kaminus"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_kaminus"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_kaminus"))->Fill(track.eta()); - } - } - if(isPIDKaonRequired) { - if (kaonPIDwithTPC) { - histos.get(HIST("data/PID/pthist_its_ka_PIDTPC"))->Fill(trackPt); - if(!trkWTOF || !kaonPIDwithTOF) histos.get(HIST("data/PID/pthist_its_ka_PIDTPC_O"))->Fill(trackPt); - } - if (trkWTOF && kaonPIDwithTOF) { - histos.get(HIST("data/PID/pthist_its_ka_PIDTOF"))->Fill(trackPt); - if (!kaonPIDwithTPC) histos.get(HIST("data/PID/pthist_its_ka_PIDTOF_O"))->Fill(trackPt); - } - if (kaonPIDwithTPC && trkWTOF && kaonPIDwithTOF) { - histos.get(HIST("data/PID/pthist_its_ka_PIDTPCTOF"))->Fill(trackPt); - } - } - // end kaons - if (isProton) { - histos.get(HIST("data/PID/pthist_its_pr"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_pr"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_pr"))->Fill(track.eta()); - if (positiveTrack) { - histos.get(HIST("data/PID/pthist_its_prplus"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_prplus"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_prplus"))->Fill(track.eta()); - } else { - histos.get(HIST("data/PID/pthist_its_prminus"))->Fill(ITStrackPt); - histos.get(HIST("data/PID/phihist_its_prminus"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_prminus"))->Fill(track.eta()); - } - } - if(isPIDProtonRequired) { - if (protonPIDwithTPC) { - histos.get(HIST("data/PID/pthist_its_pr_PIDTPC"))->Fill(trackPt); - if(!trkWTOF || !protonPIDwithTOF) histos.get(HIST("data/PID/pthist_its_pr_PIDTPC_O"))->Fill(trackPt); - } - if (trkWTOF && protonPIDwithTOF) { - histos.get(HIST("data/PID/pthist_its_pr_PIDTOF"))->Fill(trackPt); - if (!protonPIDwithTPC) histos.get(HIST("data/PID/pthist_its_pr_PIDTOF_O"))->Fill(trackPt); - } - if (protonPIDwithTPC && trkWTOF && protonPIDwithTOF) { - histos.get(HIST("data/PID/pthist_its_pr_PIDTPCTOF"))->Fill(trackPt); - } - } - // end protons - if (!isPion && !isKaon && !isProton) { - histos.get(HIST("data/PID/pthist_its_noid"))->Fill(trackPt); - histos.get(HIST("data/PID/phihist_its_noid"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_noid"))->Fill(track.eta()); - if (positiveTrack) { - histos.get(HIST("data/PID/pthist_its_noidplus"))->Fill(trackPt); - histos.get(HIST("data/PID/phihist_its_noidplus"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_noidplus"))->Fill(track.eta()); - } else { - histos.get(HIST("data/PID/pthist_its_noidminus"))->Fill(trackPt); - histos.get(HIST("data/PID/phihist_its_noidminus"))->Fill(track.phi()); - histos.get(HIST("data/PID/etahist_its_noidminus"))->Fill(track.eta()); - } - } - } - } // end ITS-only tag - */ // if (trkWTPC && isTrackSelectedTPCCuts(track)) { - if constexpr (IS_MC) { // MC + if constexpr (IS_MC) { //////////////////////// MC + // + histos.fill(HIST("MC/control/zDCA_tpc"), track.dcaZ()); + histos.fill(HIST("MC/control/xyDCA_tpc"), track.dcaXY()); + // if (makept2d) { histos.fill(HIST("MC/control/ptptconfTPCall"), reco_pt, tpcinner_pt); if (!trkWITS) @@ -1227,7 +1146,11 @@ struct qaMatchEff { histos.get(HIST("MC/phihist_toftpc"))->Fill(track.phi()); histos.get(HIST("MC/etahist_toftpc"))->Fill(track.eta()); } - } else { // DATA + } else { //////////////////////// DATA + // + histos.fill(HIST("data/control/zDCA_tpc"), track.dcaZ()); + histos.fill(HIST("data/control/xyDCA_tpc"), track.dcaXY()); + // if (makept2d) { histos.fill(HIST("data/control/ptptconfTPCall"), reco_pt, tpcinner_pt); if (!trkWITS) @@ -1238,6 +1161,17 @@ struct qaMatchEff { histos.get(HIST("data/phihist_tpc"))->Fill(track.phi()); histos.get(HIST("data/etahist_tpc"))->Fill(track.eta()); // + // monitoring vs. time (debug reasons) + if (enableMonitorVsTime && timeMonitorSetUp) { + if (track.has_collision()) { + const auto timestamp = track.collision().template bc_as().timestamp(); /// NB: in ms + histos.get(HIST("data/hTrkTPCvsTime"))->Fill(timestamp); + if (enableTHnSparseMonitorVsTime) { + histos.get(HIST("data/hTrkTPCvsTimePtEtaPosZ"))->Fill(timestamp, trackPt, track.eta(), track.collision().posZ(), 1. / trackPt, positiveTrack ? 0.5 : -0.5, track.tpcNClsFound(), track.itsNCls()); + } + } + } + // // with TOF tag if (trkWTOF) { histos.get(HIST("data/pthist_toftpc"))->Fill(trackPt); @@ -1247,6 +1181,9 @@ struct qaMatchEff { // // PID is applied if (isPion) { + histos.get(HIST("data/PID/zDCA_tpc_pi"))->Fill(track.dcaZ()); + histos.get(HIST("data/PID/xyDCA_tpc_pi"))->Fill(track.dcaXY()); + // histos.get(HIST("data/PID/pthist_tpc_pi"))->Fill(trackPt); histos.get(HIST("data/PID/phihist_tpc_pi"))->Fill(track.phi()); histos.get(HIST("data/PID/etahist_tpc_pi"))->Fill(track.eta()); @@ -1263,20 +1200,45 @@ struct qaMatchEff { if (isPIDPionRequired) { if (pionPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpc_pi_PIDTPC"))->Fill(trackPt); - if (!trkWTOF || !pionPIDwithTOF) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_piplus_PIDTPC"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_piminus_PIDTPC"))->Fill(trackPt); + if (!trkWTOF || !pionPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_pi_PIDTPC_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_piplus_PIDTPC_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_piminus_PIDTPC_O"))->Fill(trackPt); + } } if (trkWTOF && pionPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_pi_PIDTOF"))->Fill(trackPt); - if (!pionPIDwithTPC) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_piplus_PIDTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_piminus_PIDTOF"))->Fill(trackPt); + if (!pionPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpc_pi_PIDTOF_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_piplus_PIDTOF_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_piminus_PIDTOF_O"))->Fill(trackPt); + } } if (pionPIDwithTPC && trkWTOF && pionPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_pi_PIDTPCTOF"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_piplus_PIDTPCTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_piminus_PIDTPCTOF"))->Fill(trackPt); } } // end pions if (isKaon) { + histos.get(HIST("data/PID/zDCA_tpc_ka"))->Fill(track.dcaZ()); + histos.get(HIST("data/PID/xyDCA_tpc_ka"))->Fill(track.dcaXY()); + // histos.get(HIST("data/PID/pthist_tpc_ka"))->Fill(trackPt); histos.get(HIST("data/PID/phihist_tpc_ka"))->Fill(track.phi()); histos.get(HIST("data/PID/etahist_tpc_ka"))->Fill(track.eta()); @@ -1293,20 +1255,45 @@ struct qaMatchEff { if (isPIDKaonRequired) { if (kaonPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpc_ka_PIDTPC"))->Fill(trackPt); - if (!trkWTOF || !kaonPIDwithTOF) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_kaplus_PIDTPC"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_kaminus_PIDTPC"))->Fill(trackPt); + if (!trkWTOF || !kaonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_ka_PIDTPC_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_kaplus_PIDTPC_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_kaminus_PIDTPC_O"))->Fill(trackPt); + } } if (trkWTOF && kaonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_ka_PIDTOF"))->Fill(trackPt); - if (!kaonPIDwithTPC) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_kaplus_PIDTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_kaminus_PIDTOF"))->Fill(trackPt); + if (!kaonPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpc_ka_PIDTOF_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_kaplus_PIDTOF_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_kaminus_PIDTOF_O"))->Fill(trackPt); + } } if (kaonPIDwithTPC && trkWTOF && kaonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_ka_PIDTPCTOF"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_kaplus_PIDTPCTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_kaminus_PIDTPCTOF"))->Fill(trackPt); } } // end kaons if (isProton) { + histos.get(HIST("data/PID/zDCA_tpc_pr"))->Fill(track.dcaZ()); + histos.get(HIST("data/PID/xyDCA_tpc_pr"))->Fill(track.dcaXY()); + // histos.get(HIST("data/PID/pthist_tpc_pr"))->Fill(trackPt); histos.get(HIST("data/PID/phihist_tpc_pr"))->Fill(track.phi()); histos.get(HIST("data/PID/etahist_tpc_pr"))->Fill(track.eta()); @@ -1323,20 +1310,44 @@ struct qaMatchEff { if (isPIDProtonRequired) { if (protonPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpc_pr_PIDTPC"))->Fill(trackPt); - if (!trkWTOF || !protonPIDwithTOF) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_prplus_PIDTPC"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_prminus_PIDTPC"))->Fill(trackPt); + if (!trkWTOF || !protonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_pr_PIDTPC_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_prplus_PIDTPC_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_prminus_PIDTPC_O"))->Fill(trackPt); + } } if (trkWTOF && protonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_pr_PIDTOF"))->Fill(trackPt); - if (!protonPIDwithTPC) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_prplus_PIDTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_prminus_PIDTOF"))->Fill(trackPt); + if (!protonPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpc_pr_PIDTOF_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_prplus_PIDTOF_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_prminus_PIDTOF_O"))->Fill(trackPt); + } } if (protonPIDwithTPC && trkWTOF && protonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpc_pr_PIDTPCTOF"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpc_prplus_PIDTPCTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpc_prminus_PIDTPCTOF"))->Fill(trackPt); } } // end protons - if (!isPion && !isKaon && !isProton) { + if (!isPion && !isKaon && !isProton && (isPIDPionRequired || isPIDKaonRequired || isPIDProtonRequired)) { + histos.get(HIST("data/PID/zDCA_tpc_noid"))->Fill(track.dcaZ()); + histos.get(HIST("data/PID/xyDCA_tpc_noid"))->Fill(track.dcaXY()); histos.get(HIST("data/PID/pthist_tpc_noid"))->Fill(trackPt); histos.get(HIST("data/PID/phihist_tpc_noid"))->Fill(track.phi()); histos.get(HIST("data/PID/etahist_tpc_noid"))->Fill(track.eta()); @@ -1352,8 +1363,10 @@ struct qaMatchEff { } // not pions, nor kaons, nor protons } // end if DATA // - if (trkWITS && isTrackSelectedITSCuts(track)) { // ITS tag inside TPC tagged - if constexpr (IS_MC) { // MC + if (trkWITS && isTrackSelectedITSCuts(track)) { //////////////////////////////////////////// ITS tag inside TPC tagged + if constexpr (IS_MC) { //////////////////////// MC + histos.get(HIST("MC/control/zDCA_tpcits"))->Fill(track.dcaZ()); + histos.get(HIST("MC/control/xyDCA_tpcits"))->Fill(track.dcaXY()); if (makept2d) histos.fill(HIST("MC/control/ptptconfTPCITS"), reco_pt, tpcinner_pt); histos.get(HIST("MC/qopthist_tpcits"))->Fill(track.signed1Pt()); @@ -1365,13 +1378,18 @@ struct qaMatchEff { histos.get(HIST("MC/phihist_toftpcits"))->Fill(track.phi()); histos.get(HIST("MC/etahist_toftpcits"))->Fill(track.eta()); } - } else { // DATA + } else { //////////////////////// DATA + histos.get(HIST("data/control/zDCA_tpcits"))->Fill(track.dcaZ()); + histos.get(HIST("data/control/xyDCA_tpcits"))->Fill(track.dcaXY()); if (makept2d) histos.fill(HIST("data/control/ptptconfTPCITS"), reco_pt, tpcinner_pt); histos.get(HIST("data/qopthist_tpcits"))->Fill(track.signed1Pt()); // // PID is applied if (isPion) { + histos.get(HIST("data/PID/zDCA_tpcits_pi"))->Fill(track.dcaZ()); + histos.get(HIST("data/PID/xyDCA_tpcits_pi"))->Fill(track.dcaXY()); + // histos.get(HIST("data/PID/pthist_tpcits_pi"))->Fill(trackPt); histos.get(HIST("data/PID/phihist_tpcits_pi"))->Fill(track.phi()); histos.get(HIST("data/PID/etahist_tpcits_pi"))->Fill(track.eta()); @@ -1388,20 +1406,45 @@ struct qaMatchEff { if (isPIDPionRequired) { if (pionPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpcits_pi_PIDTPC"))->Fill(trackPt); - if (!trkWTOF || !pionPIDwithTOF) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_piplus_PIDTPC"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_piminus_PIDTPC"))->Fill(trackPt); + if (!trkWTOF || !pionPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_pi_PIDTPC_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_piplus_PIDTPC_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_piminus_PIDTPC_O"))->Fill(trackPt); + } } if (trkWTOF && pionPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_pi_PIDTOF"))->Fill(trackPt); - if (!pionPIDwithTPC) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_piplus_PIDTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_piminus_PIDTOF"))->Fill(trackPt); + if (!pionPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpcits_pi_PIDTOF_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_piplus_PIDTOF_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_piminus_PIDTOF_O"))->Fill(trackPt); + } } if (pionPIDwithTPC && trkWTOF && pionPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_pi_PIDTPCTOF"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_piplus_PIDTPCTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_piminus_PIDTPCTOF"))->Fill(trackPt); } } // end pions if (isKaon) { + histos.get(HIST("data/PID/zDCA_tpcits_ka"))->Fill(track.dcaZ()); + histos.get(HIST("data/PID/xyDCA_tpcits_ka"))->Fill(track.dcaXY()); + // histos.get(HIST("data/PID/pthist_tpcits_ka"))->Fill(trackPt); histos.get(HIST("data/PID/phihist_tpcits_ka"))->Fill(track.phi()); histos.get(HIST("data/PID/etahist_tpcits_ka"))->Fill(track.eta()); @@ -1418,20 +1461,45 @@ struct qaMatchEff { if (isPIDKaonRequired) { if (kaonPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpcits_ka_PIDTPC"))->Fill(trackPt); - if (!trkWTOF || !kaonPIDwithTOF) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_kaplus_PIDTPC"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_kaminus_PIDTPC"))->Fill(trackPt); + if (!trkWTOF || !kaonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_ka_PIDTPC_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_kaplus_PIDTPC_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_kaminus_PIDTPC_O"))->Fill(trackPt); + } } if (trkWTOF && kaonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_ka_PIDTOF"))->Fill(trackPt); - if (!kaonPIDwithTPC) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_kaplus_PIDTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_kaminus_PIDTOF"))->Fill(trackPt); + if (!kaonPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpcits_ka_PIDTOF_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_kaplus_PIDTOF_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_kaminus_PIDTOF_O"))->Fill(trackPt); + } } if (kaonPIDwithTPC && trkWTOF && kaonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_ka_PIDTPCTOF"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_kaplus_PIDTPCTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_kaminus_PIDTPCTOF"))->Fill(trackPt); } } // end kaons if (isProton) { + histos.get(HIST("data/PID/zDCA_tpcits_pr"))->Fill(track.dcaZ()); + histos.get(HIST("data/PID/xyDCA_tpcits_pr"))->Fill(track.dcaXY()); + // histos.get(HIST("data/PID/pthist_tpcits_pr"))->Fill(trackPt); histos.get(HIST("data/PID/phihist_tpcits_pr"))->Fill(track.phi()); histos.get(HIST("data/PID/etahist_tpcits_pr"))->Fill(track.eta()); @@ -1448,16 +1516,38 @@ struct qaMatchEff { if (isPIDProtonRequired) { if (protonPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpcits_pr_PIDTPC"))->Fill(trackPt); - if (!trkWTOF || !protonPIDwithTOF) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_prplus_PIDTPC"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_prminus_PIDTPC"))->Fill(trackPt); + if (!trkWTOF || !protonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_pr_PIDTPC_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_prplus_PIDTPC_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_prminus_PIDTPC_O"))->Fill(trackPt); + } } if (trkWTOF && protonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_pr_PIDTOF"))->Fill(trackPt); - if (!protonPIDwithTPC) + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_prplus_PIDTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_prminus_PIDTOF"))->Fill(trackPt); + if (!protonPIDwithTPC) { histos.get(HIST("data/PID/pthist_tpcits_pr_PIDTOF_O"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_prplus_PIDTOF_O"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_prminus_PIDTOF_O"))->Fill(trackPt); + } } if (protonPIDwithTPC && trkWTOF && protonPIDwithTOF) { histos.get(HIST("data/PID/pthist_tpcits_pr_PIDTPCTOF"))->Fill(trackPt); + if (positiveTrack) + histos.get(HIST("data/PID/pthist_tpcits_prplus_PIDTPCTOF"))->Fill(trackPt); + else + histos.get(HIST("data/PID/pthist_tpcits_prminus_PIDTPCTOF"))->Fill(trackPt); } } // end protons @@ -1465,8 +1555,21 @@ struct qaMatchEff { histos.get(HIST("data/phihist_tpcits"))->Fill(track.phi()); histos.get(HIST("data/etahist_tpcits"))->Fill(track.eta()); // + // monitoring vs. time (debug reasons) + if (enableMonitorVsTime && timeMonitorSetUp) { + if (track.has_collision()) { + const auto timestamp = track.collision().template bc_as().timestamp(); /// NB: in ms + histos.get(HIST("data/hTrkITSTPCvsTime"))->Fill(timestamp); + if (enableTHnSparseMonitorVsTime) { + histos.get(HIST("data/hTrkITSTPCvsTimePtEtaPosZ"))->Fill(timestamp, trackPt, track.eta(), track.collision().posZ(), 1. / trackPt, positiveTrack ? 0.5 : -0.5, track.tpcNClsFound(), track.itsNCls()); + } + } + } + // // not identified if (!isPion && !isKaon && !isProton) { + histos.get(HIST("data/PID/zDCA_tpcits_noid"))->Fill(track.dcaZ()); + histos.get(HIST("data/PID/xyDCA_tpcits_noid"))->Fill(track.dcaXY()); histos.get(HIST("data/PID/pthist_tpcits_noid"))->Fill(trackPt); histos.get(HIST("data/PID/phihist_tpcits_noid"))->Fill(track.phi()); histos.get(HIST("data/PID/etahist_tpcits_noid"))->Fill(track.eta()); @@ -1499,17 +1602,17 @@ struct qaMatchEff { for (unsigned int i = 0; i < 7; i++) { if (track.itsClusterMap() & (1 << i)) { trkHasITS = true; - if (IS_MC) { + if (IS_MC) { //////////////////////// MC histos.fill(HIST("MC/control/itsHitsMatched"), i, itsNhits); - } else { + } else { //////////////////////// DATA histos.fill(HIST("data/control/itsHitsMatched"), i, itsNhits); } } } if (!trkHasITS) { - if (IS_MC) { + if (IS_MC) { //////////////////////// MC histos.fill(HIST("MC/control/itsHitsMatched"), -1, itsNhits); - } else { + } else { //////////////////////// DATA histos.fill(HIST("data/control/itsHitsMatched"), -1, itsNhits); } } @@ -1518,25 +1621,12 @@ struct qaMatchEff { // // all tracks with pt>0.5 if (trackPt > 0.5) { - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - if constexpr (IS_MC) { - histos.get(HIST("MC/pthist_its_05"))->Fill(ITStrackPt); - histos.get(HIST("MC/phihist_its_05"))->Fill(track.phi()); - histos.get(HIST("MC/etahist_its_05"))->Fill(track.eta()); - } else { - histos.get(HIST("data/pthist_its_05"))->Fill(ITStrackPt); - histos.get(HIST("data/phihist_its_05"))->Fill(track.phi()); - histos.get(HIST("data/etahist_its_05"))->Fill(track.eta()); - } - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { - if constexpr (IS_MC) { + if constexpr (IS_MC) { //////////////////////// MC histos.get(HIST("MC/pthist_tpc_05"))->Fill(trackPt); histos.get(HIST("MC/phihist_tpc_05"))->Fill(track.phi()); histos.get(HIST("MC/etahist_tpc_05"))->Fill(track.eta()); - } else { + } else { //////////////////////// DATA histos.get(HIST("data/pthist_tpc_05"))->Fill(trackPt); histos.get(HIST("data/phihist_tpc_05"))->Fill(track.phi()); histos.get(HIST("data/etahist_tpc_05"))->Fill(track.eta()); @@ -1557,19 +1647,6 @@ struct qaMatchEff { // // positive only if (track.signed1Pt() > 0) { - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - if constexpr (IS_MC) { // MC - histos.get(HIST("MC/pthist_its_pos"))->Fill(ITStrackPt); - histos.get(HIST("MC/phihist_its_pos"))->Fill(track.phi()); - histos.get(HIST("MC/etahist_its_pos"))->Fill(track.eta()); - } else { // DATA - histos.get(HIST("data/pthist_its_pos"))->Fill(ITStrackPt); - histos.get(HIST("data/phihist_its_pos"))->Fill(track.phi()); - histos.get(HIST("data/etahist_its_pos"))->Fill(track.eta()); - } - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { if constexpr (IS_MC) { histos.get(HIST("MC/pthist_tpc_pos"))->Fill(trackPt); @@ -1597,19 +1674,6 @@ struct qaMatchEff { // // negative only if (track.signed1Pt() < 0) { - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - if constexpr (IS_MC) { - histos.get(HIST("MC/pthist_its_neg"))->Fill(ITStrackPt); - histos.get(HIST("MC/phihist_its_neg"))->Fill(track.phi()); - histos.get(HIST("MC/etahist_its_neg"))->Fill(track.eta()); - } else { - histos.get(HIST("data/pthist_its_neg"))->Fill(ITStrackPt); - histos.get(HIST("data/phihist_its_neg"))->Fill(track.phi()); - histos.get(HIST("data/etahist_its_neg"))->Fill(track.eta()); - } - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { if constexpr (IS_MC) { histos.get(HIST("MC/pthist_tpc_neg"))->Fill(trackPt); @@ -1640,20 +1704,18 @@ struct qaMatchEff { // // only primaries if (mcpart.isPhysicalPrimary()) { - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/primsec/qopthist_its_prim"))->Fill(track.signed1Pt()); - histos.get(HIST("MC/primsec/pthist_its_prim"))->Fill(ITStrackPt); - histos.get(HIST("MC/primsec/phihist_its_prim"))->Fill(track.phi()); - histos.get(HIST("MC/primsec/etahist_its_prim"))->Fill(track.eta()); - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { + histos.get(HIST("MC/primsec/zDCA_tpc_prim"))->Fill(track.dcaZ()); + histos.get(HIST("MC/primsec/xyDCA_tpc_prim"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/primsec/qopthist_tpc_prim"))->Fill(track.signed1Pt()); histos.get(HIST("MC/primsec/pthist_tpc_prim"))->Fill(trackPt); histos.get(HIST("MC/primsec/phihist_tpc_prim"))->Fill(track.phi()); histos.get(HIST("MC/primsec/etahist_tpc_prim"))->Fill(track.eta()); if (trkWITS && isTrackSelectedITSCuts(track)) { + histos.get(HIST("MC/primsec/zDCA_tpcits_prim"))->Fill(track.dcaZ()); + histos.get(HIST("MC/primsec/xyDCA_tpcits_prim"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/primsec/qopthist_tpcits_prim"))->Fill(track.signed1Pt()); histos.get(HIST("MC/primsec/pthist_tpcits_prim"))->Fill(trackPt); histos.get(HIST("MC/primsec/phihist_tpcits_prim"))->Fill(track.phi()); @@ -1664,20 +1726,18 @@ struct qaMatchEff { } else if (mcpart.getProcess() == 4) { // // only secondaries from decay - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/primsec/qopthist_its_secd"))->Fill(track.signed1Pt()); - histos.get(HIST("MC/primsec/pthist_its_secd"))->Fill(ITStrackPt); - histos.get(HIST("MC/primsec/phihist_its_secd"))->Fill(track.phi()); - histos.get(HIST("MC/primsec/etahist_its_secd"))->Fill(track.eta()); - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { + histos.get(HIST("MC/primsec/zDCA_tpc_secd"))->Fill(track.dcaZ()); + histos.get(HIST("MC/primsec/xyDCA_tpc_secd"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/primsec/qopthist_tpc_secd"))->Fill(track.signed1Pt()); histos.get(HIST("MC/primsec/pthist_tpc_secd"))->Fill(trackPt); histos.get(HIST("MC/primsec/phihist_tpc_secd"))->Fill(track.phi()); histos.get(HIST("MC/primsec/etahist_tpc_secd"))->Fill(track.eta()); if (trkWITS && isTrackSelectedITSCuts(track)) { + histos.get(HIST("MC/primsec/zDCA_tpcits_secd"))->Fill(track.dcaZ()); + histos.get(HIST("MC/primsec/xyDCA_tpcits_secd"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/primsec/qopthist_tpcits_secd"))->Fill(track.signed1Pt()); histos.get(HIST("MC/primsec/pthist_tpcits_secd"))->Fill(trackPt); histos.get(HIST("MC/primsec/phihist_tpcits_secd"))->Fill(track.phi()); @@ -1688,20 +1748,18 @@ struct qaMatchEff { } else { // // only secondaries from material - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/primsec/qopthist_its_secm"))->Fill(track.signed1Pt()); - histos.get(HIST("MC/primsec/pthist_its_secm"))->Fill(ITStrackPt); - histos.get(HIST("MC/primsec/phihist_its_secm"))->Fill(track.phi()); - histos.get(HIST("MC/primsec/etahist_its_secm"))->Fill(track.eta()); - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { + histos.get(HIST("MC/primsec/zDCA_tpc_secm"))->Fill(track.dcaZ()); + histos.get(HIST("MC/primsec/xyDCA_tpc_secm"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/primsec/qopthist_tpc_secm"))->Fill(track.signed1Pt()); histos.get(HIST("MC/primsec/pthist_tpc_secm"))->Fill(trackPt); histos.get(HIST("MC/primsec/phihist_tpc_secm"))->Fill(track.phi()); histos.get(HIST("MC/primsec/etahist_tpc_secm"))->Fill(track.eta()); if (trkWITS && isTrackSelectedITSCuts(track)) { + histos.get(HIST("MC/primsec/zDCA_tpcits_secm"))->Fill(track.dcaZ()); + histos.get(HIST("MC/primsec/xyDCA_tpcits_secm"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/primsec/qopthist_tpcits_secm"))->Fill(track.signed1Pt()); histos.get(HIST("MC/primsec/pthist_tpcits_secm"))->Fill(trackPt); histos.get(HIST("MC/primsec/phihist_tpcits_secm"))->Fill(track.phi()); @@ -1712,23 +1770,10 @@ struct qaMatchEff { // // protons only if (tpPDGCode == 2212) { - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/PID/pthist_its_pr"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_pr"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_pr"))->Fill(track.eta()); - if (positiveTrack) { - histos.get(HIST("MC/PID/pthist_its_prplus"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_prplus"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_prplus"))->Fill(track.eta()); - } else { - histos.get(HIST("MC/PID/pthist_its_prminus"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_prminus"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_prminus"))->Fill(track.eta()); - } - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { + histos.get(HIST("MC/PID/zDCA_tpc_pr"))->Fill(track.dcaZ()); + histos.get(HIST("MC/PID/xyDCA_tpc_pr"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/PID/pthist_tpc_pr"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpc_pr"))->Fill(track.phi()); histos.get(HIST("MC/PID/etahist_tpc_pr"))->Fill(track.eta()); @@ -1742,6 +1787,9 @@ struct qaMatchEff { histos.get(HIST("MC/PID/etahist_tpc_prminus"))->Fill(track.eta()); } if (trkWITS && isTrackSelectedITSCuts(track)) { + histos.get(HIST("MC/PID/zDCA_tpcits_pr"))->Fill(track.dcaZ()); + histos.get(HIST("MC/PID/xyDCA_tpcits_pr"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/PID/pthist_tpcits_pr"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpcits_pr"))->Fill(track.phi()); histos.get(HIST("MC/PID/etahist_tpcits_pr"))->Fill(track.eta()); @@ -1760,25 +1808,10 @@ struct qaMatchEff { // // pions only if (tpPDGCode == 211) { - /* - // - // ITS tracks - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/PID/pthist_its_pi"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_pi"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_pi"))->Fill(track.eta()); - if (positiveTrack) { - histos.get(HIST("MC/PID/pthist_its_piplus"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_piplus"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_piplus"))->Fill(track.eta()); - } else { - histos.get(HIST("MC/PID/pthist_its_piminus"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_piminus"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_piminus"))->Fill(track.eta()); - } - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { + histos.get(HIST("MC/PID/zDCA_tpc_pi"))->Fill(track.dcaZ()); + histos.get(HIST("MC/PID/xyDCA_tpc_pi"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/PID/pthist_tpc_pi"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpc_pi"))->Fill(track.phi()); histos.get(HIST("MC/PID/etahist_tpc_pi"))->Fill(track.eta()); @@ -1792,6 +1825,9 @@ struct qaMatchEff { histos.get(HIST("MC/PID/etahist_tpc_piminus"))->Fill(track.eta()); } if (trkWITS && isTrackSelectedITSCuts(track)) { + histos.get(HIST("MC/PID/zDCA_tpcits_pi"))->Fill(track.dcaZ()); + histos.get(HIST("MC/PID/xyDCA_tpcits_pi"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/PID/pthist_tpcits_pi"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpcits_pi"))->Fill(track.phi()); histos.get(HIST("MC/PID/etahist_tpcits_pi"))->Fill(track.eta()); @@ -1809,13 +1845,6 @@ struct qaMatchEff { // // only primary pions if (mcpart.isPhysicalPrimary()) { - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/PID/pthist_its_pi_prim"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_pi_prim"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_pi_prim"))->Fill(track.eta()); - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { histos.get(HIST("MC/PID/pthist_tpc_pi_prim"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpc_pi_prim"))->Fill(track.phi()); @@ -1830,13 +1859,6 @@ struct qaMatchEff { } else if (mcpart.getProcess() == 4) { // // only secondary pions from decay - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/PID/pthist_its_pi_secd"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_pi_secd"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_pi_secd"))->Fill(track.eta()); - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { histos.get(HIST("MC/PID/pthist_tpc_pi_secd"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpc_pi_secd"))->Fill(track.phi()); @@ -1851,13 +1873,6 @@ struct qaMatchEff { } else { // // only secondary pions from material - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/PID/pthist_its_pi_secm"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_pi_secm"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_pi_secm"))->Fill(track.eta()); - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { histos.get(HIST("MC/PID/pthist_tpc_pi_secm"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpc_pi_secm"))->Fill(track.phi()); @@ -1882,14 +1897,6 @@ struct qaMatchEff { else pdg_fill = -10.0; // - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/PID/pthist_its_nopi"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_nopi"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_nopi"))->Fill(track.eta()); - histos.get(HIST("MC/PID/pdghist_denits"))->Fill(pdg_fill); - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { histos.get(HIST("MC/PID/pthist_tpc_nopi"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpc_nopi"))->Fill(track.phi()); @@ -1906,23 +1913,10 @@ struct qaMatchEff { // // kaons only if (tpPDGCode == 321) { - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/PID/pthist_its_ka"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_ka"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_ka"))->Fill(track.eta()); - if (positiveTrack) { - histos.get(HIST("MC/PID/pthist_its_kaplus"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_kaplus"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_kaplus"))->Fill(track.eta()); - } else { - histos.get(HIST("MC/PID/pthist_its_kaminus"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_kaminus"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_kaminus"))->Fill(track.eta()); - } - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { + histos.get(HIST("MC/PID/zDCA_tpc_ka"))->Fill(track.dcaZ()); + histos.get(HIST("MC/PID/xyDCA_tpc_ka"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/PID/pthist_tpc_ka"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpc_ka"))->Fill(track.phi()); histos.get(HIST("MC/PID/etahist_tpc_ka"))->Fill(track.eta()); @@ -1936,6 +1930,9 @@ struct qaMatchEff { histos.get(HIST("MC/PID/etahist_tpc_kaminus"))->Fill(track.eta()); } if (trkWITS && isTrackSelectedITSCuts(track)) { + histos.get(HIST("MC/PID/zDCA_tpcits_ka"))->Fill(track.dcaZ()); + histos.get(HIST("MC/PID/xyDCA_tpcits_ka"))->Fill(track.dcaXY()); + // histos.get(HIST("MC/PID/pthist_tpcits_ka"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpcits_ka"))->Fill(track.phi()); histos.get(HIST("MC/PID/etahist_tpcits_ka"))->Fill(track.eta()); @@ -1954,13 +1951,6 @@ struct qaMatchEff { // // pions and kaons together if (tpPDGCode == 211 || tpPDGCode == 321) { - /* - if (trkWITS && isTrackSelectedITSCuts(track)) { - histos.get(HIST("MC/PID/pthist_its_piK"))->Fill(ITStrackPt); - histos.get(HIST("MC/PID/phihist_its_piK"))->Fill(track.phi()); - histos.get(HIST("MC/PID/etahist_its_piK"))->Fill(track.eta()); - } // end if ITS - */ if (trkWTPC && isTrackSelectedTPCCuts(track)) { histos.get(HIST("MC/PID/pthist_tpc_piK"))->Fill(trackPt); histos.get(HIST("MC/PID/phihist_tpc_piK"))->Fill(track.phi()); @@ -1984,21 +1974,84 @@ struct qaMatchEff { } } + /// Function to add histograms for time-based monitoring of matching efficiency (debug purposes) + /// BEWARE: these hitograms are ok only if looked run-by-run + void setUpTimeMonitoring(BCsWithTimeStamp const& bcs) + { + int runNumber = bcs.rawIteratorAt(0).runNumber(); + if (lastRunNumber != runNumber) { + /// execute the code in this scope only once, i.e. when the current run is considered for the first time in this DF + lastRunNumber = runNumber; + int64_t tsSOR = 0; + int64_t tsEOR = 0; + + /// reject AO2Ds for which no CCDB access is possible + if (runNumber < 500000) { + LOG(warning) << ">>> run number " << runNumber << " < 500000. access to CCDB not possible. Exiting"; + return; + } + + /// If we are here, the current run was never considered before. + /// Let's add the TH2 that we need for the monitoring + /// Let's define the x-axis according to the start-of-run (SOR) and end-of-run (EOR) times + o2::ccdb::CcdbApi ccdb_api; + ccdb_api.init(ccdburl); + std::map metadataRCT, headers; + headers = ccdb_api.retrieveHeaders(Form("RCT/Info/RunInformation/%i", runNumber), metadataRCT, -1); + tsSOR = atol(headers["SOR"].c_str()); + tsEOR = atol(headers["EOR"].c_str()); + double minMilliSec = floor(tsSOR); /// round tsSOR to the highest integer lower than tsSOR + double maxMilliSec = ceil(tsEOR); /// round tsEOR to the lowest integer higher than tsEOR + const AxisSpec axisSeconds{static_cast((maxMilliSec - minMilliSec) * 1. / 10.), minMilliSec, maxMilliSec, "time from January 1st, 1970 at UTC (unit: 10 ms)"}; + + /// add histograms now + const AxisSpec axisPtVsTime{ptBinsVsTime, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axis1overPtVsTime{ptInvserseBinsVsTime, "1/#it{p}_{T} (#it{c}/GeV)"}; + const AxisSpec axisChargeVsTime{2, -1, 1, "charge"}; + const AxisSpec axisEtaVsTime{etaBinsVsTime, "#eta"}; + const AxisSpec axisPosZVsTime{posZBinsVsTime, "posZ (cm)"}; + const AxisSpec axisTpcClstVsTime{tpcClstBinsVsTime, "TPC clusters"}; + const AxisSpec axisItsClstVsTime{itsClstBinsVsTime, "TPC clusters"}; + // TPC tracks + histos.add("data/hTrkTPCvsTime", "", kTH1D, {axisSeconds}); + if (enableTHnSparseMonitorVsTime) { + histos.add("data/hTrkTPCvsTimePtEtaPosZ", "", kTHnSparseF, {axisSeconds, axisPtVsTime, axisEtaVsTime, axisPosZVsTime, axis1overPtVsTime, axisChargeVsTime, axisTpcClstVsTime, axisItsClstVsTime}); + } + // ITS-TPC tracks + histos.add("data/hTrkITSTPCvsTime", "", kTH1D, {axisSeconds}); + if (enableTHnSparseMonitorVsTime) { + histos.add("data/hTrkITSTPCvsTimePtEtaPosZ", "", kTHnSparseF, {axisSeconds, axisPtVsTime, axisEtaVsTime, axisPosZVsTime, axis1overPtVsTime, axisChargeVsTime, axisTpcClstVsTime, axisItsClstVsTime}); + } + + /// time monitoring correctly set up + timeMonitorSetUp = true; + } + } + ////////////////////////////////////////////// /// Process MC with collision grouping /// ////////////////////////////////////////////// - void processMC(aod::Collision const& collision, soa::Join const& tracks, aod::McParticles const& mcParticles) + void processMC(soa::Filtered::iterator const& collision, soa::Join const& tracks, aod::McParticles const& mcParticles) { - fillHistograms(tracks, mcParticles); + fillHistograms(tracks, mcParticles, mcParticles); /// 3rd argument non-sense in this case + fillGeneralHistos(collision); } PROCESS_SWITCH(qaMatchEff, processMC, "process MC", false); + void processMCFilteredTracks(soa::Filtered::iterator const& collision, soa::Filtered> const& tracks, aod::McParticles const& mcParticles) + { + fillHistograms(tracks, mcParticles, mcParticles); /// 3rd argument non-sense in this case + fillGeneralHistos(collision); + } + PROCESS_SWITCH(qaMatchEff, processMCFilteredTracks, "process MC with filtered tracks with filterbit selections", false); + //////////////////////////////////////////////////////////// /// Process MC with collision grouping and IU tracks /// //////////////////////////////////////////////////////////// - void processTrkIUMC(aod::Collision const& collision, soa::Join const& tracks, aod::McParticles const& mcParticles) + void processTrkIUMC(soa::Filtered::iterator const& collision, soa::Join const& tracks, aod::McParticles const& mcParticles) { - fillHistograms(tracks, mcParticles); + fillHistograms(tracks, mcParticles, mcParticles); /// 3rd argument non-sense in this case + fillGeneralHistos(collision); } PROCESS_SWITCH(qaMatchEff, processTrkIUMC, "process MC for IU tracks", false); @@ -2007,35 +2060,54 @@ struct qaMatchEff { ///////////////////////////////////////////// void processMCNoColl(soa::Join const& tracks, aod::McParticles const& mcParticles) { - fillHistograms(tracks, mcParticles); + fillHistograms(tracks, mcParticles, mcParticles); /// 3rd argument non-sense in this case } PROCESS_SWITCH(qaMatchEff, processMCNoColl, "process MC - no collision grouping", false); //////////////////////////////////////////////// /// Process data with collision grouping /// //////////////////////////////////////////////// - void processData( - aod::Collision const& collision, soa::Join const& tracks) + void processData(soa::Filtered::iterator const& collision, soa::Join const& tracks, BCsWithTimeStamp const& bcs) { - fillHistograms(tracks, tracks); // 2nd argument not used in this case + if (enableMonitorVsTime) { + // tracks.rawIteratorAt(0).collision().bc_as().timestamp(); /// NB: in ms + setUpTimeMonitoring(bcs); + } + fillHistograms(tracks, tracks, bcs); // 2nd argument not used in this case + fillGeneralHistos(collision); } PROCESS_SWITCH(qaMatchEff, processData, "process data", true); + void processDataFilteredTracks(soa::Filtered::iterator const& collision, soa::Filtered> const& tracks, BCsWithTimeStamp const& bcs) + { + if (enableMonitorVsTime) { + // tracks.rawIteratorAt(0).collision().bc_as().timestamp(); /// NB: in ms + setUpTimeMonitoring(bcs); + } + fillHistograms(tracks, tracks, bcs); // 2nd argument not used in this case + fillGeneralHistos(collision); + } + PROCESS_SWITCH(qaMatchEff, processDataFilteredTracks, "process data with filtered tracks with filterbit selections", false); + ///////////////////////////////////////////////////////////// /// Process data with collision grouping and IU tracks /// ///////////////////////////////////////////////////////////// - void processTrkIUData(aod::Collision const& collision, soa::Join const& tracks) + void processTrkIUData(soa::Filtered::iterator const& collision, soa::Join const& tracks) { - fillHistograms(tracks, tracks); // 2nd argument not used in this case + fillHistograms(tracks, tracks, tracks); // 2nd and 3rd arguments not used in this case + fillGeneralHistos(collision); } PROCESS_SWITCH(qaMatchEff, processTrkIUData, "process data", false); /////////////////////////////////////////////// /// Process data w/o collision grouping /// /////////////////////////////////////////////// - void processDataNoColl(soa::Join const& tracks) + void processDataNoColl(soa::Join const& tracks, BCsWithTimeStamp const& bcs) { - fillHistograms(tracks, tracks); // 2nd argument not used in this case + if (enableMonitorVsTime) { + setUpTimeMonitoring(bcs); + } + fillHistograms(tracks, tracks, bcs); // 2nd argument not used in this case } PROCESS_SWITCH(qaMatchEff, processDataNoColl, "process data - no collision grouping", true); diff --git a/DPG/Tasks/AOTTrack/qaTrackSelection.cxx b/DPG/Tasks/AOTTrack/qaTrackSelection.cxx index f9bf408d6a1..bb183e4bb73 100644 --- a/DPG/Tasks/AOTTrack/qaTrackSelection.cxx +++ b/DPG/Tasks/AOTTrack/qaTrackSelection.cxx @@ -56,6 +56,13 @@ struct QaTrackCuts { void init(InitContext&) { + + histos.add("eventSelection", "Event Selection", kTH1D, {{10, 0.5, 10.5, "Selection"}}); + histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(1, "Events read"); + histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(2, "Passed Ev. Sel."); + histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(3, "Passed Contrib."); + histos.get(HIST("eventSelection"))->GetXaxis()->SetBinLabel(4, "Passed Position"); + const AxisSpec axisSelections{30, 0.5, 30.5f, "Selection"}; // histos.add("events", "events", kTH1D, {axisSelections}); for (int i = 0; i < nhist; i++) { @@ -127,6 +134,8 @@ struct QaTrackCuts { histos.addClone("NoEvSel/alltracks", "NoEvSel/customSel/alltracks"); // "NoEvSel/alltracks", "NoEvSel/hastof", "NoEvSel/hastpc", "NoEvSel/hasits", "NoEvSel/hastrd", // "sel8/alltracks", "sel8/hastof", "sel8/hastpc", "sel8/hasits", "sel8/hastrd" + histos.add("NoEvSel/customSel/tpcCrossedRows/before", "TPC Crossed rows;TPC Crossed rows", kTH1D, {{165, -0.5, 164.5}}); + histos.addClone("NoEvSel/customSel/tpcCrossedRows/before", "NoEvSel/customSel/tpcCrossedRows/after"); } } diff --git a/DPG/Tasks/CMakeLists.txt b/DPG/Tasks/CMakeLists.txt index fba7aae0174..551a2462144 100644 --- a/DPG/Tasks/CMakeLists.txt +++ b/DPG/Tasks/CMakeLists.txt @@ -10,6 +10,7 @@ # or submit itself to any jurisdiction. add_subdirectory(AOTTrack) +add_subdirectory(AOTEvent) add_subdirectory(TPC) add_subdirectory(TOF) add_subdirectory(FDD) diff --git a/DPG/Tasks/TOF/CMakeLists.txt b/DPG/Tasks/TOF/CMakeLists.txt index ead4bc47043..4aa53992717 100644 --- a/DPG/Tasks/TOF/CMakeLists.txt +++ b/DPG/Tasks/TOF/CMakeLists.txt @@ -16,5 +16,5 @@ o2physics_add_dpl_workflow(tof-skimscreation o2physics_add_dpl_workflow(tof-calib SOURCES tofOfflineCalib.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFBase COMPONENT_NAME Analysis) diff --git a/DPG/Tasks/TOF/tofSkimsTableCreator.cxx b/DPG/Tasks/TOF/tofSkimsTableCreator.cxx index e53d6248fa5..d15dfe83d53 100644 --- a/DPG/Tasks/TOF/tofSkimsTableCreator.cxx +++ b/DPG/Tasks/TOF/tofSkimsTableCreator.cxx @@ -34,10 +34,8 @@ using namespace o2::track; struct tofSkimsTableCreator { using Trks = soa::Join; - using Coll = soa::Join; + using Coll = soa::Join; // Tables to be produced Produces tableColRow; @@ -122,8 +120,7 @@ struct tofSkimsTableCreator { break; } - tableColRow(collision.globalIndex(), - evTimeTOF, + tableColRow(evTimeTOF, evTimeTOFErr, evTimeTOFMult, evTimeT0A, @@ -149,7 +146,7 @@ struct tofSkimsTableCreator { } } } - tableRow(trk.collisionId(), + tableRow(tableColRow.lastIndex(), trk.p(), trk.pt() * trk.sign(), trk.eta(), diff --git a/DPG/Tasks/TOF/tofSkimsTableCreator.h b/DPG/Tasks/TOF/tofSkimsTableCreator.h index 96481222bff..4f0ec48ed06 100644 --- a/DPG/Tasks/TOF/tofSkimsTableCreator.h +++ b/DPG/Tasks/TOF/tofSkimsTableCreator.h @@ -19,11 +19,6 @@ #ifndef DPG_TASKS_TOF_TOFSKIMSTABLECREATOR_H_ #define DPG_TASKS_TOF_TOFSKIMSTABLECREATOR_H_ -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::track; - #include "Common/TableProducer/PID/pidTOFBase.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/FT0Corrected.h" @@ -61,7 +56,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(HasTOF, hasTOF, //! Flag to check i DECLARE_SOA_TABLE(SkimmedTOFColl, "AOD", "SKIMMEDTOFCOL", //! Table of the skimmed TOF data format. One entry per collision. o2::soa::Index<>, - tofskims::CollisionId, pidtofevtime::EvTimeTOF, pidtofevtime::EvTimeTOFErr, pidtofevtime::EvTimeTOFMult, diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index 7fbb9950104..42fb1bfc2ef 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -215,12 +215,14 @@ struct TreeWriterTPCTOF { Configurable trackSelection{"trackSelection", 1, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; /// Triton Configurable maxMomTPCOnlyTr{"maxMomTPCOnlyTr", 1.5, "Maximum momentum for TPC only cut triton"}; + Configurable maxMomHardCutOnlyTr{"maxMomHardCutOnlyTr", 50, "Maximum TPC inner momentum for triton"}; Configurable nSigmaTPCOnlyTr{"nSigmaTPCOnlyTr", 4., "number of sigma for TPC only cut triton"}; Configurable nSigmaTPC_TPCTOF_Tr{"nSigmaTPC_TPCTOF_Tr", 4., "number of sigma for TPC cut for TPC and TOF combined triton"}; Configurable nSigmaTOF_TPCTOF_Tr{"nSigmaTOF_TPCTOF_Tr", 3., "number of sigma for TOF cut for TPC and TOF combined triton"}; Configurable dwnSmplFactor_Tr{"dwnSmplFactor_Tr", 1., "downsampling factor for triton, default fraction to keep is 1."}; /// Deuteron Configurable maxMomTPCOnlyDe{"maxMomTPCOnlyDe", 1.0, "Maximum momentum for TPC only cut deuteron"}; + Configurable maxMomHardCutOnlyDe{"maxMomHardCutOnlyDe", 50, "Maximum TPC inner momentum for deuteron"}; Configurable nSigmaTPCOnlyDe{"nSigmaTPCOnlyDe", 4., "number of sigma for TPC only cut deuteron"}; Configurable nSigmaTPC_TPCTOF_De{"nSigmaTPC_TPCTOF_De", 4., "number of sigma for TPC cut for TPC and TOF combined deuteron"}; Configurable nSigmaTOF_TPCTOF_De{"nSigmaTOF_TPCTOF_De", 3., "number of sigma for TOF cut for TPC and TOF combined deuteron"}; @@ -352,15 +354,15 @@ struct TreeWriterTPCTOF { rowTPCTOFTree.reserve(tracks.size()); for (auto const& trk : tracks) { /// Fill tree for tritons - if (trk.tpcInnerParam() <= maxMomTPCOnlyTr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPCOnlyTr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() <= maxMomTPCOnlyTr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPCOnlyTr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignal()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr); - } else if (trk.tpcInnerParam() > maxMomTPCOnlyTr && std::abs(trk.tofNSigmaTr()) < nSigmaTOF_TPCTOF_Tr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPC_TPCTOF_Tr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() > maxMomTPCOnlyTr && std::abs(trk.tofNSigmaTr()) < nSigmaTOF_TPCTOF_Tr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPC_TPCTOF_Tr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignal()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr); } /// Fill tree for deuterons - if (trk.tpcInnerParam() <= maxMomTPCOnlyDe && std::abs(trk.tpcNSigmaDe()) < nSigmaTPCOnlyDe && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() <= maxMomTPCOnlyDe && std::abs(trk.tpcNSigmaDe()) < nSigmaTPCOnlyDe && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignal()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De); - } else if (trk.tpcInnerParam() > maxMomTPCOnlyDe && std::abs(trk.tofNSigmaDe()) < nSigmaTOF_TPCTOF_De && std::abs(trk.tpcNSigmaDe()) < nSigmaTPC_TPCTOF_De && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() > maxMomTPCOnlyDe && std::abs(trk.tofNSigmaDe()) < nSigmaTOF_TPCTOF_De && std::abs(trk.tpcNSigmaDe()) < nSigmaTPC_TPCTOF_De && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignal()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De); } /// Fill tree for protons diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.h b/DPG/Tasks/TPC/tpcSkimsTableCreator.h index ea453e0979b..c8cce4750de 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.h +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.h @@ -16,15 +16,11 @@ #ifndef DPG_TASKS_TPC_TPCSKIMSTABLECREATOR_H_ #define DPG_TASKS_TPC_TPCSKIMSTABLECREATOR_H_ + #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/PIDResponse.h" -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::track; -using namespace o2::dataformats; namespace o2::aod { diff --git a/DPG/Tasks/TPC/tpcTreeCreatorLight.h b/DPG/Tasks/TPC/tpcTreeCreatorLight.h index 4e52d559321..df02c1de1ec 100644 --- a/DPG/Tasks/TPC/tpcTreeCreatorLight.h +++ b/DPG/Tasks/TPC/tpcTreeCreatorLight.h @@ -16,15 +16,11 @@ #ifndef DPG_TASKS_TPC_TPCTREECREATORLIGHT_H_ #define DPG_TASKS_TPC_TPCTREECREATORLIGHT_H_ + #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/PIDResponse.h" -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::track; -using namespace o2::dataformats; enum ParticleSpecies { kPionTrack = BIT(0), diff --git a/EventFiltering/CMakeLists.txt b/EventFiltering/CMakeLists.txt index db6c32ca2db..d29485a0923 100644 --- a/EventFiltering/CMakeLists.txt +++ b/EventFiltering/CMakeLists.txt @@ -10,80 +10,84 @@ # or submit itself to any jurisdiction. o2physics_add_dpl_workflow(central-event-filter-task - SOURCES cefpTask.cxx - COMPONENT_NAME Analysis - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + SOURCES cefpTask.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DataFormatsCTP + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(selected-bc-range-task - SOURCES selectBCRange.cxx - COMPONENT_NAME Analysis - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES selectBCRange.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(nuclei-filter - SOURCES PWGLF/nucleiFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES PWGLF/nucleiFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(diffraction-filter - SOURCES PWGUD/diffractionFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder - COMPONENT_NAME Analysis) + SOURCES PWGUD/diffractionFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::DGCutparHolder + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(diffraction-bcfilter - SOURCES PWGUD/diffractionBCFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::DGCutparHolder - COMPONENT_NAME Analysis) + SOURCES PWGUD/diffractionBCFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::DGCutparHolder + COMPONENT_NAME Analysis) o2physics_add_header_only_library(HFFilterHelpers - HEADERS PWGHF/HFFilterHelpers.h) + HEADERS PWGHF/HFFilterHelpers.h) o2physics_add_dpl_workflow(hf-filter - SOURCES PWGHF/HFFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2::CCDB ONNXRuntime::ONNXRuntime O2Physics::HFFilterHelpers - COMPONENT_NAME Analysis) + SOURCES PWGHF/HFFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore ONNXRuntime::ONNXRuntime O2Physics::HFFilterHelpers O2::DetectorsBase + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(hf-filter-qc - SOURCES PWGHF/HFFilterQC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore ONNXRuntime::ONNXRuntime O2Physics::HFFilterHelpers - COMPONENT_NAME Analysis) + SOURCES PWGHF/HFFilterQC.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore ONNXRuntime::ONNXRuntime O2Physics::HFFilterHelpers + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(hf-filter-prepare-ml-samples - SOURCES PWGHF/HFFilterPrepareMLSamples.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::Framework O2Physics::AnalysisCore ONNXRuntime::ONNXRuntime O2Physics::HFFilterHelpers - COMPONENT_NAME Analysis) + SOURCES PWGHF/HFFilterPrepareMLSamples.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore ONNXRuntime::ONNXRuntime O2Physics::HFFilterHelpers O2::DetectorsBase + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(cf-filter - SOURCES PWGCF/CFFilterAll.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES PWGCF/CFFilterAll.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(cf-filter-qa - SOURCES PWGCF/CFFilterQA.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES PWGCF/CFFilterQA.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(je-filter - SOURCES PWGJE/jetFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore FastJet::FastJet FastJet::Contrib - COMPONENT_NAME Analysis) + SOURCES PWGJE/jetFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(fje-filter - SOURCES PWGJE/fullJetFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore FastJet::FastJet FastJet::Contrib - COMPONENT_NAME Analysis) + SOURCES PWGJE/fullJetFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib Boost::system + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lf-strangeness-filter - SOURCES PWGLF/strangenessFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES PWGLF/strangenessFilter.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(mult-filter - SOURCES PWGMM/multFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES PWGMM/multFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(em-filter - SOURCES PWGEM/photonFilter.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES PWGEM/photonFilter.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lf-f1proton-filter + SOURCES PWGLF/filterf1proton.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) diff --git a/EventFiltering/PWGCF/CFFilterAll.cxx b/EventFiltering/PWGCF/CFFilterAll.cxx index d1837970984..6feadf1b76a 100644 --- a/EventFiltering/PWGCF/CFFilterAll.cxx +++ b/EventFiltering/PWGCF/CFFilterAll.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -93,16 +94,18 @@ static const std::vector SpeciesMinTPCClustersName{"Proton", "Deute static const std::vector SpeciesAvgTPCTOFName{"Proton", "AntiProton", "Deuteron", "AntiDeuteron"}; static const std::vector TPCTOFAvgName{"TPC Avg", "TOF Avg"}; static const std::vector PidCutsName{"TPC min", "TPC max", "TOF min", "TOF max", "TPCTOF max"}; -static const std::vector PtCutsName{"Pt min", "Pt max", "P thres"}; +static const std::vector PtCutsName{"Pt min (particle)", "Pt max (particle)", "Pt min (antiparticle)", "Pt max (antiparticle)", "P thres"}; static const std::vector ThreeBodyFilterNames{"PPP", "PPL", "PLL", "LLL"}; static const std::vector TwoBodyFilterNames{"PD", "LD"}; +static const std::vector ParticleNames{"PPP", "aPaPaP", "PPL", "aPaPaL", "PLL", "aPaLaL", "LLL", "aLaLaL", "PD", "aPaD", "LD", "aLaD"}; static const int nPidRejection = 2; static const int nTracks = 2; static const int nPidAvg = 4; static const int nPidCutsDaughers = 2; -static const int nPtCuts = 3; +static const int nPtCuts = 5; static const int nAllTriggers = 6; +static const int nTriggerAllNames = 12; static const float pidcutsTable[nTracks][kNPIDLimits]{ {-6.f, 6.f, -6.f, 6.f, 6.f}, @@ -122,9 +125,9 @@ static const float pidcutsV0DaughterTable[kNV0Daughters][nPidCutsDaughers]{ {-6.f, 6.f}, {-6.f, 6.f}}; static const float ptcutsTable[kNParticleRejection][nPtCuts]{ - {0.35f, 6.f, 0.75f}, - {0.35f, 1.6f, 99.f}, - {0.35f, 6.f, 99.f}}; + {0.35f, 6.f, 0.35f, 6.0f, 0.75f}, + {0.35f, 1.6f, 0.35f, 1.6f, 99.f}, + {0.f, 6.f, 0.f, 6.f, 99.f}}; static const float NClustersMin[1][nTracks]{ {60.0f, 60.0f}}; @@ -133,8 +136,14 @@ static const float triggerSwitches[1][nAllTriggers]{ static const float Q3Limits[1][kNThreeBodyTriggers]{ {0.6f, 0.6f, 0.6f, 0.6f}}; + static const float KstarLimits[1][kNTwoBodyTriggers]{ {1.2f, 1.2f}}; + +static const float Downsample[2][nTriggerAllNames]{ + {-1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1., -1}, + {1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.}}; + } // namespace CFTrigger namespace o2::aod @@ -155,6 +164,9 @@ struct CFFilter { Service ccdb; o2::ccdb::CcdbApi ccdbApi; + Configurable ConfRngSeed{"ConfRngSeed", 69, "Seed for downsampling"}; + TRandom3* rng; + // Configs for events Configurable ConfIsRun3{ "ConfIsRun3", @@ -334,7 +346,7 @@ struct CFFilter { "Particle PID selections for antiparticles; perfect case scenario identical to particles"}; Configurable> ConfPtCuts{ "ConfPtCuts", - {CFTrigger::ptcutsTable[0], CFTrigger::kNParticleRejection, CFTrigger::nPtCuts, CFTrigger::SpeciesNameAll, CFTrigger::PtCutsName}, + {CFTrigger::ptcutsTable[0], CFTrigger::kNParticleSpecies, CFTrigger::nPtCuts, CFTrigger::SpeciesNameAll, CFTrigger::PtCutsName}, "Particle Momentum selections"}; Configurable ConfRejectNOTDeuteron{ "ConfRejectNOTDeuteron", @@ -428,6 +440,11 @@ struct CFFilter { {CFTrigger::KstarLimits[0], 1, CFTrigger::kNTwoBodyTriggers, std::vector{"Limit"}, CFTrigger::TwoBodyFilterNames}, "kstar limit for two body trigger"}; + Configurable> ConfDownsample{ + "ConfDownsample", + {CFTrigger::Downsample[0], 2, CFTrigger::nTriggerAllNames, std::vector{"Switch", "Factor"}, CFTrigger::ParticleNames}, + "Downsample individual particle species (Switch has to be larger than 0, Factor has to smaller than 1)"}; + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; // HistogramRegistry registryQA{"registryQA", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -435,6 +452,8 @@ struct CFFilter { void init(o2::framework::InitContext&) { + rng = new TRandom3(ConfRngSeed.value); + // init the ccdb ccdb->setURL("http://alice-ccdb.cern.ch"); ccdbApi.init("http://alice-ccdb.cern.ch"); @@ -678,37 +697,49 @@ struct CFFilter { registry.add("ppp/fMultiplicity", "Multiplicity of all processed events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); registry.add("ppp/fZvtx", "Zvtx of all processed events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); registry.add("ppp/fSE_particle", "Same Event distribution", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppp/fSE_particle_downsample", "Same Event distribution (downsampled)", HistType::kTH1F, {{8000, 0, 8}}); registry.add("ppp/fSE_antiparticle", "Same Event distribution", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppp/fSE_antiparticle_downsample", "Same Event distribution (downsampled)", HistType::kTH1F, {{8000, 0, 8}}); // for ppl registry.add("ppl/fMultiplicity", "Multiplicity of all processed events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); registry.add("ppl/fZvtx", "Zvtx of all processed events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); registry.add("ppl/fSE_particle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppl/fSE_particle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); registry.add("ppl/fSE_antiparticle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ppl/fSE_antiparticle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); // for pll registry.add("pll/fMultiplicity", "Multiplicity of all processed events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); registry.add("pll/fZvtx", "Zvtx of all processed events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); registry.add("pll/fSE_particle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("pll/fSE_particle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); registry.add("pll/fSE_antiparticle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("pll/fSE_antiparticle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); // for pll registry.add("lll/fMultiplicity", "Multiplicity of all processed events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); registry.add("lll/fZvtx", "Zvtx of all processed events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); registry.add("lll/fSE_particle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("lll/fSE_particle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); registry.add("lll/fSE_antiparticle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("lll/fSE_antiparticle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); // for pd registry.add("pd/fMultiplicity", "Multiplicity of all processed events;Mult;Entries", HistType::kTH1F, {{1000, 0, 1000}}); registry.add("pd/fZvtx", "Zvtx of all processed events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); registry.add("pd/fSE_particle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("pd/fSE_particle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); registry.add("pd/fSE_antiparticle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("pd/fSE_antiparticle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); // for ld registry.add("ld/fMultiplicity", "Multiplicity of all processed events", HistType::kTH1F, {{1000, 0, 1000}}); registry.add("ld/fZvtx", "Zvtx of all processed events;Z_{vtx};Entries", HistType::kTH1F, {{1000, -15, 15}}); registry.add("ld/fSE_particle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ld/fSE_particle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); registry.add("ld/fSE_antiparticle", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); + registry.add("ld/fSE_antiparticle_downsample", "Same Event distribution;SE;Q_{3} (GeV/c)", HistType::kTH1F, {{8000, 0, 8}}); } float mMassElectron = o2::constants::physics::MassElectron; @@ -734,6 +765,7 @@ struct CFFilter { template bool isSelectedTrack(T const& track, CFTrigger::ParticleSpecies partSpecies) { + const auto charge = track.sign(); const auto pT = track.pt(); const auto eta = track.eta(); const auto tpcNClsF = track.tpcNClsFound(); @@ -745,12 +777,23 @@ struct CFFilter { const auto dcaXY = track.dcaXY(); const auto dcaZ = track.dcaZ(); - if (pT < ConfPtCuts->get(partSpecies, "Pt min")) { - return false; + if (charge > 0) { + if (pT < ConfPtCuts->get(partSpecies, "Pt min (particle)")) { + return false; + } + if (pT > ConfPtCuts->get(partSpecies, "Pt max (particle)")) { + return false; + } } - if (pT > ConfPtCuts->get(partSpecies, "Pt max")) { - return false; + if (charge < 0) { + if (pT < ConfPtCuts->get(partSpecies, "Pt min (antiparticle)")) { + return false; + } + if (pT > ConfPtCuts->get(partSpecies, "Pt max (antiparticle)")) { + return false; + } } + if (std::abs(eta) > ConfTrkEta) { return false; } @@ -1453,7 +1496,6 @@ struct CFFilter { } float Q3 = 999.f, kstar = 999.f; - // if(ConfTriggerSwitches->get(static_cast(0), CFTrigger::)>0.){ if (ConfTriggerSwitches->get("Switch", "ppp") > 0.) { // ppp trigger for (auto iProton1 = protons.begin(); iProton1 != protons.end(); ++iProton1) { @@ -1464,7 +1506,14 @@ struct CFFilter { Q3 = getQ3(*iProton1, *iProton2, *iProton3); registry.fill(HIST("ppp/fSE_particle"), Q3); if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kPPP)) { - lowQ3Triplets[CFTrigger::kPPP] += 1; + if (ConfDownsample->get("Switch", "PPP") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "PPP")) { + registry.fill(HIST("ppp/fSE_particle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kPPP] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kPPP] += 1; + } } } } @@ -1477,7 +1526,14 @@ struct CFFilter { Q3 = getQ3(*iAntiProton1, *iAntiProton2, *iAntiProton3); registry.fill(HIST("ppp/fSE_antiparticle"), Q3); if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kPPP)) { - lowQ3Triplets[CFTrigger::kPPP] += 1; + if (ConfDownsample->get("Switch", "aPaPaP") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "aPaPaP")) { + registry.fill(HIST("ppp/fSE_antiparticle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kPPP] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kPPP] += 1; + } } } } @@ -1500,7 +1556,14 @@ struct CFFilter { Q3 = getQ3(*iProton1, *iProton2, *iLambda1); registry.fill(HIST("ppl/fSE_particle"), Q3); if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kPPL)) { - lowQ3Triplets[CFTrigger::kPPL] += 1; + if (ConfDownsample->get("Switch", "PPL") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "PPL")) { + registry.fill(HIST("ppl/fSE_particle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kPPL] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kPPL] += 1; + } } } } @@ -1520,7 +1583,14 @@ struct CFFilter { Q3 = getQ3(*iAntiProton1, *iAntiProton2, *iAntiLambda1); registry.fill(HIST("ppl/fSE_antiparticle"), Q3); if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kPPL)) { - lowQ3Triplets[CFTrigger::kPPL] += 1; + if (ConfDownsample->get("Switch", "aPaPaL") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "aPaPaL")) { + registry.fill(HIST("ppl/fSE_antiparticle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kPPL] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kPPL] += 1; + } } } } @@ -1548,7 +1618,14 @@ struct CFFilter { Q3 = getQ3(*iLambda1, *iLambda2, *iProton1); registry.fill(HIST("pll/fSE_particle"), Q3); if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kPLL)) { - lowQ3Triplets[CFTrigger::kPLL] += 1; + if (ConfDownsample->get("Switch", "PLL") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "PLL")) { + registry.fill(HIST("pll/fSE_particle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kPLL] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kPLL] += 1; + } } } } @@ -1573,7 +1650,14 @@ struct CFFilter { Q3 = getQ3(*iAntiLambda1, *iAntiLambda2, *iAntiProton1); registry.fill(HIST("pll/fSE_antiparticle"), Q3); if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kPLL)) { - lowQ3Triplets[CFTrigger::kPLL] += 1; + if (ConfDownsample->get("Switch", "aPaLaL") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "aPaLaL")) { + registry.fill(HIST("pll/fSE_antiparticle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kPLL] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kPLL] += 1; + } } } } @@ -1604,7 +1688,14 @@ struct CFFilter { Q3 = getQ3(*iLambda1, *iLambda2, *iLambda3); registry.fill(HIST("lll/fSE_particle"), Q3); if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kLLL)) { - lowQ3Triplets[CFTrigger::kLLL] += 1; + if (ConfDownsample->get("Switch", "LLL") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "LLL")) { + registry.fill(HIST("lll/fSE_particle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kLLL] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kLLL] += 1; + } } } } @@ -1632,7 +1723,14 @@ struct CFFilter { Q3 = getQ3(*iAntiLambda1, *iAntiLambda2, *iAntiLambda3); registry.fill(HIST("lll/fSE_antiparticle"), Q3); if (Q3 < ConfQ3Limits->get(static_cast(0), CFTrigger::kLLL)) { - lowQ3Triplets[CFTrigger::kLLL] += 1; + if (ConfDownsample->get("Switch", "aLaLaL") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "aLaLaL")) { + registry.fill(HIST("lll/fSE_antiparticle_downsample"), Q3); + lowQ3Triplets[CFTrigger::kLLL] += 1; + } + } else { + lowQ3Triplets[CFTrigger::kLLL] += 1; + } } } } @@ -1645,16 +1743,31 @@ struct CFFilter { kstar = getkstar(*iProton, *iDeuteron); registry.fill(HIST("pd/fSE_particle"), kstar); if (kstar < ConfKstarLimits->get(static_cast(0), CFTrigger::kPD)) { - lowKstarPairs[CFTrigger::kPD] += 1; + if (ConfDownsample->get("Switch", "PD") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "PD")) { + registry.fill(HIST("pd/fSE_particle_downsample"), kstar); + lowKstarPairs[CFTrigger::kPD] += 1; + } + } else { + lowKstarPairs[CFTrigger::kPD] += 1; + } } } } + for (auto iAntiProton = antiprotons.begin(); iAntiProton != antiprotons.end(); ++iAntiProton) { for (auto iAntiDeuteron = antideuterons.begin(); iAntiDeuteron != antideuterons.end(); ++iAntiDeuteron) { kstar = getkstar(*iAntiProton, *iAntiDeuteron); registry.fill(HIST("pd/fSE_antiparticle"), kstar); if (kstar < ConfKstarLimits->get(static_cast(0), CFTrigger::kPD)) { - lowKstarPairs[CFTrigger::kPD] += 1; + if (ConfDownsample->get("Switch", "aPaD") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "aPaD")) { + registry.fill(HIST("pd/fSE_antiparticle_downsample"), kstar); + lowKstarPairs[CFTrigger::kPD] += 1; + } + } else { + lowKstarPairs[CFTrigger::kPD] += 1; + } } } } @@ -1666,7 +1779,14 @@ struct CFFilter { kstar = getkstar(*iDeuteron, *iLambda); registry.fill(HIST("ld/fSE_particle"), kstar); if (kstar < ConfKstarLimits->get(static_cast(0), CFTrigger::kLD)) { - lowKstarPairs[CFTrigger::kLD] += 1; + if (ConfDownsample->get("Switch", "LD") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "LD")) { + registry.fill(HIST("ld/fSE_particle_downsample"), kstar); + lowKstarPairs[CFTrigger::kLD] += 1; + } + } else { + lowKstarPairs[CFTrigger::kLD] += 1; + } } } } @@ -1675,12 +1795,18 @@ struct CFFilter { kstar = getkstar(*iAntiDeuteron, *iAntiLambda); registry.fill(HIST("ld/fSE_antiparticle"), kstar); if (kstar < ConfKstarLimits->get(static_cast(0), CFTrigger::kLD)) { - lowKstarPairs[CFTrigger::kLD] += 1; + if (ConfDownsample->get("Switch", "aLaD") > 0) { + if (rng->Uniform(0., 1.) < ConfDownsample->get("Factor", "aLaD")) { + registry.fill(HIST("ld/fSE_antiparticle_downsample"), kstar); + lowKstarPairs[CFTrigger::kLD] += 1; + } + } else { + lowKstarPairs[CFTrigger::kLD] += 1; + } } } } } - } // if(isSelectedEvent) // create tags for three body triggers diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index 81db86cbeb1..c2dd7f5174f 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -17,30 +17,34 @@ /// \author Marcel Lesch , TUM /// \author Alexandre Bigot , Strasbourg University /// \author Biao Zhang , CCNU +/// \author Federica Zanone , Heidelberg University +#include // needed for HFFilterHelpers, to be fixed + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/Propagator.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include - -#include "EventFiltering/filterTables.h" -#include "HFFilterHelpers.h" - +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include +#include "EventFiltering/filterTables.h" +#include "EventFiltering/PWGHF/HFFilterHelpers.h" using namespace o2; +using namespace o2::analysis; +using namespace o2::aod::hffilters; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hffilters; -using namespace hf_cuts_single_track; -using namespace hf_cuts_bdt_multiclass; struct HfFilter { // Main struct for HF triggers @@ -51,48 +55,40 @@ struct HfFilter { // Main struct for HF triggers Produces optimisationTreeCollisions; Configurable activateQA{"activateQA", 0, "flag to enable QA histos (0 no QA, 1 basic QA, 2 extended QA, 3 very extended QA)"}; + Configurable applyEventSelection{"applyEventSelection", false, "flag to enable event selection (sel8 + Zvt)"}; // parameters for all triggers - Configurable nsigmaTPCProtonLc{"nsigmaTPCProtonLc", 3., "Maximum value for TPC PID proton Nsigma for Lc candidates"}; - Configurable nsigmaTOFProtonLc{"nsigmaTOFProtonLc", 3., "Maximum value for TOF PID proton Nsigma for Lc candidates"}; - Configurable nsigmaTPCPionKaonDzero{"nsigmaTPCPionKaonDzero", 4., "Maximum value for TPC PID pion/kaon Nsigma for D0 candidates"}; - Configurable nsigmaTOFPionKaonDzero{"nsigmaTOFPionKaonDzero", 4., "Maximum value for TOF PID pion/kaon Nsigma for D0 candidates"}; - Configurable nsigmaTPCKaon3Prong{"nsigmaTPCKaon3Prong", 4., "Maximum value for TPC PID kaon Nsigma for all 3-prongs candidates"}; - Configurable nsigmaTOFKaon3Prong{"nsigmaTOFKaon3Prong", 4., "Maximum value for TOF PID kaon Nsigma for all 3-prongs candidates"}; + // nsigma PID (except for V0 and cascades) + Configurable> nSigmaPidCuts{"nSigmaPidCuts", {cutsNsigma[0], 3, 5, labelsRowsNsigma, labelsColumnsNsigma}, "Nsigma cuts for TPC/TOF PID (except for V0 and cascades)"}; + // min and max pts for tracks and bachelors (except for V0 and cascades) + Configurable> ptCuts{"ptCuts", {cutsPt[0], 2, 4, labelsRowsCutsPt, labelsColumnsCutsPt}, "minimum and maximum pT for bachelor tracks (except for V0 and cascades)"}; // parameters for high-pT triggers - Configurable pTThreshold2Prong{"pTThreshold2Prong", 8., "pT treshold for high pT 2-prong candidates for kHighPt triggers in GeV/c"}; - Configurable pTThreshold3Prong{"pTThreshold3Prong", 8., "pT treshold for high pT 3-prong candidates for kHighPt triggers in GeV/c"}; + Configurable> ptThresholds{"ptThresholds", {cutsHighPtThresholds[0], 1, 2, labelsEmpty, labelsColumnsHighPtThresholds}, "pT treshold for high pT charm hadron candidates for kHighPt triggers in GeV/c"}; // parameters for beauty triggers - Configurable deltaMassBPlus{"deltaMassBPlus", 0.3, "invariant-mass delta with respect to the B+ mass"}; - Configurable deltaMassB0{"deltaMassB0", 0.3, "invariant-mass delta with respect to the B0 mass"}; - Configurable deltaMassBs{"deltaMassBs", 0.3, "invariant-mass delta with respect to the Bs mass"}; - Configurable deltaMassCharmHadronForBeauty{"deltaMassCharmHadronForBeauty", 0.04, "invariant-mass delta for charm"}; - Configurable deltaMassLb{"deltaMassLb", 0.3, "invariant-mass delta with respect to the Lb mass"}; - Configurable deltaMassXib{"deltaMassXib", 0.3, "invariant-mass delta with respect to the Lb mass"}; - Configurable deltaMassDStar{"deltaMassDStar", 0.01, "invariant-mass delta with respect to the D* mass for B0 -> D*pi"}; - Configurable pTMinBeautyBachelor{"pTMinBeautyBachelor", 0.5, "minimum pT for bachelor pion track used to build b-hadron candidates"}; - Configurable pTMinSoftPion{"pTMinSoftPion", 0.1, "minimum pT for soft pion track used to build D* mesons in the b-hadron decay chain"}; + Configurable> deltaMassBeauty{"deltaMassBeauty", {cutsDeltaMassB[0], 1, kNBeautyParticles + 1, labelsEmpty, labelsColumnsDeltaMassB}, "invariant-mass delta with respect to the b-hadron masses in GeV/c2"}; Configurable> pTBinsTrack{"pTBinsTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCAXY pT-dependent cut"}; Configurable> cutsTrackBeauty3Prong{"cutsTrackBeauty3Prong", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for 3-prong beauty candidates"}; Configurable> cutsTrackBeauty4Prong{"cutsTrackBeauty4Prong", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for 4-prong beauty candidates"}; - std::array, 2> cutsSingleTrackBeauty; - static constexpr double cutsTrackDummy[hf_cuts_single_track::nBinsPtTrack][hf_cuts_single_track::nCutVarsTrack] = {{0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}}; - LabeledArray cutsSingleTrackDummy{cutsTrackDummy[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}; // parameters for femto triggers Configurable femtoMaxRelativeMomentum{"femtoMaxRelativeMomentum", 2., "Maximal allowed value for relative momentum between charm-proton pairs in GeV/c"}; - Configurable femtoMinProtonPt{"femtoMinProtonPt", 0.5, "Minimal required transverse momentum for proton in GeV/c"}; - Configurable femtoProtonOnlyTOF{"femtoProtonOnlyTOF", false, "Use only TOF information for proton identification if true"}; - Configurable femtoMaxNsigmaProton{"femtoMaxNsigmaProton", 3., "Maximum value for PID proton Nsigma for femto triggers"}; + Configurable> enableFemtoChannels{"enableFemtoChannels", {activeFemtoChannels[0], 1, 5, labelsEmpty, labelsColumnsFemtoChannels}, "Flags to enable/disable femto channels"}; + Configurable requireCharmMassForFemto{"requireCharmMassForFemto", false, "Flags to enable/disable cut on charm-hadron invariant-mass window for femto"}; + Configurable ptThresholdForFemtoPid{"ptThresholdForFemtoPid", 8., "pT threshold for changing strategy of proton PID in femto triggers"}; + + // double charm + Configurable> enableDoubleCharmChannels{"enableDoubleCharmChannels", {activeDoubleCharmChannels[0], 1, 3, labelsEmpty, labelsColumnsDoubleCharmChannels}, "Flags to enable/disable double charm channels"}; - // parameters for V0 triggers - Configurable minCosPaGamma{"minCosPaGamma", 0.85, "Minimal required cosine of pointing angle for photons"}; - Configurable minCosPaV0{"minCosPaV0", 0.95, "Minimal required cosine of pointing angle for K0S and Lambdas"}; - Configurable maxMassDstarToGamma{"maxMassDstarToGamma", 0.4, "Maximum invariant mass delta for D* -> D gamma"}; - Configurable maxMassDs12{"maxMassDs12", 0.88, "Maximum invariant mass delta for Ds1+ and Ds2*+"}; - Configurable maxMassXicStar{"maxMassXicStar", 1.4, "Maximum invariant mass delta for Xic(3055) and Xic(3080)"}; + // parameters for V0 + charm triggers + Configurable> cutsGammaK0sLambda{"cutsGammaK0sLambda", {cutsV0s[0], 1, 6, labelsEmpty, labelsColumnsV0s}, "Selections for V0s (gamma, K0s, Lambda) for D+V0 triggers"}; + Configurable> maxDeltaMassCharmReso{"maxDeltaMassCharmReso", {cutsMassCharmReso[0], 1, 6, labelsEmpty, labelsColumnsDeltaMasseCharmReso}, "maximum invariant-mass delta for charm hadron resonances in GeV/c2"}; + + // parameters for charm baryons to Xi bachelor + Configurable> cutsXiCascades{"cutsXiCascades", {cutsCascades[0], 1, 7, labelsEmpty, labelsColumnsCascades}, "Selections for cascades (Xi) for Xi+bachelor triggers"}; + Configurable> cutsXiBachelor{"cutsXiBachelor", {cutsCharmBaryons[0], 1, 4, labelsEmpty, labelsColumnsCharmBaryons}, "Selections for charm baryons (Xi+Pi and Xi+Ka)"}; + Configurable> cutsTrackCharmBaryonBachelor{"cutsTrackCharmBaryonBachelor", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for charm-baryon bachelor candidates"}; // parameters for ML application with ONNX Configurable applyML{"applyML", false, "Flag to enable or disable ML application"}; @@ -100,16 +96,12 @@ struct HfFilter { // Main struct for HF triggers Configurable onnxFileD0ToKPiConf{"onnxFileD0ToKPiConf", "XGBoostModel.onnx", "ONNX file for ML model for D0 candidates"}; Configurable> thresholdBDTScoreD0ToKPi{"thresholdBDTScoreD0ToKPi", {hf_cuts_bdt_multiclass::cuts[0], hf_cuts_bdt_multiclass::nBinsPt, hf_cuts_bdt_multiclass::nCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of D0 candidates"}; - Configurable onnxFileDPlusToPiKPiConf{"onnxFileDPlusToPiKPiConf", "", "ONNX file for ML model for D+ candidates"}; Configurable> thresholdBDTScoreDPlusToPiKPi{"thresholdBDTScoreDPlusToPiKPi", {hf_cuts_bdt_multiclass::cuts[0], hf_cuts_bdt_multiclass::nBinsPt, hf_cuts_bdt_multiclass::nCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of D+ candidates"}; - Configurable onnxFileDSToPiKKConf{"onnxFileDSToPiKKConf", "", "ONNX file for ML model for Ds+ candidates"}; Configurable> thresholdBDTScoreDSToPiKK{"thresholdBDTScoreDSToPiKK", {hf_cuts_bdt_multiclass::cuts[0], hf_cuts_bdt_multiclass::nBinsPt, hf_cuts_bdt_multiclass::nCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Ds+ candidates"}; - Configurable onnxFileLcToPiKPConf{"onnxFileLcToPiKPConf", "", "ONNX file for ML model for Lc+ candidates"}; Configurable> thresholdBDTScoreLcToPiKP{"thresholdBDTScoreLcToPiKP", {hf_cuts_bdt_multiclass::cuts[0], hf_cuts_bdt_multiclass::nBinsPt, hf_cuts_bdt_multiclass::nCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Lc+ candidates"}; - Configurable onnxFileXicToPiKPConf{"onnxFileXicToPiKPConf", "", "ONNX file for ML model for Xic+ candidates"}; Configurable> thresholdBDTScoreXicToPiKP{"thresholdBDTScoreXicToPiKP", {hf_cuts_bdt_multiclass::cuts[0], hf_cuts_bdt_multiclass::nBinsPt, hf_cuts_bdt_multiclass::nCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Xic+ candidates"}; @@ -120,8 +112,7 @@ struct HfFilter { // Main struct for HF triggers Configurable mlModelPathCCDB{"mlModelPathCCDB", "Analysis/PWGHF/ML/HFTrigger/", "Path on CCDB"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable ccdbPathTPC{"ccdbPathTPC", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; + int currentRun{0}; // needed to detect if the run changed and trigger update of calibrations etc. // TPC PID calibrations Configurable setTPCCalib{"setTPCCalib", 0, "0 is not use re-calibrations, 1 is compute TPC post-calibrated n-sigmas, 2 is using TPC Spline"}; @@ -131,10 +122,10 @@ struct HfFilter { // Main struct for HF triggers Configurable ccdbBBAntiPion{"ccdbBBAntiPion", "Users/l/lserksny/PIDAntiPion", "Path to the CCDB ocject for antiPion BB param"}; Configurable ccdbBBKaon{"ccdbBBKaon", "Users/l/lserksny/PIDPion", "Path to the CCDB ocject for Kaon BB param"}; Configurable ccdbBBAntiKaon{"ccdbBBAntiKaon", "Users/l/lserksny/PIDAntiPion", "Path to the CCDB ocject for antiKaon BB param"}; + Configurable ccdbPathTPC{"ccdbPathTPC", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the CCDB object"}; // parameter for Optimisation Tree Configurable applyOptimisation{"applyOptimisation", false, "Flag to enable or disable optimisation"}; - int currentRun = 0; // needed to detect if the run changed and trigger update of calibrations etc. // array of ONNX config and BDT thresholds std::array onnxFiles; @@ -148,20 +139,15 @@ struct HfFilter { // Main struct for HF triggers std::array, kNCharmParticles> hCharmHighPt{}; std::array, kNCharmParticles> hCharmProtonKstarDistr{}; std::array, kNBeautyParticles> hMassVsPtB{}; - std::array, kNCharmParticles + 6> hMassVsPtC{}; // +6 for resonances (D*+, D*0, Ds*+, Ds1+, Ds2*+, Xic*) + std::array, kNCharmParticles + 8> hMassVsPtC{}; // +6 for resonances (D*+, D*0, Ds*+, Ds1+, Ds2*+, Xic*) +2 for charm baryons (Xi+Pi, Xi+Ka) std::shared_ptr hProtonTPCPID, hProtonTOFPID; std::array, kNCharmParticles> hBDTScoreBkg{}; std::array, kNCharmParticles> hBDTScorePrompt{}; std::array, kNCharmParticles> hBDTScoreNonPrompt{}; std::array, kNV0> hArmPod{}; std::shared_ptr hV0Selected; + std::shared_ptr hMassXi; - // Histograms of TPC calibration for pion and proton - std::array hMapPion = {nullptr, nullptr}; - std::array hMapProton = {nullptr, nullptr}; - std::array, 2> hBBProton{}; - std::array, 2> hBBPion{}; - std::array, 2> hBBKaon{}; // ONNX std::array, kNCharmParticles> sessionML = {nullptr, nullptr, nullptr, nullptr, nullptr}; std::array>, kNCharmParticles> inputShapesML{}; @@ -175,11 +161,32 @@ struct HfFilter { // Main struct for HF triggers std::array dataTypeML{}; // material correction for track propagation + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - void init(o2::framework::InitContext&) + // helper object + HfFilterHelper helper; + + void init(InitContext&) { - cutsSingleTrackBeauty = {cutsTrackBeauty3Prong, cutsTrackBeauty4Prong}; + helper.setPtBinsSingleTracks(pTBinsTrack); + helper.setPtLimitsBeautyBachelor(ptCuts->get(0u, 0u), ptCuts->get(1u, 0u)); + helper.setPtLimitsDstarSoftPion(ptCuts->get(0u, 1u), ptCuts->get(1u, 1u)); + helper.setPtLimitsProtonForFemto(ptCuts->get(0u, 2u), ptCuts->get(1u, 2u)); + helper.setPtLimitsCharmBaryonBachelor(ptCuts->get(0u, 3u), ptCuts->get(1u, 3u)); + helper.setCutsSingleTrackBeauty(cutsTrackBeauty3Prong, cutsTrackBeauty4Prong); + helper.setCutsSingleTrackCharmBaryonBachelor(cutsTrackCharmBaryonBachelor); + helper.setPtThresholdPidStrategyForFemto(ptThresholdForFemtoPid); + helper.setNsigmaProtonCutsForFemto(std::array{nSigmaPidCuts->get(0u, 3u), nSigmaPidCuts->get(1u, 3u), nSigmaPidCuts->get(2u, 3u)}); + helper.setNsigmaProtonCutsForCharmBaryons(nSigmaPidCuts->get(0u, 0u), nSigmaPidCuts->get(1u, 0u)); + helper.setNsigmaPionKaonCutsForDzero(nSigmaPidCuts->get(0u, 1u), nSigmaPidCuts->get(1u, 1u)); + helper.setNsigmaKaonCutsFor3Prongs(nSigmaPidCuts->get(0u, 2u), nSigmaPidCuts->get(1u, 2u)); + helper.setDeltaMassCharmHadForBeauty(deltaMassBeauty->get(0u, kNBeautyParticles)); + helper.setV0Selections(cutsGammaK0sLambda->get(0u, 0u), cutsGammaK0sLambda->get(0u, 1u), cutsGammaK0sLambda->get(0u, 2u), cutsGammaK0sLambda->get(0u, 3u), cutsGammaK0sLambda->get(0u, 4u), cutsGammaK0sLambda->get(0u, 5u)); + helper.setXiSelections(cutsXiCascades->get(0u, 0u), cutsXiCascades->get(0u, 1u), cutsXiCascades->get(0u, 2u), cutsXiCascades->get(0u, 3u), cutsXiCascades->get(0u, 4u), cutsXiCascades->get(0u, 5u), cutsXiCascades->get(0u, 6u)); + helper.setNsigmaPiCutsForCharmBaryonBachelor(nSigmaPidCuts->get(0u, 4u), nSigmaPidCuts->get(1u, 4u)); + helper.setTpcPidCalibrationOption(setTPCCalib); hProcessedEvents = registry.add("fProcessedEvents", "HF - event filtered;;counts", HistType::kTH1F, {{kNtriggersHF + 2, -0.5, kNtriggersHF + 1.5}}); for (auto iBin = 0; iBin < kNtriggersHF + 2; ++iBin) { @@ -199,23 +206,28 @@ struct HfFilter { // Main struct for HF triggers hBDTScoreNonPrompt[iCharmPart] = registry.add(Form("f%sBDTScoreNonPromptDistr", charmParticleNames[iCharmPart].data()), Form("BDT nonprompt score distribution for %s;BDT nonprompt score;counts", charmParticleNames[iCharmPart].data()), HistType::kTH1F, {bdtAxis}); } } - hMassVsPtC[kNCharmParticles] = registry.add("fMassVsPtDStarPlus", "#it{M} vs. #it{p}_{T} distribution of triggered DStarPlus candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles]}); - hMassVsPtC[kNCharmParticles + 1] = registry.add("fMassVsPtDStarZero", "#it{M} vs. #it{p}_{T} distribution of triggered DStarZero candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 1]}); - hMassVsPtC[kNCharmParticles + 2] = registry.add("fMassVsPtDStarS", "#it{M} vs. #it{p}_{T} distribution of triggered DStarS candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 2]}); - hMassVsPtC[kNCharmParticles + 3] = registry.add("fMassVsPtDs1Plus", "#it{M} vs. #it{p}_{T} distribution of triggered Ds1Plus candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 3]}); - hMassVsPtC[kNCharmParticles + 4] = registry.add("fMassVsPtDs2StarPlus", "#it{M} vs. #it{p}_{T} distribution of triggered Ds2StarPlus candidates;#it{p}_{T} (GeV/#Delta#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 4]}); - hMassVsPtC[kNCharmParticles + 5] = registry.add("fMassVsPtXicStar", "#it{M} vs. #it{p}_{T} distribution of triggered XicStar candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 5]}); + // charm resonances + hMassVsPtC[kNCharmParticles] = registry.add("fMassVsPtDStarPlus", "#Delta#it{M} vs. #it{p}_{T} distribution of triggered DStarPlus candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles]}); + hMassVsPtC[kNCharmParticles + 1] = registry.add("fMassVsPtDStarZero", "#Delta#it{M} vs. #it{p}_{T} distribution of triggered DStarZero candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 1]}); + hMassVsPtC[kNCharmParticles + 2] = registry.add("fMassVsPtDStarS", "#Delta#it{M} vs. #it{p}_{T} distribution of triggered DStarS candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 2]}); + hMassVsPtC[kNCharmParticles + 3] = registry.add("fMassVsPtDs1Plus", "#Delta#it{M} vs. #it{p}_{T} distribution of triggered Ds1Plus candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 3]}); + hMassVsPtC[kNCharmParticles + 4] = registry.add("fMassVsPtDs2StarPlus", "#Delta#it{M} vs. #it{p}_{T} distribution of triggered Ds2StarPlus candidates;#it{p}_{T} (GeV/#Delta#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 4]}); + hMassVsPtC[kNCharmParticles + 5] = registry.add("fMassVsPtXicStar", "#Delta#it{M} vs. #it{p}_{T} distribution of triggered XicStar candidates;#it{p}_{T} (GeV/#it{c});#Delta#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 5]}); + // charm baryons to LF cascades + hMassVsPtC[kNCharmParticles + 6] = registry.add("fMassVsPtCharmBaryonToXiPi", "#it{M} vs. #it{p}_{T} distribution of triggered #Xi+#pi candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 6]}); + hMassVsPtC[kNCharmParticles + 7] = registry.add("fMassVsPtCharmBaryonToXiKa", "#it{M} vs. #it{p}_{T} distribution of triggered #Xi+K candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", HistType::kTH2F, {ptAxis, massAxisC[kNCharmParticles + 7]}); for (int iBeautyPart{0}; iBeautyPart < kNBeautyParticles; ++iBeautyPart) { hMassVsPtB[iBeautyPart] = registry.add(Form("fMassVsPt%s", beautyParticleNames[iBeautyPart].data()), Form("#it{M} vs. #it{p}_{T} distribution of triggered %s candidates;#it{p}_{T} (GeV/#it{c});#it{M} (GeV/#it{c}^{2});counts", beautyParticleNames[iBeautyPart].data()), HistType::kTH2F, {ptAxis, massAxisB[iBeautyPart]}); } for (int iV0{kPhoton}; iV0 < kNV0; ++iV0) { hArmPod[iV0] = registry.add(Form("fArmPod%s", v0Names[iV0].data()), Form("Armenteros Podolanski plot for selected %s;#it{#alpha};#it{q}_{T} (GeV/#it{c})", v0Labels[iV0].data()), HistType::kTH2F, {alphaAxis, qtAxis}); } + hMassXi = registry.add("fMassXi", "#it{M} distribution of #Xi candidates;#it{M} (GeV/#it{c}^{2});counts", HistType::kTH1F, {{100, 1.28f, 1.36f}}); if (activateQA > 1) { hProtonTPCPID = registry.add("fProtonTPCPID", "#it{N}_{#sigma}^{TPC} vs. #it{p} for selected protons;#it{p} (GeV/#it{c});#it{N}_{#sigma}^{TPC}", HistType::kTH2F, {pAxis, nSigmaAxis}); hProtonTOFPID = registry.add("fProtonTOFPID", "#it{N}_{#sigma}^{TOF} vs. #it{p} for selected protons;#it{p} (GeV/#it{c});#it{N}_{#sigma}^{TOF}", HistType::kTH2F, {pAxis, nSigmaAxis}); - hV0Selected = registry.add("fV0Selected", "Selections for V0s;;counts", HistType::kTH2F, {{7, -0.5, 6.5}, {kNV0, -0.5, kNV0 - 0.5}}); + hV0Selected = registry.add("fV0Selected", "Selections for V0s;;counts", HistType::kTH2F, {{10, -0.5, 9.5}, {kNV0, -0.5, kNV0 - 0.5}}); for (int iV0{kPhoton}; iV0 < kNV0; ++iV0) { hV0Selected->GetYaxis()->SetBinLabel(iV0 + 1, v0Labels[iV0].data()); @@ -225,8 +237,11 @@ struct HfFilter { // Main struct for HF triggers hV0Selected->GetXaxis()->SetBinLabel(3, "rej. radius"); hV0Selected->GetXaxis()->SetBinLabel(4, "rej. cos(#theta_{P})"); hV0Selected->GetXaxis()->SetBinLabel(5, "rej. AP / Mass"); - hV0Selected->GetXaxis()->SetBinLabel(6, "rej. pair cut"); - hV0Selected->GetXaxis()->SetBinLabel(7, "selected"); + hV0Selected->GetXaxis()->SetBinLabel(6, "rej. DCA V0"); + hV0Selected->GetXaxis()->SetBinLabel(7, "rej. DCA V0 daughters"); + hV0Selected->GetXaxis()->SetBinLabel(8, "rej. pair cut"); + hV0Selected->GetXaxis()->SetBinLabel(9, "rej. PID"); + hV0Selected->GetXaxis()->SetBinLabel(10, "selected"); } } @@ -235,6 +250,7 @@ struct HfFilter { // Main struct for HF triggers ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); ccdbApi.init(url); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); thresholdBDTScores = { thresholdBDTScoreD0ToKPi, @@ -254,7 +270,7 @@ struct HfFilter { // Main struct for HF triggers if (applyML && (!loadModelsFromCCDB || timestampCCDB != 0)) { for (auto iCharmPart{0}; iCharmPart < kNCharmParticles; ++iCharmPart) { if (onnxFiles[iCharmPart] != "") { - sessionML[iCharmPart].reset(InitONNXSession(onnxFiles[iCharmPart], charmParticleNames[iCharmPart], envML[iCharmPart], sessionOptions[iCharmPart], inputShapesML[iCharmPart], dataTypeML[iCharmPart], loadModelsFromCCDB, ccdbApi, mlModelPathCCDB.value, timestampCCDB)); + sessionML[iCharmPart].reset(helper.initONNXSession(onnxFiles[iCharmPart], charmParticleNames[iCharmPart], envML[iCharmPart], sessionOptions[iCharmPart], inputShapesML[iCharmPart], dataTypeML[iCharmPart], loadModelsFromCCDB, ccdbApi, mlModelPathCCDB.value, timestampCCDB)); } } } @@ -265,24 +281,33 @@ struct HfFilter { // Main struct for HF triggers } using BigTracksMCPID = soa::Join; - - Filter trackFilter = requireGlobalTrackWoDCAInFilter(); - using BigTracksPID = soa::Filtered>; + using BigTracksPID = soa::Join; + using CollsWithEvSel = soa::Join; Preslice trackIndicesPerCollision = aod::track_association::collisionId; Preslice v0sPerCollision = aod::v0data::collisionId; Preslice hf2ProngPerCollision = aod::track_association::collisionId; Preslice hf3ProngPerCollision = aod::track_association::collisionId; + Preslice cascPerCollision = aod::cascdata::collisionId; - void process(aod::Collisions const& collisions, + void process(CollsWithEvSel const& collisions, aod::BCsWithTimestamps const&, aod::V0Datas const& theV0s, + aod::V0sLinked const& v0Links, + aod::CascDatas const& cascades, aod::Hf2Prongs const& cand2Prongs, aod::Hf3Prongs const& cand3Prongs, aod::TrackAssoc const& trackIndices, BigTracksPID const& tracks) { for (const auto& collision : collisions) { + + bool keepEvent[kNtriggersHF]{false}; + if (applyEventSelection && (!collision.sel8() || std::fabs(collision.posZ()) > 11.f)) { // safety margin for Zvtx + tags(keepEvent[kHighPt2P], keepEvent[kHighPt3P], keepEvent[kBeauty3P], keepEvent[kBeauty4P], keepEvent[kFemto2P], keepEvent[kFemto3P], keepEvent[kDoubleCharm2P], keepEvent[kDoubleCharm3P], keepEvent[kDoubleCharmMix], keepEvent[kV0Charm2P], keepEvent[kV0Charm3P], keepEvent[kCharmBarToXiBach]); + continue; + } + auto thisCollId = collision.globalIndex(); if (applyOptimisation) { @@ -294,39 +319,21 @@ struct HfFilter { // Main struct for HF triggers if (applyML && (loadModelsFromCCDB && timestampCCDB == 0) && !sessionML[kD0]) { for (auto iCharmPart{0}; iCharmPart < kNCharmParticles; ++iCharmPart) { if (onnxFiles[iCharmPart] != "") { - sessionML[iCharmPart].reset(InitONNXSession(onnxFiles[iCharmPart], charmParticleNames[iCharmPart], envML[iCharmPart], sessionOptions[iCharmPart], inputShapesML[iCharmPart], dataTypeML[iCharmPart], loadModelsFromCCDB, ccdbApi, mlModelPathCCDB.value, bc.timestamp())); + sessionML[iCharmPart].reset(helper.initONNXSession(onnxFiles[iCharmPart], charmParticleNames[iCharmPart], envML[iCharmPart], sessionOptions[iCharmPart], inputShapesML[iCharmPart], dataTypeML[iCharmPart], loadModelsFromCCDB, ccdbApi, mlModelPathCCDB.value, bc.timestamp())); } } } // needed for track propagation if (currentRun != bc.runNumber()) { - o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(ccdbPathGrpMag, bc.timestamp()); + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", bc.timestamp()); o2::base::Propagator::initFieldFromGRP(grpo); // needed for TPC PID postcalibrations if (setTPCCalib == 1) { - auto calibList = ccdb->getForTimeStamp(ccdbPathTPC.value, bc.timestamp()); - if (!calibList) { - LOG(fatal) << "Can not find the TPC Post Calibration object!"; - } - - hMapPion[0] = reinterpret_cast(calibList->FindObject("mean_map_pion")); - hMapPion[1] = reinterpret_cast(calibList->FindObject("sigma_map_pion")); - hMapProton[0] = reinterpret_cast(calibList->FindObject("mean_map_proton")); - hMapProton[1] = reinterpret_cast(calibList->FindObject("sigma_map_proton")); - - if (!hMapPion[0] || !hMapPion[1] || !hMapProton[0] || !hMapProton[1]) { - LOG(fatal) << "Can not find histograms!"; - } + helper.setTpcRecalibMaps(ccdb, bc, ccdbPathTPC); } else if (setTPCCalib > 1) { - - hBBProton[0] = setValuesBB(ccdbApi, bc, ccdbBBProton); - hBBProton[1] = setValuesBB(ccdbApi, bc, ccdbBBAntiProton); - hBBPion[0] = setValuesBB(ccdbApi, bc, ccdbBBPion); - hBBPion[1] = setValuesBB(ccdbApi, bc, ccdbBBAntiPion); - hBBKaon[0] = setValuesBB(ccdbApi, bc, ccdbBBKaon); - hBBKaon[1] = setValuesBB(ccdbApi, bc, ccdbBBAntiKaon); + helper.setValuesBB(ccdbApi, bc, std::array{ccdbBBPion.value, ccdbBBAntiPion.value, ccdbBBKaon.value, ccdbBBAntiKaon.value, ccdbBBProton.value, ccdbBBAntiProton.value}); } currentRun = bc.runNumber(); @@ -334,10 +341,6 @@ struct HfFilter { // Main struct for HF triggers hProcessedEvents->Fill(0); - // collision process loop - bool keepEvent[kNtriggersHF]{false}; - // - std::vector> indicesDau2Prong{}; auto cand2ProngsThisColl = cand2Prongs.sliceBy(hf2ProngPerCollision, thisCollId); @@ -349,7 +352,7 @@ struct HfFilter { // Main struct for HF triggers auto trackPos = cand2Prong.prong0_as(); // positive daughter auto trackNeg = cand2Prong.prong1_as(); // negative daughter - auto preselD0 = isDzeroPreselected(trackPos, trackNeg, nsigmaTPCPionKaonDzero, nsigmaTOFPionKaonDzero, setTPCCalib, hMapPion, hBBPion, hBBKaon); + auto preselD0 = helper.isDzeroPreselected(trackPos, trackNeg); if (!preselD0) { continue; } @@ -383,14 +386,14 @@ struct HfFilter { // Main struct for HF triggers std::vector inputFeaturesDoD0{trackParPos.getPt(), dcaPos[0], dcaPos[1], trackParNeg.getPt(), dcaNeg[0], dcaNeg[1]}; if (dataTypeML[kD0] == 1) { - auto scores = PredictONNX(inputFeaturesD0, sessionML[kD0], inputShapesML[kD0]); - tagBDT = isBDTSelected(scores, thresholdBDTScores[kD0]); + auto scores = helper.predictONNX(inputFeaturesD0, sessionML[kD0], inputShapesML[kD0]); + tagBDT = helper.isBDTSelected(scores, thresholdBDTScores[kD0]); for (int iScore{0}; iScore < 3; ++iScore) { scoresToFill[iScore] = scores[iScore]; } } else if (dataTypeML[kD0] == 11) { - auto scores = PredictONNX(inputFeaturesDoD0, sessionML[kD0], inputShapesML[kD0]); - tagBDT = isBDTSelected(scores, thresholdBDTScores[kD0]); + auto scores = helper.predictONNX(inputFeaturesDoD0, sessionML[kD0], inputShapesML[kD0]); + tagBDT = helper.isBDTSelected(scores, thresholdBDTScores[kD0]); for (int iScore{0}; iScore < 3; ++iScore) { scoresToFill[iScore] = scores[iScore]; } @@ -414,15 +417,14 @@ struct HfFilter { // Main struct for HF triggers auto pVec2Prong = RecoDecay::pVec(pVecPos, pVecNeg); auto pt2Prong = RecoDecay::pt(pVec2Prong); - auto phi2Prong = RecoDecay::phi(pVec2Prong); if (applyOptimisation) { optimisationTreeCharm(thisCollId, pdg::Code::kD0, pt2Prong, scoresToFill[0], scoresToFill[1], scoresToFill[2]); } - auto selD0 = isSelectedD0InMassRange(pVecPos, pVecNeg, pt2Prong, phi2Prong, preselD0, deltaMassCharmHadronForBeauty, activateQA, hMassVsPtC[kD0]); + auto selD0 = helper.isSelectedD0InMassRange(pVecPos, pVecNeg, pt2Prong, preselD0, activateQA, hMassVsPtC[kD0]); - if (pt2Prong >= pTThreshold2Prong) { + if (pt2Prong >= ptThresholds->get(0u, 0u)) { keepEvent[kHighPt2P] = true; if (activateQA) { hCharmHighPt[kD0]->Fill(pt2Prong); @@ -434,8 +436,8 @@ struct HfFilter { // Main struct for HF triggers } // end multi-charm selection // compute masses already here, needed both for B0 --> D* (--> D0 Pi) Pi and Ds1 --> D* (--> D0 Pi) K0S - auto massD0Cand = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{massPi, massK}); - auto massD0BarCand = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{massK, massPi}); + auto massD0Cand = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{massPi, massKa}); + auto massD0BarCand = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{massKa, massPi}); auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); for (const auto& trackId : trackIdsThisCollision) { // start loop over tracks @@ -454,12 +456,12 @@ struct HfFilter { // Main struct for HF triggers } if (!keepEvent[kBeauty3P] && isBeautyTagged) { - int isTrackSelected = isSelectedTrackForSoftPionOrBeauty(trackParThird, dcaThird, pTMinSoftPion, pTMinBeautyBachelor, pTBinsTrack, cutsSingleTrackBeauty[kBeauty3P - 2]); + auto isTrackSelected = helper.isSelectedTrackForSoftPionOrBeauty(track, trackParThird, dcaThird, kBeauty3P); if (isTrackSelected && ((TESTBIT(selD0, 0) && track.sign() < 0) || (TESTBIT(selD0, 1) && track.sign() > 0))) { auto massCand = RecoDecay::m(std::array{pVec2Prong, pVecThird}, std::array{massD0, massPi}); auto pVecBeauty3Prong = RecoDecay::pVec(pVec2Prong, pVecThird); auto ptCand = RecoDecay::pt(pVecBeauty3Prong); - if (isTrackSelected == kRegular && std::fabs(massCand - massBPlus) <= deltaMassBPlus) { + if (TESTBIT(isTrackSelected, kForBeauty) && std::fabs(massCand - massBPlus) <= deltaMassBeauty->get(0u, 0u)) { keepEvent[kBeauty3P] = true; // fill optimisation tree for D0 if (applyOptimisation) { @@ -468,18 +470,18 @@ struct HfFilter { // Main struct for HF triggers if (activateQA) { hMassVsPtB[kBplus]->Fill(ptCand, massCand); } - } else { - std::array massDausD0{massPi, massK}; + } else if (TESTBIT(isTrackSelected, kSoftPionForBeauty)) { + std::array massDausD0{massPi, massKa}; auto massD0dau = massD0Cand; if (track.sign() < 0) { - massDausD0[0] = massK; + massDausD0[0] = massKa; massDausD0[1] = massPi; massD0dau = massD0BarCand; } auto massDstarCand = RecoDecay::m(std::array{pVecPos, pVecNeg, pVecThird}, std::array{massDausD0[0], massDausD0[1], massPi}); auto massDiffDstar = massDstarCand - massD0dau; - if (std::fabs(massDiffDstar - (massDStar - massD0)) <= deltaMassDStar) { // additional check for B0->D*pi polarization studies + if (std::fabs(massDiffDstar - (massDStar - massD0)) <= maxDeltaMassCharmReso->get(0u, 0u)) { // additional check for B0->D*pi polarization studies if (activateQA) { hMassVsPtC[kNCharmParticles]->Fill(ptCand, massDiffDstar); } @@ -496,9 +498,10 @@ struct HfFilter { // Main struct for HF triggers getPxPyPz(trackParFourth, pVecFourth); } - if (track.sign() * trackB.sign() < 0 && isSelectedTrackForSoftPionOrBeauty(trackParFourth, dcaFourth, pTMinSoftPion, pTMinBeautyBachelor, pTBinsTrack, cutsSingleTrackBeauty[kBeauty3P - 2]) == kRegular) { + auto isTrackFourthSelected = helper.isSelectedTrackForSoftPionOrBeauty(trackB, trackParFourth, dcaFourth, kBeauty3P); + if (track.sign() * trackB.sign() < 0 && TESTBIT(isTrackFourthSelected, kForBeauty)) { auto massCandB0 = RecoDecay::m(std::array{pVecBeauty3Prong, pVecFourth}, std::array{massDStar, massPi}); - if (std::fabs(massCandB0 - massB0) <= deltaMassB0) { + if (std::fabs(massCandB0 - massB0) <= deltaMassBeauty->get(0u, 2u)) { keepEvent[kBeauty3P] = true; // fill optimisation tree for D0 if (applyOptimisation) { @@ -518,10 +521,10 @@ struct HfFilter { // Main struct for HF triggers } // end beauty selection // 2-prong femto - if (!keepEvent[kFemto2P] && isCharmTagged && track.collisionId() == thisCollId) { - bool isProton = isSelectedProton4Femto(track, trackParThird, femtoMinProtonPt, femtoMaxNsigmaProton, femtoProtonOnlyTOF, setTPCCalib, hMapProton, hBBProton, activateQA, hProtonTPCPID, hProtonTOFPID); + if (!keepEvent[kFemto2P] && enableFemtoChannels->get(0u, 0u) && isCharmTagged && track.collisionId() == thisCollId && (TESTBIT(selD0, 0) || TESTBIT(selD0, 1) || !requireCharmMassForFemto)) { + bool isProton = helper.isSelectedProton4Femto(track, trackParThird, activateQA, hProtonTPCPID, hProtonTOFPID); if (isProton) { - float relativeMomentum = computeRelativeMomentum(pVecThird, pVec2Prong, massD0); + float relativeMomentum = helper.computeRelativeMomentum(pVecThird, pVec2Prong, massD0); if (applyOptimisation) { optimisationTreeFemto(thisCollId, pdg::Code::kD0, pt2Prong, scoresToFill[0], scoresToFill[1], scoresToFill[2], relativeMomentum, track.tpcNSigmaPr(), track.tofNSigmaPr()); } @@ -538,25 +541,31 @@ struct HfFilter { // Main struct for HF triggers // 2-prong with Gamma (conversion photon) auto v0sThisCollision = theV0s.sliceBy(v0sPerCollision, thisCollId); - for (auto& v0 : v0sThisCollision) { - if (!keepEvent[kV0Charm2P] && (isCharmTagged || isBeautyTagged) && (TESTBIT(selD0, 0) || (TESTBIT(selD0, 1)))) { - float v0CosinePa = v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); - auto selV0 = isSelectedV0(v0, minCosPaGamma, minCosPaV0, v0CosinePa, activateQA, hV0Selected, hArmPod); + for (const auto& v0 : v0sThisCollision) { + if (!keepEvent[kV0Charm2P] && (isCharmTagged || isBeautyTagged) && (TESTBIT(selD0, 0) || TESTBIT(selD0, 1))) { + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); + auto selV0 = helper.isSelectedV0(v0, std::array{posTrack, negTrack}, collision, activateQA, hV0Selected, hArmPod); if (selV0) { + // propagate to PV + gpu::gpustd::array dcaInfo; std::array pVecV0 = {v0.px(), v0.py(), v0.pz()}; + auto trackParV0 = o2::track::TrackPar(std::array{v0.x(), v0.y(), v0.z()}, pVecV0, 0, true); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParV0, 2.f, matCorr, &dcaInfo); + getPxPyPz(trackParV0, pVecV0); if (TESTBIT(selV0, kPhoton)) { float massDStarCand{-1.}, massDStarBarCand{999.}; float massDiffDstar{-1.}, massDiffDstarBar{999.}; if (TESTBIT(selD0, 0)) { - massDStarCand = RecoDecay::m(std::array{pVecPos, pVecNeg, pVecV0}, std::array{massPi, massK, massGamma}); + massDStarCand = RecoDecay::m(std::array{pVecPos, pVecNeg, pVecV0}, std::array{massPi, massKa, massGamma}); massDiffDstar = massDStarCand - massD0Cand; } if (TESTBIT(selD0, 1)) { - massDStarBarCand = RecoDecay::m(std::array{pVecPos, pVecNeg, pVecV0}, std::array{massK, massPi, massGamma}); + massDStarBarCand = RecoDecay::m(std::array{pVecPos, pVecNeg, pVecV0}, std::array{massKa, massPi, massGamma}); massDiffDstarBar = massDStarBarCand - massD0BarCand; } - bool isGoodDstar = (massDiffDstar < maxMassDstarToGamma); - bool isGoodDstarBar = (massDiffDstarBar < maxMassDstarToGamma); + bool isGoodDstar = (massDiffDstar < maxDeltaMassCharmReso->get(0u, 1u)); + bool isGoodDstarBar = (massDiffDstarBar < maxDeltaMassCharmReso->get(0u, 1u)); if (isGoodDstar || isGoodDstarBar) { keepEvent[kV0Charm2P] = true; @@ -589,12 +598,12 @@ struct HfFilter { // Main struct for HF triggers getPxPyPz(trackParBachelor, pVecBachelor); } - int isTrackSelected = isSelectedTrackForSoftPionOrBeauty(trackParBachelor, dcaBachelor, pTMinSoftPion, pTMinBeautyBachelor, pTBinsTrack, cutsSingleTrackDummy); - if (isTrackSelected && ((TESTBIT(selD0, 0) && trackBachelor.sign() < 0) || (TESTBIT(selD0, 1) && trackBachelor.sign() > 0))) { - std::array massDausD0{massPi, massK}; + int isTrackSelected = helper.isSelectedTrackForSoftPionOrBeauty(trackBachelor, trackParBachelor, dcaBachelor, -1); + if (TESTBIT(isTrackSelected, kSoftPion) && ((TESTBIT(selD0, 0) && trackBachelor.sign() < 0) || (TESTBIT(selD0, 1) && trackBachelor.sign() > 0))) { + std::array massDausD0{massPi, massKa}; auto massD0dau = massD0Cand; if (trackBachelor.sign() < 0) { - massDausD0[0] = massK; + massDausD0[0] = massKa; massDausD0[1] = massPi; massD0dau = massD0BarCand; } @@ -602,13 +611,13 @@ struct HfFilter { // Main struct for HF triggers auto massDiffDstar = massDStarCand - massD0dau; auto pVecDStarCand = RecoDecay::pVec(pVec2Prong, pVecBachelor); auto ptDStarCand = RecoDecay::pt(pVecDStarCand); - if (std::fabs(massDiffDstar - (massDStar - massD0)) <= deltaMassDStar) { + if (std::fabs(massDiffDstar - (massDStar - massD0)) <= maxDeltaMassCharmReso->get(0u, 0u)) { if (activateQA) { hMassVsPtC[kNCharmParticles]->Fill(ptDStarCand, massDiffDstar); } auto massDStarK0S = RecoDecay::m(std::array{pVecPos, pVecNeg, pVecBachelor, pVecV0}, std::array{massDausD0[0], massDausD0[1], massPi, massK0S}); auto massDiffDsReso = massDStarK0S - massDStarCand; - if (massDiffDsReso < maxMassDs12) { + if (massDiffDsReso < maxDeltaMassCharmReso->get(0u, 3u)) { if (activateQA) { auto pVecReso2Prong = RecoDecay::pVec(pVecDStarCand, pVecV0); auto ptCand = RecoDecay::pt(pVecReso2Prong); @@ -622,7 +631,7 @@ struct HfFilter { // Main struct for HF triggers } } } - } // end gamma selection + } // end V0 selection } // end loop over 2-prong candidates @@ -665,13 +674,13 @@ struct HfFilter { // Main struct for HF triggers } if (is3Prong[0]) { // D+ preselections - is3Prong[0] = isDplusPreselected(trackSecond, nsigmaTPCKaon3Prong, nsigmaTOFKaon3Prong, setTPCCalib, hMapPion, hBBKaon); + is3Prong[0] = helper.isDplusPreselected(trackSecond); } if (is3Prong[1]) { // Ds preselections - is3Prong[1] = isDsPreselected(pVecFirst, pVecThird, pVecSecond, trackSecond, nsigmaTPCKaon3Prong, nsigmaTOFKaon3Prong, setTPCCalib, hMapPion, hBBKaon); + is3Prong[1] = helper.isDsPreselected(pVecFirst, pVecThird, pVecSecond, trackSecond); } if (is3Prong[2] || is3Prong[3]) { // charm baryon preselections - auto presel = isCharmBaryonPreselected(trackFirst, trackThird, trackSecond, nsigmaTPCProtonLc, nsigmaTOFProtonLc, nsigmaTPCKaon3Prong, nsigmaTOFKaon3Prong, setTPCCalib, hMapProton, hBBProton, hMapPion, hBBKaon); + auto presel = helper.isCharmBaryonPreselected(trackFirst, trackThird, trackSecond); if (is3Prong[2]) { is3Prong[2] = presel; } @@ -702,14 +711,14 @@ struct HfFilter { // Main struct for HF triggers int tagBDT = 0; if (dataTypeML[iCharmPart + 1] == 1) { - auto scores = PredictONNX(inputFeatures, sessionML[iCharmPart + 1], inputShapesML[iCharmPart + 1]); - tagBDT = isBDTSelected(scores, thresholdBDTScores[iCharmPart + 1]); + auto scores = helper.predictONNX(inputFeatures, sessionML[iCharmPart + 1], inputShapesML[iCharmPart + 1]); + tagBDT = helper.isBDTSelected(scores, thresholdBDTScores[iCharmPart + 1]); for (int iScore{0}; iScore < 3; ++iScore) { scoresToFill[iCharmPart][iScore] = scores[iScore]; } } else if (dataTypeML[iCharmPart + 1] == 11) { - auto scores = PredictONNX(inputFeaturesD, sessionML[iCharmPart + 1], inputShapesML[iCharmPart + 1]); - tagBDT = isBDTSelected(scores, thresholdBDTScores[iCharmPart + 1]); + auto scores = helper.predictONNX(inputFeaturesD, sessionML[iCharmPart + 1], inputShapesML[iCharmPart + 1]); + tagBDT = helper.isBDTSelected(scores, thresholdBDTScores[iCharmPart + 1]); for (int iScore{0}; iScore < 3; ++iScore) { scoresToFill[iCharmPart][iScore] = scores[iScore]; } @@ -738,36 +747,35 @@ struct HfFilter { // Main struct for HF triggers auto pVec3Prong = RecoDecay::pVec(pVecFirst, pVecSecond, pVecThird); auto pt3Prong = RecoDecay::pt(pVec3Prong); - auto phi3Prong = RecoDecay::phi(pVec3Prong); float sign3Prong = -1 * trackFirst.sign() * trackSecond.sign() * trackThird.sign(); std::array is3ProngInMass{0}; if (is3Prong[0]) { - is3ProngInMass[0] = isSelectedDplusInMassRange(pVecFirst, pVecThird, pVecSecond, pt3Prong, phi3Prong, deltaMassCharmHadronForBeauty, activateQA, hMassVsPtC[kDplus]); + is3ProngInMass[0] = helper.isSelectedDplusInMassRange(pVecFirst, pVecThird, pVecSecond, pt3Prong, activateQA, hMassVsPtC[kDplus]); if (applyOptimisation) { optimisationTreeCharm(thisCollId, pdg::Code::kDPlus, pt3Prong, scoresToFill[0][0], scoresToFill[0][1], scoresToFill[0][2]); } } if (is3Prong[1]) { - is3ProngInMass[1] = isSelectedDsInMassRange(pVecFirst, pVecThird, pVecSecond, pt3Prong, phi3Prong, is3Prong[1], deltaMassCharmHadronForBeauty, activateQA, hMassVsPtC[kDs]); + is3ProngInMass[1] = helper.isSelectedDsInMassRange(pVecFirst, pVecThird, pVecSecond, pt3Prong, is3Prong[1], activateQA, hMassVsPtC[kDs]); if (applyOptimisation) { optimisationTreeCharm(thisCollId, pdg::Code::kDS, pt3Prong, scoresToFill[1][0], scoresToFill[1][1], scoresToFill[1][2]); } } if (is3Prong[2]) { - is3ProngInMass[2] = isSelectedLcInMassRange(pVecFirst, pVecThird, pVecSecond, pt3Prong, phi3Prong, is3Prong[2], deltaMassCharmHadronForBeauty, activateQA, hMassVsPtC[kLc]); + is3ProngInMass[2] = helper.isSelectedLcInMassRange(pVecFirst, pVecThird, pVecSecond, pt3Prong, is3Prong[2], activateQA, hMassVsPtC[kLc]); if (applyOptimisation) { optimisationTreeCharm(thisCollId, pdg::Code::kLambdaCPlus, pt3Prong, scoresToFill[2][0], scoresToFill[2][1], scoresToFill[2][2]); } } if (is3Prong[3]) { - is3ProngInMass[3] = isSelectedXicInMassRange(pVecFirst, pVecThird, pVecSecond, pt3Prong, phi3Prong, is3Prong[3], deltaMassCharmHadronForBeauty, activateQA, hMassVsPtC[kXic]); + is3ProngInMass[3] = helper.isSelectedXicInMassRange(pVecFirst, pVecThird, pVecSecond, pt3Prong, is3Prong[3], activateQA, hMassVsPtC[kXic]); if (applyOptimisation) { optimisationTreeCharm(thisCollId, pdg::Code::kXiCPlus, pt3Prong, scoresToFill[3][0], scoresToFill[3][1], scoresToFill[3][2]); } } - if (pt3Prong >= pTThreshold3Prong) { + if (pt3Prong >= ptThresholds->get(0u, 1u)) { keepEvent[kHighPt3P] = true; if (activateQA) { for (auto iCharmPart{1}; iCharmPart < kNCharmParticles; ++iCharmPart) { @@ -798,8 +806,9 @@ struct HfFilter { // Main struct for HF triggers float massCharmHypos[kNBeautyParticles - 2] = {massDPlus, massDs, massLc, massXic}; float massBeautyHypos[kNBeautyParticles - 2] = {massB0, massBs, massLb, massXib}; - float deltaMassHypos[kNBeautyParticles - 2] = {deltaMassB0, deltaMassBs, deltaMassLb, deltaMassXib}; - if (track.sign() * sign3Prong < 0 && isSelectedTrackForSoftPionOrBeauty(trackParFourth, dcaFourth, pTMinBeautyBachelor, pTMinBeautyBachelor, pTBinsTrack, cutsSingleTrackBeauty[kBeauty4P - 2]) == kRegular) { + float deltaMassHypos[kNBeautyParticles - 2] = {deltaMassBeauty->get(0u, 1u), deltaMassBeauty->get(0u, 3u), deltaMassBeauty->get(0u, 4u), deltaMassBeauty->get(0u, 5u)}; + auto isTrackSelected = helper.isSelectedTrackForSoftPionOrBeauty(track, trackParFourth, dcaFourth, kBeauty4P); + if (track.sign() * sign3Prong < 0 && TESTBIT(isTrackSelected, kForBeauty)) { for (int iHypo{0}; iHypo < kNBeautyParticles - 2 && !keepEvent[kBeauty4P]; ++iHypo) { if (isBeautyTagged[iHypo] && (TESTBIT(is3ProngInMass[iHypo], 0) || TESTBIT(is3ProngInMass[iHypo], 1))) { auto massCandB = RecoDecay::m(std::array{pVec3Prong, pVecFourth}, std::array{massCharmHypos[iHypo], massPi}); @@ -819,11 +828,11 @@ struct HfFilter { // Main struct for HF triggers } // end beauty selection // 3-prong femto - bool isProton = isSelectedProton4Femto(track, trackParFourth, femtoMinProtonPt, femtoMaxNsigmaProton, femtoProtonOnlyTOF, setTPCCalib, hMapProton, hBBProton, activateQA, hProtonTPCPID, hProtonTOFPID); + bool isProton = helper.isSelectedProton4Femto(track, trackParFourth, activateQA, hProtonTPCPID, hProtonTOFPID); if (isProton && track.collisionId() == thisCollId) { for (int iHypo{0}; iHypo < kNCharmParticles - 1 && !keepEvent[kFemto3P]; ++iHypo) { - if (isCharmTagged[iHypo]) { - float relativeMomentum = computeRelativeMomentum(pVecFourth, pVec3Prong, massCharmHypos[iHypo]); + if (isCharmTagged[iHypo] && enableFemtoChannels->get(0u, iHypo + 1) && (TESTBIT(is3ProngInMass[iHypo], 0) || TESTBIT(is3ProngInMass[iHypo], 1) || !requireCharmMassForFemto)) { + float relativeMomentum = helper.computeRelativeMomentum(pVecFourth, pVec3Prong, massCharmHypos[iHypo]); if (applyOptimisation) { optimisationTreeFemto(thisCollId, charmParticleID[iHypo], pt3Prong, scoresToFill[iHypo][0], scoresToFill[iHypo][1], scoresToFill[iHypo][2], relativeMomentum, track.tpcNSigmaPr(), track.tofNSigmaPr()); } @@ -844,28 +853,35 @@ struct HfFilter { // Main struct for HF triggers bool isGoodDsToKKPi = (isCharmTagged[kDs - 1] || isBeautyTagged[kDs - 1]) && TESTBIT(is3ProngInMass[kDs - 1], 0); bool isGoodDsToPiKK = (isCharmTagged[kDs - 1] || isBeautyTagged[kDs - 1]) && TESTBIT(is3ProngInMass[kDs - 1], 1); bool isGoodDPlus = (isCharmTagged[kDplus - 1] || isBeautyTagged[kDplus - 1]) && is3ProngInMass[kDplus - 1]; - auto massDPlusCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massK, massPi}); - auto massDsKKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massK, massK, massPi}); - auto massDsPiKK = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massK, massK}); - for (auto& v0 : v0sThisCollision) { + auto massDPlusCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massKa, massPi}); + auto massDsKKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massKa, massKa, massPi}); + auto massDsPiKK = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massKa, massKa}); + for (const auto& v0 : v0sThisCollision) { if (!keepEvent[kV0Charm3P] && (isGoodDsToKKPi || isGoodDsToPiKK || isGoodDPlus)) { - float v0CosinePa = v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); - auto v0Sel = isSelectedV0(v0, minCosPaGamma, minCosPaV0, v0CosinePa, activateQA, hV0Selected, hArmPod); - if (v0Sel > 0) { + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); + auto selV0 = helper.isSelectedV0(v0, std::array{posTrack, negTrack}, collision, activateQA, hV0Selected, hArmPod); + if (selV0 > 0) { + // propagate to PV + gpu::gpustd::array dcaInfo; std::array pVecV0 = {v0.px(), v0.py(), v0.pz()}; - if (!keepEvent[kV0Charm3P] && (isGoodDsToKKPi || isGoodDsToPiKK) && TESTBIT(v0Sel, kPhoton)) { + auto trackParV0 = o2::track::TrackPar(std::array{v0.x(), v0.y(), v0.z()}, pVecV0, 0, true); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParV0, 2.f, matCorr, &dcaInfo); + getPxPyPz(trackParV0, pVecV0); + + if (!keepEvent[kV0Charm3P] && (isGoodDsToKKPi || isGoodDsToPiKK) && TESTBIT(selV0, kPhoton)) { float massDsStarToKKPiCand{-1.}, massDsStarToPiKKCand{999.}; float massDiffDsStarToKKPi{-1.}, massDiffDsStarToPiKK{999.}; if (isGoodDsToKKPi) { - massDsStarToKKPiCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecV0}, std::array{massK, massK, massPi, massGamma}); + massDsStarToKKPiCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecV0}, std::array{massKa, massKa, massPi, massGamma}); massDiffDsStarToKKPi = massDsStarToKKPiCand - massDsKKPi; } if (isGoodDsToPiKK) { - massDsStarToPiKKCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecV0}, std::array{massPi, massK, massK, massGamma}); + massDsStarToPiKKCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecV0}, std::array{massPi, massKa, massKa, massGamma}); massDiffDsStarToPiKK = massDsStarToPiKKCand - massDsPiKK; } - bool isGoodDsStarToKKPi = (massDiffDsStarToKKPi < maxMassDstarToGamma); - bool isGoodDsStarToPiKK = (massDiffDsStarToPiKK < maxMassDstarToGamma); + bool isGoodDsStarToKKPi = (massDiffDsStarToKKPi < maxDeltaMassCharmReso->get(0u, 1u)); + bool isGoodDsStarToPiKK = (massDiffDsStarToPiKK < maxDeltaMassCharmReso->get(0u, 1u)); if (isGoodDsStarToKKPi || isGoodDsStarToPiKK) { keepEvent[kV0Charm3P] = true; @@ -882,10 +898,10 @@ struct HfFilter { // Main struct for HF triggers } } if (!keepEvent[kV0Charm3P] && isGoodDPlus) { - if (TESTBIT(v0Sel, kK0S)) { // Ds2* - auto massDsStarCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecV0}, std::array{massPi, massK, massPi, massK0S}); + if (TESTBIT(selV0, kK0S)) { // Ds2* + auto massDsStarCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecV0}, std::array{massPi, massKa, massPi, massK0S}); auto massDiffDsStar = massDsStarCand - massDPlusCand; - if (massDiffDsStar < maxMassDs12) { + if (massDiffDsStar < maxDeltaMassCharmReso->get(0u, 4u)) { if (activateQA) { auto pVecReso3Prong = RecoDecay::pVec(pVec3Prong, pVecV0); auto ptCand = RecoDecay::pt(pVecReso3Prong); @@ -894,10 +910,10 @@ struct HfFilter { // Main struct for HF triggers keepEvent[kV0Charm3P] = true; } } - if ((TESTBIT(v0Sel, kLambda) && sign3Prong > 0) || (TESTBIT(v0Sel, kAntiLambda) && sign3Prong < 0)) { // Xic(3055) and Xic(3080) - auto massXicStarCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecV0}, std::array{massPi, massK, massPi, massLambda}); - auto massDiffXicStar = massXicStarCand; - if (massDiffXicStar < maxMassXicStar) { + if ((TESTBIT(selV0, kLambda) && sign3Prong > 0) || (TESTBIT(selV0, kAntiLambda) && sign3Prong < 0)) { // Xic(3055) and Xic(3080) + auto massXicStarCand = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird, pVecV0}, std::array{massPi, massKa, massPi, massLambda}); + auto massDiffXicStar = massXicStarCand - massDPlusCand; + if (massDiffXicStar < maxDeltaMassCharmReso->get(0u, 5u)) { if (activateQA) { auto pVecReso3Prong = RecoDecay::pVec(pVec3Prong, pVecV0); auto ptCand = RecoDecay::pt(pVecReso3Prong); @@ -913,27 +929,102 @@ struct HfFilter { // Main struct for HF triggers } // end loop over 3-prong candidates - auto n2Prongs = computeNumberOfCandidates(indicesDau2Prong); - auto n3Prongs = computeNumberOfCandidates(indicesDau3Prong); + if (!keepEvent[kCharmBarToXiBach]) { + auto cascThisColl = cascades.sliceBy(cascPerCollision, thisCollId); + for (const auto& casc : cascThisColl) { + if (!casc.v0_as().has_v0Data()) { // check that V0 data are stored + continue; + } + auto bachelorCasc = casc.bachelor_as(); + auto v0 = casc.v0_as(); + auto v0Element = v0.v0Data_as(); + auto v0DauPos = v0Element.posTrack_as(); + auto v0DauNeg = v0Element.negTrack_as(); + if (!helper.isSelectedCascade(casc, v0Element, std::array{bachelorCasc, v0DauPos, v0DauNeg}, collision)) { + continue; + } + if (activateQA) { + hMassXi->Fill(casc.mXi()); + } + + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + for (const auto& trackId : trackIdsThisCollision) { // start loop over tracks + auto track = trackId.track_as(); + + // ask for opposite sign daughters (omegac daughters) + if (track.sign() * bachelorCasc.sign() >= 0) { + continue; + } + + // check if track is one of the Xi daughters + if (track.globalIndex() == bachelorCasc.globalIndex() || track.globalIndex() == v0DauPos.globalIndex() || track.globalIndex() == v0DauNeg.globalIndex()) { + continue; + } + + // propagate to PV + gpu::gpustd::array dcaInfo; + std::array pVecCascade = {casc.px(), casc.py(), casc.pz()}; + auto trackParCasc = o2::track::TrackPar(std::array{casc.x(), casc.y(), casc.z()}, pVecCascade, bachelorCasc.sign(), true); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCasc, 2.f, matCorr, &dcaInfo); + getPxPyPz(trackParCasc, pVecCascade); + + auto trackParBachelor = getTrackPar(track); + std::array pVecBachelor = {track.px(), track.py(), track.pz()}; + if (track.collisionId() != thisCollId) { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParBachelor, 2.f, noMatCorr, &dcaInfo); + getPxPyPz(trackParBachelor, pVecBachelor); + } + + auto isSelBachelor = helper.isSelectedBachelorForCharmBaryon(track, dcaInfo); + if (isSelBachelor == kRejected) { + continue; + } + + auto ptCharmBaryon = RecoDecay::pt(RecoDecay::pVec(pVecCascade, pVecBachelor)); + + if (!keepEvent[kCharmBarToXiBach] && TESTBIT(isSelBachelor, kPionForCharmBaryon)) { + auto massXiPi = RecoDecay::m(std::array{pVecCascade, pVecBachelor}, std::array{massXi, massPi}); + if (ptCharmBaryon > cutsXiBachelor->get(0u, 0u) && massXiPi >= cutsXiBachelor->get(0u, 2u) && massXiPi <= 2.8f) { + keepEvent[kCharmBarToXiBach] = true; + if (activateQA) { + hMassVsPtC[kNCharmParticles + 6]->Fill(ptCharmBaryon, massXiPi); + } + } + } + if (!keepEvent[kCharmBarToXiBach] && TESTBIT(isSelBachelor, kKaonForCharmBaryon)) { + auto massXiKa = RecoDecay::m(std::array{pVecCascade, pVecBachelor}, std::array{massXi, massKa}); + if (ptCharmBaryon > cutsXiBachelor->get(0u, 1u) && massXiKa >= cutsXiBachelor->get(0u, 3u) && massXiKa <= 2.8f) { + keepEvent[kCharmBarToXiBach] = true; + if (activateQA) { + hMassVsPtC[kNCharmParticles + 7]->Fill(ptCharmBaryon, massXiKa); + } + } + } + } + } + } + + auto n2Prongs = helper.computeNumberOfCandidates(indicesDau2Prong); + auto n3Prongs = helper.computeNumberOfCandidates(indicesDau3Prong); indicesDau2Prong.insert(indicesDau2Prong.end(), indicesDau3Prong.begin(), indicesDau3Prong.end()); - auto n23Prongs = computeNumberOfCandidates(indicesDau2Prong); + auto n23Prongs = helper.computeNumberOfCandidates(indicesDau2Prong); if (activateQA) { hN2ProngCharmCand->Fill(n2Prongs); hN3ProngCharmCand->Fill(n3Prongs); } - if (n2Prongs > 1) { + if (n2Prongs > 1 && enableDoubleCharmChannels->get(0u, 0u)) { keepEvent[kDoubleCharm2P] = true; } - if (n3Prongs > 1) { + if (n3Prongs > 1 && enableDoubleCharmChannels->get(0u, 1u)) { keepEvent[kDoubleCharm3P] = true; } - if (n23Prongs > 1) { + if (n23Prongs > 1 && enableDoubleCharmChannels->get(0u, 2u)) { keepEvent[kDoubleCharmMix] = true; } - tags(keepEvent[kHighPt2P], keepEvent[kHighPt3P], keepEvent[kBeauty3P], keepEvent[kBeauty4P], keepEvent[kFemto2P], keepEvent[kFemto3P], keepEvent[kDoubleCharm2P], keepEvent[kDoubleCharm3P], keepEvent[kDoubleCharmMix], keepEvent[kV0Charm2P], keepEvent[kV0Charm3P]); + tags(keepEvent[kHighPt2P], keepEvent[kHighPt3P], keepEvent[kBeauty3P], keepEvent[kBeauty4P], keepEvent[kFemto2P], keepEvent[kFemto3P], keepEvent[kDoubleCharm2P], keepEvent[kDoubleCharm3P], keepEvent[kDoubleCharmMix], keepEvent[kV0Charm2P], keepEvent[kV0Charm3P], keepEvent[kCharmBarToXiBach]); if (!std::accumulate(keepEvent, keepEvent + kNtriggersHF, 0)) { hProcessedEvents->Fill(1); diff --git a/EventFiltering/PWGHF/HFFilterHelpers.h b/EventFiltering/PWGHF/HFFilterHelpers.h index eb08b1a2d09..dcd9523c2a3 100644 --- a/EventFiltering/PWGHF/HFFilterHelpers.h +++ b/EventFiltering/PWGHF/HFFilterHelpers.h @@ -17,41 +17,39 @@ /// \author Marcel Lesch , TUM /// \author Alexandre Bigot , Strasbourg University /// \author Biao Zhang , CCNU +/// \author Federica Zanone , Heidelberg University #ifndef EVENTFILTERING_PWGHF_HFFILTERHELPERS_H_ #define EVENTFILTERING_PWGHF_HFFILTERHELPERS_H_ -#include "Framework/DataTypes.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/RecoDecay.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include +#include #include -#include #include #include #include -#include +#include +#include +#include "Math/GenVector/Boost.h" #include "Math/Vector3D.h" #include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -// CCDB #include "CCDB/CcdbApi.h" +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataTypes.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/O2DatabasePDGPlugin.h" -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::constants::math; +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" namespace o2::aod { @@ -71,6 +69,7 @@ enum HfTriggers { kDoubleCharmMix, kV0Charm2P, kV0Charm3P, + kCharmBarToXiBach, kNtriggersHF }; @@ -93,17 +92,23 @@ enum beautyParticles { kNBeautyParticles }; -enum beautyTrackSelection { +enum bachelorTrackSelection { kRejected = 0, kSoftPion, - kRegular + kForBeauty, + kSoftPionForBeauty, + kPionForCharmBaryon, + kKaonForCharmBaryon }; enum PIDSpecies { kEl = 0, - kKa, kPi, - kPr + kAntiPi, + kKa, + kAntiKa, + kPr, + kAntiPr }; enum V0Species { @@ -117,8 +122,8 @@ enum V0Species { static const std::array charmParticleNames{"D0", "Dplus", "Ds", "Lc", "Xic"}; static const std::array beautyParticleNames{"Bplus", "B0toDStar", "B0", "Bs", "Lb", "Xib"}; static const std::array pdgCodesCharm{421, 411, 431, 4122, 4232}; -static const std::array eventTitles = {"all", "rejected", "w/ high-#it{p}_{T} 2p charm", "w/ high-#it{p}_{T} 3p charm", "w/ 3p beauty", "w/ 4p beauty", "w/ 2p femto", "w/ 3p femto", "w/ 2p double charm", "w/ 3p double charm", "w/ 2p and 3p double charm", "w/ 2p soft gamma", "w/ 3p soft gamma"}; -static const std::array hfTriggerNames{"kHighPt2P", "kHighPt3P", "kBeauty3P", "kBeauty4P", "kFemto2P", "kFemto3P", "kDoubleCharm2P", "kDoubleCharm3P", "kDoubleCharmMix", "kV0Charm2P", "kV0Charm3P"}; +static const std::array eventTitles = {"all", "rejected", "w/ high-#it{p}_{T} 2p charm", "w/ high-#it{p}_{T} 3p charm", "w/ 3p beauty", "w/ 4p beauty", "w/ 2p femto", "w/ 3p femto", "w/ 2p double charm", "w/ 3p double charm", "w/ 2p and 3p double charm", "w/ 2p + V0", "w/ 3p + V0", "w/ charm baryon"}; +static const std::array hfTriggerNames{"kHighPt2P", "kHighPt3P", "kBeauty3P", "kBeauty4P", "kFemto2P", "kFemto3P", "kDoubleCharm2P", "kDoubleCharm3P", "kDoubleCharmMix", "kV0Charm2P", "kV0Charm3P", "kCharmBarToXiBach"}; static const std::array v0Labels{"#gamma", "K_{S}^{0}", "#Lambda", "#bar{#Lambda}"}; static const std::array v0Names{"Photon", "K0S", "Lambda", "AntiLambda"}; @@ -129,92 +134,298 @@ static const std::tuple pdgCharmDaughters{ std::array{2212, -321, 211}, // Lc std::array{2212, -321, 211}}; // Xic -static const float massPi = RecoDecay::getMassPDG(211); -static const float massK = RecoDecay::getMassPDG(321); -static const float massProton = RecoDecay::getMassPDG(2212); -static const float massPhi = RecoDecay::getMassPDG(333); -static const float massD0 = RecoDecay::getMassPDG(421); -static const float massDPlus = RecoDecay::getMassPDG(411); -static const float massDs = RecoDecay::getMassPDG(431); -static const float massLc = RecoDecay::getMassPDG(4122); -static const float massXic = RecoDecay::getMassPDG(4232); -static const float massDStar = RecoDecay::getMassPDG(413); -static const float massBPlus = RecoDecay::getMassPDG(511); -static const float massB0 = RecoDecay::getMassPDG(521); -static const float massBs = RecoDecay::getMassPDG(531); -static const float massLb = RecoDecay::getMassPDG(5122); -static const float massXib = RecoDecay::getMassPDG(5232); -static const float massGamma = RecoDecay::getMassPDG(22); -static const float massK0S = RecoDecay::getMassPDG(310); -static const float massLambda = RecoDecay::getMassPDG(3122); - -static const AxisSpec ptAxis{50, 0.f, 50.f}; -static const AxisSpec pAxis{50, 0.f, 10.f}; -static const AxisSpec kstarAxis{100, 0.f, 1.f}; -static const AxisSpec etaAxis{30, -1.5f, 1.5f}; -static const AxisSpec nSigmaAxis{100, -10.f, 10.f}; -static const AxisSpec alphaAxis{100, -1.f, 1.f}; -static const AxisSpec qtAxis{100, 0.f, 0.25f}; -static const AxisSpec bdtAxis{100, 0.f, 1.f}; -static const AxisSpec phiAxis{36, 0., TwoPI}; -static const std::array massAxisC = {AxisSpec{100, 1.65f, 2.05f}, AxisSpec{100, 1.65f, 2.05f}, AxisSpec{100, 1.75f, 2.15f}, AxisSpec{100, 2.05f, 2.45f}, AxisSpec{100, 2.25f, 2.65f}, AxisSpec{100, 0.139f, 0.159f}, AxisSpec{100, 0.f, 0.25f}, AxisSpec{100, 0.f, 0.25f}, AxisSpec{100, 0.48f, 0.88f}, AxisSpec{100, 0.48f, 0.88f}, AxisSpec{100, 1.1f, 1.4f}}; -static const std::array massAxisB = {AxisSpec{240, 4.8f, 6.0f}, AxisSpec{240, 4.8f, 6.0f}, AxisSpec{240, 4.8f, 6.0f}, AxisSpec{240, 4.8f, 6.0f}, AxisSpec{240, 5.0f, 6.2f}, AxisSpec{240, 5.0f, 6.2f}}; - -/// load the TPC spline from the CCDB -/// \param ccdbApi is Api for CCDB -/// \param bunchCrossing is the timestamp of bunchcrossing for the run number -/// \param ccdbPath is the path on CCDB -/// \return a vector include parameters for BetheBloch formula -std::vector setValuesBB(o2::ccdb::CcdbApi& ccdbApi, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string ccdbPath) +constexpr float massPi = o2::analysis::pdg::MassPiPlus; +constexpr float massKa = o2::analysis::pdg::MassKPlus; +constexpr float massProton = o2::analysis::pdg::MassProton; +constexpr float massGamma = o2::analysis::pdg::MassGamma; +constexpr float massK0S = o2::analysis::pdg::MassK0Short; +constexpr float massLambda = o2::analysis::pdg::MassLambda0; +constexpr float massXi = o2::analysis::pdg::MassXiMinus; +constexpr float massPhi = o2::analysis::pdg::MassPhi; +constexpr float massD0 = o2::analysis::pdg::MassD0; +constexpr float massDPlus = o2::analysis::pdg::MassDPlus; +constexpr float massDs = o2::analysis::pdg::MassDS; +constexpr float massLc = o2::analysis::pdg::MassLambdaCPlus; +constexpr float massXic = o2::analysis::pdg::MassXiCPlus; +constexpr float massDStar = o2::analysis::pdg::MassDStar; +constexpr float massBPlus = o2::analysis::pdg::MassBPlus; +constexpr float massB0 = o2::analysis::pdg::MassB0; +constexpr float massBs = o2::analysis::pdg::MassBS; +constexpr float massLb = o2::analysis::pdg::MassLambdaB0; +constexpr float massXib = o2::analysis::pdg::MassXiB0; + +static const o2::framework::AxisSpec ptAxis{50, 0.f, 50.f}; +static const o2::framework::AxisSpec pAxis{50, 0.f, 10.f}; +static const o2::framework::AxisSpec kstarAxis{100, 0.f, 1.f}; +static const o2::framework::AxisSpec etaAxis{30, -1.5f, 1.5f}; +static const o2::framework::AxisSpec nSigmaAxis{100, -10.f, 10.f}; +static const o2::framework::AxisSpec alphaAxis{100, -1.f, 1.f}; +static const o2::framework::AxisSpec qtAxis{100, 0.f, 0.25f}; +static const o2::framework::AxisSpec bdtAxis{100, 0.f, 1.f}; +static const o2::framework::AxisSpec phiAxis{36, 0., o2::constants::math::TwoPI}; +static const std::array massAxisC = {o2::framework::AxisSpec{100, 1.65f, 2.05f}, o2::framework::AxisSpec{100, 1.65f, 2.05f}, o2::framework::AxisSpec{100, 1.75f, 2.15f}, o2::framework::AxisSpec{100, 2.05f, 2.45f}, o2::framework::AxisSpec{100, 2.25f, 2.65f}, o2::framework::AxisSpec{100, 0.139f, 0.159f}, o2::framework::AxisSpec{100, 0.f, 0.25f}, o2::framework::AxisSpec{100, 0.f, 0.25f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{100, 1.1f, 1.4f}, o2::framework::AxisSpec{100, 2.3f, 2.9f}, o2::framework::AxisSpec{100, 2.3f, 2.9f}}; +static const std::array massAxisB = {o2::framework::AxisSpec{240, 4.8f, 6.0f}, o2::framework::AxisSpec{240, 4.8f, 6.0f}, o2::framework::AxisSpec{240, 4.8f, 6.0f}, o2::framework::AxisSpec{240, 4.8f, 6.0f}, o2::framework::AxisSpec{240, 5.0f, 6.2f}, o2::framework::AxisSpec{240, 5.0f, 6.2f}}; + +// default values for configurables +// channels to trigger on for femto +constexpr int activeFemtoChannels[1][5] = {{1, 1, 1, 1, 0}}; // pD0, pD+, pDs, pLc, pXic +static const std::vector labelsColumnsFemtoChannels = {"protonDZero", "protonDPlus", "protonDs", "protonLc", "protonXic"}; + +// min and max pT for all tracks combined (except for V0 and cascades) +constexpr float cutsPt[2][4] = {{1., 0.1, 0.8, 0.5}, + {100000., 2., 5., 100000.}}; // beauty, D*, femto, charm baryons +static const std::vector labelsColumnsCutsPt = {"Beauty", "DstarPlus", "Femto", "CharmBaryon"}; +static const std::vector labelsRowsCutsPt = {"Minimum", "Maximum"}; + +// PID cuts +constexpr float cutsNsigma[3][5] = {{3., 3., 3., 5., 3.}, // TPC proton from Lc, pi/K from D0, K from 3-prong, femto, pi/K from Xic/Omegac + {3., 3., 3., 2.5, 3.}, // TOF proton from Lc, pi/K from D0, K from 3-prong, femto, pi/K from Xic/Omegac + {999., 999., 999., 2.5, 999.}}; // Sum in quadrature of TPC and TOF (used only for femto for pT < 4 GeV/c) +static const std::vector labelsColumnsNsigma = {"PrFromLc", "PiKaFromDZero", "KaFrom3Prong", "Femto", "PiKaFromCharmBaryon"}; +static const std::vector labelsRowsNsigma = {"TPC", "TOF", "Comb"}; + +// high pt +constexpr float cutsHighPtThresholds[1][2] = {{8., 8.}}; // 2-prongs, 3-prongs +static const std::vector labelsColumnsHighPtThresholds = {"2Prongs", "3Prongs"}; + +// beauty +constexpr float cutsDeltaMassB[1][kNBeautyParticles + 1] = {{0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.04}}; // B+, B0, B0toDstar, Bs, Lb, Xib, charm daughter +static const std::vector labelsColumnsDeltaMassB = {"Bplus", "BZero", "BZeroToDstar", "Bs", "Lb", "Xib", "CharmDau"}; + +// double charm +constexpr int activeDoubleCharmChannels[1][3] = {{1, 1, 1}}; // kDoubleCharm2P, kDoubleCharm3P, kDoubleCharmMix +static const std::vector labelsColumnsDoubleCharmChannels = {"DoubleCharm2Prong", "DoubleCharm3Prong", "DoubleCharmMix"}; + +// charm resonances +constexpr float cutsMassCharmReso[1][6] = {{0.01, 0.3, 0.3, 0.88, 0.88, 1.4}}; // D*+, D*0, Ds*0, Ds1+, Ds2*+, Xic* +static const std::vector labelsColumnsDeltaMasseCharmReso = {"DstarPlus", "DstarZero", "DsStarZero", "Ds1Plus", "Ds2StarPlus", "XicStar"}; +// V0s for charm resonances +constexpr float cutsV0s[1][6] = {{0.85, 0.97, 0.5, 4., 0.02, 0.01}}; // cosPaGamma, cosPaK0sLambda, radiusK0sLambda, nSigmaPrLambda, deltaMassK0S, deltaMassLambda +static const std::vector labelsColumnsV0s = {"CosPaGamma", "CosPaK0sLambda", "RadiusK0sLambda", "NSigmaPrLambda", "DeltaMassK0s", "DeltaMassLambda"}; + +// cascades for Xi + bachelor triggers +constexpr float cutsCascades[1][7] = {{0.2, 0.01, 0.01, 0.99, 0.99, 0.3, 3.}}; // ptXiBachelor, deltaMassXi, deltaMassLambda, cosPaXi, cosPaLambda, DCAxyXi, nSigmaPid +static const std::vector labelsColumnsCascades = {"PtBachelor", "DeltaMassXi", "DeltaMassLambda", "CosPAXi", "CosPaLambda", "DCAxyXi", "NsigmaPid"}; +constexpr float cutsCharmBaryons[1][4] = {{3., 3., 2.35, 2.60}}; // MinPtXiPi, MinPtXiKa, MinMassXiPi, MinMassXiKa +static const std::vector labelsColumnsCharmBaryons = {"MinPtXiPi", "MinPtXiKa", "MinMassXiPi", "MinMassXiKa"}; + +// dummy array +static const std::vector labelsEmpty{}; +static constexpr double cutsTrackDummy[o2::analysis::hf_cuts_single_track::nBinsPtTrack][o2::analysis::hf_cuts_single_track::nCutVarsTrack] = {{0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}, {0., 10.}}; +o2::framework::LabeledArray cutsSingleTrackDummy{cutsTrackDummy[0], o2::analysis::hf_cuts_single_track::nBinsPtTrack, o2::analysis::hf_cuts_single_track::nCutVarsTrack, o2::analysis::hf_cuts_single_track::labelsPtTrack, o2::analysis::hf_cuts_single_track::labelsCutVarTrack}; + +// Main helper class + +class HfFilterHelper { - map metadata; - auto hSpline = ccdbApi.retrieveFromTFileAny(ccdbPath, metadata, bunchCrossing.timestamp()); - - if (!hSpline) { - LOG(fatal) << "File from CCDB in path " << ccdbPath << " was not found for run " << bunchCrossing.runNumber(); - } - - TAxis* axis = hSpline->GetXaxis(); - std::vector parsBB{static_cast(hSpline->GetBinContent(axis->FindBin("bb1"))), - static_cast(hSpline->GetBinContent(axis->FindBin("bb2"))), - static_cast(hSpline->GetBinContent(axis->FindBin("bb3"))), - static_cast(hSpline->GetBinContent(axis->FindBin("bb4"))), - static_cast(hSpline->GetBinContent(axis->FindBin("bb5"))), - static_cast(hSpline->GetBinContent(axis->FindBin("Resolution")))}; - return parsBB; -} - -/// Update the TPC PID baesd on the spline of particles -/// \param track is a track parameter -/// \param mMassPar is the mass of particles -/// \param paraBetheBloch vector for the parameters of BetheBloch formula -/// \return updated nsigma value for TPC PID -template -double getTPCSplineCalib(const T& track, const float mMassPar, const std::vector paraBetheBloch) -{ - auto bgScaling = 1 / mMassPar; - double expBethe = tpc::BetheBlochAleph(static_cast(track.tpcInnerParam() * bgScaling), paraBetheBloch[0], paraBetheBloch[1], paraBetheBloch[2], paraBetheBloch[3], paraBetheBloch[4]); - double expSigma = expBethe * paraBetheBloch[5]; - return static_cast((track.tpcSignal() - expBethe) / expSigma); -} + public: + /// Default constructor + HfFilterHelper() = default; + + // setters + void setPtBinsSingleTracks(std::vector ptBins) { mPtBinsTracks = ptBins; } + void setCutsSingleTrackBeauty(o2::framework::LabeledArray cutsSingleTrack3P, o2::framework::LabeledArray cutsSingleTrack4P) + { + mCutsSingleTrackBeauty3Prong = cutsSingleTrack3P; + mCutsSingleTrackBeauty4Prong = cutsSingleTrack4P; + } + void setPtLimitsProtonForFemto(float minPt, float maxPt) + { + mPtMinProtonForFemto = minPt; + mPtMaxProtonForFemto = maxPt; + } + void setPtLimitsBeautyBachelor(float minPt, float maxPt) + { + mPtMinBeautyBachelor = minPt; + mPtMaxBeautyBachelor = maxPt; + } + void setPtLimitsDstarSoftPion(float minPt, float maxPt) + { + mPtMinSoftPionForDstar = minPt; + mPtMaxSoftPionForDstar = maxPt; + } + void setPtLimitsCharmBaryonBachelor(float minPt, float maxPt) + { + mPtMinCharmBaryonBachelor = minPt; + mPtMaxCharmBaryonBachelor = maxPt; + } + + void setPtThresholdPidStrategyForFemto(float ptThreshold) { mPtThresholdPidStrategyForFemto = ptThreshold; } + void setNsigmaProtonCutsForFemto(std::array nSigmaCuts) { mNSigmaPrCutsForFemto = nSigmaCuts; } + void setNsigmaProtonCutsForCharmBaryons(float nSigmaTpc, float nSigmaTof) + { + mNSigmaTpcPrCutForCharmBaryons = nSigmaTpc; + mNSigmaTofPrCutForCharmBaryons = nSigmaTof; + } + void setNsigmaKaonCutsFor3Prongs(float nSigmaTpc, float nSigmaTof) + { + mNSigmaTpcKaCutFor3Prongs = nSigmaTpc; + mNSigmaTofKaCutFor3Prongs = nSigmaTof; + } + void setNsigmaPionKaonCutsForDzero(float nSigmaTpc, float nSigmaTof) + { + mNSigmaTpcPiKaCutForDzero = nSigmaTpc; + mNSigmaTofPiKaCutForDzero = nSigmaTof; + } + void setDeltaMassCharmHadForBeauty(float delta) { mDeltaMassCharmHadForBeauty = delta; } + void setV0Selections(float minGammaCosPa, float minK0sLambdaCosPa, float minK0sLambdaRadius, float nSigmaPrFromLambda, float deltaMassK0s, float deltaMassLambda) + { + mMinGammaCosinePa = minGammaCosPa; + mMinK0sLambdaCosinePa = minK0sLambdaCosPa; + mMinK0sLambdaRadius = minK0sLambdaRadius; + mMaxNsigmaPrForLambda = nSigmaPrFromLambda; + mDeltaMassK0s = deltaMassK0s; + mDeltaMassLambda = deltaMassLambda; + } + void setXiSelections(float minPtXiBachelor, float deltaMassXi, float deltaMassLambda, float cosPaXi, float cosPaLambdaFromXi, float maxDcaxyXi, float nSigma) + { + mMinPtXiBachelor = minPtXiBachelor; + mDeltaMassXi = deltaMassXi; + mDeltaMassLambdaFromXi = deltaMassLambda; + mCosPaXi = cosPaXi; + mCosPaLambdaFromXi = cosPaLambdaFromXi; + mMaxDcaXyXi = maxDcaxyXi; + mMaxNsigmaXiDau = nSigma; + } + void setCutsSingleTrackCharmBaryonBachelor(o2::framework::LabeledArray cutsSingleTrack) { mCutsSingleTrackCharmBaryonBachelor = cutsSingleTrack; } + void setNsigmaPiCutsForCharmBaryonBachelor(float nSigmaTpc, float nSigmaTof) + { + mNSigmaTpcPiCharmBaryonBachelor = nSigmaTpc; + mNSigmaTofPiCharmBaryonBachelor = nSigmaTof; + } + + void setTpcPidCalibrationOption(int opt) { mTpcPidCalibrationOption = opt; } + + // helper functions for selections + template + int8_t isSelectedTrackForSoftPionOrBeauty(const T track, const T1& trackPar, const T2& dca, const int& whichTrigger); + template + bool isSelectedProton4Femto(const T1& track, const T2& trackPar, const int& activateQA, H2 hProtonTPCPID, H2 hProtonTOFPID); + template + int8_t isDzeroPreselected(const T& trackPos, const T& trackNeg); + template + int8_t isDplusPreselected(const T& trackOppositeCharge); + template + int8_t isDsPreselected(const P& pTrackSameChargeFirst, const P& pTrackSameChargeSecond, const P& pTrackOppositeCharge, const T& trackOppositeCharge); + template + int8_t isCharmBaryonPreselected(const T& trackSameChargeFirst, const T& trackSameChargeSecond, const T& trackOppositeCharge); + template + int8_t isSelectedD0InMassRange(const T& pTrackPos, const T& pTrackNeg, const float& ptD, int8_t isSelected, const int& activateQA, H2 hMassVsPt); + template + int8_t isSelectedDplusInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptD, const int& activateQA, H2 hMassVsPt); + template + int8_t isSelectedDsInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptD, int8_t isSelected, const int& activateQA, H2 hMassVsPt); + template + int8_t isSelectedLcInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptLc, const int8_t isSelected, const int& activateQA, H2 hMassVsPt); + template + int8_t isSelectedXicInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptXic, const int8_t isSelected, const int& activateQA, H2 hMassVsPt); + template + int8_t isSelectedV0(const V0& v0, const std::array& dauTracks, const Coll& collision, const int& activateQA, H2 hV0Selected, std::array& hArmPod); + template + bool isSelectedCascade(const Casc& casc, const V0& v0, const std::array& dauTracks, const Coll& collision); + template + int8_t isSelectedBachelorForCharmBaryon(const T& track, const T2& dca); + template + int8_t isBDTSelected(const T& scores, const U& thresholdBDTScores); + + // helpers + template + T computeRelativeMomentum(const std::array& pTrack, const std::array& CharmCandMomentum, const T& CharmMass); + template + int computeNumberOfCandidates(std::vector> indices); + + // PID + void setValuesBB(o2::ccdb::CcdbApi& ccdbApi, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::array& ccdbPaths); + void setTpcRecalibMaps(o2::framework::Service const& ccdb, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string& ccdbPath); + + // ML + Ort::Experimental::Session* initONNXSession(std::string& onnxFile, std::string partName, Ort::Env& env, Ort::SessionOptions& sessionOpt, std::vector>& inputShapes, int& dataType, bool loadModelsFromCCDB, o2::ccdb::CcdbApi& ccdbApi, std::string mlModelPathCCDB, int64_t timestampCCDB); + template + std::array predictONNX(std::vector& inputFeatures, std::shared_ptr& session, std::vector>& inputShapes); + + private: + // selections + template + bool isSelectedKaon4Charm3Prong(const T& track, const float& nsigmaTPCKaon3Prong, const float& nsigmaTOFKaon3Prong); + template + bool isSelectedProton4CharmBaryons(const T& track, const float& nsigmaTPCProton, const float& nsigmaTOFProton); + + // PID + template + double getTPCSplineCalib(const T& track, const int& pidSpecies); + template + float getTPCPostCalib(const T& track, const int& pidSpecies); + + // helpers + template + int findBin(T1 const& binsPt, T2 value); + + // selections + std::vector mPtBinsTracks{}; // vector of pT bins for single track cuts + o2::framework::LabeledArray mCutsSingleTrackBeauty3Prong{}; // dca selections for the 3-prong b-hadron pion daughter + o2::framework::LabeledArray mCutsSingleTrackBeauty4Prong{}; // dca selections for the 4-prong b-hadron pion daughter + float mPtMinSoftPionForDstar{0.1}; // minimum pt for the D*+ soft pion + float mPtMinBeautyBachelor{0.5}; // minimum pt for the b-hadron pion daughter + float mPtMinProtonForFemto{0.8}; // minimum pt for the proton for femto + float mPtMinCharmBaryonBachelor{0.5}; // minimum pt for the bachelor pion from Xic/Omegac decays + float mPtMaxSoftPionForDstar{2.}; // maximum pt for the D*+ soft pion + float mPtMaxBeautyBachelor{100000.}; // maximum pt for the b-hadron pion daughter + float mPtMaxProtonForFemto{5.0}; // maximum pt for the proton for femto + float mPtMaxCharmBaryonBachelor{100000.}; // maximum pt for the bachelor pion from Xic/Omegac decays + float mPtThresholdPidStrategyForFemto{8.}; // pt threshold to change strategy for proton PID for femto + std::array mNSigmaPrCutsForFemto{3., 3., 3.}; // cut values for Nsigma TPC, TOF, combined for femto protons + float mNSigmaTpcPrCutForCharmBaryons{3.}; // maximum Nsigma TPC for protons in Lc and Xic decays + float mNSigmaTofPrCutForCharmBaryons{3.}; // maximum Nsigma TOF for protons in Lc and Xic decays + float mNSigmaTpcKaCutFor3Prongs{3.}; // maximum Nsigma TPC for kaons in 3-prong decays + float mNSigmaTofKaCutFor3Prongs{3.}; // maximum Nsigma TOF for kaons in 3-prong decays + float mNSigmaTpcPiKaCutForDzero{3.}; // maximum Nsigma TPC for pions/kaons in D0 decays + float mNSigmaTofPiKaCutForDzero{3.}; // maximum Nsigma TOF for pions/kaons in D0 decays + float mDeltaMassCharmHadForBeauty{0.04}; // delta mass cut for charm hadrons in B and charm excited decays + float mMinGammaCosinePa{0.85}; // minimum cosp for gammas + float mMinK0sLambdaCosinePa{0.97}; // minimum cosp for K0S and Lambda in charm excited decays + float mMinK0sLambdaRadius{0.5}; // minimum radius for K0S and Lambda in charm excited decays + float mMaxNsigmaPrForLambda{4.}; // maximum Nsigma TPC and TOF for protons in Lambda decays + float mDeltaMassK0s{0.02}; // delta mass cut for K0S in charm excited decays + float mDeltaMassLambda{0.01}; // delta mass cut for Lambda in charm excited decays + float mMinPtXiBachelor{0.1}; // minimum pt for Xi bachelor + float mDeltaMassXi{0.01}; // delta mass cut for Xi in Xic/Omegac decays + float mDeltaMassLambdaFromXi{0.01}; // delta mass cut for Lambda <- Xi in Xic/Omegac decays + float mCosPaXi{0.99}; // minimum cosp for Xi in Xic/Omegac decays + float mCosPaLambdaFromXi{0.99}; // minimum cosp for Xi in Xic/Omegac decays + float mMaxDcaXyXi{0.3}; // maximum dca for Xi in Xic/Omegac decays + float mMaxNsigmaXiDau{3.}; // maximum Nsigma TPC and TOF for Xi daughter tracks + o2::framework::LabeledArray mCutsSingleTrackCharmBaryonBachelor{}; // dca selections for the bachelor pion from Xic/Omegac decays + float mNSigmaTpcPiCharmBaryonBachelor{3.}; // maximum Nsigma TPC for pions in Xic/Omegac decays + float mNSigmaTofPiCharmBaryonBachelor{3.}; // maximum Nsigma TOF for pions in Xic/Omegac decays + + // PID recalibrations + int mTpcPidCalibrationOption{0}; // Option for TPC PID calibration (0 -> AO2D, 1 -> postcalibrations, 2 -> alternative bethe bloch parametrisation) + std::array mHistMapPiPr{}; // Map for TPC PID postcalibrations for pions and protons + std::array, 6> mBetheBlochPiKaPr{}; // Bethe-Bloch parametrisations for pions, antipions, kaons, antikaons, protons, antiprotons in TPC +}; /// Single-track cuts for bachelor track of beauty candidates +/// \param track is a track parameter /// \param trackPar is a track parameter /// \param dca is the 2d array with dcaXY and dcaZ of the track -/// \param pTMinSoftPion min pT for soft pions -/// \param pTMinBeautyBachelor min pT for beauty bachelor pions -/// \param cutsSingleTrackBeauty cuts for all tracks -/// \return 0 if track is rejected, 1 if track is soft pion, 2 if it is regular beauty -template -int isSelectedTrackForSoftPionOrBeauty(const T1& trackPar, const T2& dca, const float& pTMinSoftPion, const float& pTMinBeautyBachelor, const T3& pTBinsTrack, const T4& cutsSingleTrackBeauty) +/// \return a flag that encodes the selection for soft pions BIT(kSoftPion), tracks for beauty BIT(kForBeauty), or soft pions for beauty BIT(kSoftPionForBeauty) +template +inline int8_t HfFilterHelper::isSelectedTrackForSoftPionOrBeauty(const T track, const T1& trackPar, const T2& dca, const int& whichTrigger) { + + int8_t retValue{BIT(kSoftPion) | BIT(kForBeauty) | BIT(kSoftPionForBeauty)}; + + if (!track.isGlobalTrackWoDCA()) { + return kRejected; + } + auto pT = trackPar.getPt(); - auto pTBinTrack = findBin(pTBinsTrack, pT); + auto pTBinTrack = findBin(mPtBinsTracks, pT); if (pTBinTrack == -1) { return kRejected; } - if (pT < pTMinSoftPion) { // soft pion should be less stringent than usual tracks + if (pT < mPtMinSoftPionForDstar || pT > mPtMaxSoftPionForDstar) { // soft pion should be less stringent than usual tracks return kRejected; } @@ -226,38 +437,45 @@ int isSelectedTrackForSoftPionOrBeauty(const T1& trackPar, const T2& dca, const return kRejected; } - if (std::fabs(dca[0]) < cutsSingleTrackBeauty.get(pTBinTrack, "min_dcaxytoprimary")) { - return kRejected; // minimum DCAxy + // below only regular beauty tracks, not required for soft pions + if (pT < mPtMinBeautyBachelor || pT > mPtMaxBeautyBachelor) { + CLRBIT(retValue, kForBeauty); } - if (std::fabs(dca[0]) > cutsSingleTrackBeauty.get(pTBinTrack, "max_dcaxytoprimary")) { - return kRejected; // maximum DCAxy + + float minDca = 1000.f; + float maxDca = 0.f; + if (whichTrigger == kBeauty3P) { + minDca = mCutsSingleTrackBeauty3Prong.get(pTBinTrack, 0u); + maxDca = mCutsSingleTrackBeauty3Prong.get(pTBinTrack, 1u); + } else if (whichTrigger == kBeauty4P) { + minDca = mCutsSingleTrackBeauty4Prong.get(pTBinTrack, 0u); + maxDca = mCutsSingleTrackBeauty4Prong.get(pTBinTrack, 1u); } - // below only regular beauty tracks, not required for soft pions - if (pT < pTMinBeautyBachelor) { - return kSoftPion; + if (std::fabs(dca[0]) < minDca) { // minimum DCAxy + CLRBIT(retValue, kForBeauty); + CLRBIT(retValue, kSoftPionForBeauty); + } + if (std::fabs(dca[0]) > maxDca) { // maximum DCAxy + CLRBIT(retValue, kForBeauty); + CLRBIT(retValue, kSoftPionForBeauty); } - return kRegular; + return retValue; } /// Basic selection of proton candidates /// \param track is a track /// \param trackPar is a track parameter -/// \param femtoMinProtonPt min pT for proton candidates -/// \param femtoMaxNsigmaProton max Nsigma for proton candidates -/// \param femtoProtonOnlyTOF flag to activate PID selection with TOF only -/// \param computeTPCPostCalib flag to activate TPC PID postcalibrations -/// \param hMapProton map of nSigma mean and sigma calibrations for proton -/// \param hSplineProton spline of proton and anti-proton calibrations /// \param activateQA flag to activate the filling of QA histos /// \param hProtonTPCPID histo with NsigmaTPC vs. p /// \param hProtonTOFPID histo with NsigmaTOF vs. p /// \return true if track passes all cuts -template -bool isSelectedProton4Femto(const T1& track, const T2& trackPar, const float& femtoMinProtonPt, const float& femtoMaxNsigmaProton, const bool femtoProtonOnlyTOF, const int setTPCCalib, H3 hMapProton, const std::array, 2>& hSplineProton, const int& activateQA, H2 hProtonTPCPID, H2 hProtonTOFPID) +template +inline bool HfFilterHelper::isSelectedProton4Femto(const T1& track, const T2& trackPar, const int& activateQA, H2 hProtonTPCPID, H2 hProtonTOFPID) { - if (trackPar.getPt() < femtoMinProtonPt) { + float pt = trackPar.getPt(); + if (pt < mPtMinProtonForFemto || pt > mPtMaxProtonForFemto) { return false; } @@ -265,29 +483,33 @@ bool isSelectedProton4Femto(const T1& track, const T2& trackPar, const float& fe return false; } - // FIXME: this is applied to the wrong dca for ambiguous tracks! - if (track.isGlobalTrack() != (uint8_t) true) { + if (!track.isGlobalTrack()) { return false; // use only global tracks } float NSigmaTPC = track.tpcNSigmaPr(); float NSigmaTOF = track.tofNSigmaPr(); - float NSigma; - if (setTPCCalib == 1) { - NSigmaTPC = getTPCPostCalib(hMapProton, track, kPr); - } else if (setTPCCalib == 2) { - NSigmaTPC = getTPCSplineCalib(track, massProton, hSplineProton[0]); + if (mTpcPidCalibrationOption == 1) { + NSigmaTPC = getTPCPostCalib(track, kPr); + } else if (mTpcPidCalibrationOption == 2) { + if (track.sign() > 0) { + NSigmaTPC = getTPCSplineCalib(track, kPr); + } else { + NSigmaTPC = getTPCSplineCalib(track, kAntiPr); + } } - if (femtoProtonOnlyTOF) { - NSigma = abs(NSigmaTOF); - } else { - NSigma = sqrt(NSigmaTPC * NSigmaTPC + NSigmaTOF * NSigmaTOF); - } + float NSigma = std::sqrt(NSigmaTPC * NSigmaTPC + NSigmaTOF * NSigmaTOF); - if (NSigma > femtoMaxNsigmaProton) { - return false; + if (trackPar.getPt() <= mPtThresholdPidStrategyForFemto) { + if (NSigma > mNSigmaPrCutsForFemto[2]) { + return false; + } + } else { + if (std::fabs(NSigmaTPC) > mNSigmaPrCutsForFemto[0] || std::fabs(NSigmaTOF) > mNSigmaPrCutsForFemto[1]) { + return false; + } } if (activateQA > 1) { @@ -298,81 +520,18 @@ bool isSelectedProton4Femto(const T1& track, const T2& trackPar, const float& fe return true; } -/// Basic selection of proton candidates for Lc -/// \param track is a track -/// \param nsigmaTPCProtonLc max NsigmaTPC for proton candidates -/// \param nsigmaTOFProtonLc max NsigmaTOF for proton candidates -/// \param computeTPCPostCalib flag to activate TPC PID postcalibrations -/// \param hMapProton map of nSigma mean and sigma calibrations for proton -/// \param hSplineProton spline of proton and anti-proton calibrations -/// \return true if track passes all cuts -template -bool isSelectedProton4CharmBaryons(const T& track, const float& nsigmaTPCProtonLc, const float& nsigmaTOFProtonLc, const int setTPCCalib, H3 hMapProton, const std::array, 2>& hSplineProton) -{ - float NSigmaTPC = track.tpcNSigmaPr(); - float NSigmaTOF = track.tofNSigmaPr(); - - if (setTPCCalib == 1) { - NSigmaTPC = getTPCPostCalib(hMapProton, track, kPr); - } else if (setTPCCalib == 2) { - NSigmaTPC = getTPCSplineCalib(track, massProton, hSplineProton[0]); - } - - if (std::fabs(NSigmaTPC) > nsigmaTPCProtonLc) { - return false; - } - if (track.hasTOF() && std::fabs(NSigmaTOF) > nsigmaTOFProtonLc) { - return false; - } - - return true; -} - -/// Basic selection of kaon candidates for charm candidates -/// \param track is a track -/// \param nsigmaTPCKaon3Prong max NsigmaTPC for kaon candidates -/// \param nsigmaTOFKaon3Prong max NsigmaTOF for kaon candidates -/// \param computeTPCPostCalib flag to activate TPC PID postcalibrations -/// \param hMapKaon map of nSigma mean and sigma calibrations for kaon -/// \param hSplineKaon spline of kaon and anti-kaon calibrations -/// \return true if track passes all cuts -template -bool isSelectedKaon4Charm3Prong(const T& track, const float& nsigmaTPCKaon3Prong, const float& nsigmaTOFKaon3Prong, const int setTPCCalib, H3 hMapKaon, const std::array, 2>& hSplineKaon) -{ - float NSigmaTPC = track.tpcNSigmaKa(); - float NSigmaTOF = track.tofNSigmaKa(); - - if (setTPCCalib == 1) { - NSigmaTPC = getTPCPostCalib(hMapKaon, track, kKa); // use pion correction map for kaon for the moment - } else if (setTPCCalib == 2) { - NSigmaTPC = getTPCSplineCalib(track, massK, hSplineKaon[0]); - } - - if (std::fabs(NSigmaTPC) > nsigmaTPCKaon3Prong) { - return false; - } - if (track.hasTOF() && std::fabs(NSigmaTOF) > nsigmaTOFKaon3Prong) { - return false; - } - - return true; -} - /// Basic additional selection of D+ candidates /// \param trackOppositeCharge is the opposite charge track -/// \param nsigmaTPCKaon3Prong max NsigmaTPC for kaon candidates -/// \param nsigmaTOFKaon3Prong max NsigmaTOF for kaon candidates -/// \param computeTPCPostCalib flag to activate TPC PID postcalibrations -/// \param hMapKaon map of nSigma mean and sigma calibrations for kaon -/// \param hSplineKaon spline of kaon and anti-kaon calibrations +/// \param mNSigmaTpcKaCutFor3Prongs max NsigmaTPC for kaon candidates +/// \param mNSigmaTofKaCutFor3Prongs max NsigmaTOF for kaon candidates /// \return BIT(0) for Kpipi -template -int8_t isDplusPreselected(const T& trackOppositeCharge, const float& nsigmaTPCKaon3Prong, const float& nsigmaTOFKaon3Prong, const int setTPCCalib, H3 hMapKaon, std::array, 2>& hSplineKaon) +template +inline int8_t HfFilterHelper::isDplusPreselected(const T& trackOppositeCharge) { int8_t retValue = 0; // check PID of opposite charge track - if (!isSelectedKaon4Charm3Prong(trackOppositeCharge, nsigmaTPCKaon3Prong, nsigmaTOFKaon3Prong, setTPCCalib, hMapKaon, hSplineKaon)) { + if (!isSelectedKaon4Charm3Prong(trackOppositeCharge, mNSigmaTpcKaCutFor3Prongs, mNSigmaTofKaCutFor3Prongs)) { return retValue; } @@ -385,25 +544,20 @@ int8_t isDplusPreselected(const T& trackOppositeCharge, const float& nsigmaTPCKa /// \param pTrackSameChargeSecond is the second same-charge track momentum /// \param pTrackOppositeCharge is the opposite charge track momentum /// \param trackOppositeCharge is the opposite charge track -/// \param nsigmaTPCKaon3Prong max NsigmaTPC for kaon candidates -/// \param nsigmaTOFKaon3Prong max NsigmaTOF for kaon candidates -/// \param computeTPCPostCalib flag to activate TPC PID postcalibrations -/// \param hMapKaon map of nSigma mean and sigma calibrations for kaon -/// \param hSplineKaon spline of kaon and anti-kaon calibrations /// \return BIT(0) for KKpi, BIT(1) for piKK -template -int8_t isDsPreselected(const P& pTrackSameChargeFirst, const P& pTrackSameChargeSecond, const P& pTrackOppositeCharge, const T& trackOppositeCharge, const float& nsigmaTPCKaon3Prong, const float& nsigmaTOFKaon3Prong, const int setTPCCalib, H3 hMapKaon, const std::array, 2>& hSplineKaon) +template +inline int8_t HfFilterHelper::isDsPreselected(const P& pTrackSameChargeFirst, const P& pTrackSameChargeSecond, const P& pTrackOppositeCharge, const T& trackOppositeCharge) { int8_t retValue = 0; // check PID of opposite charge track - if (!isSelectedKaon4Charm3Prong(trackOppositeCharge, nsigmaTPCKaon3Prong, nsigmaTOFKaon3Prong, setTPCCalib, hMapKaon, hSplineKaon)) { + if (!isSelectedKaon4Charm3Prong(trackOppositeCharge, mNSigmaTpcKaCutFor3Prongs, mNSigmaTofKaCutFor3Prongs)) { return retValue; } // check delta-mass for phi resonance - auto invMassKKFirst = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge}, std::array{massK, massK}); - auto invMassKKSecond = RecoDecay::m(std::array{pTrackSameChargeSecond, pTrackOppositeCharge}, std::array{massK, massK}); + auto invMassKKFirst = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge}, std::array{massKa, massKa}); + auto invMassKKSecond = RecoDecay::m(std::array{pTrackSameChargeSecond, pTrackOppositeCharge}, std::array{massKa, massKa}); if (std::fabs(invMassKKFirst - massPhi) < 0.02) { retValue |= BIT(0); @@ -419,29 +573,19 @@ int8_t isDsPreselected(const P& pTrackSameChargeFirst, const P& pTrackSameCharge /// \param trackSameChargeFirst is the first same-charge track /// \param trackSameChargeSecond is the second same-charge track /// \param trackOppositeCharge is the opposite charge track -/// \param nsigmaTPCProtonLc max NsigmaTPC for proton candidates -/// \param nsigmaTOFProtonLc max NsigmaTOF for proton candidates -/// \param nsigmaTPCKaon3Prong max NsigmaTPC for kaon candidates -/// \param nsigmaTOFKaon3Prong max NsigmaTOF for kaon candidates -/// \param computeTPCPostCalib flag to activate TPC PID postcalibrations -/// \param hMapProton map of nSigma mean and sigma calibrations for proton -/// \param hSplineProton spline of proton and anti-proton calibrations -/// \param hMapKaon map of nSigma mean and sigma calibrations for kaon -/// \param hSplineKaon spline of kaon and anti-kaon calibrations /// \return BIT(0) for pKpi, BIT(1) for piKp -template -int8_t isCharmBaryonPreselected(const T& trackSameChargeFirst, const T& trackSameChargeSecond, const T& trackOppositeCharge, const float& nsigmaTPCProtonLc, const float& nsigmaTOFProtonLc, const float& nsigmaTPCKaon3Prong, const float& nsigmaTOFKaon3Prong, const int setTPCCalib, H3 hMapProton, const std::array, 2>& hSplineProton, H3 hMapKaon, const std::array, 2>& hSplineKaon) +template +inline int8_t HfFilterHelper::isCharmBaryonPreselected(const T& trackSameChargeFirst, const T& trackSameChargeSecond, const T& trackOppositeCharge) { int8_t retValue = 0; // check PID of opposite charge track - if (!isSelectedKaon4Charm3Prong(trackOppositeCharge, nsigmaTPCKaon3Prong, nsigmaTOFKaon3Prong, setTPCCalib, hMapKaon, hSplineKaon)) { + if (!isSelectedKaon4Charm3Prong(trackOppositeCharge, mNSigmaTpcKaCutFor3Prongs, mNSigmaTofKaCutFor3Prongs)) { return retValue; } - - if (isSelectedProton4CharmBaryons(trackSameChargeFirst, nsigmaTPCProtonLc, nsigmaTOFProtonLc, setTPCCalib, hMapProton, hSplineProton)) { + if (isSelectedProton4CharmBaryons(trackSameChargeFirst, mNSigmaTpcPrCutForCharmBaryons, mNSigmaTofPrCutForCharmBaryons)) { retValue |= BIT(0); } - if (isSelectedProton4CharmBaryons(trackSameChargeSecond, nsigmaTPCProtonLc, nsigmaTOFProtonLc, setTPCCalib, hMapProton, hSplineProton)) { + if (isSelectedProton4CharmBaryons(trackSameChargeSecond, mNSigmaTpcPrCutForCharmBaryons, mNSigmaTofPrCutForCharmBaryons)) { retValue |= BIT(1); } @@ -451,15 +595,9 @@ int8_t isCharmBaryonPreselected(const T& trackSameChargeFirst, const T& trackSam /// Basic additional selection of D0 candidates /// \param trackPos is the positive track /// \param trackNeg is the negative track -/// \param nsigmaTPCPionKaonDzero max NsigmaTPC for pion/kaon candidates -/// \param nsigmaTOFPionKaonDzero max NsigmaTOF for pion/kaon candidates -/// \param computeTPCPostCalib flag to activate TPC PID postcalibrations -/// \param hMapPion map of nSigma mean and sigma calibrations for pion -/// \param hSplinePion spline of pion and anti-pion calibrations -/// \param hSplineKaon spline of kaon and anti-kaon calibrations /// \return BIT(0) for D0, BIT(1) for D0bar -template -int8_t isDzeroPreselected(const T& trackPos, const T& trackNeg, const float& nsigmaTPCPionKaonDzero, const float& nsigmaTOFPionKaonDzero, const int setTPCCalib, H3 hMapPion, const std::array, 2>& hSplinePion, const std::array, 2>& hSplineKaon) +template +inline int8_t HfFilterHelper::isDzeroPreselected(const T& trackPos, const T& trackNeg) { int8_t retValue = 0; @@ -473,22 +611,22 @@ int8_t isDzeroPreselected(const T& trackPos, const T& trackNeg, const float& nsi float NSigmaKaTPCNeg = trackNeg.tpcNSigmaKa(); float NSigmaKaTOFNeg = trackNeg.tofNSigmaKa(); - if (setTPCCalib == 1) { - NSigmaPiTPCPos = getTPCPostCalib(hMapPion, trackPos, kPi); - NSigmaPiTPCNeg = getTPCPostCalib(hMapPion, trackNeg, kPi); - NSigmaKaTPCPos = getTPCPostCalib(hMapPion, trackPos, kKa); // use pion correction map for kaon for the moment - NSigmaKaTPCNeg = getTPCPostCalib(hMapPion, trackNeg, kKa); // use pion correction map for kaon for the moment - } else if (setTPCCalib == 2) { - NSigmaPiTPCPos = getTPCSplineCalib(trackPos, massPi, hSplinePion[0]); - NSigmaPiTPCNeg = getTPCSplineCalib(trackNeg, massPi, hSplinePion[1]); - NSigmaKaTPCPos = getTPCSplineCalib(trackPos, massK, hSplineKaon[0]); - NSigmaKaTPCNeg = getTPCSplineCalib(trackNeg, massK, hSplineKaon[1]); + if (mTpcPidCalibrationOption == 1) { + NSigmaPiTPCPos = getTPCPostCalib(trackPos, kPi); + NSigmaPiTPCNeg = getTPCPostCalib(trackNeg, kPi); + NSigmaKaTPCPos = getTPCPostCalib(trackPos, kKa); + NSigmaKaTPCNeg = getTPCPostCalib(trackNeg, kKa); + } else if (mTpcPidCalibrationOption == 2) { + NSigmaPiTPCPos = getTPCSplineCalib(trackPos, kPi); + NSigmaPiTPCNeg = getTPCSplineCalib(trackNeg, kAntiPi); + NSigmaKaTPCPos = getTPCSplineCalib(trackPos, kKa); + NSigmaKaTPCNeg = getTPCSplineCalib(trackNeg, kAntiKa); } - if ((std::fabs(NSigmaPiTPCPos) <= nsigmaTPCPionKaonDzero && (!trackPos.hasTOF() || std::fabs(NSigmaPiTOFPos) <= nsigmaTOFPionKaonDzero)) && (std::fabs(NSigmaKaTPCNeg) <= nsigmaTPCPionKaonDzero && (!trackNeg.hasTOF() || std::fabs(NSigmaKaTOFNeg) <= nsigmaTOFPionKaonDzero))) { + if ((std::fabs(NSigmaPiTPCPos) <= mNSigmaTpcPiKaCutForDzero && (!trackPos.hasTOF() || std::fabs(NSigmaPiTOFPos) <= mNSigmaTofPiKaCutForDzero)) && (std::fabs(NSigmaKaTPCNeg) <= mNSigmaTpcPiKaCutForDzero && (!trackNeg.hasTOF() || std::fabs(NSigmaKaTOFNeg) <= mNSigmaTofPiKaCutForDzero))) { retValue |= BIT(0); } - if ((std::fabs(NSigmaPiTPCNeg) <= nsigmaTPCPionKaonDzero && (!trackNeg.hasTOF() || std::fabs(NSigmaPiTOFNeg) <= nsigmaTOFPionKaonDzero)) && (std::fabs(NSigmaKaTPCPos) <= nsigmaTPCPionKaonDzero && (!trackPos.hasTOF() || std::fabs(NSigmaKaTOFPos) <= nsigmaTOFPionKaonDzero))) { + if ((std::fabs(NSigmaPiTPCNeg) <= mNSigmaTpcPiKaCutForDzero && (!trackNeg.hasTOF() || std::fabs(NSigmaPiTOFNeg) <= mNSigmaTofPiKaCutForDzero)) && (std::fabs(NSigmaKaTPCPos) <= mNSigmaTpcPiKaCutForDzero && (!trackPos.hasTOF() || std::fabs(NSigmaKaTOFPos) <= mNSigmaTofPiKaCutForDzero))) { retValue |= BIT(1); } @@ -500,29 +638,28 @@ int8_t isDzeroPreselected(const T& trackPos, const T& trackNeg, const float& nsi /// \param pTrackNeg is the negative track momentum /// \param ptD is the pt of the D0 meson candidate /// \param isSelected is the flag containing the selection tag for the D0 candidate -/// \param deltaMassCharmHadronForBeauty is the maximum delta mass value (for candidates with pT < 10 GeV/c) /// \param activateQA flag to activate the filling of QA histos /// \param hMassVsPt histo with invariant mass vs pt /// \return 1 for D0, 2 for D0bar, 3 for both template -int8_t isSelectedD0InMassRange(const T& pTrackPos, const T& pTrackNeg, const float& ptD, const float& phiD, int8_t isSelected, const float& deltaMassCharmHadronForBeauty, const int& activateQA, H2 hMassVsPt) +inline int8_t HfFilterHelper::isSelectedD0InMassRange(const T& pTrackPos, const T& pTrackNeg, const float& ptD, int8_t isSelected, const int& activateQA, H2 hMassVsPt) { int8_t retValue = 0; if (TESTBIT(isSelected, 0)) { - auto invMassD0 = RecoDecay::m(std::array{pTrackPos, pTrackNeg}, std::array{massPi, massK}); + auto invMassD0 = RecoDecay::m(std::array{pTrackPos, pTrackNeg}, std::array{massPi, massKa}); if (activateQA) { hMassVsPt->Fill(ptD, invMassD0); } - if (std::fabs(invMassD0 - massD0) < deltaMassCharmHadronForBeauty || ptD > 10) { + if (std::fabs(invMassD0 - massD0) < mDeltaMassCharmHadForBeauty || ptD > 10) { retValue |= BIT(0); } } if (TESTBIT(isSelected, 1)) { - auto invMassD0bar = RecoDecay::m(std::array{pTrackPos, pTrackNeg}, std::array{massK, massPi}); + auto invMassD0bar = RecoDecay::m(std::array{pTrackPos, pTrackNeg}, std::array{massKa, massPi}); if (activateQA) { hMassVsPt->Fill(ptD, invMassD0bar); } - if (std::fabs(invMassD0bar - massD0) < deltaMassCharmHadronForBeauty || ptD > 10) { + if (std::fabs(invMassD0bar - massD0) < mDeltaMassCharmHadForBeauty || ptD > 10) { retValue |= BIT(1); } } @@ -535,19 +672,18 @@ int8_t isSelectedD0InMassRange(const T& pTrackPos, const T& pTrackNeg, const flo /// \param pTrackSameChargeFirst is the second same-charge track momentum /// \param pTrackSameChargeFirst is the opposite charge track momentum /// \param ptD is the pt of the D+ meson candidate -/// \param deltaMassCharmHadronForBeauty is the maximum delta mass value (for candidates with pT < 10 GeV/c) /// \param activateQA flag to activate the filling of QA histos /// \param hMassVsPt histo with invariant mass vs pt /// \return BIT(0) (==1) for D+, 0 otherwise template -int8_t isSelectedDplusInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptD, const float& phiD, const float& deltaMassCharmHadronForBeauty, const int& activateQA, H2 hMassVsPt) +inline int8_t HfFilterHelper::isSelectedDplusInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptD, const int& activateQA, H2 hMassVsPt) { - auto invMassDplus = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackSameChargeSecond, pTrackOppositeCharge}, std::array{massPi, massPi, massK}); + auto invMassDplus = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackSameChargeSecond, pTrackOppositeCharge}, std::array{massPi, massPi, massKa}); if (activateQA) { hMassVsPt->Fill(ptD, invMassDplus); } - if (std::fabs(invMassDplus - massDPlus) > deltaMassCharmHadronForBeauty && ptD > 0) { + if (std::fabs(invMassDplus - massDPlus) > mDeltaMassCharmHadForBeauty && ptD > 0) { return 0; } @@ -560,29 +696,28 @@ int8_t isSelectedDplusInMassRange(const T& pTrackSameChargeFirst, const T& pTrac /// \param pTrackSameChargeFirst is the opposite charge track momentum /// \param ptD is the pt of the Ds meson candidate /// \param isSelected is the flag containing the selection tag for the Ds candidate -/// \param deltaMassCharmHadronForBeauty is the maximum delta mass value (for candidates with pT < 10 GeV/c) /// \param activateQA flag to activate the filling of QA histos /// \param hMassVsPt histo with invariant mass vs pt /// \return BIT(0) for KKpi, BIT(1) for piKK, BIT(2) for phipi, BIT(3) for piphi template -int8_t isSelectedDsInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptD, const float& phiD, int8_t isSelected, const float& deltaMassCharmHadronForBeauty, const int& activateQA, H2 hMassVsPt) +inline int8_t HfFilterHelper::isSelectedDsInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptD, int8_t isSelected, const int& activateQA, H2 hMassVsPt) { int8_t retValue = 0; if (TESTBIT(isSelected, 0)) { - auto invMassDsToKKPi = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massK, massK, massPi}); + auto invMassDsToKKPi = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massKa, massKa, massPi}); if (activateQA) { hMassVsPt->Fill(ptD, invMassDsToKKPi); } - if (std::fabs(invMassDsToKKPi - massDs) < deltaMassCharmHadronForBeauty || ptD > 10) { + if (std::fabs(invMassDsToKKPi - massDs) < mDeltaMassCharmHadForBeauty || ptD > 10) { retValue |= BIT(0); } } if (TESTBIT(isSelected, 1)) { - auto invMassDsToPiKK = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massPi, massK, massK}); + auto invMassDsToPiKK = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massPi, massKa, massKa}); if (activateQA) { hMassVsPt->Fill(ptD, invMassDsToPiKK); } - if (std::fabs(invMassDsToPiKK - massDs) < deltaMassCharmHadronForBeauty || ptD > 10) { + if (std::fabs(invMassDsToPiKK - massDs) < mDeltaMassCharmHadForBeauty || ptD > 10) { retValue |= BIT(1); } } @@ -596,29 +731,28 @@ int8_t isSelectedDsInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSa /// \param pTrackOppositeCharge is the opposite charge track momentum /// \param ptLc is the pt of the D0 meson candidate /// \param isSelected is the flag containing the selection tag for the D0 candidate -/// \param deltaMassCharmHadronForBeauty is the maximum delta mass value (for candidates with pT < 10 GeV/c) /// \param activateQA flag to activate the filling of QA histos /// \param hMassVsPt histo with invariant mass vs pt /// \return BIT(0) for pKpi with mass cut, BIT(1) for piKp with mass cut template -int8_t isSelectedLcInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptLc, const float& phiLc, const int8_t isSelected, const float& deltaMassCharmHadronForBeauty, const int& activateQA, H2 hMassVsPt) +inline int8_t HfFilterHelper::isSelectedLcInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptLc, const int8_t isSelected, const int& activateQA, H2 hMassVsPt) { int8_t retValue = 0; if (TESTBIT(isSelected, 0)) { - auto invMassLcToPKPi = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massProton, massK, massPi}); + auto invMassLcToPKPi = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massProton, massKa, massPi}); if (activateQA) { hMassVsPt->Fill(ptLc, invMassLcToPKPi); } - if (std::fabs(invMassLcToPKPi - massLc) < deltaMassCharmHadronForBeauty || ptLc > 10) { + if (std::fabs(invMassLcToPKPi - massLc) < mDeltaMassCharmHadForBeauty || ptLc > 10) { retValue |= BIT(0); } } if (TESTBIT(isSelected, 1)) { - auto invMassLcToPiKP = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massPi, massK, massProton}); + auto invMassLcToPiKP = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massPi, massKa, massProton}); if (activateQA) { hMassVsPt->Fill(ptLc, invMassLcToPiKP); } - if (std::fabs(invMassLcToPiKP - massLc) < deltaMassCharmHadronForBeauty || ptLc > 10) { + if (std::fabs(invMassLcToPiKP - massLc) < mDeltaMassCharmHadForBeauty || ptLc > 10) { retValue |= BIT(1); } } @@ -630,31 +764,30 @@ int8_t isSelectedLcInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSa /// \param pTrackSameChargeFirst is the first same-charge track momentum /// \param pTrackSameChargeSecond is the second same-charge track momentum /// \param pTrackOppositeCharge is the opposite charge track momentum -/// \param ptXic is the pt of the D0 meson candidate +/// \param ptXic is the pt of the Xic baryon candidate /// \param isSelected is the flag containing the selection tag for the D0 candidate -/// \param deltaMassCharmHadronForBeauty is the maximum delta mass value (for candidates with pT < 10 GeV/c) /// \param activateQA flag to activate the filling of QA histos /// \param hMassVsPt histo with invariant mass vs pt /// \return BIT(0) for pKpi with mass cut, BIT(1) for piKp with mass cut template -int8_t isSelectedXicInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptXic, const float& phiXic, const int8_t isSelected, const float& deltaMassCharmHadronForBeauty, const int& activateQA, H2 hMassVsPt) +inline int8_t HfFilterHelper::isSelectedXicInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptXic, const int8_t isSelected, const int& activateQA, H2 hMassVsPt) { int8_t retValue = 0; if (TESTBIT(isSelected, 0)) { - auto invMassXicToPKPi = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massProton, massK, massPi}); + auto invMassXicToPKPi = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massProton, massKa, massPi}); if (activateQA) { hMassVsPt->Fill(ptXic, invMassXicToPKPi); } - if (std::fabs(invMassXicToPKPi - massXic) < deltaMassCharmHadronForBeauty || ptXic > 10) { + if (std::fabs(invMassXicToPKPi - massXic) < mDeltaMassCharmHadForBeauty || ptXic > 10) { retValue |= BIT(0); } } if (TESTBIT(isSelected, 1)) { - auto invMassXicToPiKP = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massPi, massK, massProton}); + auto invMassXicToPiKP = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massPi, massKa, massProton}); if (activateQA) { hMassVsPt->Fill(ptXic, invMassXicToPiKP); } - if (std::fabs(invMassXicToPiKP - massXic) < deltaMassCharmHadronForBeauty || ptXic > 10) { + if (std::fabs(invMassXicToPiKP - massXic) < mDeltaMassCharmHadForBeauty || ptXic > 10) { retValue |= BIT(1); } } @@ -662,18 +795,18 @@ int8_t isSelectedXicInMassRange(const T& pTrackSameChargeFirst, const T& pTrackS return retValue; } -/// Basic selection of gamma candidates +/// Basic selection of V0 candidates /// \param v0 is the v0 candidate -/// \param minGammaCosinePa is the minimum required cosp of the gamma -/// \param gammaCosinePa is the cosp of the gamma -/// \param minV0CosinePa is the cosp of the V0s +/// \param dauTracks is a 2-element array with positive and negative V0 daughter tracks +/// \param collision is the current collision +/// \param activateQA flag to fill QA histos /// \param hV0Selected is the pointer to the QA histo for selected gammas /// \param hArmPod is the pointer to an array of QA histo AP plot before selection -/// \return true if gamma passes all cuts -template -int isSelectedV0(const T& v0, const float& minGammaCosinePa, const float& minV0CosinePa, const float& v0CosinePa, const int& activateQA, H2 hV0Selected, A hArmPod) +/// \return an integer passes all cuts +template +inline int8_t HfFilterHelper::isSelectedV0(const V0& v0, const std::array& dauTracks, const Coll& collision, const int& activateQA, H2 hV0Selected, std::array& hArmPod) { - int isSelected{BIT(kPhoton) | BIT(kK0S) | BIT(kLambda) | BIT(kAntiLambda)}; + int8_t isSelected{BIT(kPhoton) | BIT(kK0S) | BIT(kLambda) | BIT(kAntiLambda)}; if (activateQA > 1) { for (int iV0{kPhoton}; iV0 < kNV0; ++iV0) { @@ -681,70 +814,122 @@ int isSelectedV0(const T& v0, const float& minGammaCosinePa, const float& minV0C } } - if (std::fabs(v0.eta()) > 0.8) { // cut all V0s with |eta| > 0.8 + // eta of daughters + if (std::fabs(dauTracks[0].eta()) > 1. || std::fabs(dauTracks[1].eta()) > 1.) { // cut all V0 daughters with |eta| > 1. if (activateQA > 1) { for (int iV0{kPhoton}; iV0 < kNV0; ++iV0) { hV0Selected->Fill(1., iV0); } } - return 0; + return kRejected; } + // V0 radius if (v0.v0radius() < 0. || v0.v0radius() > 180.) { CLRBIT(isSelected, kPhoton); if (activateQA > 1) { hV0Selected->Fill(2., kPhoton); } } + if (v0.v0radius() < mMinK0sLambdaRadius) { + for (int iV0{kK0S}; iV0 < kNV0; ++iV0) { + CLRBIT(isSelected, iV0); + if (activateQA > 1) { + hV0Selected->Fill(2., iV0); + } + } + } - if (TESTBIT(isSelected, kPhoton) && v0CosinePa < minGammaCosinePa) { + auto v0CosinePa = v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); + // cosine of pointing angle + if (TESTBIT(isSelected, kPhoton) && v0CosinePa < mMinGammaCosinePa) { CLRBIT(isSelected, kPhoton); if (activateQA > 1) { hV0Selected->Fill(3., kPhoton); } } - - if (v0CosinePa < minV0CosinePa) { - for (int iV0{kK0S}; iV0 < kNV0; ++iV0) { + for (int iV0{kK0S}; iV0 < kNV0; ++iV0) { + if (TESTBIT(isSelected, iV0) && v0CosinePa < mMinK0sLambdaCosinePa) { + CLRBIT(isSelected, iV0); if (activateQA > 1) { hV0Selected->Fill(3., iV0); } } - CLRBIT(isSelected, kK0S); - CLRBIT(isSelected, kLambda); - CLRBIT(isSelected, kAntiLambda); } + // armenteros-podolanski / mass if (TESTBIT(isSelected, kPhoton) && (std::pow(v0.alpha() / 0.95, 2) + std::pow(v0.qtarm() / 0.05, 2)) >= 1) { CLRBIT(isSelected, kPhoton); if (activateQA > 1) { hV0Selected->Fill(4., kPhoton); } } - - if (TESTBIT(isSelected, kK0S) && std::fabs(v0.mK0Short() - massK0S) > 0.08) { + if (TESTBIT(isSelected, kK0S) && std::fabs(v0.mK0Short() - massK0S) > mDeltaMassK0s) { CLRBIT(isSelected, kK0S); if (activateQA > 1) { hV0Selected->Fill(4., kK0S); } } - if (TESTBIT(isSelected, kLambda) && std::fabs(v0.mLambda() - massLambda) > 0.1) { + if (TESTBIT(isSelected, kLambda) && std::fabs(v0.mLambda() - massLambda) > mDeltaMassLambda) { CLRBIT(isSelected, kLambda); if (activateQA > 1) { hV0Selected->Fill(4., kLambda); } } - if (TESTBIT(isSelected, kAntiLambda) && std::fabs(v0.mAntiLambda() - massLambda) > 0.1) { + if (TESTBIT(isSelected, kAntiLambda) && std::fabs(v0.mAntiLambda() - massLambda) > mDeltaMassLambda) { CLRBIT(isSelected, kAntiLambda); if (activateQA > 1) { hV0Selected->Fill(4., kAntiLambda); } } + // DCA V0 and V0 daughters + for (int iV0{kK0S}; iV0 < kNV0; ++iV0) { + if (TESTBIT(isSelected, iV0) && v0.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > 0.1f) { // we want only primary V0s + CLRBIT(isSelected, iV0); + if (activateQA > 1) { + hV0Selected->Fill(5., iV0); + } + } + if (TESTBIT(isSelected, iV0) && (v0.dcaV0daughters() > 1.f || std::fabs(v0.dcapostopv()) < 0.05f || std::fabs(v0.dcanegtopv()) < 0.05f)) { + CLRBIT(isSelected, iV0); + if (activateQA > 1) { + hV0Selected->Fill(6., iV0); + } + } + } + + // psi pair (photon only) if (TESTBIT(isSelected, kPhoton) && std::fabs(v0.psipair()) > 0.1) { CLRBIT(isSelected, kPhoton); if (activateQA > 1) { - hV0Selected->Fill(5., kPhoton); + hV0Selected->Fill(7., kPhoton); + } + } + + // PID (Lambda/AntiLambda only) + float nSigmaPrTpc[2] = {dauTracks[0].tpcNSigmaPr(), dauTracks[1].tpcNSigmaPr()}; + float nSigmaPrTof[2] = {dauTracks[0].tofNSigmaPr(), dauTracks[1].tofNSigmaPr()}; + if (mTpcPidCalibrationOption == 1) { + for (int iDau{0}; iDau < 2; ++iDau) { + nSigmaPrTpc[iDau] = getTPCPostCalib(dauTracks[iDau], kPr); + } + } else if (mTpcPidCalibrationOption == 2) { + for (int iDau{0}; iDau < 2; ++iDau) { + nSigmaPrTpc[iDau] = getTPCSplineCalib(dauTracks[iDau], (iDau == 0) ? kPr : kAntiPr); + } + } + + if (TESTBIT(isSelected, kLambda) && ((dauTracks[0].hasTPC() && std::fabs(nSigmaPrTpc[0]) > mMaxNsigmaPrForLambda) || (dauTracks[0].hasTOF() && std::fabs(nSigmaPrTof[0]) > mMaxNsigmaPrForLambda))) { + CLRBIT(isSelected, kLambda); + if (activateQA > 1) { + hV0Selected->Fill(8., kLambda); + } + } + if (TESTBIT(isSelected, kAntiLambda) && ((dauTracks[1].hasTPC() && std::fabs(nSigmaPrTpc[1]) > mMaxNsigmaPrForLambda) || (dauTracks[1].hasTOF() && std::fabs(nSigmaPrTof[1]) > mMaxNsigmaPrForLambda))) { + CLRBIT(isSelected, kAntiLambda); + if (activateQA > 1) { + hV0Selected->Fill(8., kAntiLambda); } } @@ -753,7 +938,7 @@ int isSelectedV0(const T& v0, const float& minGammaCosinePa, const float& minV0C if (TESTBIT(isSelected, iV0)) { hArmPod[iV0]->Fill(v0.alpha(), v0.qtarm()); if (activateQA > 1) { - hV0Selected->Fill(6., iV0); + hV0Selected->Fill(9., iV0); } } } @@ -762,25 +947,210 @@ int isSelectedV0(const T& v0, const float& minGammaCosinePa, const float& minV0C return isSelected; } -/// Single-track cuts for bachelor track of beauty candidates +/// Basic selection of cascade candidates +/// \param casc is the cascade candidate +/// \param v0 is the cascade daughter +/// \param dauTracks is a 3-element array with bachelor, positive and negative V0 daughter tracks +/// \param collision is the collision +/// \return true if cascade passes all cuts +template +inline bool HfFilterHelper::isSelectedCascade(const Casc& casc, const V0& v0, const std::array& dauTracks, const Coll& collision) +{ + // eta of daughters + if (std::fabs(dauTracks[0].eta()) > 1. || std::fabs(dauTracks[1].eta()) > 1. || std::fabs(dauTracks[2].eta()) > 1.) { // cut all V0 daughters with |eta| > 1. + return false; + } + + // V0 radius + if (v0.v0radius() < 1.2) { + return false; + } + + // cascade radius + if (casc.cascradius() < 0.6) { + return false; + } + + // V0 cosp + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < mCosPaLambdaFromXi) { + return false; + } + + // cascade cosp + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < mCosPaXi) { + return false; + } + + // cascade DCAxy to PV + if (std::fabs(casc.dcaXYCascToPV()) > mMaxDcaXyXi) { + return false; + } + + // Xi bachelor min pT + if (dauTracks[0].pt() < mMinPtXiBachelor) { + return false; + } + + // dau dca + if (std::fabs(casc.dcaV0daughters()) > 1.f || std::fabs(casc.dcacascdaughters()) > 1.f) { + return false; + } + + // cascade mass + if (std::fabs(casc.mXi() - massXi) > mDeltaMassXi) { + return false; + } + + // V0 mass + if (std::fabs(casc.mLambda() - massLambda) > mDeltaMassLambdaFromXi) { + return false; + } + + // PID + float nSigmaPrTpc[3] = {-999., dauTracks[1].tpcNSigmaPr(), dauTracks[2].tpcNSigmaPr()}; + float nSigmaPrTof[3] = {-999., dauTracks[1].tofNSigmaPr(), dauTracks[2].tofNSigmaPr()}; + float nSigmaPiTpc[3] = {dauTracks[0].tpcNSigmaPi(), dauTracks[1].tpcNSigmaPi(), dauTracks[2].tpcNSigmaPi()}; + float nSigmaPiTof[3] = {dauTracks[0].tofNSigmaPi(), dauTracks[1].tofNSigmaPi(), dauTracks[2].tofNSigmaPi()}; + if (mTpcPidCalibrationOption == 1) { + for (int iDau{0}; iDau < 3; ++iDau) { + nSigmaPiTpc[iDau] = getTPCPostCalib(dauTracks[iDau], kPi); + if (iDau == 0) { + continue; + } + nSigmaPrTpc[iDau] = getTPCPostCalib(dauTracks[iDau], kPr); + } + } else if (mTpcPidCalibrationOption == 2) { + for (int iDau{0}; iDau < 3; ++iDau) { + nSigmaPiTpc[iDau] = getTPCSplineCalib(dauTracks[iDau], (dauTracks[iDau].sign() > 0) ? kPi : kAntiPi); + if (iDau == 0) { + continue; + } + nSigmaPrTpc[iDau] = getTPCSplineCalib(dauTracks[iDau], (dauTracks[iDau].sign() > 0) ? kPr : kAntiPr); + } + } + + // PID to V0 tracks + if (dauTracks[0].sign() < 0) { // Xi- + if ((dauTracks[1].hasTPC() && std::fabs(nSigmaPrTpc[1]) > mMaxNsigmaXiDau) && (dauTracks[1].hasTOF() && std::fabs(nSigmaPrTof[1]) > mMaxNsigmaXiDau)) { + return false; + } + if ((dauTracks[2].hasTPC() && std::fabs(nSigmaPiTpc[2]) > mMaxNsigmaXiDau) && (dauTracks[2].hasTOF() && std::fabs(nSigmaPiTof[2]) > mMaxNsigmaXiDau)) { + return false; + } + } else if (dauTracks[0].sign() > 0) { // Xi+ + if ((dauTracks[2].hasTPC() && std::fabs(nSigmaPrTpc[2]) > mMaxNsigmaXiDau) && (dauTracks[2].hasTOF() && std::fabs(nSigmaPrTof[2]) > mMaxNsigmaXiDau)) { + return false; + } + if ((dauTracks[1].hasTPC() && std::fabs(nSigmaPiTpc[1]) > mMaxNsigmaXiDau) && (dauTracks[1].hasTOF() && std::fabs(nSigmaPiTof[1]) > mMaxNsigmaXiDau)) { + return false; + } + } + + // bachelor PID + if ((dauTracks[0].hasTPC() && std::fabs(nSigmaPiTpc[0]) > mMaxNsigmaXiDau) && (dauTracks[0].hasTOF() && std::fabs(nSigmaPiTof[0]) > mMaxNsigmaXiDau)) { + return false; + } + + // additional track cuts + for (const auto& dauTrack : dauTracks) { + // TPC clusters selections + if (dauTrack.tpcNClsFound() < 70) { // TODO: put me as a configurable please + return false; + } + if (dauTrack.tpcNClsCrossedRows() < 70) { + return false; + } + if (dauTrack.tpcCrossedRowsOverFindableCls() < 0.8) { + return false; + } + } + + return true; +} + +/// Single-track cuts for bachelor track of charm baryon candidates +/// \param track is a track +/// \param dca is the 2d array with dcaXY and dcaZ of the track +/// \return 0 if rejected, or a bitmap that contains the information whether it is selected as pion and/or kaon +template +inline int8_t HfFilterHelper::isSelectedBachelorForCharmBaryon(const T& track, const T2& dca) +{ + int8_t retValue{BIT(kPionForCharmBaryon) | BIT(kKaonForCharmBaryon)}; + + if (!track.isGlobalTrackWoDCA()) { + return kRejected; + } + + float pt = track.pt(); + if (pt < mPtMinCharmBaryonBachelor || pt > mPtMaxCharmBaryonBachelor) { + return kRejected; + } + + auto pTBinTrack = findBin(mPtBinsTracks, pt); + if (pTBinTrack == -1) { + return kRejected; + } + + if (std::fabs(dca[0]) < mCutsSingleTrackCharmBaryonBachelor.get(pTBinTrack, 0u)) { + return kRejected; // minimum DCAxy + } + if (std::fabs(dca[0]) > mCutsSingleTrackCharmBaryonBachelor.get(pTBinTrack, 1u)) { + return kRejected; // maximum DCAxy + } + + if (std::fabs(dca[1]) > 2.f) { + return kRejected; // maximum DCAz + } + + if (track.tpcNClsFound() < 70) { + return kRejected; + } + + if (track.itsNCls() < 3) { + return kRejected; + } + + float nSigmaPiTpc = track.tpcNSigmaPi(); + float nSigmaKaTpc = track.tpcNSigmaKa(); + float nSigmaPiTof = track.tofNSigmaPi(); + float nSigmaKaTof = track.tofNSigmaKa(); + if (mTpcPidCalibrationOption == 1) { + nSigmaPiTpc = getTPCPostCalib(track, kPi); + nSigmaKaTpc = getTPCPostCalib(track, kKa); + } else if (mTpcPidCalibrationOption == 2) { + nSigmaPiTpc = getTPCSplineCalib(track, (track.sign() > 0) ? kPi : kAntiPi); + nSigmaKaTpc = getTPCSplineCalib(track, (track.sign() > 0) ? kKa : kAntiKa); + } + + if ((track.hasTPC() && std::fabs(nSigmaPiTpc) > mNSigmaTpcPiCharmBaryonBachelor) && (track.hasTOF() && std::fabs(nSigmaPiTof) > mNSigmaTofPiCharmBaryonBachelor)) { + CLRBIT(retValue, kPionForCharmBaryon); + } + if ((track.hasTPC() && std::fabs(nSigmaKaTpc) > mNSigmaTpcPiCharmBaryonBachelor) && (track.hasTOF() && std::fabs(nSigmaKaTof) > mNSigmaTofPiCharmBaryonBachelor)) { + CLRBIT(retValue, kKaonForCharmBaryon); + } + + return retValue; +} + +/// BDT selections /// \param scores is a 3-element array with BDT out scores /// \param thresholdBDTScores is the LabelledArray containing the BDT cut values /// \return 0 if rejected, otherwise bitmap with BIT(RecoDecay::OriginType::Prompt) and/or BIT(RecoDecay::OriginType::NonPrompt) on template -int8_t isBDTSelected(const T& scores, const U& thresholdBDTScores) +inline int8_t HfFilterHelper::isBDTSelected(const T& scores, const U& thresholdBDTScores) { int8_t retValue = 0; if (scores.size() < 3) { return retValue; } - if (scores[0] > thresholdBDTScores.get(0u, "BDTbkg")) { + if (scores[0] > thresholdBDTScores.get(0u, 0u)) { return retValue; } - if (scores[1] > thresholdBDTScores.get(0u, "BDTprompt")) { + if (scores[1] > thresholdBDTScores.get(0u, 1u)) { retValue |= BIT(RecoDecay::OriginType::Prompt); } - if (scores[2] > thresholdBDTScores.get(0u, "BDTnonprompt")) { + if (scores[2] > thresholdBDTScores.get(0u, 2u)) { retValue |= BIT(RecoDecay::OriginType::NonPrompt); } @@ -794,7 +1164,7 @@ int8_t isBDTSelected(const T& scores, const U& thresholdBDTScores) /// \param CharmMass is the mass of the charm hadron /// \return relative momentum of pair template -T computeRelativeMomentum(const std::array& pTrack, const std::array& CharmCandMomentum, const T& CharmMass) +inline T HfFilterHelper::computeRelativeMomentum(const std::array& pTrack, const std::array& CharmCandMomentum, const T& CharmMass) { ROOT::Math::PxPyPzMVector part1(pTrack[0], pTrack[1], pTrack[2], massProton); ROOT::Math::PxPyPzMVector part2(CharmCandMomentum[0], CharmCandMomentum[1], CharmCandMomentum[2], CharmMass); @@ -812,7 +1182,7 @@ T computeRelativeMomentum(const std::array& pTrack, const std::array /// Computation of the number of candidates in an event that do not share daughter tracks /// \return 0 or 1 in case of less than 2 independent candidates in a single event, 2 otherwise template -int computeNumberOfCandidates(std::vector> indices) +inline int HfFilterHelper::computeNumberOfCandidates(std::vector> indices) { if (indices.size() < 2) { return indices.size(); @@ -864,7 +1234,7 @@ int computeNumberOfCandidates(std::vector> indices) /// \param mlModelPathCCDB is the model path in CCDB /// \param timestampCCDB is the CCDB timestamp /// \return the pointer to the ONNX Ort::Experimental::Session -Ort::Experimental::Session* InitONNXSession(std::string& onnxFile, std::string partName, Ort::Env& env, Ort::SessionOptions& sessionOpt, std::vector>& inputShapes, int& dataType, bool loadModelsFromCCDB, o2::ccdb::CcdbApi& ccdbApi, std::string mlModelPathCCDB, int64_t timestampCCDB) +inline Ort::Experimental::Session* HfFilterHelper::initONNXSession(std::string& onnxFile, std::string partName, Ort::Env& env, Ort::SessionOptions& sessionOpt, std::vector>& inputShapes, int& dataType, bool loadModelsFromCCDB, o2::ccdb::CcdbApi& ccdbApi, std::string mlModelPathCCDB, int64_t timestampCCDB) { // hard coded, we do not let the user change this sessionOpt.SetIntraOpNumThreads(1); @@ -900,7 +1270,7 @@ Ort::Experimental::Session* InitONNXSession(std::string& onnxFile, std::string p /// \param inputShapes is the input shape /// \return the array with the three output scores template -std::array PredictONNX(std::vector& inputFeatures, std::shared_ptr& session, std::vector>& inputShapes) +inline std::array HfFilterHelper::predictONNX(std::vector& inputFeatures, std::shared_ptr& session, std::vector>& inputShapes) { std::array scores{-1., 2., 2.}; std::vector inputTensor{}; @@ -927,44 +1297,206 @@ std::array PredictONNX(std::vector& inputFeatures, std::shared_ptr& ccdbPaths) +{ + for (int iSpecie{0u}; iSpecie < 6; ++iSpecie) { + std::map metadata; + auto hSpline = ccdbApi.retrieveFromTFileAny(ccdbPaths[iSpecie], metadata, bunchCrossing.timestamp()); + + if (!hSpline) { + LOG(fatal) << "File from CCDB in path " << ccdbPaths[iSpecie] << " was not found for run " << bunchCrossing.runNumber(); + } + + TAxis* axis = hSpline->GetXaxis(); + mBetheBlochPiKaPr[iSpecie] = {static_cast(hSpline->GetBinContent(axis->FindBin("bb1"))), + static_cast(hSpline->GetBinContent(axis->FindBin("bb2"))), + static_cast(hSpline->GetBinContent(axis->FindBin("bb3"))), + static_cast(hSpline->GetBinContent(axis->FindBin("bb4"))), + static_cast(hSpline->GetBinContent(axis->FindBin("bb5"))), + static_cast(hSpline->GetBinContent(axis->FindBin("Resolution")))}; + } +} + +/// load the TPC PID recalibration maps from the CCDB +/// \param ccdb is the CCDB object +/// \param bunchCrossing is the timestamp of bunchcrossing for the run number +/// \param ccdbPath is the path on CCDB for postcalibrations +inline void HfFilterHelper::setTpcRecalibMaps(o2::framework::Service const& ccdb, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string& ccdbPath) +{ + auto calibList = ccdb->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); + if (!calibList) { + LOG(fatal) << "Can not find the TPC Post Calibration object!"; + } + mHistMapPiPr[0] = nullptr; + mHistMapPiPr[1] = nullptr; + mHistMapPiPr[2] = nullptr; + mHistMapPiPr[3] = nullptr; + + mHistMapPiPr[0] = reinterpret_cast(calibList->FindObject("mean_map_pion")); + mHistMapPiPr[1] = reinterpret_cast(calibList->FindObject("sigma_map_pion")); + mHistMapPiPr[2] = reinterpret_cast(calibList->FindObject("mean_map_proton")); + mHistMapPiPr[3] = reinterpret_cast(calibList->FindObject("sigma_map_proton")); + + if (!mHistMapPiPr[0] || !mHistMapPiPr[1] || !mHistMapPiPr[0] || !mHistMapPiPr[1]) { + LOG(fatal) << "Can not find histograms!"; + } +} + +/// Basic selection of proton candidates for Lc +/// \param track is a track +/// \param nsigmaTPCProton max NsigmaTPC for proton candidates +/// \param nsigmaTOFProton max NsigmaTOF for proton candidates +/// \return true if track passes all cuts +template +inline bool HfFilterHelper::isSelectedProton4CharmBaryons(const T& track, const float& nsigmaTPCProton, const float& nsigmaTOFProton) +{ + float NSigmaTPC = track.tpcNSigmaPr(); + float NSigmaTOF = track.tofNSigmaPr(); + + if (mTpcPidCalibrationOption == 1) { + NSigmaTPC = getTPCPostCalib(track, kPr); + } else if (mTpcPidCalibrationOption == 2) { + if (track.sign() > 0) { + NSigmaTPC = getTPCSplineCalib(track, kPr); + } else { + NSigmaTPC = getTPCSplineCalib(track, kAntiPr); + } + } + + if (std::fabs(NSigmaTPC) > nsigmaTPCProton) { + return false; + } + if (track.hasTOF() && std::fabs(NSigmaTOF) > nsigmaTOFProton) { + return false; + } + + return true; +} + +/// Basic selection of kaon candidates for charm candidates +/// \param track is a track +/// \param nsigmaTPCKaon max NsigmaTPC for kaon candidates +/// \param nsigmaTOFKaon max NsigmaTOF for kaon candidates +/// \return true if track passes all cuts +template +inline bool HfFilterHelper::isSelectedKaon4Charm3Prong(const T& track, const float& nsigmaTPCKaon, const float& nsigmaTOFKaon) +{ + float NSigmaTPC = track.tpcNSigmaKa(); + float NSigmaTOF = track.tofNSigmaKa(); + + if (mTpcPidCalibrationOption == 1) { + NSigmaTPC = getTPCPostCalib(track, kKa); + } else if (mTpcPidCalibrationOption == 2) { + if (track.sign() > 0) { + NSigmaTPC = getTPCSplineCalib(track, kKa); + } else { + NSigmaTPC = getTPCSplineCalib(track, kAntiKa); + } + } + + if (std::fabs(NSigmaTPC) > mNSigmaTpcKaCutFor3Prongs) { + return false; + } + if (track.hasTOF() && std::fabs(NSigmaTOF) > mNSigmaTofKaCutFor3Prongs) { + return false; + } + + return true; +} + +/// Update the TPC PID baesd on the spline of particles +/// \param track is a track parameter +/// \param pidSpecies is the particle species to be considered +/// \return updated nsigma value for TPC PID +template +inline double HfFilterHelper::getTPCSplineCalib(const T& track, const int& pidSpecies) +{ + float mMassPar{0.}; + if (pidSpecies == kPi || pidSpecies == kAntiPi) { + mMassPar = massPi; + } else if (pidSpecies == kKa || pidSpecies == kAntiKa) { + mMassPar = massKa; + } else if (pidSpecies == kPr || pidSpecies == kAntiPr) { + mMassPar = massProton; + } else { + LOGP(fatal, "TPC recalibrated Nsigma requested for unknown particle species, return 999"); + return 999.; + } + + auto bgScaling = 1 / mMassPar; + double expBethe = tpc::BetheBlochAleph(static_cast(track.tpcInnerParam() * bgScaling), mBetheBlochPiKaPr[pidSpecies][0], mBetheBlochPiKaPr[pidSpecies][1], mBetheBlochPiKaPr[pidSpecies][2], mBetheBlochPiKaPr[pidSpecies][3], mBetheBlochPiKaPr[pidSpecies][4]); + double expSigma = expBethe * mBetheBlochPiKaPr[pidSpecies][5]; + return static_cast((track.tpcSignal() - expBethe) / expSigma); +} + /// compute TPC postcalibrated nsigma based on calibration histograms from CCDB /// \param hCalibMean calibration histograms of mean from CCDB /// \param hCalibSigma calibration histograms of sigma from CCDB /// \param track is the track /// \param pidSpecies is the PID species /// \return the corrected Nsigma value for the PID species -template -float getTPCPostCalib(const array& hCalibMap, const T& track, const int pidSpecies) +template +inline float HfFilterHelper::getTPCPostCalib(const T& track, const int& pidSpecies) { - auto tpcNCls = track.tpcNClsFound(); - auto tpcPin = track.tpcInnerParam(); - auto eta = track.eta(); - auto tpcNSigma = 0.; + float tpcNCls = track.tpcNClsFound(); + float tpcPin = track.tpcInnerParam(); + float eta = track.eta(); + float tpcNSigma{0.}; + int iHist{0}; if (pidSpecies == kKa) { tpcNSigma = track.tpcNSigmaKa(); + iHist = 0; // same as pions } else if (pidSpecies == kPi) { tpcNSigma = track.tpcNSigmaPi(); + iHist = 0; } else if (pidSpecies == kPr) { tpcNSigma = track.tpcNSigmaPr(); + iHist = 2; } else { LOG(fatal) << "Wrong PID Species be selected, please check!"; } - auto binTPCNCls = hCalibMap[0]->GetXaxis()->FindBin(tpcNCls); + if (!mHistMapPiPr[iHist] || !mHistMapPiPr[iHist + 1]) { + LOGP(warn, "Postcalibration TPC PID histograms not set. Use default Nsigma values."); + } + + auto binTPCNCls = mHistMapPiPr[iHist]->GetXaxis()->FindBin(tpcNCls); binTPCNCls = (binTPCNCls == 0 ? 1 : binTPCNCls); - binTPCNCls = std::min(hCalibMap[0]->GetXaxis()->GetNbins(), binTPCNCls); - auto binPin = hCalibMap[0]->GetYaxis()->FindBin(tpcPin); + binTPCNCls = std::min(mHistMapPiPr[iHist]->GetXaxis()->GetNbins(), binTPCNCls); + auto binPin = mHistMapPiPr[iHist]->GetYaxis()->FindBin(tpcPin); binPin = (binPin == 0 ? 1 : binPin); - binPin = std::min(hCalibMap[0]->GetYaxis()->GetNbins(), binPin); - auto binEta = hCalibMap[0]->GetZaxis()->FindBin(eta); + binPin = std::min(mHistMapPiPr[iHist]->GetYaxis()->GetNbins(), binPin); + auto binEta = mHistMapPiPr[iHist]->GetZaxis()->FindBin(eta); binEta = (binEta == 0 ? 1 : binEta); - binEta = std::min(hCalibMap[0]->GetZaxis()->GetNbins(), binEta); + binEta = std::min(mHistMapPiPr[iHist]->GetZaxis()->GetNbins(), binEta); - auto mean = hCalibMap[0]->GetBinContent(binTPCNCls, binPin, binEta); - auto width = hCalibMap[1]->GetBinContent(binTPCNCls, binPin, binEta); + auto mean = mHistMapPiPr[iHist]->GetBinContent(binTPCNCls, binPin, binEta); + auto width = mHistMapPiPr[iHist + 1]->GetBinContent(binTPCNCls, binPin, binEta); return (tpcNSigma - mean) / width; } + +/// Finds pT bin in an array. +/// \param bins array of pT bins +/// \param value pT +/// \return index of the pT bin +/// \note Accounts for the offset so that pt bin array can be used to also configure a histogram axis. +template +inline int HfFilterHelper::findBin(T1 const& binsPt, T2 value) +{ + if (value < binsPt.front()) { + return -1; + } + if (value >= binsPt.back()) { + return -1; + } + return std::distance(binsPt.begin(), std::upper_bound(binsPt.begin(), binsPt.end(), value)) - 1; +} + } // namespace hffilters /// definition of tables diff --git a/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx b/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx index ec43e3770ec..72a530c015c 100644 --- a/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx +++ b/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx @@ -18,26 +18,29 @@ /// \author Alexandre Bigot , Strasbourg University /// \author Biao Zhang , CCNU +#include // needed for HFFilterHelpers, to be fixed + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/Propagator.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -// needed for HFFilterHelpers, to be fixed -#include - -#include "HFFilterHelpers.h" - +#include "Common/Core/trackUtilities.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include +#include "EventFiltering/PWGHF/HFFilterHelpers.h" using namespace o2; +using namespace o2::analysis; +using namespace o2::aod::hffilters; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hffilters; struct HfFilterPrepareMlSamples { // Main struct @@ -47,7 +50,7 @@ struct HfFilterPrepareMlSamples { // Main struct // parameters for production of training samples Configurable fillSignal{"fillSignal", true, "Flag to fill derived tables with signal for ML trainings"}; Configurable fillBackground{"fillBackground", true, "Flag to fill derived tables with background for ML trainings"}; - Configurable donwSampleBkgFactor{"donwSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; // CCDB configuration o2::ccdb::CcdbApi ccdbApi; @@ -59,7 +62,7 @@ struct HfFilterPrepareMlSamples { // Main struct o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int currentRun = 0; // needed to detect if the run changed and trigger update of calibrations etc. - void init(o2::framework::InitContext&) + void init(InitContext&) { ccdb->setURL(url.value); ccdb->setCaching(true); @@ -72,7 +75,7 @@ struct HfFilterPrepareMlSamples { // Main struct void process(aod::Hf2Prongs const& cand2Prongs, aod::Hf3Prongs const& cand3Prongs, - aod::McParticles const& particlesMC, + aod::McParticles const& mcParticles, soa::Join const& collisions, BigTracksMCPID const&, aod::BCsWithTimestamps const&) @@ -110,18 +113,18 @@ struct HfFilterPrepareMlSamples { // Main struct auto pVec2Prong = RecoDecay::pVec(pVecPos, pVecNeg); auto pt2Prong = RecoDecay::pt(pVec2Prong); - auto invMassD0 = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{massPi, massK}); - auto invMassD0bar = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{massK, massPi}); + auto invMassD0 = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{massPi, massKa}); + auto invMassD0bar = RecoDecay::m(std::array{pVecPos, pVecNeg}, std::array{massKa, massPi}); int8_t sign = 0; int8_t flag = RecoDecay::OriginType::None; // D0(bar) → π± K∓ bool isInCorrectColl{false}; - auto indexRec = RecoDecay::getMatchedMCRec(particlesMC, std::array{trackPos, trackNeg}, pdg::Code::kD0, array{+kPiPlus, -kKPlus}, true, &sign); + auto indexRec = RecoDecay::getMatchedMCRec(mcParticles, std::array{trackPos, trackNeg}, pdg::Code::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign); if (indexRec > -1) { - auto particle = particlesMC.rawIteratorAt(indexRec); - flag = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + flag = RecoDecay::getCharmHadronOrigin(mcParticles, particle); isInCorrectColl = (collision.mcCollisionId() == particle.mcCollisionId()); if (flag < RecoDecay::OriginType::Prompt) { continue; @@ -129,7 +132,7 @@ struct HfFilterPrepareMlSamples { // Main struct } float pseudoRndm = trackPos.pt() * 1000. - (int64_t)(trackPos.pt() * 1000); - if ((fillSignal && indexRec > -1) || (fillBackground && indexRec < 0 && pseudoRndm < donwSampleBkgFactor)) { + if ((fillSignal && indexRec > -1) || (fillBackground && indexRec < 0 && pseudoRndm < downSampleBkgFactor)) { train2P(invMassD0, invMassD0bar, pt2Prong, trackParPos.getPt(), dcaPos[0], dcaPos[1], trackPos.tpcNSigmaPi(), trackPos.tpcNSigmaKa(), trackPos.tofNSigmaPi(), trackPos.tofNSigmaKa(), trackParNeg.getPt(), dcaNeg[0], dcaNeg[1], trackNeg.tpcNSigmaPi(), trackNeg.tpcNSigmaKa(), trackNeg.tofNSigmaPi(), trackNeg.tofNSigmaKa(), flag, isInCorrectColl); } @@ -177,49 +180,49 @@ struct HfFilterPrepareMlSamples { // Main struct auto pVec3Prong = RecoDecay::pVec(pVecFirst, pVecSecond, pVecThird); auto pt3Prong = RecoDecay::pt(pVec3Prong); - auto invMassDplus = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massK, massPi}); + auto invMassDplus = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massKa, massPi}); - auto invMassDsToKKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massK, massK, massPi}); - auto invMassDsToPiKK = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massK, massK}); + auto invMassDsToKKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massKa, massKa, massPi}); + auto invMassDsToPiKK = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massKa, massKa}); - auto invMassLcToPKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massProton, massK, massPi}); - auto invMassLcToPiKP = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massK, massProton}); + auto invMassLcToPKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massProton, massKa, massPi}); + auto invMassLcToPiKP = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massKa, massProton}); - auto invMassXicToPKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massProton, massK, massPi}); - auto invMassXicToPiKP = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massK, massProton}); + auto invMassXicToPKPi = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massProton, massKa, massPi}); + auto invMassXicToPiKP = RecoDecay::m(std::array{pVecFirst, pVecSecond, pVecThird}, std::array{massPi, massKa, massProton}); float deltaMassKKFirst = -1.f; float deltaMassKKSecond = -1.f; if (TESTBIT(cand3Prong.hfflag(), o2::aod::hf_cand_3prong::DecayType::DsToKKPi)) { - deltaMassKKFirst = std::abs(RecoDecay::m(std::array{pVecFirst, pVecSecond}, std::array{massK, massK}) - massPhi); - deltaMassKKSecond = std::abs(RecoDecay::m(std::array{pVecThird, pVecSecond}, std::array{massK, massK}) - massPhi); + deltaMassKKFirst = std::abs(RecoDecay::m(std::array{pVecFirst, pVecSecond}, std::array{massKa, massKa}) - massPhi); + deltaMassKKSecond = std::abs(RecoDecay::m(std::array{pVecThird, pVecSecond}, std::array{massKa, massKa}) - massPhi); } int8_t sign = 0; int8_t flag = RecoDecay::OriginType::None; int8_t channel = -1; // D± → π± K∓ π± - auto indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kDPlus, array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + auto indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); if (indexRec >= 0) { channel = kDplus; } if (indexRec < 0) { // Ds± → K± K∓ π± - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kDS, array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); if (indexRec >= 0) { channel = kDs; } } if (indexRec < 0) { // Λc± → p± K∓ π± - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); if (indexRec >= 0) { channel = kLc; } } if (indexRec < 0) { // Ξc± → p± K∓ π± - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kXiCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); if (indexRec >= 0) { channel = kXic; } @@ -227,8 +230,8 @@ struct HfFilterPrepareMlSamples { // Main struct bool isInCorrectColl{false}; if (indexRec > -1) { - auto particle = particlesMC.rawIteratorAt(indexRec); - flag = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + flag = RecoDecay::getCharmHadronOrigin(mcParticles, particle); isInCorrectColl = (collision.mcCollisionId() == particle.mcCollisionId()); if (flag < RecoDecay::OriginType::Prompt) { continue; @@ -236,7 +239,7 @@ struct HfFilterPrepareMlSamples { // Main struct } float pseudoRndm = trackFirst.pt() * 1000. - (int64_t)(trackFirst.pt() * 1000); - if ((fillSignal && indexRec > -1) || (fillBackground && indexRec < 0 && pseudoRndm < donwSampleBkgFactor)) { + if ((fillSignal && indexRec > -1) || (fillBackground && indexRec < 0 && pseudoRndm < downSampleBkgFactor)) { train3P(invMassDplus, invMassDsToKKPi, invMassDsToPiKK, invMassLcToPKPi, invMassLcToPiKP, invMassXicToPKPi, invMassXicToPiKP, pt3Prong, deltaMassKKFirst, deltaMassKKSecond, trackParFirst.getPt(), dcaFirst[0], dcaFirst[1], trackFirst.tpcNSigmaPi(), trackFirst.tpcNSigmaKa(), trackFirst.tpcNSigmaPr(), trackFirst.tofNSigmaPi(), trackFirst.tofNSigmaKa(), trackFirst.tofNSigmaPr(), trackParSecond.getPt(), dcaSecond[0], dcaSecond[1], trackSecond.tpcNSigmaPi(), trackSecond.tpcNSigmaKa(), trackSecond.tpcNSigmaPr(), trackSecond.tofNSigmaPi(), trackSecond.tofNSigmaKa(), trackSecond.tofNSigmaPr(), diff --git a/EventFiltering/PWGHF/HFFilterQC.cxx b/EventFiltering/PWGHF/HFFilterQC.cxx index 2e4e497d18c..734b2f189f5 100644 --- a/EventFiltering/PWGHF/HFFilterQC.cxx +++ b/EventFiltering/PWGHF/HFFilterQC.cxx @@ -17,18 +17,18 @@ /// \author Biao Zhang , CCNU /// \author Alexandre Bigot , Strasbourg University +#include // needed for HFFilterHelpers, to be fixed + #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -// needed for HFFilterHelpers, to be fixed -#include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "EventFiltering/filterTables.h" -#include "HFFilterHelpers.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "EventFiltering/PWGHF/HFFilterHelpers.h" using namespace o2; using namespace o2::aod; @@ -44,7 +44,7 @@ struct HfFilterQc { // Main struct for HF trigger QC HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - void init(o2::framework::InitContext&) + void init(InitContext&) { // Initialize the histograms hPartPerEvent[0] = registry.add("hPartPerEventAll", "All events;;number of particles", HistType::kTH2F, {{kNCharmParticles, -0.5, kNCharmParticles - 0.5}, {11, -0.5, 10.5}}); @@ -65,13 +65,13 @@ struct HfFilterQc { // Main struct for HF trigger QC /// Loops over particle species and checks whether the analysed particle is the correct one /// \param pdgDau tuple with PDG daughter codes for the desired decay - /// \param particlesMC table with MC particles + /// \param mcParticles table with MC particles /// \param particle MC particle /// \param nParticles array with number of particles found for each particle species /// \param triggerDecision array with trigger decision template constexpr void checkParticleDecay(std::tuple pdgDau, - const T& particlesMC, + const T& mcParticles, const U& particle, A& nParticles, const std::array& triggerDecision) @@ -83,7 +83,7 @@ struct HfFilterQc { // Main struct for HF trigger QC return; } else { int8_t sign = 0; - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdgCodesCharm[I], std::get(pdgDau), true, &sign, 2)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodesCharm[I], std::get(pdgDau), true, &sign, 2)) { nParticles[I]++; hPtDistr[0]->Fill(static_cast(I), static_cast(particle.pt())); for (auto iTrig = 0; iTrig < kNtriggersHF; ++iTrig) { @@ -94,12 +94,12 @@ struct HfFilterQc { // Main struct for HF trigger QC } // Going for next element. - checkParticleDecay(pdgDau, particlesMC, particle, nParticles, triggerDecision); + checkParticleDecay(pdgDau, mcParticles, particle, nParticles, triggerDecision); } } void process(HfFilter const& filterDecision, - McParticles const& particlesMC) + McParticles const& mcParticles) { bool hasHighPt2P = filterDecision.hasHfHighPt2P(); bool hasHighPt3P = filterDecision.hasHfHighPt3P(); @@ -110,16 +110,17 @@ struct HfFilterQc { // Main struct for HF trigger QC bool hasDoubleCharm2P = filterDecision.hasHfDoubleCharm2P(); bool hasDoubleCharm3P = filterDecision.hasHfDoubleCharm3P(); bool hasDoubleCharmMix = filterDecision.hasHfDoubleCharmMix(); - bool hasHfSoftGamma2P = filterDecision.hasHfSoftGamma2P(); - bool hasHfSoftGamma3P = filterDecision.hasHfSoftGamma3P(); - bool isTriggered = hasHighPt2P || hasHighPt3P || hasBeauty3P || hasBeauty4P || hasFemto2P || hasFemto3P || hasDoubleCharm2P || hasDoubleCharm3P || hasDoubleCharmMix || hasHfSoftGamma2P || hasHfSoftGamma3P; - auto triggerDecision = std::array{isTriggered, hasHighPt2P, hasHighPt3P, hasBeauty3P, hasBeauty4P, hasFemto2P, hasFemto3P, hasDoubleCharm2P, hasDoubleCharm3P, hasDoubleCharmMix, hasHfSoftGamma2P, hasHfSoftGamma3P}; + bool hasHfV02P = filterDecision.hasHfV0Charm2P(); + bool hasHfV03P = filterDecision.hasHfV0Charm3P(); + bool hasCharmBarToXiBach = filterDecision.hasHfCharmBarToXiBach(); + bool isTriggered = hasHighPt2P || hasHighPt3P || hasBeauty3P || hasBeauty4P || hasFemto2P || hasFemto3P || hasDoubleCharm2P || hasDoubleCharm3P || hasDoubleCharmMix || hasHfV02P || hasHfV03P || hasCharmBarToXiBach; + auto triggerDecision = std::array{isTriggered, hasHighPt2P, hasHighPt3P, hasBeauty3P, hasBeauty4P, hasFemto2P, hasFemto3P, hasDoubleCharm2P, hasDoubleCharm3P, hasDoubleCharmMix, hasHfV02P, hasHfV03P, hasCharmBarToXiBach}; std::array nPart{0}; // Loop over the MC particles - for (auto const& particle : particlesMC) { + for (const auto& particle : mcParticles) { // Check if the particle is of interest - checkParticleDecay(pdgCharmDaughters, particlesMC, particle, nPart, triggerDecision); + checkParticleDecay(pdgCharmDaughters, mcParticles, particle, nPart, triggerDecision); } for (auto iPart = 0; iPart < kNCharmParticles; ++iPart) { diff --git a/EventFiltering/PWGJE/fullJetFilter.cxx b/EventFiltering/PWGJE/fullJetFilter.cxx index 7a81ed67b3c..4b03bd01cf0 100644 --- a/EventFiltering/PWGJE/fullJetFilter.cxx +++ b/EventFiltering/PWGJE/fullJetFilter.cxx @@ -12,10 +12,16 @@ // Full Jet Filter // Author: Gijs van Weelden +#include #include #include +#include #include +#include + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCTP/Configuration.h" #include "EMCALBase/Geometry.h" #include "ReconstructionDataFormats/Track.h" #include "Framework/runDataProcessing.h" @@ -39,37 +45,74 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using selectedClusters = o2::soa::Filtered; -using filteredJets = o2::soa::Filtered; struct fullJetFilter { + using collisionInfo = soa::Join::iterator; + using BCsWithBcSelsRun3 = soa::Join; + using selectedClusters = o2::soa::Filtered; + using filteredFullJets = o2::soa::Filtered; + using filteredNeutralJets = o2::soa::Filtered; + enum { kEMCALReadout = 0, kJetFullHighPt, + kJetFullLowPt, kJetNeutralHighPt, + kJetNeutralLowPt, + kGammaVeryHighPtEMCAL, + kGammaVeryHighPtDCAL, kGammaHighPtEMCAL, kGammaHighPtDCAL, kGammaLowPtEMCAL, kGammaLowPtDCAL, + kGammaVeryLowPtEMCAL, + kGammaVeryLowPtDCAL, kCategories }; enum class ThresholdType_t { + VERY_HIGH_THRESHOLD, HIGH_THRESHOLD, - LOW_THRESHOLD + LOW_THRESHOLD, + VERY_LOW_THRESHOLD + }; + + enum class EMCALHWTriggerConfiguration { + MB_ONLY, + EMC_TRIGGERD, + UNKNOWN + }; + + enum EMCALHardwareTrigger { + TRG_MB, + TRG_EMC7, + TRG_DMC7, + TRG_NTriggers }; Produces tags; - OutputObj hProcessedEvents{"hProcessedEvents"}; + OutputObj hProcessedEvents{"hProcessedEvents"}; OutputObj hEmcClusterPtEta{"hEmcClusterPtEta"}; OutputObj hEmcClusterPtPhi{"hEmcClusterPtPhi"}; + OutputObj hEmcClusterPtEtaMinBias{"hEmcClusterPtEtaMinBias"}; + OutputObj hEmcClusterPtPhiMinBias{"hEmcClusterPtPhiMinBias"}; + OutputObj hEmcClusterPtEtaLevel0{"hEmcClusterPtEtaLevel0"}; + OutputObj hEmcClusterPtPhiLevel0{"hEmcClusterPtPhiLevel0"}; OutputObj hSelectedClusterPtEta{"hSelectedClusterEta"}; OutputObj hSelectedClusterPtPhi{"hSelectedClusterPhi"}; + OutputObj hSelectedClusterPtEtaLow{"hSelectedClusterEtaLow"}; + OutputObj hSelectedClusterPtPhiLow{"hSelectedClusterPhiLow"}; OutputObj hEmcJetPtEta{"hEmcJetEta"}; OutputObj hEmcJetPtPhi{"hEmcJetPhi"}; OutputObj hSelectedJetPtEta{"hSelectedJetEta"}; OutputObj hSelectedJetPtPhi{"hSelectedJetPhi"}; + OutputObj hSelectedJetPtEtaLow{"hSelectedJetEtaLow"}; + OutputObj hSelectedJetPtPhiLow{"hSelectedJetPhiLow"}; + OutputObj hSelectedGammaEMCALPtEtaVeryHigh{"hSelectedGammaEMCALEtaVeryHigh"}; + OutputObj hSelectedGammaEMCALPtPhiVeryHigh{"hSelectedGammaEMCALPhiVeryHigh"}; + OutputObj hSelectedGammaDCALPtEtaVeryHigh{"hSelectedGammaDCALEtaVeryHigh"}; + OutputObj hSelectedGammaDCALPtPhiVeryHigh{"hSelectedGammaDCALPhiVeryHigh"}; OutputObj hSelectedGammaEMCALPtEta{"hSelectedGammaEMCALEta"}; OutputObj hSelectedGammaEMCALPtPhi{"hSelectedGammaEMCALPhi"}; OutputObj hSelectedGammaDCALPtEta{"hSelectedGammaDCALEta"}; @@ -78,19 +121,50 @@ struct fullJetFilter { OutputObj hSelectedGammaEMCALPtPhiLow{"hSelectedGammaEMCALPhiLow"}; OutputObj hSelectedGammaDCALPtEtaLow{"hSelectedGammaDCALEtaLow"}; OutputObj hSelectedGammaDCALPtPhiLow{"hSelectedGammaDCALPhiLow"}; + OutputObj hSelectedGammaEMCALPtEtaVeryLow{"hSelectedGammaEMCALEtaVeryLow"}; + OutputObj hSelectedGammaEMCALPtPhiVeryLow{"hSelectedGammaEMCALPhiVeryLow"}; + OutputObj hSelectedGammaDCALPtEtaVeryLow{"hSelectedGammaDCALEtaVeryLow"}; + OutputObj hSelectedGammaDCALPtPhiVeryLow{"hSelectedGammaDCALPhiVeryLow"}; + OutputObj hMaxJetPt{"hMaxJetPt"}; + OutputObj hSelectMaxJetPt{"hSelectMaxJetPt"}; + OutputObj hSelectMaxJetPtLow{"hSelectMaxJetPtLow"}; + OutputObj hMaxClusterEMCAL{"hMaxClusterEMCAL"}; + OutputObj hMaxClusterDCAL{"hMaxClusterDCAL"}; + OutputObj hMaxClusterEMCALMinBias{"hMaxClusterEMCALMinBias"}; + OutputObj hMaxClusterDCALMinBias{"hMaxClusterDCALMinBias"}; + OutputObj hMaxClusterEMCALLevel0{"hMaxClusterEMCALLevel0"}; + OutputObj hMaxClusterDCALLevel0{"hMaxClusterDCALLevel0"}; + OutputObj hSelectGammaVeryHighMaxClusterEMCAL{"hSelectGammaVeryHighMaxClusterEMCAL"}; + OutputObj hSelectGammaMaxClusterEMCAL{"hSelectGammaMaxClusterEMCAL"}; + OutputObj hSelectGammaLowMaxClusterEMCAL{"hSelectGammaLowMaxClusterEMCAL"}; + OutputObj hSelectGammaVeryLowMaxClusterEMCAL{"hSelectGammaVeryLowMaxClusterEMCAL"}; + OutputObj hSelectGammaVeryHighMaxClusterDCAL{"hSelectGammaVeryHighMaxClusterDCAL"}; + OutputObj hSelectGammaMaxClusterDCAL{"hSelectGammaMaxClusterDCAL"}; + OutputObj hSelectGammaLowMaxClusterDCAL{"hSelectGammaLowMaxClusterDCAL"}; + OutputObj hSelectGammaVeryLowMaxClusterDCAL{"hSelectGammaVertLowMaxClusterDCAL"}; // Configurables Configurable f_jetPtMin{"f_jetPtMin", 0.0, "minimum jet pT cut"}; + Configurable f_jetPtMinLow{"f_jetPtMinLow", 0.0, "minimum jet pT cut (low threshold)"}; + Configurable f_jetPtMinMB{"f_jetPtMinMB", 0.0, "minimum jet pT cut (MB-only runs)"}; + Configurable f_jetPtMinLowMB{"f_jetPtMinLowMB", 0.0, "minimum jet pT cut (low threshold, MB-only runs)"}; Configurable f_clusterPtMin{"f_clusterPtMin", 0.0, "minimum cluster pT cut"}; Configurable f_jetR{"f_jetR", 20, "jet R * 100 to trigger on"}; - Configurable f_JetType{"f_JetType", 0, "Jet type used for the selection (0 - full jets, 1 - neutral jets)"}; Configurable f_ObservalbeGammaTrigger{"fObservableGammaTrigger", 0, "Observable for the gamma trigger (0 - Energy, 1 - pt)"}; Configurable b_PublishReadoutTrigger{"b_publishReadoutTrigger", false, "Publish EMCAL readout status as trigger flag"}; Configurable b_PublishNeutralJetTrigger{"b_publishNeutralJetTrigger", false, "Publish trigger on neutral jets"}; + Configurable f_gammaPtMinEMCALVeryHigh{"f_gammaPtMinEMCALVeryHigh", 9.0, "minimum gamma pT cut in EMCAL very high threshold"}; Configurable f_gammaPtMinEMCALHigh{"f_gammaPtMinEMCALHigh", 4.0, "minimum gamma pT cut in EMCAL high threshold"}; Configurable f_gammaPtMinEMCALLow{"f_gammaPtMinEMCALLow", 1.5, "minimum gamma pT cut in EMCAL low threshold"}; + Configurable f_gammaPtMinEMCALVeryLow{"f_gammaPtMinEMCALVeryLow", 0.5, "minimum gamma pT cut in EMCAL very low threshold"}; + Configurable f_gammaPtMinDCALVeryHigh{"f_gammaPtMinDCALVeryHigh", 9.0, "minimum gamma pT cut in DCAL very high threshold"}; Configurable f_gammaPtMinDCALHigh{"f_gammaPtMinDCALHigh", 4.0, "minimum gamma pT cut in DCAL high threshold"}; Configurable f_gammaPtMinDCALLow{"f_gammaPtMinDCALLow", 1.5, "minimum gamma pT cut in DCAL low threshold"}; + Configurable f_gammaPtMinDCALVeryLow{"f_gammaPtMinDCALVeryLow", 0.5, "minimum gamma pT cut in DCAL very low threshold"}; + Configurable f_gammaPtMinEMCALHighMB{"f_gammaPtMinEMCALHighMB", 4.0, "minimum gamma pT cut in EMCAL high threshold (MB-only runs)"}; + Configurable f_gammaPtMinEMCALLowMB{"f_gammaPtMinEMCALLowMB", 1.5, "minimum gamma pT cut in EMCAL low threshold (MB-only runs)"}; + Configurable f_gammaPtMinDCALHighMB{"f_gammaPtMinDCALHighMB", 4.0, "minimum gamma pT cut in DCAL high threshold (MB-only runs)"}; + Configurable f_gammaPtMinDCALLowMB{"f_gammaPtMinDCALLowMB", 1.5, "minimum gamma pT cut in DCAL low threshold (MB-only runs)"}; Configurable f_minClusterTime{"f_minClusterTime", -999, "Min. cluster time for gamma trigger (ns)"}; Configurable f_maxClusterTime{"f_maxClusterTime", 999, "Max. cluster time for gamma trigger (ns)"}; Configurable f_PhiEmcalOrDcal{"f_PhiEmcalOrDcal", 4, "if cluster phi is less than this value, count it to be EMCAL"}; @@ -102,6 +176,11 @@ struct fullJetFilter { Configurable b_DoFiducialCut{"b_DoFiducialCut", false, "do a fiducial cut on jets to check if they are in the emcal"}; Configurable b_RejectExoticClusters{"b_RejectExoticClusters", true, "Reject exotic clusters"}; + int lastRun = -1; + EMCALHWTriggerConfiguration mHardwareTriggerConfig = EMCALHWTriggerConfiguration::UNKNOWN; + + Service ccdb; + void init(o2::framework::InitContext&) { @@ -116,16 +195,28 @@ struct fullJetFilter { Float_t kMinEta = -1.; Float_t kMaxEta = 1.; - hProcessedEvents.setObject(new TH1I("hProcessedEvents", ";;Number of filtered events", kCategories, -0.5, kCategories - 0.5)); + hProcessedEvents.setObject(new TH1D("hProcessedEvents", ";;Number of filtered events", kCategories, -0.5, kCategories - 0.5)); hEmcClusterPtEta.setObject(new TH2F("hEmcClusterPtEta", Form("Emc Clusters;%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); hEmcClusterPtPhi.setObject(new TH2F("hEmcClusterPtPhi", Form("Emc Clusters;%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); + hEmcClusterPtEtaMinBias.setObject(new TH2F("hEmcClusterPtEtaMinBias", Form("Emc Clusters (MB);%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); + hEmcClusterPtPhiMinBias.setObject(new TH2F("hEmcClusterPtPhiMinBias", Form("Emc Clusters (MB);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); + hEmcClusterPtEtaLevel0.setObject(new TH2F("hEmcClusterPtEtaLevel0", Form("Emc Clusters (L0);%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); + hEmcClusterPtPhiLevel0.setObject(new TH2F("hEmcClusterPtPhiLevel0", Form("Emc Clusters (L0);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); hSelectedClusterPtEta.setObject(new TH2F("hSelectedClusterPtEta", Form("Selected Clusters;%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); hSelectedClusterPtPhi.setObject(new TH2F("hSelectedClusterPtPhi", Form("Selected Clusters;%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); + hSelectedClusterPtEtaLow.setObject(new TH2F("hSelectedClusterPtEtaLow", Form("Selected Clusters (low threshold);%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); + hSelectedClusterPtPhiLow.setObject(new TH2F("hSelectedClusterPtPhiLow", Form("Selected Clusters (low threshold);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); hEmcJetPtEta.setObject(new TH2F("hEmcJetPtEta", "Emc Jets;#it{p}_{T};#eta", nPtBins, kMinPt, kMaxPt, nEtaBins, kMinEta, kMaxEta)); hEmcJetPtPhi.setObject(new TH2F("hEmcJetPtPhi", "Emc Jets;#it{p}_{T};#phi", nPtBins, kMinPt, kMaxPt, nPhiBins, kMinPhi, kMaxPhi)); hSelectedJetPtEta.setObject(new TH2F("hSelectedJetPtEta", "Selected Jets;#it{p}_{T};#eta", nPtBins, kMinPt, kMaxPt, nEtaBins, kMinEta, kMaxEta)); hSelectedJetPtPhi.setObject(new TH2F("hSelectedJetPtPhi", "Selected Jets;#it{p}_{T};#phi", nPtBins, kMinPt, kMaxPt, nPhiBins, kMinPhi, kMaxPhi)); + hSelectedJetPtEtaLow.setObject(new TH2F("hSelectedJetPtEtaLow", "Selected Jets (low threshold);#it{p}_{T};#eta", nPtBins, kMinPt, kMaxPt, nEtaBins, kMinEta, kMaxEta)); + hSelectedJetPtPhiLow.setObject(new TH2F("hSelectedJetPtPhiLow", "Selected Jets (low threshold);#it{p}_{T};#phi", nPtBins, kMinPt, kMaxPt, nPhiBins, kMinPhi, kMaxPhi)); + hSelectedGammaEMCALPtEtaVeryHigh.setObject(new TH2F("hSelectedGammaEMCALEtaVeryHigh", Form("Selected Gammas EMCAL (very high threshold);%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); + hSelectedGammaEMCALPtPhiVeryHigh.setObject(new TH2F("hSelectedGammaEMCALPhiVeryHigh", Form("Selected Gammas EMCAL (very high threshold);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); + hSelectedGammaDCALPtEtaVeryHigh.setObject(new TH2F("hSelectedGammaDCALEtaVeryHigh", Form("Selected Gammas DCAL (very high threshold);%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); + hSelectedGammaDCALPtPhiVeryHigh.setObject(new TH2F("hSelectedGammaDCALPhiVeryHigh", Form("Selected Gammas DCAL (very high threshold);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); hSelectedGammaEMCALPtEta.setObject(new TH2F("hSelectedGammaEMCALPtEta", Form("Selected Gammas EMCAL;%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); hSelectedGammaEMCALPtPhi.setObject(new TH2F("hSelectedGammaEMCALPtPhi", Form("Selected Gammas EMCAL;%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); hSelectedGammaDCALPtEta.setObject(new TH2F("hSelectedGammaDCALPtEta", Form("Selected Gammas DCAL;%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); @@ -134,12 +225,36 @@ struct fullJetFilter { hSelectedGammaEMCALPtPhiLow.setObject(new TH2F("hSelectedGammaEMCALPtPhiLow", Form("Selected Gammas EMCAL (low threshold);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); hSelectedGammaDCALPtEtaLow.setObject(new TH2F("hSelectedGammaDCALPtEtaLow", Form("Selected Gammas DCAL (low threshold);%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); hSelectedGammaDCALPtPhiLow.setObject(new TH2F("hSelectedGammaDCALPtPhiLow", Form("Selected Gammas DCAL (low threshold);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); + hSelectedGammaEMCALPtEtaVeryLow.setObject(new TH2F("hSelectedGammaEMCALEtaVeryLow", Form("Selected Gammas EMCAL (very low threshold);%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); + hSelectedGammaEMCALPtPhiVeryLow.setObject(new TH2F("hSelectedGammaEMCALPhiVeryLow", Form("Selected Gammas EMCAL (very low threshold);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); + hSelectedGammaDCALPtEtaVeryLow.setObject(new TH2F("hSelectedGammaDCALEtaVeryLow", Form("Selected Gammas DCAL (very low threshold);%s;#eta", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nEtaBins, kMinEta, kMaxEta)); + hSelectedGammaDCALPtPhiVeryLow.setObject(new TH2F("hSelectedGammaDCALPhiVeryLow", Form("Selected Gammas DCAL (very low threshold);%s;#phi", (f_ObservalbeGammaTrigger == 0) ? "E (GeV)" : "#it{p}_{T}"), nPtBins, kMinPt, kMaxPt / 2, nPhiBins, kMinPhi, kMaxPhi)); + + hMaxJetPt.setObject(new TH1D("hMaxJetPt", "Max. jet pt", nPtBins, kMinPt, kMaxPt)); + hSelectMaxJetPt.setObject(new TH1D("hSelectMaxJetPt", "Max. jet pt selected collisions", nPtBins, kMinPt, kMaxPt)); + hSelectMaxJetPtLow.setObject(new TH1D("hSelectMaxJetPtLow", "Max. jet pt selected collisions (low threshold)", nPtBins, kMinPt, kMaxPt)); + hMaxClusterEMCAL.setObject(new TH1D("hMaxClusterEMCAL", "Max.cluster pt EMCAL", nPtBins, kMinPt, kMaxPt)); + hMaxClusterDCAL.setObject(new TH1D("hMaxClusterDCAL", "Max. cluster pt DCAL", nPtBins, kMinPt, kMaxPt)); + hMaxClusterEMCALMinBias.setObject(new TH1D("hMaxClusterEMCALMinBias", "Max.cluster pt EMCAL (min. bias)", nPtBins, kMinPt, kMaxPt)); + hMaxClusterDCALMinBias.setObject(new TH1D("hMaxClusterDCALMinBias", "Max. cluster pt DCAL (mib. bias)", nPtBins, kMinPt, kMaxPt)); + hMaxClusterEMCALLevel0.setObject(new TH1D("hMaxClusterEMCALLevel0", "Max.cluster pt EMCAL (Level-0)", nPtBins, kMinPt, kMaxPt)); + hMaxClusterDCALLevel0.setObject(new TH1D("hMaxClusterDCALLevel0", "Max. cluster pt DCAL (Level-0)", nPtBins, kMinPt, kMaxPt)); + hSelectGammaVeryHighMaxClusterEMCAL.setObject(new TH1D("hSelectGammaVeryHighMaxClusterEMCAL", "Max. cluster pt selected Gamms EMCAL (very high threshold)", nPtBins, kMinPt, kMaxPt)); + hSelectGammaMaxClusterEMCAL.setObject(new TH1D("hSelectGammaMaxClusterEMCAL", "Max. cluster pt selected Gamms EMCAL", nPtBins, kMinPt, kMaxPt)); + hSelectGammaLowMaxClusterEMCAL.setObject(new TH1D("hSelectGammaLowMaxClusterEMCAL", "Max. cluster pt selected Gamms EMCAL (low threshold)", nPtBins, kMinPt, kMaxPt)); + hSelectGammaVeryLowMaxClusterEMCAL.setObject(new TH1D("hSelectGammaVeryLowMaxClusterEMCAL", "Max. cluster pt selected Gamms EMCAL (very low threshold)", nPtBins, kMinPt, kMaxPt)); + hSelectGammaVeryHighMaxClusterDCAL.setObject(new TH1D("hSelectGammaVeryHighMaxClusterDCAL", "Max. cluster pt selected Gamms DCAL (very high threshold)", nPtBins, kMinPt, kMaxPt)); + hSelectGammaMaxClusterDCAL.setObject(new TH1D("hSelectGammaMaxClusterDCAL", "Max. cluster pt selected Gamms DCAL", nPtBins, kMinPt, kMaxPt)); + hSelectGammaLowMaxClusterDCAL.setObject(new TH1D("hSelectGammaLowMaxClusterDCAL", "Max. cluster pt selected Gamms DCAL (low threshold)", nPtBins, kMinPt, kMaxPt)); + hSelectGammaVeryLowMaxClusterDCAL.setObject(new TH1D("hSelectGammaVertLowMaxClusterDCAL", "Max. cluster pt selected Gamms DCAL (very low threshold)", nPtBins, kMinPt, kMaxPt)); LOG(info) << "Jet trigger: " << (b_doJetTrigger ? "on" : "off"); LOG(info) << "Gamma trigger: " << (b_doJetTrigger ? "on" : "off"); - LOG(info) << "Thresholds gamma trigger: EG1 " << f_gammaPtMinEMCALHigh << " GeV, DG1 " << f_gammaPtMinDCALHigh << " GeV, EG2 " << f_gammaPtMinEMCALLow << " GeV, DG2 " << f_gammaPtMinDCALLow << " GeV"; + LOG(info) << "Thresholds gamma trigger (L0-triggered runs): EG1 " << f_gammaPtMinEMCALHigh << " GeV, DG1 " << f_gammaPtMinDCALHigh << " GeV, EG2 " << f_gammaPtMinEMCALLow << " GeV, DG2 " << f_gammaPtMinDCALLow << " GeV"; + LOG(info) << "Thresholds gamma trigger (MB-triggered runs): EG1 " << f_gammaPtMinEMCALHighMB << " GeV, DG1 " << f_gammaPtMinDCALHighMB << " GeV, EG2 " << f_gammaPtMinEMCALLowMB << " GeV, DG2 " << f_gammaPtMinDCALLowMB << " GeV"; LOG(info) << "Gamma trigger observable: " << (f_ObservalbeGammaTrigger == 0 ? "Energy" : "pt"); - LOG(info) << "Jet trigger: Type: " << (f_JetType == 0 ? "Full jets" : "Neutral jets") << ", R: " << (static_cast(f_jetR) / 100.) << ", pt > " << f_jetPtMin << " cluster(" << f_clusterPtMin << ")"; + LOG(info) << "Jet trigger: R: " << (static_cast(f_jetR) / 100.) << ", pt (high threshold) > " << f_jetPtMin << " GeV/c, (low threshold) > " << f_jetPtMinLow << " GeV/c, cluster(" << f_clusterPtMin << ")"; + LOG(info) << "Jet thresholds min-bias triggered runs: High " << f_jetPtMinMB << " GeV/c, low " << f_jetPtMinLowMB << " GeV/c"; LOG(info) << "Ignore EMCAL flag: " << (b_IgnoreEmcalFlag ? "yes" : "no"); LOG(info) << "Publishing neutral jet trigger: " << (b_PublishNeutralJetTrigger ? "yes" : "no"); LOG(info) << "Publishing EMCAL trigger: " << (b_PublishReadoutTrigger ? "yes" : "no"); @@ -152,7 +267,8 @@ struct fullJetFilter { Filter clusterDefinitionSelection = o2::aod::emcalcluster::definition == static_cast(clusDef); Filter jetRadiusSelection = o2::aod::jet::r == f_jetR; - Bool_t isJetInEmcal(filteredJets::iterator const& jet) + template + Bool_t isJetInEmcal(JetIterator const& jet) { double emcalEtaMin = -0.7, emcalEtaMax = 0.7, emcalPhiMin = 1.40, emcalPhiMax = 3.26; // Phi: 80 - 187 deg double R = jet.r() * 1e-2; // Jet R is saved as round(100*R) @@ -162,26 +278,63 @@ struct fullJetFilter { return false; } - Bool_t isEvtSelected(double const& jetpt) + EMCALHWTriggerConfiguration getHWTriggerConfiguration(o2::ctp::CTPConfiguration& ctpconfig) { - if (jetpt > f_jetPtMin) { - return true; + EMCALHWTriggerConfiguration result = EMCALHWTriggerConfiguration::UNKNOWN; + bool hasMinBias = false, hasL0 = false; + for (auto& cls : ctpconfig.getCTPClasses()) { + auto trgclsname = boost::algorithm::to_upper_copy(cls.name); + if (trgclsname.find("-EMC") == std::string::npos) { + // Not an EMCAL trigger class + continue; + } + std::vector tokens; + std::stringstream tokenizer(trgclsname.data()); + std::string buf; + while (std::getline(tokenizer, buf, '-')) { + tokens.emplace_back(buf); + } + if (tokens[1] != "B") { + // Not bucket in both beams + continue; + } + LOG(info) << "Found trigger class: " << trgclsname; + if (tokens[0] == "C0TVX") { + hasMinBias = true; + } + if (tokens[0] == "CTVXEMC" || tokens[0] == "CTVXDMC") { + hasL0 = true; + } } - return false; + if (hasL0) { + result = EMCALHWTriggerConfiguration::EMC_TRIGGERD; + } else if (hasMinBias) { + result = EMCALHWTriggerConfiguration::MB_ONLY; + } + return result; } - Bool_t isEvtSelectedGamma(double const& gammapt, o2::emcal::AcceptanceType_t subdet, ThresholdType_t thresholdt) + float getGammaThreshold(o2::emcal::AcceptanceType_t subdet, ThresholdType_t thresholdt, bool mblike) { float threshold = 0; + // Very-high and very-low threshold only needed and supported for trigger-like data switch (subdet) { case o2::emcal::AcceptanceType_t::EMCAL_ACCEPTANCE: { switch (thresholdt) { + case ThresholdType_t::VERY_HIGH_THRESHOLD: { + threshold = mblike ? FLT_MAX : f_gammaPtMinEMCALVeryHigh; + break; + } case ThresholdType_t::HIGH_THRESHOLD: { - threshold = f_gammaPtMinEMCALHigh; + threshold = mblike ? f_gammaPtMinEMCALHighMB : f_gammaPtMinEMCALHigh; break; } case ThresholdType_t::LOW_THRESHOLD: { - threshold = f_gammaPtMinEMCALLow; + threshold = mblike ? f_gammaPtMinEMCALLowMB : f_gammaPtMinEMCALLow; + break; + } + case ThresholdType_t::VERY_LOW_THRESHOLD: { + threshold = mblike ? FLT_MAX : f_gammaPtMinEMCALVeryLow; break; } } @@ -189,19 +342,89 @@ struct fullJetFilter { } case o2::emcal::AcceptanceType_t::DCAL_ACCEPTANCE: { switch (thresholdt) { + case ThresholdType_t::VERY_HIGH_THRESHOLD: { + threshold = mblike ? FLT_MAX : f_gammaPtMinDCALVeryHigh; + break; + } case ThresholdType_t::HIGH_THRESHOLD: { - threshold = f_gammaPtMinDCALHigh; + threshold = mblike ? f_gammaPtMinDCALHighMB : f_gammaPtMinDCALHigh; break; } case ThresholdType_t::LOW_THRESHOLD: { - threshold = f_gammaPtMinDCALLow; + threshold = mblike ? f_gammaPtMinDCALLowMB : f_gammaPtMinDCALLow; + break; + } + case ThresholdType_t::VERY_LOW_THRESHOLD: { + threshold = mblike ? FLT_MAX : f_gammaPtMinDCALVeryLow; break; } } break; } - case o2::emcal::AcceptanceType_t::NON_ACCEPTANCE: + case o2::emcal::AcceptanceType_t::NON_ACCEPTANCE: { + threshold = FLT_MAX; + break; + } + } + return threshold; + } + + double getJetThreshold(ThresholdType_t thresholdt, bool mblike) + { + float threshold = 0.; + switch (thresholdt) { + case ThresholdType_t::HIGH_THRESHOLD: + threshold = mblike ? f_jetPtMinMB : f_jetPtMin; + break; + case ThresholdType_t::LOW_THRESHOLD: + threshold = mblike ? f_jetPtMinLowMB : f_jetPtMinLow; + break; + default: + // Very low and very high threshold not supported for jet trigger + threshold = FLT_MAX; + } + return threshold; + } + + Bool_t isEvtSelectedJet(double const& jetpt, ThresholdType_t thresholdt) + { + float threshold = 0; + switch (mHardwareTriggerConfig) { + case EMCALHWTriggerConfiguration::EMC_TRIGGERD: { + threshold = getJetThreshold(thresholdt, false); + break; + } + case EMCALHWTriggerConfiguration::MB_ONLY: { + threshold = getJetThreshold(thresholdt, true); + break; + } + case EMCALHWTriggerConfiguration::UNKNOWN: { + // No EMCAL trigger present in run - cannot select thresholds + return false; + } + } + if (jetpt > threshold) { + return true; + } + return false; + } + + Bool_t isEvtSelectedGamma(double const& gammapt, o2::emcal::AcceptanceType_t subdet, ThresholdType_t thresholdt) + { + float threshold = 0; + switch (mHardwareTriggerConfig) { + case EMCALHWTriggerConfiguration::EMC_TRIGGERD: { + threshold = getGammaThreshold(subdet, thresholdt, false); + break; + } + case EMCALHWTriggerConfiguration::MB_ONLY: { + threshold = getGammaThreshold(subdet, thresholdt, true); + break; + } + case EMCALHWTriggerConfiguration::UNKNOWN: { + // No EMCAL trigger present in run - cannot select thresholds return false; + } } if (gammapt > threshold) { return true; @@ -217,99 +440,269 @@ struct fullJetFilter { return false; } - void process(soa::Join::iterator const& collision, filteredJets const& jets, selectedClusters const& clusters) + bool isEMCALMinBias(collisionInfo const& collision) const { - bool keepEvent[kCategories]{false}; - double maxClusterObservableEMCAL = -1., maxClusterObservableDCAL = -1., maxSelectedJetPt = -1.; + return collision.alias_bit(kTVXinEMC); + } - if (!b_IgnoreEmcalFlag && !collision.alias_bit(kTVXinEMC)) { - tags(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); - return; // Skip events where EMCAL is not live - } + bool isEMCALLevel0(collisionInfo const& collision) const + { + return collision.alias_bit(kEMC7) || collision.alias_bit(kDMC7); + } - if (b_PublishReadoutTrigger && collision.alias_bit(kTVXinEMC)) { - keepEvent[kEMCALReadout] = true; + bool isEMCALLevel1(collisionInfo const& collision) const + { + return collision.alias_bit(kEG1) || collision.alias_bit(kEG2) || collision.alias_bit(kDG1) || collision.alias_bit(kDG2) || collision.alias_bit(kEJ1) || collision.alias_bit(kEJ2) || collision.alias_bit(kDJ1) || collision.alias_bit(kDJ2); + } + + bool hasEMCALData(collisionInfo const& collision) const + { + return isEMCALMinBias(collision) || isEMCALLevel0(collision) || isEMCALLevel1(collision); + } + + void runGammaTrigger(const selectedClusters& clusters, std::bitset hardwaretriggers, std::array& keepEvent) + { + double maxClusterObservableEMCAL = -1., maxClusterObservableDCAL = -1.; + static constexpr std::array thresholds = {{ThresholdType_t::VERY_HIGH_THRESHOLD, ThresholdType_t::HIGH_THRESHOLD, ThresholdType_t::LOW_THRESHOLD, ThresholdType_t::VERY_LOW_THRESHOLD}}; + static constexpr std::array subdets = {{o2::emcal::AcceptanceType_t::EMCAL_ACCEPTANCE, o2::emcal::AcceptanceType_t::DCAL_ACCEPTANCE}}; + std::array acceptanceHistsPtEta{{hSelectedGammaEMCALPtEtaVeryHigh.object.get(), hSelectedGammaDCALPtEtaVeryHigh.object.get(), hSelectedGammaEMCALPtEta.object.get(), hSelectedGammaDCALPtEta.object.get(), hSelectedGammaEMCALPtEtaLow.object.get(), hSelectedGammaDCALPtEtaLow.object.get(), hSelectedGammaEMCALPtEtaVeryLow.object.get(), hSelectedGammaDCALPtEtaVeryLow.object.get()}}, + acceptanceHistsPtPhi{{hSelectedGammaEMCALPtPhiVeryHigh.object.get(), hSelectedGammaDCALPtPhiVeryHigh.object.get(), hSelectedGammaEMCALPtPhi.object.get(), hSelectedGammaDCALPtPhi.object.get(), hSelectedGammaEMCALPtPhiLow.object.get(), hSelectedGammaDCALPtPhiLow.object.get(), hSelectedGammaEMCALPtPhiVeryLow.object.get(), hSelectedGammaDCALPtPhiVeryLow.object.get()}}; + std::array maxClusterPtHists = {{hSelectGammaVeryHighMaxClusterEMCAL.object.get(), hSelectGammaVeryHighMaxClusterDCAL.object.get(), hSelectGammaMaxClusterEMCAL.object.get(), hSelectGammaMaxClusterDCAL.object.get(), hSelectGammaLowMaxClusterEMCAL.object.get(), hSelectGammaLowMaxClusterDCAL.object.get(), hSelectGammaVeryLowMaxClusterEMCAL.object.get(), hSelectGammaVeryLowMaxClusterDCAL.object.get()}}; + struct ClusterData { + float mTriggerObservable; + float mEta; + float mPhi; + }; + std::vector analysedClusters; + for (const auto& cluster : clusters) { + if (b_RejectExoticClusters && cluster.isExotic()) { + continue; + } + if (cluster.time() < f_minClusterTime || cluster.time() > f_maxClusterTime) { + continue; + } + double observableGamma = (f_ObservalbeGammaTrigger == 0) ? cluster.energy() : cluster.energy() / std::cosh(cluster.eta()); + if (TVector2::Phi_0_2pi(cluster.phi()) < 4 && observableGamma > maxClusterObservableEMCAL) { + maxClusterObservableEMCAL = observableGamma; + } else if (TVector2::Phi_0_2pi(cluster.phi()) > 4 && observableGamma > maxClusterObservableDCAL) { + maxClusterObservableDCAL = observableGamma; + } + hEmcClusterPtEta->Fill(observableGamma, cluster.eta()); + hEmcClusterPtPhi->Fill(observableGamma, cluster.phi()); + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_EMC7) || hardwaretriggers.test(EMCALHardwareTrigger::TRG_DMC7)) { + hEmcClusterPtEtaLevel0->Fill(observableGamma, cluster.eta()); + hEmcClusterPtPhiLevel0->Fill(observableGamma, cluster.phi()); + } + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_MB)) { + hEmcClusterPtEtaMinBias->Fill(observableGamma, cluster.eta()); + hEmcClusterPtPhiMinBias->Fill(observableGamma, cluster.phi()); + } + analysedClusters.push_back({static_cast(observableGamma), cluster.eta(), cluster.phi()}); + } + hMaxClusterEMCAL->Fill(maxClusterObservableEMCAL); + hMaxClusterDCAL->Fill(maxClusterObservableDCAL); + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_MB)) { + hMaxClusterEMCALMinBias->Fill(maxClusterObservableEMCAL); + hMaxClusterDCALMinBias->Fill(maxClusterObservableDCAL); + } + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_EMC7)) { + hMaxClusterEMCALLevel0->Fill(maxClusterObservableEMCAL); + } + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_DMC7)) { + hMaxClusterDCALLevel0->Fill(maxClusterObservableDCAL); } + for (decltype(thresholds.size()) ithreshold = 0; ithreshold < thresholds.size(); ithreshold++) { + if (thresholds[ithreshold] == ThresholdType_t::VERY_LOW_THRESHOLD) { + // Accept very-low threshold only in case of min. bias input to EMCAL/DCAL + if (!hardwaretriggers.test(EMCALHardwareTrigger::TRG_MB)) { + continue; + } + } + for (decltype(thresholds.size()) isubdet = 0; isubdet < subdets.size(); isubdet++) { + if (isEvtSelectedGamma(subdets[isubdet] == o2::emcal::AcceptanceType_t::EMCAL_ACCEPTANCE ? maxClusterObservableEMCAL : maxClusterObservableDCAL, subdets[isubdet], thresholds[ithreshold])) { + maxClusterPtHists[ithreshold * subdets.size() + isubdet]->Fill(subdets[isubdet] == o2::emcal::AcceptanceType_t::EMCAL_ACCEPTANCE ? maxClusterObservableEMCAL : maxClusterObservableDCAL); + keepEvent[kGammaVeryHighPtEMCAL + ithreshold * subdets.size() + isubdet] = true; + for (auto& cluster : analysedClusters) { + acceptanceHistsPtEta[ithreshold * subdets.size() + isubdet]->Fill(cluster.mTriggerObservable, cluster.mEta); + acceptanceHistsPtPhi[ithreshold * subdets.size() + isubdet]->Fill(cluster.mTriggerObservable, cluster.mPhi); + } + } + } + } + } - if (b_doJetTrigger) { - // Store pt of leading jet inside of the emcal to trigger on - for (const auto& jet : jets) { - hEmcJetPtEta->Fill(jet.pt(), jet.eta()); - hEmcJetPtPhi->Fill(jet.pt(), jet.phi()); - if (jet.pt() > maxSelectedJetPt) { - if (b_DoFiducialCut) { - if (isJetInEmcal(jet)) { - maxSelectedJetPt = jet.pt(); - } - } else { + template + void runJetTrigger(JetCollection const& jets, selectedClusters const& clusters, std::array& keepEvent) + { + int jettype = 0; + if constexpr (std::is_same::value) { + LOG(detail) << "Running full jet filter"; + jettype = 0; + } else if constexpr (std::is_same::value) { + LOG(detail) << "Running neutral jet filter"; + jettype = 1; + } else { + LOG(error) << "Unknown jet type"; + return; + } + double maxSelectedJetPt = 0.; + // Store pt of leading jet inside of the emcal to trigger on + static constexpr std::array + thresholds = {{ThresholdType_t::HIGH_THRESHOLD, ThresholdType_t::LOW_THRESHOLD}}; + std::array acceptanceHistsPtEtaSel = {{hSelectedJetPtEta.object.get(), hSelectedJetPtEtaLow.object.get()}}, + acceptanceHistsPtPhiSel = {{hSelectedJetPtPhi.object.get(), hSelectedJetPtPhiLow.object.get()}}, + acceptanceHistsClusterPtEtaSel = {{hSelectedClusterPtEta.object.get(), hSelectedClusterPtEtaLow.object.get()}}, + acceptanceHistsClusterPtPhiSel = {{hSelectedClusterPtPhi.object.get(), hSelectedClusterPtPhiLow.object.get()}}; + std::array maxJetPtHists = {{hSelectMaxJetPt.object.get(), hSelectMaxJetPtLow.object.get()}}; + for (const auto& jet : jets) { + hEmcJetPtEta->Fill(jet.pt(), jet.eta()); + hEmcJetPtPhi->Fill(jet.pt(), jet.phi()); + if (jet.pt() > maxSelectedJetPt) { + if (b_DoFiducialCut) { + if (isJetInEmcal(jet)) { maxSelectedJetPt = jet.pt(); } + } else { + maxSelectedJetPt = jet.pt(); } } - if (isEvtSelected(maxSelectedJetPt)) { - keepEvent[f_JetType == 0 ? kJetFullHighPt : kJetNeutralHighPt] = true; + } + hMaxJetPt->Fill(maxSelectedJetPt); + for (decltype(thresholds.size()) ithreshold = 0; ithreshold < thresholds.size(); ithreshold++) { + if (isEvtSelectedJet(maxSelectedJetPt, thresholds[ithreshold])) { + maxJetPtHists[ithreshold]->Fill(maxSelectedJetPt); + std::size_t triggerIndex = kCategories; + if (jettype == 0) { + switch (thresholds[ithreshold]) { + case ThresholdType_t::HIGH_THRESHOLD: + triggerIndex = kJetFullHighPt; + break; + case ThresholdType_t::LOW_THRESHOLD: + triggerIndex = kJetFullLowPt; + break; + default: + // Very high / very low thresholds not supported for jet trigger + break; + } + } else { + switch (thresholds[ithreshold]) { + case ThresholdType_t::HIGH_THRESHOLD: + triggerIndex = kJetNeutralHighPt; + break; + case ThresholdType_t::LOW_THRESHOLD: + triggerIndex = kJetNeutralLowPt; + break; + default: + // Very high / very low thresholds not supported for jet trigger + break; + } + } + keepEvent[triggerIndex] = true; for (const auto& jet : jets) { if (isJetInEmcal(jet)) { - hSelectedJetPtEta->Fill(jet.pt(), jet.eta()); - hSelectedJetPtPhi->Fill(jet.pt(), jet.phi()); + acceptanceHistsPtEtaSel[ithreshold]->Fill(jet.pt(), jet.eta()); + acceptanceHistsPtPhiSel[ithreshold]->Fill(jet.pt(), jet.phi()); } } for (const auto& cluster : clusters) { double clusterPt = cluster.energy() / std::cosh(cluster.eta()); - hSelectedClusterPtEta->Fill(clusterPt, cluster.eta()); - hSelectedClusterPtPhi->Fill(clusterPt, cluster.phi()); + acceptanceHistsClusterPtEtaSel[ithreshold]->Fill(clusterPt, cluster.eta()); + acceptanceHistsClusterPtPhiSel[ithreshold]->Fill(clusterPt, cluster.phi()); } } } + } - if (b_doGammaTrigger) { - static constexpr std::array thresholds = {{ThresholdType_t::HIGH_THRESHOLD, ThresholdType_t::LOW_THRESHOLD}}; - static constexpr std::array subdets = {{o2::emcal::AcceptanceType_t::EMCAL_ACCEPTANCE, o2::emcal::AcceptanceType_t::DCAL_ACCEPTANCE}}; - std::array acceptanceHistsPtEta{{hSelectedGammaEMCALPtEta.object.get(), hSelectedGammaDCALPtEta.object.get(), hSelectedGammaEMCALPtEtaLow.object.get(), hSelectedGammaDCALPtEtaLow.object.get()}}, - acceptanceHistsPtPhi{{hSelectedGammaEMCALPtPhi.object.get(), hSelectedGammaDCALPtPhi.object.get(), hSelectedGammaEMCALPtPhiLow.object.get(), hSelectedGammaDCALPtPhiLow.object.get()}}; - struct ClusterData { - float mTriggerObservable; - float mEta; - float mPhi; - }; - std::vector analysedClusters; - for (const auto& cluster : clusters) { - if (b_RejectExoticClusters && cluster.isExotic()) { - continue; - } - if (cluster.time() < f_minClusterTime || cluster.time() > f_maxClusterTime) { - continue; + template + void runTrigger(collisionInfo const& collision, JetCollection const& jets, selectedClusters const& clusters, BCsWithBcSelsRun3 const& bcs) + { + int run = bcs.iteratorAt(0).runNumber(); + // extract bc pattern from CCDB for data or anchored MC only + if (run != lastRun && run >= 500000) { + lastRun = run; + constexpr bool isFullJets = std::is_same::value; + constexpr bool isNeutralJets = std::is_same::value; + int64_t ts = bcs.iteratorAt(0).timestamp(); + // Request run number in addition to timestamp in order to handle concurrent runs + std::map metadata; + metadata["runNumber"] = std::to_string(run); + mHardwareTriggerConfig = getHWTriggerConfiguration(*(ccdb->getSpecific("CTP/Config/Config", ts, metadata))); + switch (mHardwareTriggerConfig) { + case EMCALHWTriggerConfiguration::MB_ONLY: { + LOG(info) << "Found hardware trigger configuration Min. bias only"; + LOG(info) << "Gamma thresholds: High " << f_gammaPtMinEMCALHighMB << ", Low " << f_gammaPtMinEMCALLowMB << " (EMCAL), High " << f_gammaPtMinDCALHighMB << ", Low " << f_gammaPtMinDCALLowMB << " (DCAL)"; + LOG(info) << "No extreme gamma thresholds used"; + LOG(info) << "Jet thresholds: High " << f_jetPtMinMB << ", Low " << f_jetPtMinLowMB; + LOG(info) << "Jet type: full jets " << (isFullJets ? "yes" : "no") << ", neutral jets " << (isNeutralJets ? "yes" : "no"); + break; } - double observableGamma = (f_ObservalbeGammaTrigger == 0) ? cluster.energy() : cluster.energy() / std::cosh(cluster.eta()); - if (TVector2::Phi_0_2pi(cluster.phi()) < 4 && observableGamma > maxClusterObservableEMCAL) { - maxClusterObservableEMCAL = observableGamma; - } else if (TVector2::Phi_0_2pi(cluster.phi()) > 4 && observableGamma > maxClusterObservableDCAL) { - maxClusterObservableDCAL = observableGamma; + case EMCALHWTriggerConfiguration::EMC_TRIGGERD: { + LOG(info) << "Found hardware trigger configuration L0-triggered"; + LOG(info) << "Gamma thresholds: High " << f_gammaPtMinEMCALHigh << ", Low " << f_gammaPtMinEMCALLow << " (EMCAL), High " << f_gammaPtMinDCALHigh << ", Low " << f_gammaPtMinDCALLow << " (DCAL)"; + LOG(info) << "Extreme gamma thresholds: Very high " << f_gammaPtMinEMCALVeryHigh << ", very low " << f_gammaPtMinEMCALVeryLow << " (EMCAL), very high " << f_gammaPtMinDCALVeryHigh << ", very low " << f_gammaPtMinDCALVeryLow << " (DCAL)"; + LOG(info) << "Jet thresholds: High " << f_jetPtMin << ", Low " << f_jetPtMinLow; + LOG(info) << "Jet type: full jets " << (isFullJets ? "yes" : "no") << ", neutral jets " << (isNeutralJets ? "yes" : "no"); + break; } - hEmcClusterPtEta->Fill(observableGamma, cluster.eta()); - hEmcClusterPtPhi->Fill(observableGamma, cluster.phi()); - analysedClusters.push_back({static_cast(observableGamma), cluster.eta(), cluster.phi()}); - } - for (int ithreshold = 0; ithreshold < thresholds.size(); ithreshold++) { - for (int isubdet = 0; isubdet < subdets.size(); isubdet++) { - if (isEvtSelectedGamma(subdets[isubdet] == o2::emcal::AcceptanceType_t::EMCAL_ACCEPTANCE ? maxClusterObservableEMCAL : maxClusterObservableDCAL, subdets[isubdet], thresholds[ithreshold])) { - keepEvent[kGammaHighPtEMCAL + ithreshold * subdets.size() + isubdet] = true; - for (auto& cluster : analysedClusters) { - acceptanceHistsPtEta[ithreshold * subdets.size() + isubdet]->Fill(cluster.mTriggerObservable, cluster.mEta); - acceptanceHistsPtPhi[ithreshold * subdets.size() + isubdet]->Fill(cluster.mTriggerObservable, cluster.mPhi); - } - } + case EMCALHWTriggerConfiguration::UNKNOWN: { + std::cout << "No EMCAL trigger class found for run, event selection will not be possible" << std::endl; + break; } } } + std::array keepEvent; + std::fill(keepEvent.begin(), keepEvent.end(), false); + + if (!b_IgnoreEmcalFlag && !hasEMCALData(collision)) { + tags(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6], keepEvent[7], keepEvent[8], keepEvent[9], keepEvent[10], keepEvent[11], keepEvent[12]); + return; // Skip events where EMCAL is not live + } + + if (b_PublishReadoutTrigger && isEMCALMinBias(collision)) { + keepEvent[kEMCALReadout] = true; + } + + std::bitset hardwaretriggers; + if (collision.alias_bit(triggerAliases::kTVXinEMC)) { + hardwaretriggers.set(EMCALHardwareTrigger::TRG_MB, true); + } + if (collision.alias_bit(triggerAliases::kEMC7)) { + hardwaretriggers.set(EMCALHardwareTrigger::TRG_EMC7, true); + } + if (collision.alias_bit(triggerAliases::kDMC7)) { + hardwaretriggers.set(EMCALHardwareTrigger::TRG_DMC7, true); + } + + if (b_doJetTrigger) { + runJetTrigger(jets, clusters, keepEvent); + } + + if (b_doGammaTrigger) { + runGammaTrigger(clusters, hardwaretriggers, keepEvent); + } + for (int iDecision{0}; iDecision < kCategories; iDecision++) { if (keepEvent[iDecision]) { hProcessedEvents->Fill(iDecision); } } - tags(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); - } // process() + tags(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6], keepEvent[7], keepEvent[8], keepEvent[9], keepEvent[10], keepEvent[11], keepEvent[12]); + } + + void processFullJetTrigger(collisionInfo const& collision, filteredFullJets const& jets, selectedClusters const& clusters, BCsWithBcSelsRun3 const& bcs) + { + // Trigger selection (full jet case) + runTrigger(collision, jets, clusters, bcs); + } + PROCESS_SWITCH(fullJetFilter, processFullJetTrigger, "run full jet triggere code", true); + + void processNeutralJetTrigger(collisionInfo const& collision, filteredNeutralJets const& jets, selectedClusters const& clusters, BCsWithBcSelsRun3 const& bcs) + { + // Trigger selection (neutral jet case) + runTrigger(collision, jets, clusters, bcs); + } + PROCESS_SWITCH(fullJetFilter, processNeutralJetTrigger, "run neutral jet triggere code", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfg) diff --git a/EventFiltering/PWGLF/filterf1proton.cxx b/EventFiltering/PWGLF/filterf1proton.cxx new file mode 100644 index 00000000000..1be0ae2bc8b --- /dev/null +++ b/EventFiltering/PWGLF/filterf1proton.cxx @@ -0,0 +1,636 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file filterf1proton.cxx +/// \brief Selection of events with triplets and pairs for femtoscopic studies +/// +/// \author Sourav Kundu, sourav.kundu@cern.ch + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../filterTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "CommonConstants/MathConstants.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGHF/Core/PDG.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct filterf1proton { + + Produces tags; + + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + + // Configs for events + Configurable ConfEvtSelectZvtx{"ConfEvtSelectZvtx", true, "Event selection includes max. z-Vertex"}; + Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + + // Configs for track PID + Configurable ConfUseManualPIDproton{"ConfUseManualPIDproton", true, "True: use home-made PID solution for proton "}; + Configurable ConfUseManualPIDkaon{"ConfUseManualPIDkaon", true, "True: use home-made PID solution for kaon "}; + Configurable ConfUseManualPIDpion{"ConfUseManualPIDpion", true, "True: use home-made PID solution for pion "}; + Configurable ConfUseManualPIDdaughterPion{"ConfUseManualPIDdaughterPion", true, "True: use home-made PID solution for pion from V0"}; + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "ccdb-url"}; + Configurable ConfPIDBBProton{"ConfPIDBBProton", "Users/a/ariedel/FinalTrigger/PIDProton", "Path to the CCDB ocject for proton BB param"}; + Configurable ConfPIDBBAntiProton{"ConfPIDBBAntiProton", "Analysis/PWGHF/ML/HFTrigger/TPC/AntiProton", "Path to the CCDB ocject for anti-proton BB param"}; + Configurable ConfPIDBBKaon{"ConfPIDBBKaon", "Analysis/PWGHF/ML/HFTrigger/TPC/Kaon", "Path to the CCDB ocject for kaon BB param"}; + Configurable ConfPIDBBAntiKaon{"ConfPIDBBAntiKaon", "Analysis/PWGHF/ML/HFTrigger/TPC/AntiKaon", "Path to the CCDB ocject for anti-kaon BB param"}; + Configurable ConfPIDBBPion{"ConfPIDBBPion", "Analysis/PWGHF/ML/HFTrigger/TPC/Pion", "Path to the CCDB ocject for pion BB param"}; + Configurable ConfPIDBBAntiPion{"ConfPIDBBAntiPion", "Analysis/PWGHF/ML/HFTrigger/TPC/AntiPion", "Path to the CCDB ocject for anti-pion BB param"}; + Configurable ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; + Configurable ConfPIDCutsTPCF1Proton{"ConfPIDCutsTPCF1Proton", 2, "Particle PID selections using TPC"}; + Configurable ConfPIDCutsTOFF1Proton{"ConfPIDCutsTOFF1Proton", 2, "Particle PID selections using TOF"}; + Configurable strategyPIDPion{"strategyPIDPion", 0, "PID strategy Pion"}; + Configurable strategyPIDKaon{"strategyPIDKaon", 0, "PID strategy Kaon"}; + Configurable strategyPIDProton{"strategyPIDProton", 1, "PID strategy Proton"}; + Configurable pionMomentumPID{"pionMomentumPID", 0.5, "pi momentum range for TPC PID selection"}; + Configurable kaonMomentumPID{"kaonMomentumPID", 0.45, "ka momentum range for TPC PID selection"}; + Configurable protonMomentumPID{"protonMomentumPID", 0.75, "pr momentum range for TPC PID selection"}; + + // Configs for track cut + Configurable ConfPtCutsF1Proton{"ConfPtCutsF1Proton", 0.1, "Particle Momentum selections"}; + Configurable ConfTrkEtaF1Proton{"ConfTrkEtaF1Proton", 0.85, "Eta"}; + Configurable ConfTPCNClustersMinF1Proton{"ConfTPCNClustersMinF1Proton", 80, " Minimum number of TPC cluster"}; + Configurable ConfTrkTPCcRowsMinF1Proton{"ConfTrkTPCcRowsMinF1Proton", 70, "Minimum number of crossed TPC rows"}; + Configurable ConfTrkTPCfClsF1Proton{"ConfTrkTPCfClsF1Proton", 0.83, "Minimum fraction of crossed rows over findable clusters"}; + Configurable ConfTrkTPCsClsMaxF1Proton{"ConfTrkTPCsClsMaxF1Proton", 160, "Maximum number of shared TPC clusters"}; + Configurable ConfTrkITSnclsMinF1Proton{"ConfTrkITSnclsMinF1Proton", 0, "Minimum number of ITS clusters"}; + Configurable ConfTrkITSnclsIbMinF1Proton{"ConfTrkITSnclsIbMinF1Proton", 0, "Minimum number of ITS clusters in the inner barrel"}; + Configurable ConfTrkDCAxyMaxF1Proton{"ConfTrkDCAxyMaxF1Proton", 0.15, "Maximum DCA_xy"}; + Configurable ConfTrkDCAzMaxF1Proton{"ConfTrkDCAzMaxF1Proton", 0.3, "Maximum DCA_z"}; + + // Checks taken from global track definition + Configurable ConfTrkRequireChi2MaxTPC{"ConfTrkRequireChi2MaxTPC", false, "True: require max chi2 per TPC cluster"}; + Configurable ConfTrkRequireChi2MaxITS{"ConfTrkRequireChi2MaxITS", false, "True: require max chi2 per ITS cluster"}; + Configurable ConfTrkMaxChi2PerClusterTPC{"ConfTrkMaxChi2PerClusterTPC", 4.0f, "Minimal track selection: max allowed chi2 per TPC cluster"}; // 4.0 is default + Configurable ConfTrkMaxChi2PerClusterITS{"ConfTrkMaxChi2PerClusterITS", 36.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"}; + + // Configs for V0 + Configurable ConfV0PtMin{"ConfV0PtMin", 0.f, "Minimum transverse momentum of V0"}; + Configurable ConfV0DCADaughMax{"ConfV0DCADaughMax", 1.8f, "Maximum DCA between the V0 daughters"}; + Configurable ConfV0CPAMin{"ConfV0CPAMin", 0.985f, "Minimum CPA of V0"}; + Configurable ConfV0TranRadV0Min{"ConfV0TranRadV0Min", 0.2f, "Minimum transverse radius"}; + Configurable ConfV0TranRadV0Max{"ConfV0TranRadV0Max", 100.f, "Maximum transverse radius"}; + Configurable ConfV0DecVtxMax{"ConfV0DecVtxMax", 100.f, "Maximum distance from primary vertex"}; + Configurable cMaxV0DCA{"cMaxV0DCA", 0.3, "Minimum V0 CosPA to PV"}; + Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 40, "Maximum V0 life time"}; + Configurable cSigmaMassKs0{"cSigmaMassKs0", 2, "Sigma cut on KS0 mass"}; + + // config for V0 daughters + Configurable ConfDaughEta{"ConfDaughEta", 0.85f, "V0 Daugh sel: max eta"}; + Configurable ConfDaughTPCnclsMin{"ConfDaughTPCnclsMin", 60.f, "V0 Daugh sel: Min. nCls TPC"}; + Configurable ConfDaughDCAMin{"ConfDaughDCAMin", 0.04f, "V0 Daugh sel: Max. DCA Daugh to PV (cm)"}; + Configurable ConfDaughPIDCuts{"ConfDaughPIDCuts", 3, "PID selections for KS0 daughters"}; + + // Configs for F1 candidate + Configurable cMaxMassKKs0{"cMaxMassKKs0", 1.04, "Mass cut on K-KS0 pair"}; + Configurable cMaxMassF1{"cMaxMassF1", 1.80001, "Mass cut on F1 resonance"}; + Configurable cMinF1Pt{"cMinF1Pt", 1.0, "Minimum pT cut on F1"}; + Configurable cMinKaonPt{"cMinKaonPt", 0.3, "Minimum pT cut on Kaon daughter"}; + Configurable cMaxProtonPt{"cMaxProtonPt", 2.0, "Maximum pT cut on Proton"}; + + // config Femto relative momentum + Configurable cMaxRelMom{"cMaxRelMom", 0.5, "Relative momentum cut"}; + + // Histogram + HistogramRegistry qaRegistry{"QAHistos", { + {"hEventstat", "hEventstat", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, + {"hInvMassf1", "hInvMassf1", {HistType::kTH2F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}}}}, + {"hInvMassf1Like", "hInvMassf1Like", {HistType::kTH2F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}}}}, + {"hInvMassf1kstar", "hInvMassf1kstar", {HistType::kTH3F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}, {8, 0.0f, 0.8f}}}}, + {"hkstarDist", "hkstarDist", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, + {"hDCAxy", "hDCAxy", {HistType::kTH1F, {{100, -5.0f, 5.0f}}}}, + {"hDCAz", "hDCAz", {HistType::kTH1F, {{100, -5.0f, 5.0f}}}}, + {"hPhi", "hPhi", {HistType::kTH1F, {{70, 0.0f, 7.0f}}}}, + {"hEta", "hEta", {HistType::kTH1F, {{20, -1.0f, 1.0f}}}}, + {"hNsigmaPtpionTPC", "hNsigmaPtpionTPC", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtpionTOF", "hNsigmaPtpionTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtkaonTPC", "hNsigmaPtkaonTPC", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtkaonTOF", "hNsigmaPtkaonTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtprotonTPC", "hNsigmaPtprotonTPC", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtprotonTOF", "hNsigmaPtprotonTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hInvMassk0", "hInvMassk0", {HistType::kTH2F, {{200, 0.4f, 0.6f}, {100, 0.0f, 10.0f}}}}, + }, + OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + ccdb->setURL(url.value); + ccdbApi.init(url); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + } + + template + bool isSelectedEvent(T const& col) + { + if (ConfEvtSelectZvtx && std::abs(col.posZ()) > ConfEvtZvtx) { + return false; + } + return true; + } + + template + bool isSelectedTrack(T const& track) + { + const auto pT = track.pt(); + const auto eta = track.eta(); + const auto tpcNClsF = track.tpcNClsFound(); + const auto tpcRClsC = track.tpcCrossedRowsOverFindableCls(); + const auto tpcNClsC = track.tpcNClsCrossedRows(); + const auto tpcNClsS = track.tpcNClsShared(); + const auto itsNCls = track.itsNCls(); + const auto itsNClsIB = track.itsNClsInnerBarrel(); + const auto dcaXY = track.dcaXY(); + const auto dcaZ = track.dcaZ(); + if (pT < ConfPtCutsF1Proton) { + return false; + } + if (std::abs(eta) > ConfTrkEtaF1Proton) { + return false; + } + if (tpcNClsF < ConfTPCNClustersMinF1Proton) { + return false; + } + if (tpcRClsC < ConfTrkTPCfClsF1Proton) { + return false; + } + if (tpcNClsC < ConfTrkTPCcRowsMinF1Proton) { + return false; + } + if (tpcNClsS > ConfTrkTPCsClsMaxF1Proton) { + return false; + } + if (itsNCls < ConfTrkITSnclsMinF1Proton) { + return false; + } + if (itsNClsIB < ConfTrkITSnclsIbMinF1Proton) { + return false; + } + if (std::abs(dcaXY) > ConfTrkDCAxyMaxF1Proton) { + return false; + } + if (std::abs(dcaZ) > ConfTrkDCAzMaxF1Proton) { + return false; + } + // TODO: which dca, put dcaxy for now + if (ConfRejectNotPropagatedTracks && std::abs(dcaXY) > 1e3) { + return false; + } + if (ConfTrkRequireChi2MaxTPC && track.tpcChi2NCl() >= ConfTrkMaxChi2PerClusterTPC) { + return false; + } + if (ConfTrkRequireChi2MaxITS && track.itsChi2NCl() >= ConfTrkMaxChi2PerClusterITS) { + return false; + } + if (ConfTrkTPCRefit && !track.hasTPC()) { + return false; + } + if (ConfTrkITSRefit && !track.hasITS()) { + return false; + } + return true; + } + + template + double updatePID(T const& track, double bgScaling, std::vector BB) + { + double expBethe = tpc::BetheBlochAleph(static_cast(track.tpcInnerParam() * bgScaling), BB[0], BB[1], BB[2], BB[3], BB[4]); + double expSigma = expBethe * BB[5]; + return static_cast((track.tpcSignal() - expBethe) / expSigma); + } + + template + bool isSelectedV0Daughter(T const& track, float charge, double nsigmaV0Daughter) + { + const auto eta = track.eta(); + const auto tpcNClsF = track.tpcNClsFound(); + const auto dcaXY = track.dcaXY(); + const auto sign = track.sign(); + + if (charge < 0 && sign > 0) { + return false; + } + if (charge > 0 && sign < 0) { + return false; + } + if (std::abs(eta) > ConfDaughEta) { + return false; + } + if (tpcNClsF < ConfDaughTPCnclsMin) { + return false; + } + if (std::abs(dcaXY) < ConfDaughDCAMin) { + return false; + } + + if (std::abs(nsigmaV0Daughter) > ConfDaughPIDCuts) { + return false; + } + return true; + } + + template + bool SelectionPID(const T& candidate, int PIDstrategy, int particle, double updatensigma) + { + if (PIDstrategy == 1) { + if (particle == 0) { + if (std::abs(candidate.p()) < pionMomentumPID && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton) { + return true; + } else if (std::abs(candidate.p()) >= pionMomentumPID && candidate.hasTOF() && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaPi()) < ConfPIDCutsTOFF1Proton) { + return true; + } + } else if (particle == 1) { + if (std::abs(candidate.p()) < kaonMomentumPID && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton) { + return true; + } else if (std::abs(candidate.p()) >= kaonMomentumPID && candidate.hasTOF() && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaKa()) < ConfPIDCutsTOFF1Proton) { + return true; + } + } else if (particle == 2) { + if (std::abs(candidate.p()) < protonMomentumPID && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton) { + return true; + } else if (std::abs(candidate.p()) >= protonMomentumPID && candidate.hasTOF() && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaPr()) < ConfPIDCutsTOFF1Proton) { + return true; + } + } + } else if (PIDstrategy == 0) { + if (candidate.hasTOF()) { + if (particle == 0 && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaPi()) < ConfPIDCutsTOFF1Proton) { + return true; + } else if (particle == 1 && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaKa()) < ConfPIDCutsTOFF1Proton) { + return true; + } else if (particle == 2 && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaPr()) < ConfPIDCutsTOFF1Proton) { + return true; + } + } else if (std::abs(updatensigma) < ConfPIDCutsTPCF1Proton) { + return true; + } + } + return false; + } + + template + bool SelectionV0(Collision const& collision, V0 const& candidate) + { + if (fabs(candidate.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) > cMaxV0DCA) { + return false; + } + + const float pT = candidate.pt(); + const std::vector decVtx = {candidate.x(), candidate.y(), candidate.z()}; + const float tranRad = candidate.v0radius(); + const float dcaDaughv0 = candidate.dcaV0daughters(); + const float cpav0 = candidate.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); + + float CtauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::analysis::pdg::MassK0Short; + float lowmasscutks0 = 0.497 - 2.0 * cSigmaMassKs0; + float highmasscutks0 = 0.497 + 2.0 * cSigmaMassKs0; + + if (pT < ConfV0PtMin) { + return false; + } + if (dcaDaughv0 > ConfV0DCADaughMax) { + return false; + } + if (cpav0 < ConfV0CPAMin) { + return false; + } + if (tranRad < ConfV0TranRadV0Min) { + return false; + } + if (tranRad > ConfV0TranRadV0Max) { + return false; + } + for (size_t i = 0; i < decVtx.size(); i++) { + if (decVtx.at(i) > ConfV0DecVtxMax) { + return false; + } + } + if (fabs(CtauK0s) > cMaxV0LifeTime || candidate.mK0Short() < lowmasscutks0 || candidate.mK0Short() > highmasscutks0) { + return false; + } + return true; + } + + float getkstar(const ROOT::Math::PtEtaPhiMVector part1, + const ROOT::Math::PtEtaPhiMVector part2) + { + const ROOT::Math::PtEtaPhiMVector trackSum = part1 + part2; + const float beta = trackSum.Beta(); + const float betax = + beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = + beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + ROOT::Math::PxPyPzMVector PartOneCMS(part1); + ROOT::Math::PxPyPzMVector PartTwoCMS(part2); + const ROOT::Math::Boost boostPRF = + ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + const ROOT::Math::PxPyPzMVector trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); + } + + std::vector setValuesBB(o2::ccdb::CcdbApi& ccdbApi, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string ccdbPath) + { + map metadata; + auto h = ccdbApi.retrieveFromTFileAny(ccdbPath, metadata, bunchCrossing.timestamp()); + // auto h = ccdb->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); // check if possible to use this without getting fatal + if (!h) { + std::vector dummy; + LOG(info) << "File from CCDB in path " << ccdbPath << " was not found for run " << bunchCrossing.runNumber() << "and timestamp" << bunchCrossing.timestamp() << ". Will use default PID task values!"; + return dummy; + } + LOG(info) << "File from CCDB in path " << ccdbPath << " was found for run " << bunchCrossing.runNumber() << "!"; + + TAxis* axis = h->GetXaxis(); + std::vector v{static_cast(h->GetBinContent(axis->FindBin("bb1"))), + static_cast(h->GetBinContent(axis->FindBin("bb2"))), + static_cast(h->GetBinContent(axis->FindBin("bb3"))), + static_cast(h->GetBinContent(axis->FindBin("bb4"))), + static_cast(h->GetBinContent(axis->FindBin("bb5"))), + static_cast(h->GetBinContent(axis->FindBin("Resolution")))}; + return v; + } + + std::vector BBProton, BBAntiproton, BBPion, BBAntipion, BBKaon, BBAntikaon; + ROOT::Math::PtEtaPhiMVector F1Vector, KKs0Vector; + double massPi = o2::analysis::pdg::MassPiPlus; + double massKa = o2::analysis::pdg::MassKPlus; + double massPr = o2::constants::physics::MassProton; + double massK0s = o2::analysis::pdg::MassK0Short; + double massF1{0.}; + double masskKs0{0.}; + double pT{0.}; + int currentRunNumber = -999; + int lastRunNumber = -999; + double betaX = 0; + double betaY = 0; + double betaZ = 0; + double relativeMomentum = 999; + // Pre-filters for primary track + Filter acceptanceFilter = nabs(aod::track::eta) < ConfTrkEtaF1Proton && nabs(aod::track::pt) > ConfPtCutsF1Proton; + Filter dcaFilter = nabs(aod::track::dcaXY) < ConfTrkDCAxyMaxF1Proton && nabs(aod::track::dcaZ) < ConfTrkDCAzMaxF1Proton; + + // using EventCandidates = soa::Join; + using EventCandidates = aod::Collisions; + using ResoV0s = aod::V0Datas; + using PrimaryTrackCandidates = soa::Filtered>; + + void processF1Proton(EventCandidates::iterator const& collision, aod::BCsWithTimestamps const&, PrimaryTrackCandidates const& tracks, ResoV0s const& V0s) + { + bool keepEventF1Proton = false; + int numberF1 = 0; + if (isSelectedEvent(collision)) { + if (ConfUseManualPIDproton || ConfUseManualPIDkaon || ConfUseManualPIDpion) { + currentRunNumber = collision.bc_as().runNumber(); + if (currentRunNumber != lastRunNumber) { + auto bc = collision.bc_as(); + if (ConfUseManualPIDproton) { + BBProton = setValuesBB(ccdbApi, bc, ConfPIDBBProton); + BBAntiproton = setValuesBB(ccdbApi, bc, ConfPIDBBAntiProton); + } + if (ConfUseManualPIDpion) { + BBPion = setValuesBB(ccdbApi, bc, ConfPIDBBPion); + BBAntipion = setValuesBB(ccdbApi, bc, ConfPIDBBAntiPion); + } + if (ConfUseManualPIDkaon) { + BBKaon = setValuesBB(ccdbApi, bc, ConfPIDBBKaon); + BBAntikaon = setValuesBB(ccdbApi, bc, ConfPIDBBAntiKaon); + } + lastRunNumber = currentRunNumber; + } + } + + // keep track of indices + std::vector PionIndex = {}; + std::vector KaonIndex = {}; + std::vector ProtonIndex = {}; + + // keep charge of track + std::vector PionCharge = {}; + std::vector KaonCharge = {}; + std::vector ProtonCharge = {}; + + // Prepare vectors for different species + std::vector protons, kaons, pions, kshorts; + float kstar = 999.f; + + for (auto& track : tracks) { + + if (!isSelectedTrack(track)) + continue; + qaRegistry.fill(HIST("hDCAxy"), track.dcaXY()); + qaRegistry.fill(HIST("hDCAz"), track.dcaZ()); + qaRegistry.fill(HIST("hEta"), track.eta()); + qaRegistry.fill(HIST("hPhi"), track.phi()); + double nTPCSigmaP[3]{track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + double nTPCSigmaN[3]{track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + if (ConfUseManualPIDproton) { + auto bgScalingProton = 1 / massPr; // momentum scaling? + if (BBProton.size() == 6) + nTPCSigmaP[2] = updatePID(track, bgScalingProton, BBProton); + if (BBAntiproton.size() == 6) + nTPCSigmaN[2] = updatePID(track, bgScalingProton, BBAntiproton); + } + if (ConfUseManualPIDkaon) { + auto bgScalingKaon = 1 / massKa; // momentum scaling? + if (BBKaon.size() == 6) + nTPCSigmaP[1] = updatePID(track, bgScalingKaon, BBKaon); + if (BBAntikaon.size() == 6) + nTPCSigmaN[1] = updatePID(track, bgScalingKaon, BBAntikaon); + } + if (ConfUseManualPIDpion) { + auto bgScalingPion = 1 / massPi; // momentum scaling? + if (BBPion.size() == 6) + nTPCSigmaP[0] = updatePID(track, bgScalingPion, BBPion); + if (BBAntipion.size() == 6) + nTPCSigmaN[0] = updatePID(track, bgScalingPion, BBAntipion); + } + + if ((track.sign() > 0 && SelectionPID(track, strategyPIDPion, 0, nTPCSigmaP[0])) || (track.sign() < 0 && SelectionPID(track, strategyPIDPion, 0, nTPCSigmaN[0]))) { + ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), massPi); + pions.push_back(temp); + PionIndex.push_back(track.globalIndex()); + PionCharge.push_back(track.sign()); + if (track.sign() > 0) { + qaRegistry.fill(HIST("hNsigmaPtpionTPC"), nTPCSigmaP[0], track.pt()); + } + if (track.sign() < 0) { + qaRegistry.fill(HIST("hNsigmaPtpionTPC"), nTPCSigmaN[0], track.pt()); + } + if (track.hasTOF()) { + qaRegistry.fill(HIST("hNsigmaPtpionTOF"), track.tofNSigmaPi(), track.pt()); + } + } + + if ((track.pt() > cMinKaonPt && track.sign() > 0 && SelectionPID(track, strategyPIDKaon, 1, nTPCSigmaP[1])) || (track.pt() > cMinKaonPt && track.sign() < 0 && SelectionPID(track, strategyPIDKaon, 1, nTPCSigmaN[1]))) { + ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), massKa); + kaons.push_back(temp); + KaonIndex.push_back(track.globalIndex()); + KaonCharge.push_back(track.sign()); + if (track.sign() > 0) { + qaRegistry.fill(HIST("hNsigmaPtkaonTPC"), nTPCSigmaP[1], track.pt()); + } + if (track.sign() < 0) { + qaRegistry.fill(HIST("hNsigmaPtkaonTPC"), nTPCSigmaN[1], track.pt()); + } + if (track.hasTOF()) { + qaRegistry.fill(HIST("hNsigmaPtkaonTOF"), track.tofNSigmaKa(), track.pt()); + } + } + + if ((track.pt() < cMaxProtonPt && track.sign() > 0 && SelectionPID(track, strategyPIDProton, 2, nTPCSigmaP[2])) || (track.pt() < cMaxProtonPt && track.sign() < 0 && SelectionPID(track, strategyPIDProton, 2, nTPCSigmaN[2]))) { + ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), massPr); + protons.push_back(temp); + ProtonIndex.push_back(track.globalIndex()); + ProtonCharge.push_back(track.sign()); + if (track.sign() > 0) { + qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), nTPCSigmaP[2], track.pt()); + } + if (track.sign() < 0) { + qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), nTPCSigmaN[2], track.pt()); + } + if (track.hasTOF()) { + qaRegistry.fill(HIST("hNsigmaPtprotonTOF"), track.tofNSigmaPr(), track.pt()); + } + } + } // track loop end + + // keep track of daugher indices to avoid selfcorrelations + std::vector KshortPosDaughIndex = {}; + std::vector KshortNegDaughIndex = {}; + + for (auto& v0 : V0s) { + + if (!SelectionV0(collision, v0)) { + continue; + } + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + double nTPCSigmaPos[1]{postrack.tpcNSigmaPi()}; + double nTPCSigmaNeg[1]{negtrack.tpcNSigmaPi()}; + if (ConfUseManualPIDdaughterPion) { + auto bgScalingPion = 1 / massPi; // momentum scaling? + if (BBPion.size() == 6) + nTPCSigmaPos[0] = updatePID(postrack, bgScalingPion, BBPion); + if (BBAntipion.size() == 6) + nTPCSigmaNeg[0] = updatePID(negtrack, bgScalingPion, BBAntipion); + } + if (!isSelectedV0Daughter(postrack, 1, nTPCSigmaPos[0])) { + continue; + } + if (!isSelectedV0Daughter(negtrack, -1, nTPCSigmaNeg[0])) { + continue; + } + qaRegistry.fill(HIST("hInvMassk0"), v0.mK0Short(), v0.pt()); + ROOT::Math::PtEtaPhiMVector temp(v0.pt(), v0.eta(), v0.phi(), massK0s); + kshorts.push_back(temp); + KshortPosDaughIndex.push_back(postrack.globalIndex()); + KshortNegDaughIndex.push_back(negtrack.globalIndex()); + } + + if (pions.size() != 0 && kaons.size() != 0 && kshorts.size() != 0) { + for (auto ipion = pions.begin(); ipion != pions.end(); ++ipion) { + for (auto ikaon = kaons.begin(); ikaon != kaons.end(); ++ikaon) { + auto i1 = std::distance(pions.begin(), ipion); + auto i2 = std::distance(kaons.begin(), ikaon); + // if(PionCharge.at(i1)*KaonCharge.at(i2)>0)continue; + if (PionIndex.at(i1) == KaonIndex.at(i2)) + continue; + for (auto ikshort = kshorts.begin(); ikshort != kshorts.end(); ++ikshort) { + auto i3 = std::distance(kshorts.begin(), ikshort); + if (PionIndex.at(i1) == KshortPosDaughIndex.at(i3)) + continue; + if (PionIndex.at(i1) == KshortNegDaughIndex.at(i3)) + continue; + KKs0Vector = kaons.at(i2) + kshorts.at(i3); + if (KKs0Vector.M() > cMaxMassKKs0) + continue; + F1Vector = KKs0Vector + pions.at(i1); + if (F1Vector.M() > cMaxMassF1) + continue; + if (F1Vector.Pt() < cMinF1Pt) + continue; + if (PionCharge.at(i1) * KaonCharge.at(i2) > 0) { + qaRegistry.fill(HIST("hInvMassf1Like"), F1Vector.M(), F1Vector.Pt()); + continue; + } + qaRegistry.fill(HIST("hInvMassf1"), F1Vector.M(), F1Vector.Pt()); + numberF1 = numberF1 + 1; + for (auto iproton = protons.begin(); iproton != protons.end(); ++iproton) { + auto i4 = std::distance(protons.begin(), iproton); + if (ProtonIndex.at(i4) == PionIndex.at(i1)) + continue; + if (ProtonIndex.at(i4) == KaonIndex.at(i2)) + continue; + if (ProtonIndex.at(i4) == KshortPosDaughIndex.at(i3)) + continue; + if (ProtonIndex.at(i4) == KshortNegDaughIndex.at(i3)) + continue; + kstar = getkstar(F1Vector, *iproton); + qaRegistry.fill(HIST("hkstarDist"), kstar); + if (kstar > cMaxRelMom) + continue; + qaRegistry.fill(HIST("hInvMassf1kstar"), F1Vector.M(), F1Vector.Pt(), kstar); + keepEventF1Proton = true; + } + } + } + } + } + } + qaRegistry.fill(HIST("hEventstat"), 0.5); + if (numberF1 > 0) { + qaRegistry.fill(HIST("hEventstat"), 1.5); + } + if (keepEventF1Proton) { + qaRegistry.fill(HIST("hEventstat"), 2.5); + } + tags(keepEventF1Proton); + } + PROCESS_SWITCH(filterf1proton, processF1Proton, "Process for trigger", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfg) +{ + return WorkflowSpec{adaptAnalysisTask(cfg, TaskName{"lf-f1proton-filter"})}; +} diff --git a/EventFiltering/PWGLF/nucleiFilter.cxx b/EventFiltering/PWGLF/nucleiFilter.cxx index ddf9a4afad1..e3d97aa03de 100644 --- a/EventFiltering/PWGLF/nucleiFilter.cxx +++ b/EventFiltering/PWGLF/nucleiFilter.cxx @@ -175,7 +175,7 @@ struct nucleiFilter { qaHists.fill(HIST("fProcessedEvents"), iDecision + 1); } } - tags(keepEvent[0], keepEvent[1], keepEvent[2]); + tags(keepEvent[2]); } }; diff --git a/EventFiltering/PWGLF/strangenessFilter.cxx b/EventFiltering/PWGLF/strangenessFilter.cxx index 038635d2f9a..59c46af62c1 100644 --- a/EventFiltering/PWGLF/strangenessFilter.cxx +++ b/EventFiltering/PWGLF/strangenessFilter.cxx @@ -14,6 +14,11 @@ /// \author Francesca Ercolessi (francesca.ercolessi@cern.ch) /// \since June 1, 2021 +#include +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/Propagator.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -22,14 +27,15 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/PIDResponse.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" +#include "PWGHF/Core/PDG.h" #include "../filterTables.h" -#include using namespace o2; using namespace o2::framework; @@ -46,8 +52,9 @@ struct strangenessFilter { HistogramRegistry QAHistos{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry QAHistosTopologicalVariables{"QAHistosTopologicalVariables", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry QAHistosTriggerParticles{"QAHistosTriggerParticles", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry QAHistosStrangenessTracking{"QAHistosStrangenessTracking", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry EventsvsMultiplicity{"EventsvsMultiplicity", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - OutputObj hProcessedEvents{TH1F("hProcessedEvents", "Strangeness - event filtered; Event counter; Number of events", 10, 0., 10.)}; + OutputObj hProcessedEvents{TH1F("hProcessedEvents", "Strangeness - event filtered; Event counter; Number of events", 14, 0., 14.)}; OutputObj hCandidate{TH1F("hCandidate", "; Candidate pass selection; Number of events", 30, 0., 30.)}; OutputObj hEvtvshMinPt{TH1F("hEvtvshMinPt", " Number of h-Xi events with pT_h higher than thrd; hadrons with p_{T}>bincenter (GeV/c); Number of events", 11, 0., 11.)}; OutputObj hhXiPairsvsPt{TH1F("hhXiPairsvsPt", "pt distributions of Xi in events with a trigger particle; #it{p}_{T} (GeV/c); Number of Xi", 100, 0., 10.)}; @@ -93,8 +100,33 @@ struct strangenessFilter { Configurable hMinPt{"hMinPt", 1.0f, "Min pt for trigger particles"}; Configurable isTrackFilter{"isTrackFilter", true, "Apply track myTrackSelections"}; + // Settings for strangeness tracking filter + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpMagPath{"grpMagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable bz{"bz", -5., "magnetic field"}; + Configurable minPtTrackedCascade{"minPtTrackedCascade", 0., "Min. pt for tracked cascades"}; + Configurable massWindowTrackedOmega{"massWindowTrackedOmega", 0.05, "Inv. mass window for tracked Omega-"}; + Configurable massWindowXiExclTrackedOmega{"massWindowXiExclTrackedOmega", 0.005, "Inv. mass window for exclusion of Xi for tracked Omega-"}; + Configurable massWindowTrackedXi{"massWindowTrackedXi", 0.05, "Inv. mass window for tracked Xi-"}; + Configurable massWindowLambda{"massWindowLambda", 0.05, "Inv. mass window for Lambda (ST)"}; + Configurable maxMatchingChi2TrackedCascade{"maxMatchingChi2TrackedCascade", 2000., "Max matching chi2 for tracked cascades"}; + Configurable recalculateMasses{"recalculateMasses", true, "Recalculate Xi/Omega masses"}; + + Configurable maxNSigmaBachelorTrackedXi{"maxNSigmaBachelorTrackedXi", 3., "Max Nsigma for bachelor of tracked Xi (pi)"}; + Configurable maxNSigmaBachelorTrackedOmega{"maxNSigmaBachelorTrackedOmega", 3., "Max Nsigma for bachelor of tracked Xi (Ka)"}; + Configurable maxNSigmaV0PrTrackedCascade{"maxNSigmaV0PrTrackedCascade", 3., "Max Nsigma for proton from V0 fromtracked Xi"}; + Configurable maxNSigmaV0PiTrackedCascade{"maxNSigmaV0PiTrackedCascade", 3., "Max Nsigma for pion from V0 fromtracked Xi"}; + Configurable minPtTrackedV0{"minPtTrackedV0", 0., "Min. pt for tracked V0"}; + Configurable minPtTracked3Body{"minPtTracked3Body", 0., "Min. pt for tracked 3Body"}; + void init(o2::framework::InitContext&) { + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + mTrackSelector.SetTrackType(o2::aod::track::TrackTypeEnum::Track); mTrackSelector.SetPtRange(hMinPt, 1e10f); mTrackSelector.SetEtaRange(-hEta, hEta); @@ -120,6 +152,10 @@ struct strangenessFilter { hProcessedEvents->GetXaxis()->SetBinLabel(8, "#Xi-YN"); hProcessedEvents->GetXaxis()->SetBinLabel(9, "#Omega high radius"); hProcessedEvents->GetXaxis()->SetBinLabel(10, "#Xi"); + hProcessedEvents->GetXaxis()->SetBinLabel(11, "trk. #Xi"); + hProcessedEvents->GetXaxis()->SetBinLabel(12, "trk. #Omega"); + hProcessedEvents->GetXaxis()->SetBinLabel(13, "trk. V^{0}"); + hProcessedEvents->GetXaxis()->SetBinLabel(14, "trk. 3body"); hCandidate->GetXaxis()->SetBinLabel(1, "All"); hCandidate->GetXaxis()->SetBinLabel(2, "Has_V0"); @@ -235,6 +271,32 @@ struct strangenessFilter { QAHistos.add("hHasTOFPi", "pi dau has TOF", HistType::kTH2F, {{2, 0, 2}, {ptAxis}}); QAHistos.add("hRapXi", "Rap Xi", HistType::kTH1F, {{100, -1, 1}}); QAHistos.add("hRapOmega", "Rap Omega", HistType::kTH1F, {{100, -1, 1}}); + + QAHistosStrangenessTracking.add("hStRVsPtTrkCasc", "Tracked cascades;p_{T} (GeV/#it{c});R (cm)", HistType::kTH2D, {{200, 0., 10.}, {200, 0., 50}}); + QAHistosStrangenessTracking.add("hMassOmegaTrkCasc", "Tracked cascades;m_{#Omega} (GeV/#it{c}^{2})", HistType::kTH1D, {{1000, 1., 3.}}); + QAHistosStrangenessTracking.add("hMassXiTrkCasc", "Tracked cascades;m_{#Xi} (GeV/#it{c}^{2})", HistType::kTH1D, {{1000, 1., 3.}}); + QAHistosStrangenessTracking.add("hMassV0TrkCasc", "Tracked cascades;m_{V^{0}} (GeV/#it{c}^{2})", HistType::kTH1D, {{1000, 1., 3.}}); + QAHistosStrangenessTracking.add("hMatchChi2TrkCasc", "Tracked cascades;#chi^{2}", HistType::kTH1D, {{1000, 0., 2000.}}); + QAHistosStrangenessTracking.add("hMassOmegaVsMatchChi2TrkCasc", "Tracked cascades;m_{#Omega} (GeV/#it{c}^{2});#chi^{2}", HistType::kTH2D, {{1000, 1., 3.}, {1000, 0., 2000.}}); + QAHistosStrangenessTracking.add("hMassXiVsMatchChi2TrkCasc", "Tracked cascades;m_{#Xi} (GeV/#it{c}^{2});#chi^{2}", HistType::kTH2D, {{1000, 1., 3.}, {1000, 0., 2000.}}); + QAHistosStrangenessTracking.add("hMassOmegaVsTopChi2TrkCasc", "Tracked cascades;m_{#Omega} (GeV/#it{c}^{2});#chi^{2}", HistType::kTH2D, {{1000, 1., 3.}, {1000, 0., 2000.}}); + QAHistosStrangenessTracking.add("hMassXiVsTopChi2TrkCasc", "Tracked cascades;m_{#Xi} (GeV/#it{c}^{2});#chi^{2}", HistType::kTH2D, {{1000, 1., 3.}, {1000, 0., 2000.}}); + QAHistosStrangenessTracking.add("hNSigmaTpcPiTrkCascBachelor", "Tracked cascades;N_{#sigma, #pi}", HistType::kTH1D, {{100, -5., 5.}}); + QAHistosStrangenessTracking.add("hNSigmaTpcKaTrkCascBachelor", "Tracked cascades;N_{#sigma, K}", HistType::kTH1D, {{100, -5., 5.}}); + QAHistosStrangenessTracking.add("hNSigmaTpcPrTrkCascV0", "Tracked cascades;N_{#sigma, p}", HistType::kTH1D, {{100, -5., 5.}}); + QAHistosStrangenessTracking.add("hNSigmaTpcPiTrkCascV0", "Tracked cascades;N_{#sigma, #pi}", HistType::kTH1D, {{100, -5., 5.}}); + QAHistosStrangenessTracking.add("hMassH3LTrkV0", "Tracked V0;m_{H3L} (GeV/#it{c}^{2})", HistType::kTH1D, {{1000, 2.8, 3.8}}); + QAHistosStrangenessTracking.add("hMassH4LTrkV0", "Tracked V0;m_{H4L} (GeV/#it{c}^{2})", HistType::kTH1D, {{1000, 3.8, 4.8}}); + QAHistosStrangenessTracking.add("hMassH3LTrk3body", "Tracked 3body;m_{H3L} (GeV/#it{c}^{2})", HistType::kTH1D, {{200, 0., 10.}}); + QAHistosStrangenessTracking.add("hMassHe4LTrk3body", "Tracked 3body;m_{He4L} (GeV/#it{c}^{2})", HistType::kTH1D, {{200, 0., 10.}}); + QAHistosStrangenessTracking.add("hDcaXY", "DCA;DCA_{xy} (cm)", HistType::kTH1D, {{200, -.5, .5}}); + QAHistosStrangenessTracking.add("hDcaXYVsPt", "DCA;p_{T} (GeV/#it{c});DCA_{xy} (cm)", HistType::kTH2D, {{200, 0., 10.}, {200, -.5, .5}}); + QAHistosStrangenessTracking.add("hDcaZ", "DCA;DCA_{z} (cm)", HistType::kTH1D, {{200, -.5, .5}}); + QAHistosStrangenessTracking.add("hDcaZVsPt", "DCA;p_{T} (GeV/#it{c});DCA_{z} (cm)", HistType::kTH2D, {{200, 0., 10.}, {200, -.5, .5}}); + QAHistosStrangenessTracking.add("hDcaVsPt", "DCA;DCA (cm);p_{T} (GeV/#it{c})", HistType::kTH2D, {{200, 0., .5}, {200, 0., 10.}}); + QAHistosStrangenessTracking.add("hDcaVsR", "DCA;DCA (cm);R (cm)", HistType::kTH2D, {{200, 0., .5}, {200, 0., 10.}}); + QAHistosStrangenessTracking.add("hPtCascCand", "cascades;p_{T} (GeV/#it{c})", HistType::kTH1D, {{200, 0., 10.}}); + QAHistosStrangenessTracking.add("hPtCascTracked", "tracked cascades;p_{T} (GeV/#it{c})", HistType::kTH1D, {{200, 0., 10.}}); } } @@ -246,33 +308,42 @@ struct strangenessFilter { // using CollisionCandidatesRun3 = soa::Join::iterator; using CollisionCandidatesRun3 = soa::Join::iterator; using TrackCandidates = soa::Filtered>; - using DaughterTracks = soa::Join; + using DaughterTracks = soa::Join; using Cascades = aod::CascDataExt; + Service ccdb; + int runNumber; + //////////////////////////////////////////////////////// ////////// Strangeness Filter - Run 2 conv ///////////// //////////////////////////////////////////////////////// + void fillTriggerTable(bool keepEvent[]) + { + strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6], keepEvent[7], keepEvent[8], keepEvent[9], keepEvent[10]); + } + void processRun2(CollisionCandidates const& collision, TrackCandidates const& tracks, Cascades const& fullCasc, aod::V0sLinked const&, aod::V0Datas const& v0data, DaughterTracks& dtracks) { // Is event good? [0] = Omega, [1] = high-pT hadron + Xi, [2] = 2Xi, [3] = 3Xi, [4] = 4Xi, [5] single-Xi, [6] Omega with high radius - bool keepEvent[7]{false, false, false, false, false, false, false}; + // [7] tracked Xi, [8] tracked Omega, [9] tracked V0, [10] tracked 3Body + bool keepEvent[11]{}; // explicitly zero-initialised if (kint7 && !collision.alias_bit(kINT7)) { - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); + fillTriggerTable(keepEvent); return; } if (sel7 && !collision.sel7()) { - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); + fillTriggerTable(keepEvent); return; } if (sel8 && !collision.sel8()) { - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); + fillTriggerTable(keepEvent); return; } if (TMath::Abs(collision.posZ()) > cutzvertex) { - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); + fillTriggerTable(keepEvent); return; } @@ -319,98 +390,98 @@ struct strangenessFilter { // Total momentum xiptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); // Proper lifetime - xiproperlifetime = RecoDecay::getMassPDG(3312) * xipos / (xiptotmom + 1e-13); - omegaproperlifetime = RecoDecay::getMassPDG(3334) * xipos / (xiptotmom + 1e-13); + xiproperlifetime = o2::analysis::pdg::MassXiMinus * xipos / (xiptotmom + 1e-13); + omegaproperlifetime = o2::analysis::pdg::MassOmegaMinus * xipos / (xiptotmom + 1e-13); if (casc.sign() == 1) { if (TMath::Abs(casc.dcapostopv()) < dcamesontopv) { continue; - }; + } if (TMath::Abs(casc.dcanegtopv()) < dcabaryontopv) { continue; - }; + } if (TMath::Abs(posdau.tpcNSigmaPi()) > nsigmatpcpi) { continue; - }; + } if (TMath::Abs(negdau.tpcNSigmaPr()) > nsigmatpcpr) { continue; - }; + } } else { if (TMath::Abs(casc.dcanegtopv()) < dcamesontopv) { continue; - }; + } if (TMath::Abs(casc.dcapostopv()) < dcabaryontopv) { continue; - }; + } if (TMath::Abs(posdau.tpcNSigmaPr()) > nsigmatpcpr) { continue; - }; + } if (TMath::Abs(negdau.tpcNSigmaPi()) > nsigmatpcpi) { continue; - }; + } } // these selection differ for Xi and Omegas: if (TMath::Abs(posdau.eta()) > etadau) { continue; - }; + } if (TMath::Abs(negdau.eta()) > etadau) { continue; - }; + } if (TMath::Abs(bachelor.eta()) > etadau) { continue; - }; + } if (TMath::Abs(casc.dcabachtopv()) < dcabachtopv) { continue; - }; + } if (casc.v0radius() < v0radius) { continue; - }; + } if (casc.cascradius() < cascradius) { continue; - }; + } if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < v0cospa) { continue; - }; + } if (casc.dcaV0daughters() > dcav0dau) { continue; - }; + } if (casc.dcacascdaughters() > dcacascdau) { continue; - }; + } if (TMath::Abs(casc.mLambda() - constants::physics::MassLambda) > masslambdalimit) { continue; - }; + } if (TMath::Abs(casc.eta()) > eta) { continue; - }; + } isXi = (TMath::Abs(bachelor.tpcNSigmaPi()) < nsigmatpcpi) && (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaxi) && (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && - (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) < ximasswindow) && - (TMath::Abs(casc.mOmega() - RecoDecay::getMassPDG(3334)) > omegarej) && + (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) < ximasswindow) && + (TMath::Abs(casc.mOmega() - o2::analysis::pdg::MassOmegaMinus) > omegarej) && (xiproperlifetime < properlifetimefactor * ctauxi) && (TMath::Abs(casc.yXi()) < rapidity); // add PID on bachelor isXiYN = (TMath::Abs(bachelor.tpcNSigmaPi()) < nsigmatpcpi) && (casc.cascradius() > lowerradiusXiYN) && - (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) < ximasswindow) && - (TMath::Abs(casc.mOmega() - RecoDecay::getMassPDG(3334)) > omegarej) && + (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) < ximasswindow) && + (TMath::Abs(casc.mOmega() - o2::analysis::pdg::MassOmegaMinus) > omegarej) && (xiproperlifetime < properlifetimefactor * ctauxi) && (TMath::Abs(casc.yXi()) < rapidity); // add PID on bachelor isOmega = (TMath::Abs(bachelor.tpcNSigmaKa()) < nsigmatpcka) && (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaomega) && (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && (casc.cascradius() < upperradiusOmega) && - (TMath::Abs(casc.mOmega() - RecoDecay::getMassPDG(3334)) < omegamasswindow) && - (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) > xirej) && + (TMath::Abs(casc.mOmega() - o2::analysis::pdg::MassOmegaMinus) < omegamasswindow) && + (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) > xirej) && (omegaproperlifetime < properlifetimefactor * ctauomega) && (TMath::Abs(casc.yOmega()) < rapidity); // add PID on bachelor isOmegalargeR = (TMath::Abs(bachelor.tpcNSigmaKa()) < nsigmatpcka) && (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaomega) && (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && (casc.cascradius() > lowerradiusOmega) && - (TMath::Abs(casc.mOmega() - RecoDecay::getMassPDG(3334)) < omegamasswindow) && - (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) > xirej) && + (TMath::Abs(casc.mOmega() - o2::analysis::pdg::MassOmegaMinus) < omegamasswindow) && + (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) > xirej) && (omegaproperlifetime < properlifetimefactor * ctauomega) && (TMath::Abs(casc.yOmega()) < rapidity); // add PID on bachelor @@ -421,7 +492,7 @@ struct strangenessFilter { // Plot for estimates if (tracks.size() > 0) triggcounterForEstimates = 1; - if (triggcounterForEstimates && (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) < 0.01)) + if (triggcounterForEstimates && (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) < 0.01)) hhXiPairsvsPt->Fill(casc.pt()); // Fill the histogram with all the Xis produced in events with a trigger particle // End plot for estimates } @@ -504,7 +575,7 @@ struct strangenessFilter { } // Filling the table - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); + fillTriggerTable(keepEvent); } // PROCESS_SWITCH(strangenessFilter, processRun2, "Process data Run2", true); @@ -513,20 +584,22 @@ struct strangenessFilter { ////////// Strangeness Filter - Run 3 MC ///////////// ////////////////////////////////////////////////////// - void processRun3(CollisionCandidatesRun3 const& collision, TrackCandidates const& tracks, Cascades const& fullCasc, aod::V0sLinked const&, aod::V0Datas const& v0data, DaughterTracks& dtracks) + void processRun3(CollisionCandidatesRun3 const& collision, TrackCandidates const& tracks, Cascades const& fullCasc, aod::V0sLinked const&, aod::V0Datas const& v0data, DaughterTracks& dtracks, + aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& cascades, aod::AssignedTrackedV0s const& trackedV0s, aod::AssignedTracked3Bodys const& tracked3Bodys, aod::BCsWithTimestamps const&) { // Is event good? [0] = Omega, [1] = high-pT hadron + Xi, [2] = 2Xi, [3] = 3Xi, [4] = 4Xi, [5] single-Xi, [6] Omega with high radius - bool keepEvent[7]{false, false, false, false, false, false, false}; + // [7] tracked Xi, [8] tracked Omega, [9] tracked V0, [10] tracked 3Body + bool keepEvent[11]{}; // explicitly zero-initialised if (sel8 && !collision.sel8()) { - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); + fillTriggerTable(keepEvent); return; } // all processed events after event selection hProcessedEvents->Fill(0.5); if (TMath::Abs(collision.posZ()) > cutzvertex) { - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); + fillTriggerTable(keepEvent); return; } QAHistos.fill(HIST("hVtxZ"), collision.posZ()); @@ -582,92 +655,92 @@ struct strangenessFilter { // Total momentum xiptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); // Proper lifetime - xiproperlifetime = RecoDecay::getMassPDG(3312) * xipos / (xiptotmom + 1e-13); - omegaproperlifetime = RecoDecay::getMassPDG(3334) * xipos / (xiptotmom + 1e-13); + xiproperlifetime = o2::analysis::pdg::MassXiMinus * xipos / (xiptotmom + 1e-13); + omegaproperlifetime = o2::analysis::pdg::MassOmegaMinus * xipos / (xiptotmom + 1e-13); if (casc.sign() > 0) { if (TMath::Abs(casc.dcapostopv()) < dcamesontopv) { continue; - }; + } hCandidate->Fill(2.5); if (TMath::Abs(casc.dcanegtopv()) < dcabaryontopv) { continue; - }; + } hCandidate->Fill(3.5); if (TMath::Abs(posdau.tpcNSigmaPi()) > nsigmatpcpi) { continue; - }; + } hCandidate->Fill(4.5); if (TMath::Abs(negdau.tpcNSigmaPr()) > nsigmatpcpr) { continue; - }; + } hCandidate->Fill(5.5); } else if (casc.sign() < 0) { if (TMath::Abs(casc.dcanegtopv()) < dcamesontopv) { continue; - }; + } hCandidate->Fill(2.5); if (TMath::Abs(casc.dcapostopv()) < dcabaryontopv) { continue; - }; + } hCandidate->Fill(3.5); if (TMath::Abs(negdau.tpcNSigmaPi()) > nsigmatpcpi) { continue; - }; + } hCandidate->Fill(4.5); if (TMath::Abs(posdau.tpcNSigmaPr()) > nsigmatpcpr) { continue; - }; + } hCandidate->Fill(5.5); } if (TMath::Abs(posdau.eta()) > etadau) { continue; - }; + } if (TMath::Abs(negdau.eta()) > etadau) { continue; - }; + } if (TMath::Abs(bachelor.eta()) > etadau) { continue; - }; + } hCandidate->Fill(6.5); if (TMath::Abs(casc.dcabachtopv()) < dcabachtopv) { continue; - }; + } hCandidate->Fill(7.5); if (casc.v0radius() < v0radius) { continue; - }; + } hCandidate->Fill(8.5); if (casc.cascradius() < cascradius) { continue; - }; + } hCandidate->Fill(9.5); if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < v0cospa) { continue; - }; + } hCandidate->Fill(10.5); if (casc.dcaV0daughters() > dcav0dau) { continue; - }; + } hCandidate->Fill(11.5); if (casc.dcacascdaughters() > dcacascdau) { continue; - }; + } hCandidate->Fill(12.5); if (TMath::Abs(casc.mLambda() - constants::physics::MassLambda) > masslambdalimit) { continue; - }; + } hCandidate->Fill(13.5); if (TMath::Abs(casc.eta()) > eta) { continue; - }; + } hCandidate->Fill(14.5); if (hastof && (!posdau.hasTOF() && posdau.pt() > ptthrtof) && (!negdau.hasTOF() && negdau.pt() > ptthrtof) && (!bachelor.hasTOF() && bachelor.pt() > ptthrtof)) { continue; - }; + } hCandidate->Fill(15.5); // Fill selections QA for XiMinus @@ -687,21 +760,21 @@ struct strangenessFilter { isXi = (TMath::Abs(bachelor.tpcNSigmaPi()) < nsigmatpcpi) && (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaxi) && (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && - (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) < ximasswindow) && - (TMath::Abs(casc.mOmega() - RecoDecay::getMassPDG(3334)) > omegarej) && + (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) < ximasswindow) && + (TMath::Abs(casc.mOmega() - o2::analysis::pdg::MassOmegaMinus) > omegarej) && (xiproperlifetime < properlifetimefactor * ctauxi) && (TMath::Abs(casc.yXi()) < rapidity); isXiYN = (TMath::Abs(bachelor.tpcNSigmaPi()) < nsigmatpcpi) && (casc.cascradius() > lowerradiusXiYN) && - (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) < ximasswindow) && - (TMath::Abs(casc.mOmega() - RecoDecay::getMassPDG(3334)) > omegarej) && + (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) < ximasswindow) && + (TMath::Abs(casc.mOmega() - o2::analysis::pdg::MassOmegaMinus) > omegarej) && (xiproperlifetime < properlifetimefactor * ctauxi) && (TMath::Abs(casc.yXi()) < rapidity); isOmega = (TMath::Abs(bachelor.tpcNSigmaKa()) < nsigmatpcka) && (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaomega) && (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && - (TMath::Abs(casc.mOmega() - RecoDecay::getMassPDG(3334)) < omegamasswindow) && - (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) > xirej) && + (TMath::Abs(casc.mOmega() - o2::analysis::pdg::MassOmegaMinus) < omegamasswindow) && + (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) > xirej) && (casc.cascradius() < upperradiusOmega) && (omegaproperlifetime < properlifetimefactor * ctauomega) && (TMath::Abs(casc.yOmega()) < rapidity); @@ -709,8 +782,8 @@ struct strangenessFilter { (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) > casccospaomega) && (casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()) > dcav0topv) && (casc.cascradius() > lowerradiusOmega) && - (TMath::Abs(casc.mOmega() - RecoDecay::getMassPDG(3334)) < omegamasswindow) && - (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) > xirej) && + (TMath::Abs(casc.mOmega() - o2::analysis::pdg::MassOmegaMinus) < omegamasswindow) && + (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) > xirej) && (omegaproperlifetime < properlifetimefactor * ctauomega) && (TMath::Abs(casc.yOmega()) < rapidity); @@ -763,7 +836,7 @@ struct strangenessFilter { if (triggcounterForEstimates > 0) break; } - if (triggcounterForEstimates && (TMath::Abs(casc.mXi() - RecoDecay::getMassPDG(3312)) < 0.01)) + if (triggcounterForEstimates && (TMath::Abs(casc.mXi() - o2::analysis::pdg::MassXiMinus) < 0.01)) hhXiPairsvsPt->Fill(casc.pt()); // Fill the histogram with all the Xis produced in events with a trigger particle // End plot for estimates } @@ -829,7 +902,7 @@ struct strangenessFilter { for (int i = 0; i < 11; i++) { EvtwhMinPt[i] = 0.; EvtwhMinPtXi[i] = 0.; - ThrdPt[i] = (float)i; + ThrdPt[i] = static_cast(i); } // QA tracks @@ -912,6 +985,129 @@ struct strangenessFilter { keepEvent[6] = true; } + // strangeness tracking selection + const auto bc = collision.bc_as(); + if (runNumber != bc.runNumber()) { + runNumber = bc.runNumber(); + auto timestamp = bc.timestamp(); + + if (o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, timestamp)) { + o2::base::Propagator::initFieldFromGRP(grpo); + } else if (o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp(grpMagPath, timestamp)) { + o2::base::Propagator::initFieldFromGRP(grpmag); + } else { + LOG(fatal) << "Got nullptr from CCDB for path " << grpMagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << timestamp; + } + } + + const auto primaryVertex = getPrimaryVertex(collision); + o2::dataformats::DCA impactParameterTrk; + + for (const auto& casc : fullCasc) { + QAHistosStrangenessTracking.fill(HIST("hPtCascCand"), casc.pt()); + } + + for (const auto& trackedCascade : trackedCascades) { + const auto trackCasc = trackedCascade.track_as(); + QAHistosStrangenessTracking.fill(HIST("hPtCascTracked"), trackCasc.pt()); + QAHistosStrangenessTracking.fill(HIST("hStRVsPtTrkCasc"), trackCasc.pt(), RecoDecay::sqrtSumOfSquares(trackCasc.x(), trackCasc.y())); + QAHistosStrangenessTracking.fill(HIST("hMatchChi2TrkCasc"), trackedCascade.matchingChi2()); + QAHistosStrangenessTracking.fill(HIST("hMassOmegaVsMatchChi2TrkCasc"), trackedCascade.omegaMass(), trackedCascade.matchingChi2()); + QAHistosStrangenessTracking.fill(HIST("hMassXiVsMatchChi2TrkCasc"), trackedCascade.xiMass(), trackedCascade.matchingChi2()); + QAHistosStrangenessTracking.fill(HIST("hMassOmegaVsTopChi2TrkCasc"), trackedCascade.omegaMass(), trackedCascade.topologyChi2()); + QAHistosStrangenessTracking.fill(HIST("hMassXiVsTopChi2TrkCasc"), trackedCascade.xiMass(), trackedCascade.topologyChi2()); + + auto trackParCovTrk = getTrackParCov(trackCasc); + o2::base::Propagator::Instance()->propagateToDCA(primaryVertex, trackParCovTrk, bz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrNONE, &impactParameterTrk); + + QAHistosStrangenessTracking.fill(HIST("hDcaXY"), impactParameterTrk.getY()); + QAHistosStrangenessTracking.fill(HIST("hDcaXYVsPt"), trackParCovTrk.getPt(), impactParameterTrk.getY()); + QAHistosStrangenessTracking.fill(HIST("hDcaZ"), impactParameterTrk.getZ()); + QAHistosStrangenessTracking.fill(HIST("hDcaZVsPt"), trackParCovTrk.getPt(), impactParameterTrk.getZ()); + QAHistosStrangenessTracking.fill(HIST("hDcaVsPt"), impactParameterTrk.getY(), trackCasc.pt()); + QAHistosStrangenessTracking.fill(HIST("hDcaVsR"), impactParameterTrk.getY(), RecoDecay::sqrtSumOfSquares(trackCasc.x(), trackCasc.y())); + + // const auto itsTrack = trackedCascade.itsTrack(); + const auto cascade = trackedCascade.cascade(); + const auto bachelor = cascade.bachelor_as(); + const auto v0 = cascade.v0_as(); + const auto negTrack = v0.negTrack_as(); + const auto posTrack = v0.posTrack_as(); + + std::array masses{o2::analysis::pdg::MassProton, o2::analysis::pdg::MassPiMinus}; + std::array, 2> momenta; + std::array nsigma; + if (trackCasc.sign() < 0) { + // Omega-, Xi- + momenta[0] = {posTrack.px(), posTrack.py(), posTrack.pz()}; + momenta[1] = {negTrack.px(), negTrack.py(), negTrack.pz()}; + nsigma[0] = posTrack.tpcNSigmaPr(); + nsigma[1] = negTrack.tpcNSigmaPi(); + } else { + // Omega+, Xi+ + momenta[0] = {negTrack.px(), negTrack.py(), negTrack.pz()}; + momenta[1] = {posTrack.px(), posTrack.py(), posTrack.pz()}; + nsigma[0] = negTrack.tpcNSigmaPr(); + nsigma[1] = posTrack.tpcNSigmaPi(); + } + + const auto v0mass = RecoDecay::m(momenta, masses); + QAHistosStrangenessTracking.fill(HIST("hMassV0TrkCasc"), v0mass); + QAHistosStrangenessTracking.fill(HIST("hNSigmaTpcPrTrkCascV0"), nsigma[0]); + QAHistosStrangenessTracking.fill(HIST("hNSigmaTpcPiTrkCascV0"), nsigma[1]); + QAHistosStrangenessTracking.fill(HIST("hNSigmaTpcPiTrkCascBachelor"), bachelor.tpcNSigmaPi()); + QAHistosStrangenessTracking.fill(HIST("hNSigmaTpcKaTrkCascBachelor"), bachelor.tpcNSigmaKa()); + + momenta[0] = {posTrack.px() + negTrack.px(), posTrack.py() + negTrack.py(), posTrack.pz() + negTrack.pz()}; + momenta[1] = {bachelor.px(), bachelor.py(), bachelor.pz()}; + masses = {o2::analysis::pdg::MassLambda0, o2::analysis::pdg::MassK0}; + const auto massOmega = recalculateMasses ? RecoDecay::m(momenta, masses) : trackedCascade.omegaMass(); + if (posTrack.hasTPC() && negTrack.hasTPC()) { + QAHistosStrangenessTracking.fill(HIST("hMassOmegaTrkCasc"), massOmega); + } + masses = {o2::analysis::pdg::MassLambda0, o2::analysis::pdg::MassPi0}; + const auto massXi = recalculateMasses ? RecoDecay::m(momenta, masses) : trackedCascade.xiMass(); + if (posTrack.hasTPC() && negTrack.hasTPC()) { + QAHistosStrangenessTracking.fill(HIST("hMassXiTrkCasc"), massXi); + } + + if ((trackCasc.pt() > minPtTrackedCascade) && + (trackedCascade.matchingChi2() < maxMatchingChi2TrackedCascade) && + (std::abs(v0mass - o2::analysis::pdg::MassLambda0) < massWindowLambda) && + (std::abs(nsigma[0]) < maxNSigmaV0PrTrackedCascade) && + (std::abs(nsigma[1]) < maxNSigmaV0PiTrackedCascade)) { + // Xi + if ((std::abs(massXi - o2::analysis::pdg::MassXiMinus) < massWindowTrackedXi) && + (std::abs(bachelor.tpcNSigmaPi()) < maxNSigmaBachelorTrackedXi)) { + keepEvent[7] = true; + } + // Omega + if ((std::abs(massOmega - o2::analysis::pdg::MassOmegaMinus) < massWindowTrackedOmega) && + (std::abs(massXi - o2::analysis::pdg::MassXiMinus) >= massWindowXiExclTrackedOmega) && + (std::abs(bachelor.tpcNSigmaKa()) < maxNSigmaBachelorTrackedOmega)) { + keepEvent[8] = true; + } + } + } + + for (const auto& trackedV0 : trackedV0s) { + const auto trackV0 = trackedV0.track_as(); + QAHistosStrangenessTracking.fill(HIST("hMassH3LTrkV0"), trackedV0.h3Lmass()); + QAHistosStrangenessTracking.fill(HIST("hMassH4LTrkV0"), trackedV0.h4Lmass()); + if (trackV0.pt() > minPtTrackedV0) { + keepEvent[9] = true; + } + } + + for (const auto& tracked3Body : tracked3Bodys) { + const auto track3Body = tracked3Body.track_as(); + QAHistosStrangenessTracking.fill(HIST("hMassH3LTrk3body"), tracked3Body.h3Lmass()); + QAHistosStrangenessTracking.fill(HIST("hMassHe4LTrk3body"), tracked3Body.he4Lmass()); + if (track3Body.pt() > minPtTracked3Body) { + keepEvent[10] = true; + } + } + // Fill centrality dependent histos if (keepEvent[0]) { hProcessedEvents->Fill(2.5); @@ -937,9 +1133,21 @@ struct strangenessFilter { if (xicounter > 0) { hProcessedEvents->Fill(9.5); } + if (keepEvent[7]) { + hProcessedEvents->Fill(10.5); + } + if (keepEvent[8]) { + hProcessedEvents->Fill(11.5); + } + if (keepEvent[9]) { + hProcessedEvents->Fill(12.5); + } + if (keepEvent[10]) { + hProcessedEvents->Fill(13.5); + } // Filling the table - strgtable(keepEvent[0], keepEvent[1], keepEvent[2], keepEvent[3], keepEvent[4], keepEvent[5], keepEvent[6]); + fillTriggerTable(keepEvent); } // PROCESS_SWITCH(strangenessFilter, processRun3, "Process Run3", true); diff --git a/EventFiltering/PWGMM/multFilter.cxx b/EventFiltering/PWGMM/multFilter.cxx index e4cde802bed..f204a34d830 100644 --- a/EventFiltering/PWGMM/multFilter.cxx +++ b/EventFiltering/PWGMM/multFilter.cxx @@ -64,6 +64,10 @@ struct multFilter { Configurable avPyT0A{"avPyT0A", 8.16, "nch from pythia T0A"}; Configurable avPyT0C{"avPyT0C", 8.83, "nch from pythia T0C"}; Configurable avPyFV0{"avPyFV0", 21.44, "nch from pythia FV0"}; + + Configurable maxFV0FT0Cm{"maxFV0FT0Cm", 10000., "upper cut on FV0+FT0C mult"}; + Configurable maxFT0m{"maxFT0m", 10000., "upper cut on FT0 mult"}; + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "URL of the CCDB database"}; @@ -495,8 +499,20 @@ struct multFilter { static_for<0, 7>([&](auto i) { constexpr int index = i.value; if (estimator[index] > cut[index]) { - multiplicity.fill(HIST(nhEst_after[index]), estimator[index]); - keepEvent[index] = true; + if (index == 3) { + if (estimator[index] < maxFT0m) { + multiplicity.fill(HIST(nhEst_after[index]), estimator[index]); + keepEvent[index] = true; + } + } else if (index == 5) { + if (estimator[index] < maxFV0FT0Cm) { + multiplicity.fill(HIST(nhEst_after[index]), estimator[index]); + keepEvent[index] = true; + } + } else { + multiplicity.fill(HIST(nhEst_after[index]), estimator[index]); + keepEvent[index] = true; + } } }); diff --git a/EventFiltering/PWGUD/diffractionBCFilter.cxx b/EventFiltering/PWGUD/diffractionBCFilter.cxx index ed15a8ab0f4..25537c86c4f 100644 --- a/EventFiltering/PWGUD/diffractionBCFilter.cxx +++ b/EventFiltering/PWGUD/diffractionBCFilter.cxx @@ -240,23 +240,24 @@ struct DGBCFilterRun3 { // histograms with cut statistics // bin: - // 0: All collisions - // 1: DG candidate - // 2: not clean FIT - // 3: number of FwdTracks > 0 - // 4: not all global tracks are vtx tracks - // 5: not all vtx tracks are global tracks - // 6: fraction of tracks with TOF hit too low - // 7: number of vtx tracks out of range - // 8: has not good PID information - // 9: track pt out of range - // 10: track eta out of range - // 11: net charge out of range - // 12: IVM out of range + // 1: All collisions + // 2: DG candidate + // 3: FIT veto + // 4: number of FwdTracks > 0 + // 5: not all global tracks are PV tracks + // 6: not all PV tracks are global tracks + // 7: ITS only PV tracks + // 8: fraction of tracks with TOF hit too low + // 9: number of PV tracks out of range + // 10: PV tracks without good PID information + // 11: PV track pt out of range + // 13: PV track eta out of range + // 14: net charge out of range + // 15: IVM out of range HistogramRegistry registry{ "registry", { - {"aftercut", "#aftercut", {HistType::kTH1F, {{13, -0.5, 12.5}}}}, + {"aftercut", "#aftercut", {HistType::kTH1F, {{14, -0.5, 13.5}}}}, }}; void init(InitContext&) diff --git a/EventFiltering/PWGUD/diffractionFilter.cxx b/EventFiltering/PWGUD/diffractionFilter.cxx index dac8174c02d..71f628a90ea 100644 --- a/EventFiltering/PWGUD/diffractionFilter.cxx +++ b/EventFiltering/PWGUD/diffractionFilter.cxx @@ -16,6 +16,7 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" +#include "Framework/StaticFor.h" #include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/DGSelector.h" #include "PWGUD/Core/UDHelpers.h" @@ -31,37 +32,89 @@ struct DGFilterRun3 { // Productions Produces filterTable; - // DGCutparHolders + // Configurables + int64_t collCounter; + int64_t verbose; + Configurable Verbose{"Verbose", {0}, "With extra log output"}; DGCutparHolder diffCuts = DGCutparHolder(); Configurable diffCutsHolder{"DiffCuts", {}, "Diffractive events cuts"}; // DG selector DGSelector dgSelector; - // histograms with cut statistics + // histogram stat/aftercuts with cut statistics // bin: // 1: All collisions // 2: DG candidate - // 3: not clean FIT + // 3: FIT veto // 4: number of FwdTracks > 0 - // 5: not all global tracks are vtx tracks - // 6: not all vtx tracks are global tracks - // 7: fraction of tracks with TOF hit too low - // 8: number of vtx tracks out of range - // 9: has not good PID information - // 10: track pt out of range - // 11: track eta out of range - // 12: net charge out of range - // 13: IVM out of range + // 5: not all global tracks are PV tracks + // 6: not all PV tracks are global tracks + // 7: ITS only PV tracks + // 8: fraction of tracks with TOF hit too low + // 9: number of PV tracks out of range + // 10: PV tracks without good PID information + // 11: PV track pt out of range + // 13: PV track eta out of range + // 14: net charge out of range + // 15: IVM out of range + // initinitialize HistogramRegistry + static constexpr std::string_view hcFITs[5] = {"FIT/cleanFITFV0A", "FIT/cleanFITFT0A", "FIT/cleanFITFT0C", "FIT/cleanFITFDDA", "FIT/cleanFITFDDC"}; HistogramRegistry registry{ "registry", - { - {"aftercuts", "#aftercuts", {HistType::kTH1F, {{13, -0.5, 12.5}}}}, - }}; + {}}; void init(InitContext&) { + // reset collision counter + collCounter = 0; + verbose = (int64_t)Verbose; + if (verbose <= 0) { + verbose = 1000000000000; + } + + // cut holder diffCuts = (DGCutparHolder)diffCutsHolder; + + // create histograms + // stat + registry.add("stat/aftercuts", "Cut efficiencies", {HistType::kTH1F, {{14, -0.5, 13.5}}}); + + // FIT + registry.add("FIT/cleanFIT", "Rejection by FIT veto versus tested BC range", {HistType::kTH2F, {{21, -0.5, 20.5}, {2, -0.5, 1.5}}}); + for (auto n{0}; n < 5; n++) { + registry.add(hcFITs[n].data(), hcFITs[n].data(), {HistType::kTH2F, {{21, -0.5, 20.5}, {2, -0.5, 1.5}}}); + } + registry.add("FIT/FV0Atime", "Time of FV0A [ns]", {HistType::kTH1F, {{6001, -20.005, 40.005}}}); + registry.add("FIT/FT0Atime", "Time of FT0A [ns]", {HistType::kTH1F, {{6001, -20.005, 40.005}}}); + registry.add("FIT/FT0Ctime", "Time of FT0C [ns]", {HistType::kTH1F, {{6001, -20.005, 40.005}}}); + registry.add("FIT/FDDAtime", "Time of FDDA [ns]", {HistType::kTH1F, {{6001, -20.005, 40.005}}}); + registry.add("FIT/FDDCtime", "Time of FDDC [ns]", {HistType::kTH1F, {{6001, -20.005, 40.005}}}); + + // collision + registry.add("collisions/tracksAll", "Number of tracks per collision", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/PVTracksAll", "Number of PV tracks per collision", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/globalTracksAll", "Number of global tracks per collision", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/netChargeAll", "Net charge of PV tracks versus number of PV tracks of all collisions", {HistType::kTH2F, {{51, -0.5, 50.5}, {41, -20.5, 20.5}}}); + registry.add("collisions/dtcvsrPVtrwTOFAll", "Collision time resolution as function of the fraction of PV tracks with TOF hit of all collisions", {HistType::kTH2F, {{1001, -0.05, 100.05}, {101, -0.005, 1.005}}}); + registry.add("collisions/rPVtrwTOFAll", "Fraction of PV tracks with TOF hit versus number of PV tracks of all collisions", {HistType::kTH2F, {{100, 0.5, 100.5}, {101, -0.005, 1.005}}}); + registry.add("collisions/forwardTracksAll", "Number of forward tracks per collision", {HistType::kTH2F, {{5, -0.5, 4.5}, {101, -0.5, 100.5}}}); + + registry.add("collisions/tracksDG", "Number of tracks per DG collision", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/PVTracksDG", "Number of PV tracks per DG collision", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/globalTracksDG", "Number of global tracks per DG collision", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/netChargeDG", "Net charge of PV tracks versus number of PV tracks of DG collisions", {HistType::kTH2F, {{51, -0.5, 50.5}, {41, -20.5, 20.5}}}); + registry.add("collisions/dtcvsrPVtrwTOFDG", "Collision time resolution as function of the fraction of PV tracks with TOF hit of DG candidates", {HistType::kTH2F, {{1001, -0.05, 100.05}, {101, -0.005, 1.005}}}); + registry.add("collisions/rPVtrwTOFDG", "Fraction of PV tracks with TOF hit versus number of PV tracks of DG collisions", {HistType::kTH2F, {{100, 0.5, 100.5}, {101, -0.005, 1.005}}}); + registry.add("collisions/forwardTracksDG", "Number of forward tracks per DG collision", {HistType::kTH2F, {{5, -0.5, 4.5}, {101, -0.5, 100.5}}}); + + // tracks + registry.add("tracks/etavsptAll", "eta versus pt of PV tracks of all collisions", {HistType::kTH2F, {{401, -2.005, 2.005}, {1000, 0., 10.}}}); + registry.add("tracks/etavsptDGwT", "eta versus pt of PV tracks with TOF hit in DG collisions", {HistType::kTH2F, {{401, -2.005, 2.005}, {1000, 0., 10.}}}); + registry.add("tracks/etavsptDGnT", "eta versus pt of PV tracks without TOF hit in DG collisions", {HistType::kTH2F, {{401, -2.005, 2.005}, {1000, 0., 10.}}}); + + // forwardTracks + registry.add("forwardTracks/timeResolution", "Time resolution of forward tracks as function of track type [ns]", {HistType::kTH2F, {{5, -0.5, 4.5}, {10001, -0.005, 100.005}}}); } // some general Collisions and Tracks filter @@ -87,11 +140,10 @@ struct DGFilterRun3 { aod::FV0As& fv0as, aod::FDDs& fdds) { - // initialize LOGF(debug, "(); + auto rgtrwTOF = udhelpers::rPVtrwTOF(tracks, collision.numContrib()); + if ((collCounter % verbose) == 0) { + auto bc1 = collision.bc_as(); + LOGF(info, "BCId %d/%d isDG %d PV tracks %d rgtrwTOF %f", bc1.globalBC(), bc2.globalBC(), isDGEvent + 1, collision.numContrib(), rgtrwTOF); + } + + // update QC histograms + // FIT + if (bc2.has_foundFV0()) { + registry.fill(HIST("FIT/FV0Atime"), bc2.foundFV0().time()); + } + if (bc2.has_foundFT0()) { + registry.fill(HIST("FIT/FT0Atime"), bc2.foundFT0().timeA()); + registry.fill(HIST("FIT/FT0Ctime"), bc2.foundFT0().timeC()); + } + if (bc2.has_foundFDD()) { + registry.fill(HIST("FIT/FDDAtime"), bc2.foundFDD().timeA()); + registry.fill(HIST("FIT/FDDCtime"), bc2.foundFDD().timeC()); + } + + auto FITlims = std::vector(5, 1000000.); + bool isDGcandidate = true; + for (int nMinBC = 0; nMinBC <= 20; nMinBC++) { + auto bcSlice = udhelpers::compatibleBCs(collision, 0, bcs, nMinBC); + isDGcandidate = true; + for (auto const& bc : bcSlice) { + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits()); + } + registry.get(HIST("FIT/cleanFIT"))->Fill(nMinBC, isDGcandidate * 1.); + + // loop over single detectors + static_for<0, 4>([&](auto n) { + FITlims[n] = 0.; + isDGcandidate = true; + for (auto const& bc : bcSlice) { + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), FITlims); + } + constexpr int index = n.value; + registry.fill(HIST(hcFITs[index]), nMinBC, isDGcandidate * 1.); + FITlims[n] = 1000000.; + }); + } + + // collisions + registry.fill(HIST("collisions/tracksAll"), tracks.size()); + registry.fill(HIST("collisions/PVTracksAll"), collision.numContrib()); + Partition goodTracks = requireGlobalTrackInFilter(); + goodTracks.bindTable(tracks); + registry.get(HIST("collisions/globalTracksAll"))->Fill(goodTracks.size()); + auto netCharge = udhelpers::netCharge(tracks); + registry.fill(HIST("collisions/netChargeAll"), collision.numContrib(), netCharge); + registry.fill(HIST("collisions/dtcvsrPVtrwTOFAll"), collision.collisionTimeRes(), rgtrwTOF); + registry.fill(HIST("collisions/rPVtrwTOFAll"), collision.numContrib(), rgtrwTOF); + if (ccs) { + registry.fill(HIST("collisions/tracksDG"), tracks.size()); + registry.fill(HIST("collisions/PVTracksDG"), collision.numContrib()); + registry.get(HIST("collisions/globalTracksDG"))->Fill(goodTracks.size()); + registry.fill(HIST("collisions/netChargeDG"), collision.numContrib(), netCharge); + registry.fill(HIST("collisions/dtcvsrPVtrwTOFDG"), collision.collisionTimeRes(), rgtrwTOF); + registry.fill(HIST("collisions/rPVtrwTOFDG"), collision.numContrib(), rgtrwTOF); + } + + // tracks + for (auto const& track : tracks) { + if (track.isPVContributor()) { + registry.fill(HIST("tracks/etavsptAll"), track.eta(), track.pt()); + if (ccs) { + if (track.hasTOF()) { + registry.fill(HIST("tracks/etavsptDGwT"), track.eta(), track.pt()); + } else { + registry.fill(HIST("tracks/etavsptDGnT"), track.eta(), track.pt()); + } + } + } + } + + // forward tracks + int nforwardTracks[5] = {0}; + for (auto track : fwdtracks) { + nforwardTracks[track.trackType()]++; + registry.fill(HIST("forwardTracks/timeResolution"), track.trackType(), track.trackTimeRes()); + } + for (auto ii = 0; ii < 5; ii++) { + registry.fill(HIST("collisions/forwardTracksAll"), ii, nforwardTracks[ii]); + if (ccs) { + registry.fill(HIST("collisions/forwardTracksDG"), ii, nforwardTracks[ii]); + } + } + + // update collision counter + collCounter++; } }; diff --git a/EventFiltering/cefpTask.cxx b/EventFiltering/cefpTask.cxx index 4d2d5cc1172..718a857d7dc 100644 --- a/EventFiltering/cefpTask.cxx +++ b/EventFiltering/cefpTask.cxx @@ -23,13 +23,16 @@ #include "filterTables.h" +#include "CCDB/BasicCCDBManager.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/LHCConstants.h" #include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsCTP/Scalers.h" // we need to add workflow options before including Framework/runDataProcessing void customize(std::vector& workflowOptions) @@ -211,7 +214,9 @@ struct centralEventFilterTask { HistogramRegistry scalers{"scalers", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; Produces tags; Configurable cfgTimingCut{"cfgTimingCut", 1.f, "nsigma timing cut associating BC and collisions"}; + Service ccdb; + FILTER_CONFIGURABLE(F1ProtonFilters); FILTER_CONFIGURABLE(NucleiFilters); FILTER_CONFIGURABLE(DiffractionFilters); FILTER_CONFIGURABLE(DqFilters); @@ -223,8 +228,16 @@ struct centralEventFilterTask { FILTER_CONFIGURABLE(FullJetFilters); FILTER_CONFIGURABLE(PhotFilters); + int mRunNumber{-1}; + o2::InteractionRecord mEndOfITSramp{0, 0}; + void init(o2::framework::InitContext& initc) { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(true); + LOG(debug) << "Start init"; int nCols{0}; for (auto& table : mDownscaling) { @@ -261,8 +274,72 @@ struct centralEventFilterTask { } } + void initCCDB(int runNumber) + { + if (mRunNumber == runNumber) { + return; + } + mRunNumber = runNumber; + auto rd = ccdb->getRunDuration(mRunNumber); + ccdb->setTimestamp((rd.first + rd.second) / 2); + auto* scl = ccdb->get("CTP/Calib/Scalers"); + scl->convertRawToO2(); + auto svec = scl->getScalerRecordO2(); + mEndOfITSramp = svec[0].intRecord; + + auto* itsRamp = ccdb->get>("ITS/Calib/RampDuration"); + uint64_t toleranceInBC = (itsRamp->at(0) + itsRamp->at(1)) * 1.e9 / constants::lhc::LHCBunchSpacingNS; + mEndOfITSramp += toleranceInBC; + } + void run(ProcessingContext& pc) { + + // Filling output table + auto bcTabConsumer = pc.inputs().get(aod::MetadataTrait>::metadata::tableLabel()); + auto bcTabPtr{bcTabConsumer->asArrowTable()}; + auto collTabConsumer = pc.inputs().get(aod::MetadataTrait>::metadata::tableLabel()); + auto collTabPtr{collTabConsumer->asArrowTable()}; + auto evSelConsumer = pc.inputs().get(aod::MetadataTrait>::metadata::tableLabel()); + auto evSelTabPtr{evSelConsumer->asArrowTable()}; + + auto columnGloBCId{bcTabPtr->GetColumnByName(aod::BC::GlobalBC::mLabel)}; + auto columnCollBCId{collTabPtr->GetColumnByName(aod::Collision::BCId::mLabel)}; + auto columnCollTime{collTabPtr->GetColumnByName(aod::Collision::CollisionTime::mLabel)}; + auto columnCollTimeRes{collTabPtr->GetColumnByName(aod::Collision::CollisionTimeRes::mLabel)}; + auto columnFoundBC{evSelTabPtr->GetColumnByName(o2::aod::evsel::FoundBCId::mLabel)}; + auto columnRunNumber{bcTabPtr->GetColumnByName(aod::BC::RunNumber::mLabel)}; + + auto chunkCollBCid{columnCollBCId->chunk(0)}; + auto chunkCollTime{columnCollTime->chunk(0)}; + auto chunkCollTimeRes{columnCollTimeRes->chunk(0)}; + auto chunkGloBC{columnGloBCId->chunk(0)}; + auto chunkFoundBC{columnFoundBC->chunk(0)}; + auto chunkRunNumber{columnRunNumber->chunk(0)}; + + auto CollBCIdArray = std::static_pointer_cast>(chunkCollBCid); + auto CollTimeArray = std::static_pointer_cast>(chunkCollTime); + auto CollTimeResArray = std::static_pointer_cast>(chunkCollTimeRes); + auto GloBCArray = std::static_pointer_cast>(chunkGloBC); + auto FoundBCArray = std::static_pointer_cast>(chunkFoundBC); + auto RunNumberArray = std::static_pointer_cast>(chunkRunNumber); + + if (RunNumberArray->length()) { + initCCDB(RunNumberArray->Value(0)); + } + + if (CollTimeArray->length() == 0) { + LOG(warn) << "The collision table in the current folder is empty."; + } + + int startCollision{0}; + // for (int iC{0}; iC < CollBCIdArray->length(); ++iC) { + // if (o2::InteractionRecord::long2IR(GloBCArray->Value(CollBCIdArray->Value(iC))) > mEndOfITSramp) { + // break; + // } + // startCollision = iC; + // } + auto mScalers{scalers.get(HIST("mScalers"))}; auto mFiltered{scalers.get(HIST("mFiltered"))}; auto mCovariance{scalers.get(HIST("mCovariance"))}; @@ -299,7 +376,7 @@ struct centralEventFilterTask { for (int64_t iC{0}; iC < column->num_chunks(); ++iC) { auto chunk{column->chunk(iC)}; auto boolArray = std::static_pointer_cast(chunk); - for (int64_t iS{0}; iS < chunk->length(); ++iS) { + for (int64_t iS{startCollision}; iS < chunk->length(); ++iS) { if (boolArray->Value(iS)) { mScalers->Fill(binCenter); outTrigger[entry] |= triggerBit; @@ -315,8 +392,8 @@ struct centralEventFilterTask { } } } - mScalers->SetBinContent(1, mScalers->GetBinContent(1) + nEvents); - mFiltered->SetBinContent(1, mFiltered->GetBinContent(1) + nEvents); + mScalers->SetBinContent(1, mScalers->GetBinContent(1) + nEvents - startCollision); + mFiltered->SetBinContent(1, mFiltered->GetBinContent(1) + nEvents - startCollision); for (uint64_t iE{0}; iE < outTrigger.size(); ++iE) { for (int iB{0}; iB < 64; ++iB) { @@ -337,42 +414,16 @@ struct centralEventFilterTask { } } - // Filling output table - auto bcTabConsumer = pc.inputs().get(aod::MetadataTrait>::metadata::tableLabel()); - auto bcTabPtr{bcTabConsumer->asArrowTable()}; - auto collTabConsumer = pc.inputs().get(aod::MetadataTrait>::metadata::tableLabel()); - auto collTabPtr{collTabConsumer->asArrowTable()}; - auto evSelConsumer = pc.inputs().get(aod::MetadataTrait>::metadata::tableLabel()); - auto evSelTabPtr{evSelConsumer->asArrowTable()}; - + /// Filling the output table if (outDecision.size() != static_cast(collTabPtr->num_rows())) { LOG(fatal) << "Inconsistent number of rows across Collision table and CEFP decision vector."; } if (outDecision.size() != static_cast(evSelTabPtr->num_rows())) { LOG(fatal) << "Inconsistent number of rows across EvSel table and CEFP decision vector."; } - - auto columnGloBCId{bcTabPtr->GetColumnByName(aod::BC::GlobalBC::mLabel)}; - auto columnBCId{collTabPtr->GetColumnByName(aod::Collision::BCId::mLabel)}; - auto columnCollTime{collTabPtr->GetColumnByName(aod::Collision::CollisionTime::mLabel)}; - auto columnCollTimeRes{collTabPtr->GetColumnByName(aod::Collision::CollisionTimeRes::mLabel)}; - auto columnFoundBC{evSelTabPtr->GetColumnByName(o2::aod::evsel::FoundBCId::mLabel)}; - - auto chunkBC{columnBCId->chunk(0)}; - auto chunkCollTime{columnCollTime->chunk(0)}; - auto chunkCollTimeRes{columnCollTimeRes->chunk(0)}; - auto chunkGloBC{columnGloBCId->chunk(0)}; - auto chunkFoundBC{columnFoundBC->chunk(0)}; - - auto BCArray = std::static_pointer_cast>(chunkBC); - auto CollTimeArray = std::static_pointer_cast>(chunkCollTime); - auto CollTimeResArray = std::static_pointer_cast>(chunkCollTimeRes); - auto GloBCArray = std::static_pointer_cast>(chunkGloBC); - auto FoundBCArray = std::static_pointer_cast>(chunkFoundBC); - for (uint64_t iD{0}; iD < outDecision.size(); ++iD) { uint64_t foundBC = FoundBCArray->Value(iD) >= 0 && FoundBCArray->Value(iD) < GloBCArray->length() ? GloBCArray->Value(FoundBCArray->Value(iD)) : -1; - tags(BCArray->Value(iD), GloBCArray->Value(BCArray->Value(iD)), foundBC, CollTimeArray->Value(iD), CollTimeResArray->Value(iD), outTrigger[iD], outDecision[iD]); + tags(CollBCIdArray->Value(iD), GloBCArray->Value(CollBCIdArray->Value(iD)), foundBC, CollTimeArray->Value(iD), CollTimeResArray->Value(iD), outTrigger[iD], outDecision[iD]); } } diff --git a/EventFiltering/filterTables.h b/EventFiltering/filterTables.h index b01647dfe3d..6f11b8bca0b 100644 --- a/EventFiltering/filterTables.h +++ b/EventFiltering/filterTables.h @@ -21,8 +21,6 @@ namespace o2::aod { namespace filtering { -DECLARE_SOA_COLUMN(H2, hasH2, bool); //! -DECLARE_SOA_COLUMN(H3, hasH3, bool); //! DECLARE_SOA_COLUMN(He, hasHe, bool); //! // diffraction @@ -38,17 +36,18 @@ DECLARE_SOA_COLUMN(DiElectron, hasDiElectron, bool); //! dielectron trigger DECLARE_SOA_COLUMN(DiMuon, hasDiMuon, bool); //! dimuon trigger with low pT on muons // heavy flavours -DECLARE_SOA_COLUMN(HfHighPt2P, hasHfHighPt2P, bool); //! high-pT 2-prong charm hadron -DECLARE_SOA_COLUMN(HfHighPt3P, hasHfHighPt3P, bool); //! high-pT 3-prong charm hadron -DECLARE_SOA_COLUMN(HfBeauty3P, hasHfBeauty3P, bool); //! 3-prong beauty hadron -DECLARE_SOA_COLUMN(HfBeauty4P, hasHfBeauty4P, bool); //! 4-prong beauty hadron -DECLARE_SOA_COLUMN(HfFemto2P, hasHfFemto2P, bool); //! 2-prong charm-hadron - N pair -DECLARE_SOA_COLUMN(HfFemto3P, hasHfFemto3P, bool); //! 3-prong charm-hadron - N pair -DECLARE_SOA_COLUMN(HfDoubleCharm2P, hasHfDoubleCharm2P, bool); //! at least two 2-prong charm-hadron candidates -DECLARE_SOA_COLUMN(HfDoubleCharm3P, hasHfDoubleCharm3P, bool); //! at least two 3-prong charm-hadron candidates -DECLARE_SOA_COLUMN(HfDoubleCharmMix, hasHfDoubleCharmMix, bool); //! at least one 2-prong and one 3-prong charm-hadron candidates -DECLARE_SOA_COLUMN(HfSoftGamma2P, hasHfSoftGamma2P, bool); //! soft gamma with 2-prong charm hadron -DECLARE_SOA_COLUMN(HfSoftGamma3P, hasHfSoftGamma3P, bool); //! soft gamma with 3-prong charm hadron +DECLARE_SOA_COLUMN(HfHighPt2P, hasHfHighPt2P, bool); //! high-pT 2-prong charm hadron +DECLARE_SOA_COLUMN(HfHighPt3P, hasHfHighPt3P, bool); //! high-pT 3-prong charm hadron +DECLARE_SOA_COLUMN(HfBeauty3P, hasHfBeauty3P, bool); //! 3-prong beauty hadron +DECLARE_SOA_COLUMN(HfBeauty4P, hasHfBeauty4P, bool); //! 4-prong beauty hadron +DECLARE_SOA_COLUMN(HfFemto2P, hasHfFemto2P, bool); //! 2-prong charm-hadron - N pair +DECLARE_SOA_COLUMN(HfFemto3P, hasHfFemto3P, bool); //! 3-prong charm-hadron - N pair +DECLARE_SOA_COLUMN(HfDoubleCharm2P, hasHfDoubleCharm2P, bool); //! at least two 2-prong charm-hadron candidates +DECLARE_SOA_COLUMN(HfDoubleCharm3P, hasHfDoubleCharm3P, bool); //! at least two 3-prong charm-hadron candidates +DECLARE_SOA_COLUMN(HfDoubleCharmMix, hasHfDoubleCharmMix, bool); //! at least one 2-prong and one 3-prong charm-hadron candidates +DECLARE_SOA_COLUMN(HfV0Charm2P, hasHfV0Charm2P, bool); //! V0 with 2-prong charm hadron +DECLARE_SOA_COLUMN(HfV0Charm3P, hasHfV0Charm3P, bool); //! V0 with 3-prong charm hadron +DECLARE_SOA_COLUMN(HfCharmBarToXiBach, hasHfCharmBarToXiBach, bool); //! Charm baryon to Xi + bachelor // CF two body triggers DECLARE_SOA_COLUMN(PD, hasPD, bool); //! has d-p pair @@ -64,13 +63,19 @@ DECLARE_SOA_COLUMN(LLL, hasLLL, bool); //! has L-L-L tripletD DECLARE_SOA_COLUMN(JetChHighPt, hasJetChHighPt, bool); //! high-pT charged jet // full jets -DECLARE_SOA_COLUMN(EMCALReadout, hasEMCALinReadout, bool); //! EMCAL readout -DECLARE_SOA_COLUMN(JetFullHighPt, hasJetFullHighPt, bool); //! high-pT full jet -DECLARE_SOA_COLUMN(JetNeutralHighPt, hasJetNeutralHighPt, bool); //! high-pT neutral jet -DECLARE_SOA_COLUMN(GammaHighPtEMCAL, hasGammaHighPtEMCAL, bool); //! Photon trigger in EMCAL, high threshold -DECLARE_SOA_COLUMN(GammaHighPtDCAL, hasGammaHighPtDCAL, bool); //! Photon trigger in DCAL, high threshold -DECLARE_SOA_COLUMN(GammaLowPtEMCAL, hasGammaLowPtEMCAL, bool); //! Photon trigger in EMCAL, low threshold -DECLARE_SOA_COLUMN(GammaLowPtDCAL, hasGammaLowPtDCAL, bool); //! Photon trigger in DCAL, low threshold +DECLARE_SOA_COLUMN(EMCALReadout, hasEMCALinReadout, bool); //! EMCAL readout +DECLARE_SOA_COLUMN(JetFullHighPt, hasJetFullHighPt, bool); //! high-pT full jet +DECLARE_SOA_COLUMN(JetFullLowPt, hasJetFullLowPt, bool); //! low-pT full jet +DECLARE_SOA_COLUMN(JetNeutralHighPt, hasJetNeutralHighPt, bool); //! high-pT neutral jet +DECLARE_SOA_COLUMN(JetNeutralLowPt, hasJetNeutralLowPt, bool); //! low-pT neutral jet +DECLARE_SOA_COLUMN(GammaVeryHighPtEMCAL, hasGammaVeryHighPtEMCAL, bool); //! Photon trigger in EMCAL, very high threshold +DECLARE_SOA_COLUMN(GammaVeryHighPtDCAL, hasGammaVeryHighPtDCAL, bool); //! Photon trigger in DCAL, very high threshold +DECLARE_SOA_COLUMN(GammaHighPtEMCAL, hasGammaHighPtEMCAL, bool); //! Photon trigger in EMCAL, high threshold +DECLARE_SOA_COLUMN(GammaHighPtDCAL, hasGammaHighPtDCAL, bool); //! Photon trigger in DCAL, high threshold +DECLARE_SOA_COLUMN(GammaLowPtEMCAL, hasGammaLowPtEMCAL, bool); //! Photon trigger in EMCAL, low threshold +DECLARE_SOA_COLUMN(GammaLowPtDCAL, hasGammaLowPtDCAL, bool); //! Photon trigger in DCAL, low threshold +DECLARE_SOA_COLUMN(GammaVeryLowPtEMCAL, hasGammaVeryLowPtEMCAL, bool); //! Photon trigger in EMCAL, very low threshold +DECLARE_SOA_COLUMN(GammaVeryLowPtDCAL, hasGammaVeryLowPtDCAL, bool); //! Photon trigger in DCAL, very low threshold // strangeness (lf) DECLARE_SOA_COLUMN(Omega, hasOmega, bool); //! at leat 1 Omega @@ -80,6 +85,13 @@ DECLARE_SOA_COLUMN(TripleXi, hasTripleXi, bool); //! at least 3 DECLARE_SOA_COLUMN(QuadrupleXi, hasQuadrupleXi, bool); //! at least 4 Xi DECLARE_SOA_COLUMN(SingleXiYN, hasSingleXiYN, bool); //! at least 1 Xi with high radius (YN interactions) DECLARE_SOA_COLUMN(OmegaLargeRadius, hasOmegaLargeRadius, bool); //! at least 1 Omega with high radius +DECLARE_SOA_COLUMN(TrackedCascade, hasTrackedCascade, bool); //! at least 1 tracked cascade +DECLARE_SOA_COLUMN(TrackedXi, hasTrackedXi, bool); //! at least 1 tracked Xi +DECLARE_SOA_COLUMN(TrackedOmega, hasTrackedOmega, bool); //! at least 1 tracked Omega +DECLARE_SOA_COLUMN(Tracked3Body, hasTracked3Body, bool); //! at least 1 tracked 3Body + +// F1-proton +DECLARE_SOA_COLUMN(TriggerEventF1Proton, triggereventf1proton, bool); //! F1 - proton femto trigger event // multiplicity DECLARE_SOA_COLUMN(HighTrackMult, hasHighTrackMult, bool); //! high trk muliplicity @@ -120,7 +132,7 @@ DECLARE_SOA_COLUMN(BCend, hasBCend, uint64_t); //! CEFP bcrange // nuclei DECLARE_SOA_TABLE(NucleiFilters, "AOD", "NucleiFilters", //! - filtering::H2, filtering::H3, filtering::He); + filtering::He); using NucleiFilter = NucleiFilters::iterator; // diffraction @@ -139,7 +151,7 @@ using DqFilter = DqFilters::iterator; // heavy flavours DECLARE_SOA_TABLE(HfFilters, "AOD", "HfFilters", //! - filtering::HfHighPt2P, filtering::HfHighPt3P, filtering::HfBeauty3P, filtering::HfBeauty4P, filtering::HfFemto2P, filtering::HfFemto3P, filtering::HfDoubleCharm2P, filtering::HfDoubleCharm3P, filtering::HfDoubleCharmMix, filtering::HfSoftGamma2P, filtering::HfSoftGamma3P); + filtering::HfHighPt2P, filtering::HfHighPt3P, filtering::HfBeauty3P, filtering::HfBeauty4P, filtering::HfFemto2P, filtering::HfFemto3P, filtering::HfDoubleCharm2P, filtering::HfDoubleCharm3P, filtering::HfDoubleCharmMix, filtering::HfV0Charm2P, filtering::HfV0Charm3P, filtering::HfCharmBarToXiBach); using HfFilter = HfFilters::iterator; @@ -154,16 +166,21 @@ DECLARE_SOA_TABLE(JetFilters, "AOD", "JetFilters", //! using JetFilter = JetFilters::iterator; DECLARE_SOA_TABLE(FullJetFilters, "AOD", "FullJetFilters", //! - filtering::EMCALReadout, filtering::JetFullHighPt, filtering::JetNeutralHighPt, filtering::GammaHighPtEMCAL, filtering::GammaHighPtDCAL, filtering::GammaLowPtEMCAL, filtering::GammaLowPtDCAL); + filtering::EMCALReadout, filtering::JetFullHighPt, filtering::JetFullLowPt, filtering::JetNeutralHighPt, filtering::JetNeutralLowPt, filtering::GammaVeryHighPtEMCAL, filtering::GammaVeryHighPtDCAL, filtering::GammaHighPtEMCAL, filtering::GammaHighPtDCAL, filtering::GammaLowPtEMCAL, filtering::GammaLowPtDCAL, filtering::GammaVeryLowPtEMCAL, filtering::GammaVeryLowPtDCAL); using FullJetFilter = FullJetFilters::iterator; // strangeness (lf) DECLARE_SOA_TABLE(StrangenessFilters, "AOD", "LFStrgFilters", //! - filtering::Omega, filtering::hadronXi, filtering::DoubleXi, filtering::TripleXi, filtering::QuadrupleXi, filtering::SingleXiYN, filtering::OmegaLargeRadius); + filtering::Omega, filtering::hadronXi, filtering::DoubleXi, filtering::TripleXi, filtering::QuadrupleXi, filtering::SingleXiYN, filtering::OmegaLargeRadius, filtering::TrackedCascade, filtering::TrackedXi, filtering::TrackedOmega, filtering::Tracked3Body); using StrangenessFilter = StrangenessFilters::iterator; +// F1 proton +DECLARE_SOA_TABLE(F1ProtonFilters, "AOD", "F1ProtonFilters", //! + filtering::TriggerEventF1Proton); +using F1ProtonFilter = F1ProtonFilters::iterator; + // multiplicity DECLARE_SOA_TABLE(MultFilters, "AOD", "MultFilters", //! filtering::HighTrackMult, filtering::HighMultFv0, filtering::HighFv0Flat, filtering::HighFt0Mult, filtering::HighFt0Flat, filtering::HighFt0cFv0Mult, filtering::HighFt0cFv0Flat, filtering::LeadingPtTrack); @@ -187,11 +204,11 @@ DECLARE_SOA_TABLE(BCRanges, "AOD", "BCRanges", //! using BCRange = BCRanges::iterator; /// List of the available filters, the description of their tables and the name of the tasks -constexpr int NumberOfFilters{10}; -constexpr std::array AvailableFilters{"NucleiFilters", "DiffractionFilters", "DqFilters", "HfFilters", "CFFilters", "JetFilters", "FullJetFilters", "StrangenessFilters", "MultFilters", "PhotFilters"}; -constexpr std::array FilterDescriptions{"NucleiFilters", "DiffFilters", "DqFilters", "HfFilters", "CFFilters", "JetFilters", "FullJetFilters", "LFStrgFilters", "MultFilters", "PhotFilters"}; -constexpr std::array FilteringTaskNames{"o2-analysis-nuclei-filter", "o2-analysis-diffraction-filter", "o2-analysis-dq-filter-pp", "o2-analysis-hf-filter", "o2-analysis-cf-filter", "o2-analysis-je-filter", "o2-analysis-fje-filter", "o2-analysis-lf-strangeness-filter", "o2-analysis-mult-filter", "o2-analysis-em-filter"}; -constexpr o2::framework::pack FiltersPack; +constexpr int NumberOfFilters{11}; +constexpr std::array AvailableFilters{"NucleiFilters", "DiffractionFilters", "DqFilters", "HfFilters", "CFFilters", "JetFilters", "FullJetFilters", "StrangenessFilters", "MultFilters", "PhotFilters", "F1ProtonFilters"}; +constexpr std::array FilterDescriptions{"NucleiFilters", "DiffFilters", "DqFilters", "HfFilters", "CFFilters", "JetFilters", "FullJetFilters", "LFStrgFilters", "MultFilters", "PhotFilters", "F1ProtonFilters"}; +constexpr std::array FilteringTaskNames{"o2-analysis-nuclei-filter", "o2-analysis-diffraction-filter", "o2-analysis-dq-filter-pp-with-association", "o2-analysis-hf-filter", "o2-analysis-cf-filter", "o2-analysis-je-filter", "o2-analysis-fje-filter", "o2-analysis-lf-strangeness-filter", "o2-analysis-mult-filter", "o2-analysis-em-filter", "o2-analysis-lf-f1proton-filter"}; +constexpr o2::framework::pack FiltersPack; static_assert(o2::framework::pack_size(FiltersPack) == NumberOfFilters); template diff --git a/PWGCF/DataModel/CorrelationsDerived.h b/PWGCF/DataModel/CorrelationsDerived.h index 1a50c524c43..5f88fc15c6f 100644 --- a/PWGCF/DataModel/CorrelationsDerived.h +++ b/PWGCF/DataModel/CorrelationsDerived.h @@ -50,10 +50,14 @@ DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); //! Centrality/multiplic } // namespace cfcollision DECLARE_SOA_TABLE(CFCollisions, "AOD", "CFCOLLISION", //! Reduced collision table o2::soa::Index<>, - cfcollision::CFMcCollisionId, bc::RunNumber, collision::PosZ, cfcollision::Multiplicity, timestamp::Timestamp); +DECLARE_SOA_TABLE(CFCollLabels, "AOD", "CFCOLLLABEL", //! Labels for reduced collision table + cfcollision::CFMcCollisionId); using CFCollision = CFCollisions::iterator; +using CFCollLabel = CFCollLabels::iterator; +using CFCollisionsWithLabel = soa::Join; +using CFCollisionWithLabel = CFCollisionsWithLabel::iterator; namespace cftrack { @@ -66,10 +70,15 @@ DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign (positive, negati } // namespace cftrack DECLARE_SOA_TABLE(CFTracks, "AOD", "CFTRACK", //! Reduced track table o2::soa::Index<>, - cftrack::CFCollisionId, cftrack::CFMcParticleId, + cftrack::CFCollisionId, cftrack::Pt, cftrack::Eta, cftrack::Phi, cftrack::Sign, track::TrackType); +DECLARE_SOA_TABLE(CFTrackLabels, "AOD", "CFTRACKLABEL", //! Labels for reduced track table + cftrack::CFMcParticleId); using CFTrack = CFTracks::iterator; +using CFTrackLabel = CFTrackLabels::iterator; +using CFTracksWithLabel = soa::Join; +using CFTrackWithLabel = CFTracksWithLabel::iterator; } // namespace o2::aod #endif // O2_ANALYSIS_CFDERIVED_H diff --git a/PWGCF/DataModel/FemtoDerived.h b/PWGCF/DataModel/FemtoDerived.h index 6ec12313dd3..036f69775a6 100644 --- a/PWGCF/DataModel/FemtoDerived.h +++ b/PWGCF/DataModel/FemtoDerived.h @@ -56,6 +56,12 @@ enum ParticleType { kNParticleTypes //! Number of particle types }; +enum MomentumType { + kPt, //! transverse momentum + kPreco, //! reconstructed/propagated momentum at the vertex + kPtpc //! momentum at the inner wall of the TPC (useful for PID plots) +}; + static constexpr std::string_view ParticleTypeName[kNParticleTypes] = {"Tracks", "V0", "V0Child", "Cascade", "CascadeBachelor"}; //! Naming of the different particle types static constexpr std::string_view TempFitVarName[kNParticleTypes] = {"/hDCAxy", "/hCPA", "/hDCAxy", "/hCPA", "/hDCAxy"}; @@ -112,14 +118,24 @@ DECLARE_SOA_DYNAMIC_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFind [](uint8_t tpcNClsFindable, uint8_t tpcNClsCrossedRows) -> float { return (float)tpcNClsCrossedRows / (float)tpcNClsFindable; }); +DECLARE_SOA_COLUMN(TPCNSigmaEl, tpcNSigmaEl, float); //! Nsigma separation with the TPC detector for electron +DECLARE_SOA_COLUMN(TPCNSigmaPi, tpcNSigmaPi, float); //! Nsigma separation with the TPC detector for pion +DECLARE_SOA_COLUMN(TPCNSigmaKa, tpcNSigmaKa, float); //! Nsigma separation with the TPC detector for kaon +DECLARE_SOA_COLUMN(TPCNSigmaPr, tpcNSigmaPr, float); //! Nsigma separation with the TPC detector for proton +DECLARE_SOA_COLUMN(TPCNSigmaDe, tpcNSigmaDe, float); //! Nsigma separation with the TPC detector for deuteron +DECLARE_SOA_COLUMN(TOFNSigmaEl, tofNSigmaEl, float); //! Nsigma separation with the TPC detector for electron +DECLARE_SOA_COLUMN(TOFNSigmaPi, tofNSigmaPi, float); //! Nsigma separation with the TPC detector for pion +DECLARE_SOA_COLUMN(TOFNSigmaKa, tofNSigmaKa, float); //! Nsigma separation with the TPC detector for kaon +DECLARE_SOA_COLUMN(TOFNSigmaPr, tofNSigmaPr, float); //! Nsigma separation with the TPC detector for proton +DECLARE_SOA_COLUMN(TOFNSigmaDe, tofNSigmaDe, float); //! Nsigma separation with the TPC detector for deuteron DECLARE_SOA_COLUMN(DaughDCA, daughDCA, float); //! DCA between daughters DECLARE_SOA_COLUMN(TransRadius, transRadius, float); //! Transverse radius of the decay vertex DECLARE_SOA_COLUMN(DecayVtxX, decayVtxX, float); //! X position of the decay vertex DECLARE_SOA_COLUMN(DecayVtxY, decayVtxY, float); //! Y position of the decay vertex DECLARE_SOA_COLUMN(DecayVtxZ, decayVtxZ, float); //! Z position of the decay vertex DECLARE_SOA_COLUMN(MKaon, mKaon, float); //! The invariant mass of V0 candidate, assuming kaon - } // namespace femtodreamparticle + DECLARE_SOA_TABLE(FDParticles, "AOD", "FDPARTICLE", o2::soa::Index<>, femtodreamparticle::FDCollisionId, @@ -152,33 +168,23 @@ DECLARE_SOA_TABLE(FDExtParticles, "AOD", "FDEXTPARTICLE", track::DcaXY, track::DcaZ, track::TPCSignal, - pidtpc_tiny::TPCNSigmaStoreEl, - pidtpc_tiny::TPCNSigmaStorePi, - pidtpc_tiny::TPCNSigmaStoreKa, - pidtpc_tiny::TPCNSigmaStorePr, - pidtpc_tiny::TPCNSigmaStoreDe, - pidtof_tiny::TOFNSigmaStoreEl, - pidtof_tiny::TOFNSigmaStorePi, - pidtof_tiny::TOFNSigmaStoreKa, - pidtof_tiny::TOFNSigmaStorePr, - pidtof_tiny::TOFNSigmaStoreDe, + femtodreamparticle::TPCNSigmaEl, + femtodreamparticle::TPCNSigmaPi, + femtodreamparticle::TPCNSigmaKa, + femtodreamparticle::TPCNSigmaPr, + femtodreamparticle::TPCNSigmaDe, + femtodreamparticle::TOFNSigmaEl, + femtodreamparticle::TOFNSigmaPi, + femtodreamparticle::TOFNSigmaKa, + femtodreamparticle::TOFNSigmaPr, + femtodreamparticle::TOFNSigmaDe, femtodreamparticle::DaughDCA, femtodreamparticle::TransRadius, femtodreamparticle::DecayVtxX, femtodreamparticle::DecayVtxY, femtodreamparticle::DecayVtxZ, femtodreamparticle::MKaon, - femtodreamparticle::TPCCrossedRowsOverFindableCls, - pidtpc_tiny::TPCNSigmaEl, - pidtpc_tiny::TPCNSigmaPi, - pidtpc_tiny::TPCNSigmaKa, - pidtpc_tiny::TPCNSigmaPr, - pidtpc_tiny::TPCNSigmaDe, - pidtof_tiny::TOFNSigmaEl, - pidtof_tiny::TOFNSigmaPi, - pidtof_tiny::TOFNSigmaKa, - pidtof_tiny::TOFNSigmaPr, - pidtof_tiny::TOFNSigmaDe); + femtodreamparticle::TPCCrossedRowsOverFindableCls) using FDFullParticle = FDExtParticles::iterator; /// FemtoDreamTrackMC @@ -186,25 +192,25 @@ namespace femtodreamMCparticle { /// Distinuishes the different particle origins enum ParticleOriginMCTruth { - kPrimary, //! Primary track or V0 - kDaughter, //! Particle from a decay - kMaterial, //! Particle from a material - kNotPrimary, //! Not primary particles (kept for compatibility reasons with the FullProducer task. will be removed, since we look at "non primaries" more differentially now) - kFake, //! particle, that has NOT the PDG code of the current analysed particle - kDaughterLambda, //! Daughter from a Lambda decay - kDaughterSigmaplus, //! Daughter from a Sigma^plus decay + kPrimary, //! Primary track or V0 + kSecondary, //! Particle from a decay + kMaterial, //! Particle from a material + kNotPrimary, //! Not primary particles (kept for compatibility reasons with the FullProducer task. will be removed, since we look at "non primaries" more differentially now) + kFake, //! particle, that has NOT the PDG code of the current analysed particle + kSecondaryDaughterLambda, //! Daughter from a Lambda decay + kSecondaryDaughterSigmaplus, //! Daughter from a Sigma^plus decay kNOriginMCTruthTypes }; //! Naming of the different OriginMCTruth types static constexpr std::string_view ParticleOriginMCTruthName[kNOriginMCTruthTypes] = { "_Primary", - "_Daughter", + "_Secondary", "_Material", "_NotPrimary", "_Fake", - "_DaughterLambda", - "DaughterSigmaPlus"}; + "_SecondaryDaughterLambda", + "_SecondaryDaughterSigmaPlus"}; /// Distinguished between reconstructed and truth enum MCType { diff --git a/PWGCF/DataModel/singletrackselector.h b/PWGCF/DataModel/singletrackselector.h new file mode 100644 index 00000000000..6155c1eafea --- /dev/null +++ b/PWGCF/DataModel/singletrackselector.h @@ -0,0 +1,182 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \brief create a table for single track selection. +/// \author Sofia Tomassini +/// \since 30 May 2023 + +#ifndef PWGCF_DATAMODEL_SINGLETRACKSELECTOR_H_ +#define PWGCF_DATAMODEL_SINGLETRACKSELECTOR_H_ + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/PIDResponse.h" +#include "Framework/Logger.h" +#include "Common/DataModel/Multiplicity.h" + +namespace o2::aod +{ +namespace singletrackselector +{ +template +typename binningType::binned_t packInTable(const float& valueToBin) +{ + if (valueToBin <= binningType::binned_min) { + return binningType::underflowBin; + } else if (valueToBin >= binningType::binned_max) { + return binningType::overflowBin; + } else { + return static_cast(valueToBin / binningType::bin_width); + } +} + +template +float unPack(const typename binningType::binned_t& b) +{ + return static_cast(binningType::bin_width * b); +} + +template +typename binningType::binned_t packInTableOffset(const float& valueToBin) +{ + if (valueToBin <= binningType::binned_min) { + return binningType::underflowBin; + } else if (valueToBin >= binningType::binned_max) { + return binningType::overflowBin; + } else { + return static_cast(((valueToBin - (binningType::binned_max - binningType::binned_min) * 0.5) / binningType::bin_width)); + } +} + +template +float unPackOffset(const typename binningType::binned_t& b) +{ + return static_cast((binningType::binned_max - binningType::binned_min) * 0.5 + binningType::bin_width * b); +} + +namespace storedcrossedrows +{ +struct binning { + public: + typedef int8_t binned_t; + static constexpr int nbins = (1 << 8 * sizeof(binned_t)) - 2; + static constexpr binned_t overflowBin = nbins >> 1; + static constexpr binned_t underflowBin = -(nbins >> 1); + static constexpr float binned_max = 253.5; + static constexpr float binned_min = -0.5; + static constexpr float bin_width = (binned_max - binned_min) / nbins; +}; +} // namespace storedcrossedrows + +namespace nsigma +{ +struct binning { + public: + typedef int8_t binned_t; + static constexpr int nbins = (1 << 8 * sizeof(binned_t)) - 2; + static constexpr binned_t overflowBin = nbins >> 1; + static constexpr binned_t underflowBin = -(nbins >> 1); + static constexpr float binned_max = 10.0; + static constexpr float binned_min = -10.0; + static constexpr float bin_width = (binned_max - binned_min) / nbins; +}; +} // namespace nsigma + +DECLARE_SOA_INDEX_COLUMN(Collision, collision); // Index to the collision +DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); +DECLARE_SOA_COLUMN(HasITS, hasITS, bool); +DECLARE_SOA_COLUMN(Px, px, float); // Momentum of the track +DECLARE_SOA_COLUMN(Py, py, float); // Momentum of the track +DECLARE_SOA_COLUMN(Pz, pz, float); // Momentum of the track +DECLARE_SOA_DYNAMIC_COLUMN(P, p, + [](float px, float py, float pz) -> float { return std::sqrt(px * px + py * py + pz * pz); }); // Momentum of the track +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, + [](float px, float py) -> float { return std::sqrt(px * px + py * py); }); // Momentum of the track +DECLARE_SOA_COLUMN(TPCInnerParam, tpcInnerParam, float); // vertex position along z +DECLARE_SOA_COLUMN(TPCSignal, tpcSignal, float); // vertex position along z +DECLARE_SOA_COLUMN(Beta, beta, float); +DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); // impact parameter of the track +DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); // impact parameter of the track +DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, float); // Number of TPC clusters +DECLARE_SOA_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, float); +DECLARE_SOA_COLUMN(TPCChi2NCl, tpcChi2NCl, float); // TPC chi2 +DECLARE_SOA_COLUMN(ITSNCls, itsNCls, float); // Number of ITS clusters +DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, float); // ITS chi2 +DECLARE_SOA_COLUMN(Sign, sign, int8_t); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(StoredCrossedRows, storedCrossedRows, storedcrossedrows::binning::binned_t); +DECLARE_SOA_COLUMN(StoredTOFNSigmaPr, storedTofNSigmaPr, nsigma::binning::binned_t); +DECLARE_SOA_COLUMN(StoredTPCNSigmaPr, storedTpcNSigmaPr, nsigma::binning::binned_t); +DECLARE_SOA_COLUMN(StoredTOFNSigmaDe, storedTofNSigmaDe, nsigma::binning::binned_t); +DECLARE_SOA_COLUMN(StoredTPCNSigmaDe, storedTpcNSigmaDe, nsigma::binning::binned_t); + +DECLARE_SOA_DYNAMIC_COLUMN(CrossedRows, tpcNClsCrossedRows, + [](storedcrossedrows::binning::binned_t binned) -> float { return singletrackselector::unPackOffset(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPr, tofNSigmaPr, + [](nsigma::binning::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPr, tpcNSigmaPr, + [](nsigma::binning::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaDe, tofNSigmaDe, + [](nsigma::binning::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaDe, tpcNSigmaDe, + [](nsigma::binning::binned_t nsigma_binned) -> float { return singletrackselector::unPack(nsigma_binned); }); + +DECLARE_SOA_DYNAMIC_COLUMN(Energy, energy, + [](float px, float py, float pz, float mass) -> float { return sqrt(px * px + py * py + pz * pz + mass * mass); }); + +DECLARE_SOA_COLUMN(GlobalIndex, globalIndex, int64_t); // Index to the collision +DECLARE_SOA_COLUMN(Mult, mult, int); // Multiplicity of the collision +DECLARE_SOA_COLUMN(PosZ, posZ, int); // Vertex of the collision + +} // namespace singletrackselector + +DECLARE_SOA_TABLE(SingleTrackSel, "AOD", "STSEL", // Table of the variables for single track selection. + o2::soa::Index<>, + singletrackselector::CollisionId, + singletrackselector::HasITS, + singletrackselector::HasTOF, + singletrackselector::Px, + singletrackselector::Py, + singletrackselector::Pz, + singletrackselector::TPCInnerParam, + singletrackselector::TPCSignal, + singletrackselector::Beta, + singletrackselector::DcaXY, + singletrackselector::DcaZ, + singletrackselector::TPCNClsFound, + singletrackselector::TPCCrossedRowsOverFindableCls, + singletrackselector::TPCChi2NCl, + singletrackselector::ITSNCls, + singletrackselector::ITSChi2NCl, + singletrackselector::Sign, + singletrackselector::Eta, + singletrackselector::Phi, + singletrackselector::StoredCrossedRows, + singletrackselector::StoredTOFNSigmaPr, + singletrackselector::StoredTPCNSigmaPr, + singletrackselector::StoredTOFNSigmaDe, + singletrackselector::StoredTPCNSigmaDe, + singletrackselector::P, + singletrackselector::Pt, + singletrackselector::CrossedRows, + singletrackselector::TOFNSigmaPr, + singletrackselector::TPCNSigmaPr, + singletrackselector::TOFNSigmaDe, + singletrackselector::TPCNSigmaDe, + singletrackselector::Energy); + +DECLARE_SOA_TABLE(SingleCollSel, "AOD", "SCSEL", // Table of the variables for single track selection. + singletrackselector::GlobalIndex, + singletrackselector::Mult, + singletrackselector::PosZ); +} // namespace o2::aod +#endif // PWGCF_DATAMODEL_SINGLETRACKSELECTOR_H_ diff --git a/PWGCF/FemtoDream/CMakeLists.txt b/PWGCF/FemtoDream/CMakeLists.txt index 6cceb1d200e..383f229439d 100644 --- a/PWGCF/FemtoDream/CMakeLists.txt +++ b/PWGCF/FemtoDream/CMakeLists.txt @@ -24,6 +24,11 @@ o2physics_add_dpl_workflow(femtodream-pair-track-track PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtodream-pair-track-track-track + SOURCES femtoDreamPairTaskTrackTrackTrack.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtodream-debug-track SOURCES femtoDreamDebugTrack.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGCF/FemtoDream/FemtoDreamCollisionSelection.h b/PWGCF/FemtoDream/FemtoDreamCollisionSelection.h index 794e30abdd5..5c35e861453 100644 --- a/PWGCF/FemtoDream/FemtoDreamCollisionSelection.h +++ b/PWGCF/FemtoDream/FemtoDreamCollisionSelection.h @@ -80,8 +80,8 @@ class FemtoDreamCollisionSelection /// \tparam T type of the collision /// \param col Collision /// \return whether or not the collisions fulfills the specified selections - template - bool isSelected(T const& col) + template + bool isSelectedCollision(C const& col) { if (std::abs(col.posZ()) > mZvtxMax) { return false; @@ -101,6 +101,32 @@ class FemtoDreamCollisionSelection return true; } + template + bool isEmptyCollision(C const& col, T const& tracks, TC& trackCuts) + { + // check if there is no selected track + for (auto const& track : tracks) { + if (trackCuts.isSelectedMinimal(track)) { + return false; + } + } + return true; + } + + template + bool isEmptyCollision(C const& col, V const& V0s, VC& V0Cuts, T const& Tracks) + { + // check if there is no selected V0 + for (auto const& V0 : V0s) { + auto postrack = V0.template posTrack_as(); + auto negtrack = V0.template negTrack_as(); + if (V0Cuts.isSelectedMinimal(col, V0, postrack, negtrack)) { + return false; + } + } + return true; + } + /// Some basic QA of the event /// \tparam T type of the collision /// \param col Collision diff --git a/PWGCF/FemtoDream/FemtoDreamContainer.h b/PWGCF/FemtoDream/FemtoDreamContainer.h index 1fc03cec83e..7850ff5401f 100644 --- a/PWGCF/FemtoDream/FemtoDreamContainer.h +++ b/PWGCF/FemtoDream/FemtoDreamContainer.h @@ -19,6 +19,7 @@ #ifndef PWGCF_FEMTODREAM_FEMTODREAMCONTAINER_H_ #define PWGCF_FEMTODREAM_FEMTODREAMCONTAINER_H_ +#include #include #include @@ -69,7 +70,7 @@ class FemtoDreamContainer /// \param kTAxis axis object for the kT axis /// \param mTAxis axis object for the mT axis template - void init_base(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis, T kTAxis, T mTAxis, T multAxis3D, T mTAxis3D, bool use3dplots) + void init_base(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis, T kTAxis, T mTAxis, T multAxis3D, T mTAxis3D, bool use3dplots, bool extendedplots) { mHistogramRegistry->add((folderName + "/relPairDist").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); @@ -85,6 +86,9 @@ class FemtoDreamContainer if (use3dplots) { mHistogramRegistry->add((folderName + "/relPairkstarmTMult").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2}); Multiplicity").c_str(), kTH3F, {femtoObsAxis, mTAxis3D, multAxis3D}); } + if (extendedplots) { + mHistogramRegistry->add((folderName + "/mTPtPart1PtPart2").c_str(), "; #it{m}_{T} (GeV/#it{c}^{2}); #it{p} _{T} Particle 1 (GeV/#it{c}); #it{p} _{T} Particle 1 (GeV/#it{c})", kTH3F, {mTAxis3D, {375, 0., 7.5}, {375, 0., 7.5}}); + } } /// Initializes specialized Monte Carlo truth histograms for the task @@ -100,7 +104,7 @@ class FemtoDreamContainer mHistogramRegistry->add((folderName + "/relPairkstarMult_ReconNoFake").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); mHistogramRegistry->add((folderName + "/hNoMCtruthPairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); mHistogramRegistry->add((folderName + "/hFakePairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); - mHistogramRegistry->add((folderName + "/kstar_resolution").c_str(), "; #it{k} _{T} reconstructed (GeV/#it{c}); #it{k} _{T} truth (GeV/#it{c})", kTH2F, {femtoObsAxis, femtoObsAxis}); + mHistogramRegistry->add((folderName + "/kstar_resolution").c_str(), "; #it{k}_{*} reconstructed (GeV/#it{c}); #it{k}_{*} truth (GeV/#it{c})", kTH2F, {femtoObsAxis, femtoObsAxis}); } /// Templated function to initialize the histograms for the task @@ -114,13 +118,14 @@ class FemtoDreamContainer /// \param mTBins mT binning for the histograms /// \param isMC add Monte Carlo truth histograms to the output file template - void init(HistogramRegistry* registry, T& kstarBins, T& multBins, T& kTBins, T& mTBins, T& multBins3D, T& mTBins3D, bool isMC, bool use3dplots) + void init(HistogramRegistry* registry, T& kstarBins, T& multBins, T& kTBins, T& mTBins, T& multBins3D, T& mTBins3D, bool isMC, bool use3dplots, bool extendedplots, float highkstarCut) { mHistogramRegistry = registry; std::string femtoObs; if constexpr (mFemtoObs == femtoDreamContainer::Observable::kstar) { femtoObs = "#it{k*} (GeV/#it{c})"; } + mHighkstarCut = highkstarCut; std::vector tmpVecMult = multBins; framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; framework::AxisSpec femtoObsAxis = {kstarBins, femtoObs.c_str()}; @@ -132,10 +137,10 @@ class FemtoDreamContainer std::string folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kRecon]); - init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, use3dplots); + init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, use3dplots, extendedplots); if (isMC) { folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]); - init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, use3dplots); + init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, use3dplots, extendedplots); init_MC(folderName, femtoObs, femtoObsAxis, multAxis, mTAxis); } } @@ -158,7 +163,7 @@ class FemtoDreamContainer /// \param part2 Particle two /// \param mult Multiplicity of the event template - void setPair_base(const float femtoObs, const float mT, T const& part1, T const& part2, const int mult, bool use3dplots) + void setPair_base(const float femtoObs, const float mT, T const& part1, T const& part2, const int mult, bool use3dplots, bool extendedplots) { const float kT = FemtoDreamMath::getkT(part1, mMassOne, part2, mMassTwo); mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/relPairDist"), femtoObs); @@ -174,6 +179,9 @@ class FemtoDreamContainer if (use3dplots) { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmTMult"), femtoObs, mT, mult); } + if (extendedplots) { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/mTPtPart1PtPart2"), mT, part1.pt(), part2.pt()); + } } /// Called by setPair only in case of Monte Carlo truth @@ -204,17 +212,22 @@ class FemtoDreamContainer /// \param part2 Particle two /// \param mult Multiplicity of the event template - void setPair(T const& part1, T const& part2, const int mult, bool use3dplots) + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots, bool extendedplots) { float femtoObs, femtoObsMC; // Calculate femto observable and the mT with reconstructed information if constexpr (mFemtoObs == femtoDreamContainer::Observable::kstar) { femtoObs = FemtoDreamMath::getkstar(part1, mMassOne, part2, mMassTwo); } + if (mHighkstarCut > 0) { + if (femtoObs > mHighkstarCut) { + return; + } + } const float mT = FemtoDreamMath::getmT(part1, mMassOne, part2, mMassTwo); if (mHistogramRegistry) { - setPair_base(femtoObs, mT, part1, part2, mult, use3dplots); + setPair_base(femtoObs, mT, part1, part2, mult, use3dplots, extendedplots); if constexpr (isMC) { if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { @@ -225,7 +238,7 @@ class FemtoDreamContainer const float mTMC = FemtoDreamMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); if (abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates - setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots); + setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots, extendedplots); setPair_MC(femtoObsMC, femtoObs, mT, mult); } else { mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); @@ -247,6 +260,7 @@ class FemtoDreamContainer float mMassTwo = 0.f; ///< PDG mass of particle 2 int mPDGOne = 0; ///< PDG code of particle 1 int mPDGTwo = 0; ///< PDG code of particle 2 + float mHighkstarCut = 6.; }; } // namespace o2::analysis::femtoDream diff --git a/PWGCF/FemtoDream/FemtoDreamContainerThreeBody.h b/PWGCF/FemtoDream/FemtoDreamContainerThreeBody.h new file mode 100644 index 00000000000..128b8a26169 --- /dev/null +++ b/PWGCF/FemtoDream/FemtoDreamContainerThreeBody.h @@ -0,0 +1,227 @@ +// 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 FemtoDreamContainer.h +/// \brief Definition of the FemtoDreamContainer +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Valentina Mantovani Sarti, valentina.mantovani-sarti@tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de + +#ifndef PWGCF_FEMTODREAM_FEMTODREAMCONTAINERTHREEBODY_H_ +#define PWGCF_FEMTODREAM_FEMTODREAMCONTAINERTHREEBODY_H_ + +#include +#include +#include + +#include "Framework/HistogramRegistry.h" +#include "FemtoDreamMath.h" + +#include "Math/Vector4D.h" +#include "TMath.h" +#include "TDatabasePDG.h" + +using namespace o2::framework; + +namespace o2::analysis::femtoDream +{ + +namespace femtoDreamContainerThreeBody +{ +/// Femtoscopic observable to be computed +enum Observable { Q3 ///< Q3 +}; + +/// Type of the event processind +enum EventType { same, ///< Pair from same event + mixed ///< Pair from mixed event +}; +}; // namespace femtoDreamContainerThreeBody + +/// \class FemtoDreamContainerThreeBody +/// \brief Container for all histogramming related to the correlation function. The two +/// particles of the pair are passed here, and the correlation function and QA histograms +/// are filled according to the specified observable +/// \tparam eventType Type of the event (same/mixed) +/// \tparam obs Observable to be computed (Q_3/...) +template +class FemtoDreamContainerThreeBody +{ + public: + /// Destructor + virtual ~FemtoDreamContainerThreeBody() = default; + + /// Initializes histograms for the task in case of three-body femtoscopy + /// Called by init both in case of reconstructed data/ Monte Carlo, and for Monte Carlo Truth + /// \tparam T type of the axis Object + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) + /// \param femtoObs Title of the femto observable axis + /// \param femtoObsAxis axis object for the femto observable axis + /// \param multAxis axis object for the multiplicity axis + template + void init_base(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis) + { + + mHistogramRegistry->add((folderName + "/relTripletDist").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); + mHistogramRegistry->add((folderName + "/relTripletQ3Mult").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); + } + + /// Initializes specialized Monte Carlo truth histograms for the task in case of three-body femtoscopy + /// internal function called by init only in case of Monte Carlo truth + /// \tparam T type of the xxis Object + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) + /// \param femtoObsAxis axis object for the femto observable axis + template + void init_MC(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis) + { + mHistogramRegistry->add((folderName + "/relPairDist_ReconNoFake").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); + mHistogramRegistry->add((folderName + "/relPairQ3Mult_ReconNoFake").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); + mHistogramRegistry->add((folderName + "/hNoMCtruthTripletCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + mHistogramRegistry->add((folderName + "/hFakeTripletCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + mHistogramRegistry->add((folderName + "/Q3_resolution").c_str(), "; #it{Q}_{3} reconstructed (GeV/#it{c}); #it{Q}_{3} truth (GeV/#it{c})", kTH2F, {femtoObsAxis, femtoObsAxis}); + } + + /// Templated function to initialize the histograms for the task in case of three-body femtoscopy + /// Always calls init_base to initialize the histograms for data/ Monte Carlo reconstructed + /// In case of Monte Carlo, calls init_base again for Monte Carlo truth and the specialized function init_MC for additional histogramms + /// \tparam T type of the configurable for the axis configuration + /// \param registry Histogram registry to be passed + /// \param Q3Bins Q3 binning for the histograms + /// \param multBins multiplicity binning for the histograms + /// \param isMC add Monte Carlo truth histograms to the output file + template + void init(HistogramRegistry* registry, T& Q3Bins, T& multBins, bool isMC) + { + mHistogramRegistry = registry; + std::string femtoObs; + if constexpr (mFemtoObs == femtoDreamContainerThreeBody::Observable::Q3) { + femtoObs = "#it{Q}_{3} (GeV/#it{c})"; + } + std::vector tmpVecMult = multBins; + framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; + framework::AxisSpec femtoObsAxis = {Q3Bins, femtoObs.c_str()}; + + std::string folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kRecon]); + + init_base(folderName, femtoObs, femtoObsAxis, multAxis); + if (isMC) { + folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]); + init_base(folderName, femtoObs, femtoObsAxis, multAxis); + init_MC(folderName, femtoObs, femtoObsAxis, multAxis); + } + } + + /// Set the PDG codes of the three particles involved + /// \param pdg1 PDG code of particle one + /// \param pdg2 PDG code of particle two + /// \param pdg3 PDG code of particle three + void setPDGCodes(const int pdg1, const int pdg2, const int pdg3) + { + mMassOne = TDatabasePDG::Instance()->GetParticle(pdg1)->Mass(); + mMassTwo = TDatabasePDG::Instance()->GetParticle(pdg2)->Mass(); + mMassThree = TDatabasePDG::Instance()->GetParticle(pdg3)->Mass(); + mPDGOne = pdg1; + mPDGTwo = pdg2; + mPDGThree = pdg3; + } + + /// Pass a triplet to the container and compute all the relevant observables + /// Called by setTriplet both in case of data/ and Monte Carlo reconstructed and for Monte Carlo truth + /// \tparam T type of the femtodreamparticle + /// \param part1 Particle one + /// \param part2 Particle two + /// \param part3 Particle three + /// \param mult Multiplicity of the event + template + void setTriplet_base(const float femtoObs, T const& part1, T const& part2, T const& part3, const int mult) + { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/relTripletDist"), femtoObs); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/relTripletQ3Mult"), femtoObs, mult); + } + + /// Called by setTriplet only in case of Monte Carlo truth + /// Fills MC truth specific histogramms: + /// - Q3 distribution plots with RECONSTRUCTED information but ONLY for non-fake candidates; needed for purity calculations of tracks + /// - Q3 resolution matrix + /// Note: Standard histograms with MC truth information are filled with the setPair_base function + /// \param part1 Particle one + /// \param part2 Particle two + /// \param part3 Particle three + /// \param mult Multiplicity of the event + void setTriplet_MC(const float femtoObsMC, const float femtoObs, const int mult) + { + if (mHistogramRegistry) { + // Fill the Q3 distributions with the reconstructed information but only for particles with the right PDG code + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/relPairDist_ReconNoFake"), femtoObs); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/relPairkstarMult_ReconNoFake"), femtoObs, mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/kstar_resolution"), femtoObsMC, femtoObs); + } + } + + /// Templated function to handle data/ Monte Carlo reconstructed and Monte Carlo truth + /// Always calls setTriplet_base to compute the observables with reconstructed data + /// In case of Monte Carlo, calls setTriplet_base with MC info and specialized function setTriplet_MC for additional histogramms + /// \tparam T type of the femtodreamparticle + /// \param part1 Particle one + /// \param part2 Particle two + /// \param part3 Particle three + /// \param mult Multiplicity of the event + template + void setTriplet(T const& part1, T const& part2, T const& part3, const int mult) + { + float femtoObs, femtoObsMC; + // Calculate femto observable and the mT with reconstructed information + if constexpr (mFemtoObs == femtoDreamContainerThreeBody::Observable::Q3) { + femtoObs = FemtoDreamMath::getQ3(part1, mMassOne, part2, mMassTwo, part3, mMassThree); + } + + if (mHistogramRegistry) { + setTriplet_base(femtoObs, part1, part2, part3, mult); + + if constexpr (isMC) { + if (part1.has_fdMCParticle() && part2.has_fdMCParticle() && part3.has_fdMCParticle()) { + // calculate the femto observable with MC truth information + if constexpr (mFemtoObs == femtoDreamContainerThreeBody::Observable::Q3) { + femtoObsMC = FemtoDreamMath::getQ3(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo, part3.fdMCParticle(), mMassThree); + } + + if (abs(part1.fdMCParticle().pdgMCTruth()) == mPDGOne && abs(part2.fdMCParticle().pdgMCTruth()) == mPDGTwo && abs(part3.fdMCParticle().pdgMCTruth()) == mPDGThree) { // Note: all triplet-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setTriplet_base(femtoObsMC, part1.fdMCParticle(), part2.fdMCParticle(), part3.fdMCParticle(), mult); + setTriplet_MC(femtoObsMC, femtoObs, mult); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hFakeTripletCounter"), 0); + } + + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]) + HIST("/hNoMCtruthTripletCounter"), 0); + } + } + } + } + + protected: + HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output + static constexpr std::string_view mFolderSuffix[2] = {"SameEvent", "MixedEvent"}; ///< Folder naming for the output according to mEventType + static constexpr femtoDreamContainerThreeBody::Observable mFemtoObs = obs; ///< Femtoscopic observable to be computed (according to femtoDreamContainerThreeBody::Observable) + static constexpr int mEventType = eventType; ///< Type of the event (same/mixed, according to femtoDreamContainerThreeBody::EventType) + float mMassOne = 0.f; ///< PDG mass of particle 1 + float mMassTwo = 0.f; ///< PDG mass of particle 1 + float mMassThree = 0.f; ///< PDG mass of particle 3; if relevant + int mPDGOne = 0; ///< PDG code of particle 1 + int mPDGTwo = 0; ///< PDG code of particle 2 + int mPDGThree = 0; ///< PDG code of particle 3; if relevant +}; + +} // namespace o2::analysis::femtoDream + +#endif // PWGCF_FEMTODREAM_FEMTODREAMCONTAINERTHREEBODY_H_ diff --git a/PWGCF/FemtoDream/FemtoDreamCutculator.h b/PWGCF/FemtoDream/FemtoDreamCutculator.h index 54b8f424165..fbc6fcaad67 100644 --- a/PWGCF/FemtoDream/FemtoDreamCutculator.h +++ b/PWGCF/FemtoDream/FemtoDreamCutculator.h @@ -131,10 +131,10 @@ class FemtoDreamCutculator /// Automatically retrieves track PID from the dpl-config.json /// \param prefix Prefix which is added to the name of the Configurable - void setPIDSelectionFromFile(const char* prefixPID, const char* prefixTrack) + void setPIDSelectionFromFile(const char* prefix) { - std::string PIDnodeName = std::string(prefixPID) + "species"; - std::string PIDNsigmaNodeName = std::string(prefixTrack) + "PIDnSigmaMax"; + 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"); @@ -233,7 +233,7 @@ class FemtoDreamCutculator std::cout << input << std::endl; } } else { - if (selVec.size() == 0) { + if (selVec.size() == 1) { input = selVec[0].getSelectionValue(); std::cout << input << std::endl; } else { @@ -330,18 +330,22 @@ class FemtoDreamCutculator std::cout << output << " (number representation)" << std::endl; std::cout << "PID for these species is stored:" << std::endl; int index = 0; + int randomIndex = 0; + std::random_device rd; + std::mt19937 rng(rd()); + std::uniform_int_distribution uni(0, mPIDValues.size() - 1); for (auto id : mPIDspecies) { std::cout << o2::track::PID::getName(id) << " : " << index++ << std::endl; if (SysChecks) { // Seed the random number generator - std::random_device rd; - std::mt19937 rng(rd()); // Select a random element - std::uniform_int_distribution uni(0, mPIDValues.size() - 1); - int randomIndex = uni(rng); - std::cout << "Nsigma: " << mPIDValues[randomIndex] << std::endl; + randomIndex = uni(rng); + std::cout << "Nsigma TPC: " << mPIDValues[randomIndex] << std::endl; + randomIndex = uni(rng); + std::cout << "Nsigma TPCTOF: " << mPIDValues[randomIndex] << std::endl; } } + std::cout << "+++++++++++++++++++++++++++++++++" << std::endl; } private: diff --git a/PWGCF/FemtoDream/FemtoDreamEventHisto.h b/PWGCF/FemtoDream/FemtoDreamEventHisto.h index 9b33efe20ac..d44dba5ddc6 100644 --- a/PWGCF/FemtoDream/FemtoDreamEventHisto.h +++ b/PWGCF/FemtoDream/FemtoDreamEventHisto.h @@ -34,9 +34,11 @@ class FemtoDreamEventHisto void init(HistogramRegistry* registry) { mHistogramRegistry = registry; - mHistogramRegistry->add("Event/zvtxhist", "; vtx_{z} (cm); Entries", kTH1F, {{300, -12.5, 12.5}}); - mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{16384, 0, 32768}}); - mHistogramRegistry->add("Event/MultNTr", "; vMultNTr; Entries", kTH1F, {{200, 0, 200}}); + mHistogramRegistry->add("Event/hZvtx", "; vtx_{z} (cm); Entries", kTH1F, {{300, -12.5, 12.5}}); + mHistogramRegistry->add("Event/hMultV0M", "; vMultV0M; Entries", kTH1F, {{16384, 0, 32768}}); + mHistogramRegistry->add("Event/hMultNTr", "; vMultNTr; Entries", kTH1F, {{200, 0, 200}}); + mHistogramRegistry->add("Event/hMultNTrVsZvtx", "; vMultNTr; vtx_{z} (cm)", kTH2F, {{200, 0, 200}, {300, -12.5, 12.5}}); + mHistogramRegistry->add("Event/hMultNTrVsMultV0M", "; vMultNTr; vMultV0M", kTH2F, {{200, 0, 200}, {16384, 0, 32768}}); } /// Some basic QA of the event @@ -46,9 +48,11 @@ class FemtoDreamEventHisto void fillQA(T const& col) { if (mHistogramRegistry) { - mHistogramRegistry->fill(HIST("Event/zvtxhist"), col.posZ()); - mHistogramRegistry->fill(HIST("Event/MultV0M"), col.multV0M()); - mHistogramRegistry->fill(HIST("Event/MultNTr"), col.multNtr()); + mHistogramRegistry->fill(HIST("Event/hZvtx"), col.posZ()); + mHistogramRegistry->fill(HIST("Event/hMultV0M"), col.multV0M()); + mHistogramRegistry->fill(HIST("Event/hMultNTr"), col.multNtr()); + mHistogramRegistry->fill(HIST("Event/hMultNTrVsZvtx"), col.multNtr(), col.posZ()); + mHistogramRegistry->fill(HIST("Event/hMultNTrVsMultV0M"), col.multNtr(), col.multV0M()); } } diff --git a/PWGCF/FemtoDream/FemtoDreamMath.h b/PWGCF/FemtoDream/FemtoDreamMath.h index 74d4c14aaac..259c59ceb87 100644 --- a/PWGCF/FemtoDream/FemtoDreamMath.h +++ b/PWGCF/FemtoDream/FemtoDreamMath.h @@ -92,13 +92,14 @@ class FemtoDreamMath template static float getQ3(const T& part1, const float mass1, const T& part2, const float mass2, const T& part3, const float mass3) { - float E1 = sqrt(pow(part1.px(), 2) + pow(part1.py(), 2) + pow(part1.pz(), 2) + pow(mass1, 2)); - float E2 = sqrt(pow(part2.px(), 2) + pow(part2.py(), 2) + pow(part2.pz(), 2) + pow(mass2, 2)); - float E3 = sqrt(pow(part3.px(), 2) + pow(part3.py(), 2) + pow(part3.pz(), 2) + pow(mass3, 2)); - const ROOT::Math::PxPyPzEVector vecpart1(part1.px(), part1.py(), part1.pz(), E1); - const ROOT::Math::PxPyPzEVector vecpart2(part2.px(), part2.py(), part2.pz(), E2); - const ROOT::Math::PxPyPzEVector vecpart3(part3.px(), part3.py(), part3.pz(), E3); + const ROOT::Math::PtEtaPhiMVector vecpart01(part1.pt(), part1.eta(), part1.phi(), mass1); + const ROOT::Math::PtEtaPhiMVector vecpart02(part2.pt(), part2.eta(), part2.phi(), mass2); + const ROOT::Math::PtEtaPhiMVector vecpart03(part3.pt(), part3.eta(), part3.phi(), mass3); + + const ROOT::Math::PxPyPzEVector vecpart1(vecpart01); + const ROOT::Math::PxPyPzEVector vecpart2(vecpart02); + const ROOT::Math::PxPyPzEVector vecpart3(vecpart03); ROOT::Math::PxPyPzEVector q12 = getqij(vecpart1, vecpart2); ROOT::Math::PxPyPzEVector q23 = getqij(vecpart2, vecpart3); diff --git a/PWGCF/FemtoDream/FemtoDreamObjectSelection.h b/PWGCF/FemtoDream/FemtoDreamObjectSelection.h index 6095b59c8bd..e63b09ab5ed 100644 --- a/PWGCF/FemtoDream/FemtoDreamObjectSelection.h +++ b/PWGCF/FemtoDream/FemtoDreamObjectSelection.h @@ -51,8 +51,8 @@ class FemtoDreamObjectSelection void fillSelectionHistogram() { int nBins = mSelections.size(); - mHistogramRegistry->add((static_cast(o2::aod::femtodreamparticle::ParticleTypeName[part]) + "/cuthist").c_str(), "; Cut; Value", kTH1F, {{nBins, 0, static_cast(nBins)}}); - auto hist = mHistogramRegistry->get(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/cuthist")); + mQAHistogramRegistry->add((static_cast(o2::aod::femtodreamparticle::ParticleTypeName[part]) + "/cuthist").c_str(), "; Cut; Value", kTH1F, {{nBins, 0, static_cast(nBins)}}); + auto hist = mQAHistogramRegistry->get(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/cuthist")); for (size_t i = 0; i < mSelections.size(); ++i) { hist->GetXaxis()->SetBinLabel(i + 1, Form("%u", mSelections.at(i).getSelectionVariable())); hist->SetBinContent(i + 1, mSelections.at(i).getSelectionValue()); @@ -97,7 +97,7 @@ class FemtoDreamObjectSelection } /// Then, the sorted selections are added to the overall container of cuts - for (const auto& sel : sels) { + for (auto& sel : sels) { mSelections.push_back(sel); } } @@ -187,7 +187,8 @@ class FemtoDreamObjectSelection } protected: - HistogramRegistry* mHistogramRegistry; ///< For QA output + HistogramRegistry* mHistogramRegistry; ///< For Analysis QA output + HistogramRegistry* mQAHistogramRegistry; ///< For QA output std::vector> mSelections; ///< Vector containing all selections }; diff --git a/PWGCF/FemtoDream/FemtoDreamParticleHisto.h b/PWGCF/FemtoDream/FemtoDreamParticleHisto.h index 429daf7d25e..a0c1db30714 100644 --- a/PWGCF/FemtoDream/FemtoDreamParticleHisto.h +++ b/PWGCF/FemtoDream/FemtoDreamParticleHisto.h @@ -18,6 +18,7 @@ #ifndef PWGCF_FEMTODREAM_FEMTODREAMPARTICLEHISTO_H_ #define PWGCF_FEMTODREAM_FEMTODREAMPARTICLEHISTO_H_ +#include #include #include "PWGCF/DataModel/FemtoDerived.h" #include "Framework/HistogramRegistry.h" @@ -47,25 +48,31 @@ class FemtoDreamParticleHisto /// \param tempFitVarpTAxis axis object for the pT axis in the pT vs. tempFitVar plots /// \param tempFitVarAxis axis object for the tempFitVar axis template - void init_base(std::string folderName, std::string tempFitVarAxisTitle, T& tempFitVarpTAxis, T& tempFitVarAxis) + void init_base(std::string folderName, std::string tempFitVarAxisTitle, T& tempFitVarMomentumAxis, T& tempFitVarAxis) { std::string folderSuffix = static_cast(o2::aod::femtodreamMCparticle::MCTypeName[mc]).c_str(); /// Histograms of the kinematic properties mHistogramRegistry->add((folderName + folderSuffix + "/hPt").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); mHistogramRegistry->add((folderName + folderSuffix + "/hEta").c_str(), "; #eta; Entries", kTH1F, {{200, -1.5, 1.5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{200, 0, 2. * M_PI}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{200, 0, TMath::TwoPi()}}); /// particle specific histogramms for the TempFitVar column in FemtoDreamParticles if constexpr (o2::aod::femtodreamMCparticle::MCType::kRecon == mc) { - mHistogramRegistry->add((folderName + folderSuffix + static_cast(o2::aod::femtodreamparticle::TempFitVarName[mParticleType])).c_str(), ("; #it{p}_{T} (GeV/#it{c}); " + tempFitVarAxisTitle).c_str(), kTH2F, {{tempFitVarpTAxis}, {tempFitVarAxis}}); + mHistogramRegistry->add((folderName + folderSuffix + static_cast(o2::aod::femtodreamparticle::TempFitVarName[mParticleType])).c_str(), ("; #it{p}_{T} (GeV/#it{c}); " + tempFitVarAxisTitle).c_str(), kTH2F, {{tempFitVarMomentumAxis}, {tempFitVarAxis}}); } } // comment - template - void init_debug(std::string folderName) + template + void init_debug(std::string folderName, T& tempFitVarMomentumAxis, T& NsigmaTPCAxis, T& NsigmaTOFAxis, T& NsigmaTPCTOFAxis, T& InvMassAxis) { + std::string folderSuffix = static_cast(o2::aod::femtodreamMCparticle::MCTypeName[mc]).c_str(); + + mHistogramRegistry->add((folderName + folderSuffix + "/hMomentumVsEta").c_str(), "; #it{p} (GeV/#it{c}); #eta", kTH2F, {{500, 0, 10}, {300, -1.5, 1.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hMomentumVsPhi").c_str(), "; #it{p} (GeV/#it{c}); #phi", kTH2F, {{500, 0, 10}, {360, 0., TMath::TwoPi()}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hEtaVsPhi").c_str(), "; #eta; #phi", kTH2F, {{300, -1.5, 1.5}, {360, 0., TMath::TwoPi()}}); + if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kTrack || mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0Child) { 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}}); @@ -76,33 +83,35 @@ class FemtoDreamParticleHisto mHistogramRegistry->add((folderName + folderSuffix + "/hTPCshared").c_str(), "; TPC shared clusters; Entries", kTH1F, {{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}_{T} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/hDCA").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", kTH2F, {{100, 0, 10}, {301, 0., 1.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAz").c_str(), "; #it{p} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {tempFitVarMomentumAxis, {500, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCA").c_str(), "; #it{p} (GeV/#it{c}); DCA (cm)", kTH2F, {tempFitVarMomentumAxis, {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_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{e}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{#pi}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{K}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{p}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); - mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{d}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_el").c_str(), "n#sigma_{TPC}^{e}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_pi").c_str(), "n#sigma_{TPC}^{#pi}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_K").c_str(), "n#sigma_{TPC}^{K}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_p").c_str(), "n#sigma_{TPC}^{p}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_d").c_str(), "n#sigma_{TPC}^{d}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_el").c_str(), "n#sigma_{TOF}^{e}", kTH2F, {tempFitVarMomentumAxis, NsigmaTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_pi").c_str(), "n#sigma_{TOF}^{#pi}", kTH2F, {tempFitVarMomentumAxis, NsigmaTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_K").c_str(), "n#sigma_{TOF}^{K}", kTH2F, {tempFitVarMomentumAxis, NsigmaTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_p").c_str(), "n#sigma_{TOF}^{p}", kTH2F, {tempFitVarMomentumAxis, NsigmaTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_d").c_str(), "n#sigma_{TOF}^{d}", kTH2F, {tempFitVarMomentumAxis, NsigmaTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_el").c_str(), "n#sigma_{comb}^{e}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_pi").c_str(), "n#sigma_{comb}^{#pi}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_K").c_str(), "n#sigma_{comb}^{K}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_p").c_str(), "n#sigma_{comb}^{p}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCTOFAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_d").c_str(), "n#sigma_{comb}^{d}", kTH2F, {tempFitVarMomentumAxis, NsigmaTPCTOFAxis}); } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0) { mHistogramRegistry->add((folderName + folderSuffix + "/hDaughDCA").c_str(), "; DCA^{daugh} (cm); Entries", kTH1F, {{1000, 0, 10}}); mHistogramRegistry->add((folderName + folderSuffix + "/hTransRadius").c_str(), "; #it{r}_{xy} (cm); Entries", kTH1F, {{1500, 0, 150}}); mHistogramRegistry->add((folderName + folderSuffix + "/hDecayVtxX").c_str(), "; #it{Vtx}_{x} (cm); Entries", kTH1F, {{2000, 0, 200}}); mHistogramRegistry->add((folderName + folderSuffix + "/hDecayVtxY").c_str(), "; #it{Vtx}_{y} (cm)); Entries", kTH1F, {{2000, 0, 200}}); mHistogramRegistry->add((folderName + folderSuffix + "/hDecayVtxZ").c_str(), "; #it{Vtx}_{z} (cm); Entries", kTH1F, {{2000, 0, 200}}); - mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassLambda").c_str(), "; M_{#Lambda}; Entries", kTH1F, {{600, 0.f, 3.f}}); - mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassAntiLambda").c_str(), "; M_{#bar{#Lambda}}; Entries", kTH1F, {{600, 0.f, 3.f}}); - mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassLambdaAntiLambda").c_str(), "; M_{#Lambda}; M_{#bar{#Lambda}}", kTH2F, {{600, 0.f, 3.f}, {600, 0.f, 3.f}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassLambda").c_str(), "; M_{#Lambda}; Entries", kTH1F, {InvMassAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hpTInvMassLambda").c_str(), "; p_{T} (GeV/#it{c{}); M_{#Lambda}", kTH2F, {tempFitVarMomentumAxis, InvMassAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassAntiLambda").c_str(), "; M_{#bar{#Lambda}}; Entries", kTH1F, {InvMassAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hpTInvMassAntiLambda").c_str(), "; M_{#bar{#Lambda}}; Entries", kTH2F, {tempFitVarMomentumAxis, InvMassAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassLambdaAntiLambda").c_str(), "; M_{#Lambda}; M_{#bar{#Lambda}}", kTH2F, {InvMassAxis, InvMassAxis}); } } @@ -120,20 +129,24 @@ class FemtoDreamParticleHisto std::string folderSuffix = static_cast(o2::aod::femtodreamMCparticle::MCTypeName[o2::aod::femtodreamMCparticle::MCType::kTruth]).c_str(); mHistogramRegistry->add((folderName + folderSuffix + "/hPt_ReconNoFake").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hPDG").c_str(), "; PDG; Entries", kTH1I, {{6001, -3000.5, 3000.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hOrigin_MC").c_str(), "; Origin; Entries", kTH1I, {{7, -0.5, 6.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hNoMCtruthCounter").c_str(), "; Counter; Entries", kTH1I, {{1, -0.5, 0.5}}); if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kTrack || mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0Child) { /// Track histograms - mHistogramRegistry->add((folderName + folderSuffix + "/hPDG").c_str(), "; PDG; Entries", kTH1I, {{6001, -3000, 3000}}); - mHistogramRegistry->add((folderName + folderSuffix + "/hOrigin_MC").c_str(), "; Origin; Entries", kTH1I, {{7, 0, 7}}); - mHistogramRegistry->add((folderName + folderSuffix + "/hNoMCtruthCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); // DCA plots + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Primary").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Secondary").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Material").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Fake").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); - mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_DaughterLambda").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); - mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_DaughterSigmaplus").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); - mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Primary").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); - mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Daughter").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_SecondaryDaughterLambda").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_SecondaryDaughterSigmaplus").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0) { + mHistogramRegistry->add((folderName + folderSuffix + "/hCPA_Primary").c_str(), "; #it{p}_{T} (GeV/#it{c}); CPA", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hCPA_Secondary").c_str(), "; #it{p}_{T} (GeV/#it{c}); CPA", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hCPA_Material").c_str(), "; #it{p}_{T} (GeV/#it{c}); CPA", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hCPA_Fake").c_str(), "; #it{p}_{T} (GeV/#it{c}); CPA", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); /// V0 histograms /// to be implemented } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kCascade) { @@ -153,7 +166,7 @@ class FemtoDreamParticleHisto /// \param tempFitVarBins binning of the tempFitVar (DCA_xy in case of tracks, CPA in case of V0s, etc.) /// \param isMC add Monte Carlo truth histograms to the output file template - void init(HistogramRegistry* registry, T& tempFitVarpTBins, T& tempFitVarBins, bool isMC, int pdgCode, bool isDebug = false) + void init(HistogramRegistry* registry, T& MomentumBins, T& tempFitVarBins, T& NsigmaTPCBins, T& NsigmaTOFBins, T& NsigmaTPCTOFBins, T& InvMassBins, bool isMC, int pdgCode, bool isDebug = false) { mPDG = pdgCode; if (registry) { @@ -173,19 +186,23 @@ class FemtoDreamParticleHisto LOG(fatal) << "FemtoDreamParticleHisto: Histogramming for requested object not defined - quitting!"; } - framework::AxisSpec tempFitVarpTAxis = {tempFitVarpTBins, "#it{p}_{T} (GeV/#it{c})"}; // the pT binning may vary + framework::AxisSpec tempFitVarMomentumAxis = {MomentumBins, "p (#it{GeV/c})"}; framework::AxisSpec tempFitVarAxis = {tempFitVarBins, tempFitVarAxisTitle}; + framework::AxisSpec NsigmaTPCAxis = {NsigmaTPCBins, "n#sigma_{TPC}"}; + framework::AxisSpec NsigmaTOFAxis = {NsigmaTOFBins, "n#sigma_{TOF}"}; + framework::AxisSpec NsigmaTPCTOFAxis = {NsigmaTPCTOFBins, "n#sigma_{TPC+TOF}"}; + framework::AxisSpec InvMassAxis = {InvMassBins, "M_{inv} (GeV/#it{c}^{2})"}; std::string folderName = (static_cast(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]).c_str() + static_cast(mFolderSuffix[mFolderSuffixType])).c_str(); // Fill here the actual histogramms by calling init_base and init_MC - init_base(folderName, tempFitVarAxisTitle, tempFitVarpTAxis, tempFitVarAxis); + init_base(folderName, tempFitVarAxisTitle, tempFitVarMomentumAxis, tempFitVarAxis); if (isDebug) { - init_debug(folderName); + init_debug(folderName, tempFitVarMomentumAxis, NsigmaTPCAxis, NsigmaTOFAxis, NsigmaTPCTOFAxis, InvMassAxis); } if (isMC) { - init_base(folderName, tempFitVarAxisTitle, tempFitVarpTAxis, tempFitVarAxis); - init_MC(folderName, tempFitVarAxisTitle, tempFitVarpTAxis, tempFitVarAxis); + init_base(folderName, tempFitVarAxisTitle, tempFitVarMomentumAxis, tempFitVarAxis); + init_MC(folderName, tempFitVarAxisTitle, tempFitVarMomentumAxis, tempFitVarAxis); } } } @@ -209,8 +226,29 @@ class FemtoDreamParticleHisto } template - void fillQA_debug(T const& part) + void fillQA_debug(T const& part, aod::femtodreamparticle::MomentumType MomentumType) { + float momentum; + switch (MomentumType) { + case aod::femtodreamparticle::kPt: + momentum = part.pt(); + break; + case aod::femtodreamparticle::kPreco: + momentum = part.p(); + break; + case aod::femtodreamparticle::kPtpc: + LOG(warn) << "Momentum at TPC inner wall is only available if the Producer Task generates debug information."; + momentum = part.tpcInnerParam(); + break; + default: + LOG(warn) << "MomentumType " << MomentumType << " no implemented. Use pT of the Track for debug Histograms."; + momentum = part.pt(); + } + + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hMomentumVsEta"), momentum, part.eta()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hMomentumVsPhi"), momentum, part.phi()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hEtaVsPhi"), part.eta(), part.phi()); + // Histograms holding further debug information if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kTrack || mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0Child) { mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hCharge"), part.sign()); @@ -222,24 +260,24 @@ class FemtoDreamParticleHisto 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("/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"), part.pt(), part.dcaZ()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hDCA"), part.pt(), 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"), part.p(), part.tpcSignal()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_el"), part.p(), part.tpcNSigmaEl()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_pi"), part.p(), part.tpcNSigmaPi()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_K"), part.p(), part.tpcNSigmaKa()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_p"), part.p(), part.tpcNSigmaPr()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_d"), part.p(), part.tpcNSigmaDe()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_el"), part.p(), part.tofNSigmaEl()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_pi"), part.p(), part.tofNSigmaPi()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_K"), part.p(), part.tofNSigmaKa()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_p"), part.p(), part.tofNSigmaPr()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_d"), part.p(), part.tofNSigmaDe()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_el"), part.p(), std::sqrt(part.tpcNSigmaEl() * part.tpcNSigmaEl() + part.tofNSigmaEl() * part.tofNSigmaEl())); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_pi"), part.p(), 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"), part.p(), 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("/nSigmaComb_p"), part.p(), std::sqrt(part.tpcNSigmaPr() * part.tpcNSigmaPr() + part.tofNSigmaPr() * part.tofNSigmaPr())); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_d"), part.p(), std::sqrt(part.tpcNSigmaDe() * part.tpcNSigmaDe() + part.tofNSigmaDe() * part.tofNSigmaDe())); + 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_el"), momentum, part.tpcNSigmaEl()); + 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("/nSigmaTPC_p"), momentum, part.tpcNSigmaPr()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_d"), momentum, part.tpcNSigmaDe()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_el"), momentum, part.tofNSigmaEl()); + 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("/nSigmaTOF_p"), momentum, part.tofNSigmaPr()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_d"), momentum, part.tofNSigmaDe()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_el"), momentum, std::sqrt(part.tpcNSigmaEl() * part.tpcNSigmaEl() + part.tofNSigmaEl() * part.tofNSigmaEl())); + 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("/nSigmaComb_p"), momentum, std::sqrt(part.tpcNSigmaPr() * part.tpcNSigmaPr() + part.tofNSigmaPr() * part.tofNSigmaPr())); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_d"), momentum, std::sqrt(part.tpcNSigmaDe() * part.tpcNSigmaDe() + part.tofNSigmaDe() * part.tofNSigmaDe())); } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0) { mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hDaughDCA"), part.daughDCA()); mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hTransRadius"), part.transRadius()); @@ -247,7 +285,9 @@ class FemtoDreamParticleHisto mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hDecayVtxY"), part.decayVtxY()); mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hDecayVtxZ"), part.decayVtxZ()); mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hInvMassLambda"), part.mLambda()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hpTInvMassLambda"), momentum, part.mLambda()); mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hInvMassAntiLambda"), part.mAntiLambda()); + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hpTInvMassAntiLambda"), momentum, part.mAntiLambda()); mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/hInvMassLambdaAntiLambda"), part.mLambda(), part.mAntiLambda()); } } @@ -277,8 +317,8 @@ class FemtoDreamParticleHisto mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_Primary"), part.pt(), part.tempFitVar()); break; - case (o2::aod::femtodreamMCparticle::kDaughter): - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_Daughter"), + case (o2::aod::femtodreamMCparticle::kSecondary): + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_Secondary"), part.pt(), part.tempFitVar()); break; case (o2::aod::femtodreamMCparticle::kMaterial): @@ -289,12 +329,12 @@ class FemtoDreamParticleHisto mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_Fake"), part.pt(), part.tempFitVar()); break; - case (o2::aod::femtodreamMCparticle::kDaughterLambda): - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_DaughterLambda"), + case (o2::aod::femtodreamMCparticle::kSecondaryDaughterLambda): + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_SecondaryDaughterLambda"), part.pt(), part.tempFitVar()); break; - case (o2::aod::femtodreamMCparticle::kDaughterSigmaplus): - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_DaughterSigmaplus"), + case (o2::aod::femtodreamMCparticle::kSecondaryDaughterSigmaplus): + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_SecondaryDaughterSigmaplus"), part.pt(), part.tempFitVar()); break; default: @@ -302,6 +342,26 @@ class FemtoDreamParticleHisto } } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kV0) { /// V0 histograms + switch (mctruthorigin) { + case (o2::aod::femtodreamMCparticle::kPrimary): + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hCPA_Primary"), + part.pt(), part.tempFitVar()); + break; + case (o2::aod::femtodreamMCparticle::kSecondary): + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hCPA_Secondary"), + part.pt(), part.tempFitVar()); + break; + case (o2::aod::femtodreamMCparticle::kMaterial): + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hCPA_Material"), + part.pt(), part.tempFitVar()); + break; + case (o2::aod::femtodreamMCparticle::kFake): + mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hCPA_Fake"), + part.pt(), part.tempFitVar()); + break; + default: + LOG(fatal) << "femtodreamparticleMC: not known value for ParticleOriginMCTruth - please check. Quitting!"; + } } else if constexpr (mParticleType == o2::aod::femtodreamparticle::ParticleType::kCascade) { /// Cascade histograms } else { @@ -317,13 +377,13 @@ class FemtoDreamParticleHisto /// \tparam isMC fills the additional histograms for Monte Carlo truth /// \param part particle for which the histograms should be filled template - void fillQA(T const& part) + void fillQA(T const& part, aod::femtodreamparticle::MomentumType MomemtumType) { std::string tempFitVarName; if (mHistogramRegistry) { fillQA_base(part); if constexpr (isDebug) { - fillQA_debug(part); + fillQA_debug(part, MomemtumType); } if constexpr (isMC) { if (part.has_fdMCParticle()) { diff --git a/PWGCF/FemtoDream/FemtoDreamSelection.h b/PWGCF/FemtoDream/FemtoDreamSelection.h index 0f6af9a11c6..cb3b76ac36e 100644 --- a/PWGCF/FemtoDream/FemtoDreamSelection.h +++ b/PWGCF/FemtoDream/FemtoDreamSelection.h @@ -17,6 +17,11 @@ #define PWGCF_FEMTODREAM_FEMTODREAMSELECTION_H_ #include +#include "Framework/HistogramRegistry.h" +#include "PWGCF/DataModel/FemtoDerived.h" + +using namespace o2; +using namespace o2::framework; namespace o2::analysis::femtoDream { @@ -100,15 +105,34 @@ class FemtoDreamSelection /// \param cutContainer Bit-wise container for the systematic variations /// \param counter Position in the bit-wise container for the systematic variations to be modified template - void checkSelectionSetBit(selValDataType observable, T& cutContainer, size_t& counter) + void checkSelectionSetBit(selValDataType observable, T& cutContainer, size_t& counter, HistogramRegistry* registry) { /// If the selection is fulfilled the bit at the specified position (counter) within the bit-wise container is set to 1 if (isSelected(observable)) { cutContainer |= 1UL << counter; + if (registry) { + registry->fill(HIST("AnalysisQA/CutCounter"), 8 * sizeof(o2::aod::femtodreamparticle::cutContainerType)); + } + } else { + if (registry) { + registry->fill(HIST("AnalysisQA/CutCounter"), counter); + } } ++counter; } + template + void checkSelectionSetBitPID(selValDataType observable, T& cutContainer) + { + /// If the selection is fulfilled the bit at the specified position (counter) within the bit-wise container is set to 1 + if (isSelected(observable)) { + cutContainer |= 1UL; + } else { + cutContainer |= 0UL; + } + cutContainer <<= 1; + } + private: selValDataType mSelVal{0.f}; ///< Value used for the selection selVariableDataType mSelVar; ///< Variable used for the selection diff --git a/PWGCF/FemtoDream/FemtoDreamTrackSelection.h b/PWGCF/FemtoDream/FemtoDreamTrackSelection.h index a2ab3d47181..e8b8c260825 100644 --- a/PWGCF/FemtoDream/FemtoDreamTrackSelection.h +++ b/PWGCF/FemtoDream/FemtoDreamTrackSelection.h @@ -99,7 +99,7 @@ class FemtoDreamTrackSelection : public FemtoDreamObjectSelection - void init(HistogramRegistry* registry); + void init(HistogramRegistry* QAregistry, HistogramRegistry* Registry); /// Passes the species to the task for which PID needs to be stored /// \tparam T Data type of the configurable passed to the functions @@ -176,7 +176,6 @@ class FemtoDreamTrackSelection : public FemtoDreamObjectSelection -void FemtoDreamTrackSelection::init(HistogramRegistry* registry) +void FemtoDreamTrackSelection::init(HistogramRegistry* QAregistry, HistogramRegistry* Registry) { - if (registry) { - mHistogramRegistry = registry; + if (QAregistry && Registry) { + mHistogramRegistry = Registry; + mQAHistogramRegistry = QAregistry; std::string folderName = static_cast(o2::aod::femtodreamparticle::ParticleTypeName[part]) + "/" + static_cast(o2::aod::femtodreamparticle::TrackTypeName[tracktype]); /// check whether the number of selection exceeds the bitmap size @@ -302,38 +302,38 @@ void FemtoDreamTrackSelection::init(HistogramRegistry* registry) if (nSelections > 8 * sizeof(cutContainerType)) { LOG(fatal) << "FemtoDreamTrackCuts: Number of selections too large for your container - quitting!"; } - - mHistogramRegistry->add((folderName + "/hPt").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); - mHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", kTH1F, {{200, -1.5, 1.5}}); - mHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{200, 0, 2. * M_PI}}); - mHistogramRegistry->add((folderName + "/hTPCfindable").c_str(), "; TPC findable clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); - mHistogramRegistry->add((folderName + "/hTPCfound").c_str(), "; TPC found clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); - mHistogramRegistry->add((folderName + "/hTPCcrossedOverFindalbe").c_str(), "; TPC ratio findable; Entries", kTH1F, {{100, 0.5, 1.5}}); - mHistogramRegistry->add((folderName + "/hTPCcrossedRows").c_str(), "; TPC crossed rows; Entries", kTH1F, {{163, 0, 163}}); - mHistogramRegistry->add((folderName + "/hTPCfindableVsCrossed").c_str(), ";TPC findable clusters ; TPC crossed rows;", kTH2F, {{163, 0, 163}, {163, 0, 163}}); - mHistogramRegistry->add((folderName + "/hTPCshared").c_str(), "; TPC shared clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); - mHistogramRegistry->add((folderName + "/hITSclusters").c_str(), "; ITS clusters; Entries", kTH1F, {{10, -0.5, 9.5}}); - mHistogramRegistry->add((folderName + "/hITSclustersIB").c_str(), "; ITS clusters in IB; Entries", kTH1F, {{10, -0.5, 9.5}}); - mHistogramRegistry->add((folderName + "/hDCAxy").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); - mHistogramRegistry->add((folderName + "/hDCAz").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); - mHistogramRegistry->add((folderName + "/hDCA").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", kTH2F, {{100, 0, 10}, {301, 0., 1.5}}); - mHistogramRegistry->add((folderName + "/hTPCdEdX").c_str(), "; #it{p} (GeV/#it{c}); TPC Signal", kTH2F, {{100, 0, 10}, {1000, 0, 1000}}); - mHistogramRegistry->add((folderName + "/nSigmaTPC_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTPC_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTPC_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTPC_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTPC_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTOF_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTOF_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTOF_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTOF_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaTOF_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaComb_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaComb_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaComb_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaComb_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); - mHistogramRegistry->add((folderName + "/nSigmaComb_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/hPt").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); + mQAHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", kTH1F, {{200, -1.5, 1.5}}); + mQAHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{200, 0, 2. * M_PI}}); + mQAHistogramRegistry->add((folderName + "/hTPCfindable").c_str(), "; TPC findable clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); + mQAHistogramRegistry->add((folderName + "/hTPCfound").c_str(), "; TPC found clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); + mQAHistogramRegistry->add((folderName + "/hTPCcrossedOverFindalbe").c_str(), "; TPC ratio findable; Entries", kTH1F, {{100, 0.5, 1.5}}); + mQAHistogramRegistry->add((folderName + "/hTPCcrossedRows").c_str(), "; TPC crossed rows; Entries", kTH1F, {{163, 0, 163}}); + mQAHistogramRegistry->add((folderName + "/hTPCfindableVsCrossed").c_str(), ";TPC findable clusters ; TPC crossed rows;", kTH2F, {{163, 0, 163}, {163, 0, 163}}); + mQAHistogramRegistry->add((folderName + "/hTPCshared").c_str(), "; TPC shared clusters; Entries", kTH1F, {{163, -0.5, 162.5}}); + mQAHistogramRegistry->add((folderName + "/hITSclusters").c_str(), "; ITS clusters; Entries", kTH1F, {{10, -0.5, 9.5}}); + mQAHistogramRegistry->add((folderName + "/hITSclustersIB").c_str(), "; ITS clusters in IB; Entries", kTH1F, {{10, -0.5, 9.5}}); + mQAHistogramRegistry->add((folderName + "/hDCAxy").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/hDCAz").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/hDCA").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", kTH2F, {{100, 0, 10}, {301, 0., 1.5}}); + mQAHistogramRegistry->add((folderName + "/hTPCdEdX").c_str(), "; #it{p} (GeV/#it{c}); TPC Signal", kTH2F, {{100, 0, 10}, {1000, 0, 1000}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTPC_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTPC_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTPC_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTPC_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTPC_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTOF_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTOF_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTOF_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTOF_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaTOF_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaComb_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaComb_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaComb_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaComb_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mQAHistogramRegistry->add((folderName + "/nSigmaComb_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); } + /// set cuts nPtMinSel = getNSelections(femtoDreamTrackSelection::kpTMin); nPtMaxSel = getNSelections(femtoDreamTrackSelection::kpTMax); @@ -367,7 +367,18 @@ void FemtoDreamTrackSelection::init(HistogramRegistry* registry) template auto FemtoDreamTrackSelection::getNsigmaTPC(T const& track, o2::track::PID pid) { - return o2::aod::pidutils::tpcNSigma(pid, track); + if (pid == o2::track::PID::Electron) + return track.tpcNSigmaEl(); + else if (pid == o2::track::PID::Pion) + return track.tpcNSigmaPi(); + else if (pid == o2::track::PID::Kaon) + return track.tpcNSigmaKa(); + else if (pid == o2::track::PID::Proton) + return track.tpcNSigmaPr(); + else if (pid == o2::track::PID::Deuteron) + return track.tpcNSigmaDe(); + else + return 999.f; } template @@ -377,8 +388,18 @@ auto FemtoDreamTrackSelection::getNsigmaTOF(T const& track, o2::track::PID pid) if (!track.hasTOF()) { return 999.f; } - - return o2::aod::pidutils::tofNSigma(pid, track); + if (pid == o2::track::PID::Electron) + return track.tofNSigmaEl(); + else if (pid == o2::track::PID::Pion) + return track.tofNSigmaPi(); + else if (pid == o2::track::PID::Kaon) + return track.tofNSigmaKa(); + else if (pid == o2::track::PID::Proton) + return track.tofNSigmaPr(); + else if (pid == o2::track::PID::Deuteron) + return track.tofNSigmaDe(); + else + return 999.f; } template @@ -463,7 +484,6 @@ std::array FemtoDreamTrackSelection::getCutContainer(T cons cutContainerType output = 0; size_t counter = 0; cutContainerType outputPID = 0; - size_t counterPID = 0; const auto sign = track.sign(); const auto pT = track.pt(); const auto eta = track.eta(); @@ -488,14 +508,13 @@ std::array FemtoDreamTrackSelection::getCutContainer(T cons const auto selVariable = sel.getSelectionVariable(); if (selVariable == femtoDreamTrackSelection::kPIDnSigmaMax) { /// PID needs to be handled a bit differently since we may need more than one species - for (size_t i = 0; i < pidTPC.size(); ++i) { + for (size_t i = 0; i < mPIDspecies.size(); ++i) { auto pidTPCVal = pidTPC.at(i) - nSigmaPIDOffsetTPC; auto pidTOFVal = pidTOF.at(i) - nSigmaPIDOffsetTOF; - sel.checkSelectionSetBit(pidTPCVal, outputPID, counterPID); auto pidComb = std::sqrt(pidTPCVal * pidTPCVal + pidTOFVal * pidTOFVal); - sel.checkSelectionSetBit(pidComb, outputPID, counterPID); + sel.checkSelectionSetBitPID(pidTPCVal, outputPID); + sel.checkSelectionSetBitPID(pidComb, outputPID); } - } else { /// for the rest it's all the same switch (selVariable) { @@ -539,7 +558,7 @@ std::array FemtoDreamTrackSelection::getCutContainer(T cons case (femtoDreamTrackSelection::kPIDnSigmaMax): break; } - sel.checkSelectionSetBit(observable, output, counter); + sel.checkSelectionSetBit(observable, output, counter, mHistogramRegistry); } } return {output, outputPID}; @@ -548,37 +567,37 @@ std::array FemtoDreamTrackSelection::getCutContainer(T cons template void FemtoDreamTrackSelection::fillQA(T const& track) { - if (mHistogramRegistry) { - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hPt"), track.pt()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hEta"), track.eta()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hPhi"), track.phi()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCfindable"), track.tpcNClsFindable()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCfound"), track.tpcNClsFound()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCcrossedOverFindalbe"), track.tpcCrossedRowsOverFindableCls()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCcrossedRows"), track.tpcNClsCrossedRows()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCfindableVsCrossed"), track.tpcNClsFindable(), track.tpcNClsCrossedRows()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCshared"), track.tpcNClsShared()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hITSclusters"), track.itsNCls()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hITSclustersIB"), track.itsNClsInnerBarrel()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hDCAxy"), track.pt(), track.dcaXY()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hDCAz"), track.pt(), track.dcaZ()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hDCA"), track.pt(), std::sqrt(pow(track.dcaXY(), 2.) + pow(track.dcaZ(), 2.))); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCdEdX"), track.p(), track.tpcSignal()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_el"), track.p(), track.tpcNSigmaEl()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_pi"), track.p(), track.tpcNSigmaPi()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_K"), track.p(), track.tpcNSigmaKa()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_p"), track.p(), track.tpcNSigmaPr()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_d"), track.p(), track.tpcNSigmaDe()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_el"), track.p(), track.tofNSigmaEl()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_pi"), track.p(), track.tofNSigmaPi()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_K"), track.p(), track.tofNSigmaKa()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_p"), track.p(), track.tofNSigmaPr()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_d"), track.p(), track.tofNSigmaDe()); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_el"), track.p(), std::sqrt(track.tpcNSigmaEl() * track.tpcNSigmaEl() + track.tofNSigmaEl() * track.tofNSigmaEl())); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_pi"), track.p(), std::sqrt(track.tpcNSigmaPi() * track.tpcNSigmaPi() + track.tofNSigmaPi() * track.tofNSigmaPi())); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_K"), track.p(), std::sqrt(track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa())); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_p"), track.p(), std::sqrt(track.tpcNSigmaPr() * track.tpcNSigmaPr() + track.tofNSigmaPr() * track.tofNSigmaPr())); - mHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_d"), track.p(), std::sqrt(track.tpcNSigmaDe() * track.tpcNSigmaDe() + track.tofNSigmaDe() * track.tofNSigmaDe())); + if (mQAHistogramRegistry) { + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hPt"), track.pt()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hEta"), track.eta()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hPhi"), track.phi()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCfindable"), track.tpcNClsFindable()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCfound"), track.tpcNClsFound()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCcrossedOverFindalbe"), track.tpcCrossedRowsOverFindableCls()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCcrossedRows"), track.tpcNClsCrossedRows()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCfindableVsCrossed"), track.tpcNClsFindable(), track.tpcNClsCrossedRows()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCshared"), track.tpcNClsShared()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hITSclusters"), track.itsNCls()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hITSclustersIB"), track.itsNClsInnerBarrel()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hDCAxy"), track.pt(), track.dcaXY()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hDCAz"), track.pt(), track.dcaZ()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hDCA"), track.pt(), std::sqrt(pow(track.dcaXY(), 2.) + pow(track.dcaZ(), 2.))); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/hTPCdEdX"), track.p(), track.tpcSignal()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_el"), track.p(), track.tpcNSigmaEl()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_pi"), track.p(), track.tpcNSigmaPi()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_K"), track.p(), track.tpcNSigmaKa()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_p"), track.p(), track.tpcNSigmaPr()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTPC_d"), track.p(), track.tpcNSigmaDe()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_el"), track.p(), track.tofNSigmaEl()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_pi"), track.p(), track.tofNSigmaPi()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_K"), track.p(), track.tofNSigmaKa()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_p"), track.p(), track.tofNSigmaPr()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaTOF_d"), track.p(), track.tofNSigmaDe()); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_el"), track.p(), std::sqrt(track.tpcNSigmaEl() * track.tpcNSigmaEl() + track.tofNSigmaEl() * track.tofNSigmaEl())); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_pi"), track.p(), std::sqrt(track.tpcNSigmaPi() * track.tpcNSigmaPi() + track.tofNSigmaPi() * track.tofNSigmaPi())); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_K"), track.p(), std::sqrt(track.tpcNSigmaKa() * track.tpcNSigmaKa() + track.tofNSigmaKa() * track.tofNSigmaKa())); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_p"), track.p(), std::sqrt(track.tpcNSigmaPr() * track.tpcNSigmaPr() + track.tofNSigmaPr() * track.tofNSigmaPr())); + mQAHistogramRegistry->fill(HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/") + HIST(o2::aod::femtodreamparticle::TrackTypeName[tracktype]) + HIST("/nSigmaComb_d"), track.p(), std::sqrt(track.tpcNSigmaDe() * track.tpcNSigmaDe() + track.tofNSigmaDe() * track.tofNSigmaDe())); } } diff --git a/PWGCF/FemtoDream/FemtoDreamV0Selection.h b/PWGCF/FemtoDream/FemtoDreamV0Selection.h index 37ed2a8e370..a347b75b820 100644 --- a/PWGCF/FemtoDream/FemtoDreamV0Selection.h +++ b/PWGCF/FemtoDream/FemtoDreamV0Selection.h @@ -74,7 +74,7 @@ class FemtoDreamV0Selection template - void init(HistogramRegistry* registry); + void init(HistogramRegistry* QAregistry, HistogramRegistry* Registry); template bool isSelectedMinimal(C const& col, V const& v0, T const& posTrack, @@ -277,10 +277,11 @@ class FemtoDreamV0Selection template -void FemtoDreamV0Selection::init(HistogramRegistry* registry) +void FemtoDreamV0Selection::init(HistogramRegistry* QAregistry, HistogramRegistry* Registry) { - if (registry) { - mHistogramRegistry = registry; + if (QAregistry && Registry) { + mHistogramRegistry = Registry; + mQAHistogramRegistry = QAregistry; fillSelectionHistogram(); fillSelectionHistogram(); @@ -298,73 +299,73 @@ void FemtoDreamV0Selection::init(HistogramRegistry* registry) std::string folderName = static_cast( o2::aod::femtodreamparticle::ParticleTypeName[part]); /// \todo initialize histograms for children tracks of v0s - mHistogramRegistry->add((folderName + "/hPt").c_str(), - "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, - {{1000, 0, 10}}); - mHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", - kTH1F, {{1000, -1, 1}}); - mHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", - kTH1F, {{1000, 0, 2. * M_PI}}); - mHistogramRegistry->add((folderName + "/hDaughDCA").c_str(), - "; DCA^{daugh} (cm); Entries", kTH1F, - {{1000, 0, 10}}); - mHistogramRegistry->add((folderName + "/hTransRadius").c_str(), - "; #it{r}_{xy} (cm); Entries", kTH1F, - {{1500, 0, 150}}); - mHistogramRegistry->add((folderName + "/hDecayVtxX").c_str(), - "; #it{Vtx}_{x} (cm); Entries", kTH1F, - {{2000, 0, 200}}); - mHistogramRegistry->add((folderName + "/hDecayVtxY").c_str(), - "; #it{Vtx}_{y} (cm)); Entries", kTH1F, - {{2000, 0, 200}}); - mHistogramRegistry->add((folderName + "/hDecayVtxZ").c_str(), - "; #it{Vtx}_{z} (cm); Entries", kTH1F, - {{2000, 0, 200}}); - mHistogramRegistry->add((folderName + "/hCPA").c_str(), - "; #it{cos #theta_{p}}; Entries", kTH1F, - {{1000, 0.9, 1.}}); - mHistogramRegistry->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.}}); - mHistogramRegistry->add((folderName + "/hInvMassLambda").c_str(), "", kTH1F, - {massAxisLambda}); - mHistogramRegistry->add((folderName + "/hInvMassAntiLambda").c_str(), "", - kTH1F, {massAxisAntiLambda}); - mHistogramRegistry->add((folderName + "/hInvMassLambdaAntiLambda").c_str(), - "", kTH2F, {massAxisLambda, massAxisAntiLambda}); + 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( - mHistogramRegistry); + mQAHistogramRegistry, mHistogramRegistry); NegDaughTrack.init( - mHistogramRegistry); - - mHistogramRegistry->add("LambdaQA/hInvMassLambdaNoCuts", "No cuts", kTH1F, - {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaInvMassCut", - "Invariant mass cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMin", "Minimum Pt cut", - kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMax", "Maximum Pt cut", - kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaEtaMax", "Maximum Eta cut", - kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaDCAV0Daugh", - "V0-daughters DCA cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaCPA", "CPA cut", kTH1F, - {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMin", - "Minimum transverse radius cut", kTH1F, - {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMax", - "Maximum transverse radius cut", kTH1F, - {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaDecVtxMax", - "Maximum distance on decay vertex cut", kTH1F, - {massAxisLambda}); + 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 @@ -499,47 +500,47 @@ void FemtoDreamV0Selection::fillLambdaQA(C const& col, V const& v0, const float invMassLambda = v0.mLambda(); - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaNoCuts"), v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaNoCuts"), v0.mLambda()); if (invMassLambda > fInvMassLowLimit && invMassLambda < fInvMassUpLimit) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaInvMassCut"), - v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaInvMassCut"), + v0.mLambda()); } if (pT > pTV0Min) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMin"), - v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMin"), + v0.mLambda()); } if (pT < pTV0Max) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMax"), - v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMax"), + v0.mLambda()); } if (std::abs(eta) < etaV0Max) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaEtaMax"), - v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaEtaMax"), + v0.mLambda()); } if (dcaDaughv0 < DCAV0DaughMax) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDCAV0Daugh"), - v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDCAV0Daugh"), + v0.mLambda()); } if (cpav0 > CPAV0Min) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaCPA"), v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaCPA"), v0.mLambda()); } if (tranRad > TranRadV0Min) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMin"), - v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMin"), + v0.mLambda()); } if (tranRad < TranRadV0Max) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMax"), - v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMax"), + v0.mLambda()); } bool write = true; for (size_t i = 0; i < decVtx.size(); i++) { write = write && (decVtx.at(i) < DecVtxMax); } if (write) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDecVtxMax"), - v0.mLambda()); + mQAHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDecVtxMax"), + v0.mLambda()); } } @@ -593,7 +594,7 @@ std::array if (selVariable == femtoDreamV0Selection::kV0DecVtxMax) { for (size_t i = 0; i < decVtx.size(); ++i) { auto decVtxValue = decVtx.at(i); - sel.checkSelectionSetBit(decVtxValue, output, counter); + sel.checkSelectionSetBit(decVtxValue, output, counter, nullptr); } } else { switch (selVariable) { @@ -624,7 +625,7 @@ std::array case (femtoDreamV0Selection::kV0DecVtxMax): break; } - sel.checkSelectionSetBit(observable, output, counter); + sel.checkSelectionSetBit(observable, output, counter, nullptr); } } return { @@ -641,56 +642,56 @@ template fill( + if (mQAHistogramRegistry) { + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hPt"), v0.pt()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hEta"), v0.eta()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hPhi"), v0.phi()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hDaughDCA"), v0.dcaV0daughters()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hTransRadius"), v0.v0radius()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hDecayVtxX"), v0.x()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hDecayVtxY"), v0.y()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hDecayVtxZ"), v0.z()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hCPA"), v0.v0cosPA(col.posX(), col.posY(), col.posZ())); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hCPAvsPt"), v0.pt(), v0.v0cosPA(col.posX(), col.posY(), col.posZ())); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hInvMassLambda"), v0.mLambda()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hInvMassAntiLambda"), v0.mAntiLambda()); - mHistogramRegistry->fill( + mQAHistogramRegistry->fill( HIST(o2::aod::femtodreamparticle::ParticleTypeName[part]) + HIST("/hInvMassLambdaAntiLambda"), v0.mLambda(), v0.mAntiLambda()); diff --git a/PWGCF/FemtoDream/FemtoUtils.h b/PWGCF/FemtoDream/FemtoUtils.h index 95840d272d4..8b2047cbb90 100644 --- a/PWGCF/FemtoDream/FemtoUtils.h +++ b/PWGCF/FemtoDream/FemtoUtils.h @@ -17,29 +17,31 @@ #define PWGCF_FEMTODREAM_FEMTOUTILS_H_ #include +#include +#include #include "Framework/ASoAHelpers.h" #include "PWGCF/DataModel/FemtoDerived.h" namespace o2::analysis::femtoDream { -enum kDetector { kTPC = 0, - kTPCTOF = 1, - kNdetectors = 2 }; +enum kDetector { kTPC, + kTPCTOF, + kNdetectors }; /// internal function that returns the kPIDselection element corresponding to a /// specifica n-sigma value \param nSigma number of sigmas for PID /// \param vNsigma vector with the number of sigmas of interest /// \return kPIDselection corresponding to n-sigma -int getPIDselection(const float nSigma, const std::vector& vNsigma) +int getPIDselection(float nSigma, std::vector vNsigma) { - for (std::size_t i = 0; i < vNsigma.size(); i++) { - if (abs(nSigma - vNsigma[i]) < 1e-3) { - return static_cast(i); - } + std::sort(vNsigma.begin(), vNsigma.end(), std::greater<>()); + auto it = std::find(vNsigma.begin(), vNsigma.end(), nSigma); + if (it == vNsigma.end()) { + it = vNsigma.begin() + 1; + LOG(warn) << "Invalid value of nSigma: " << nSigma << ". Return the first value of the vector: " << *(it); } - LOG(warn) << "Invalid value of nSigma: " << nSigma << ". Return the first value of the vector: " << vNsigma[0]; - return 0; + return std::distance(vNsigma.begin(), it); } /// function that checks whether the PID selection specified in the vectors is @@ -51,20 +53,17 @@ int getPIDselection(const float nSigma, const std::vector& vNsigma) /// \param vNsigma vector with available n-sigma selections for PID /// \param kDetector enum corresponding to the PID technique /// \return Whether the PID selection specified in the vectors is fulfilled -bool isPIDSelected(aod::femtodreamparticle::cutContainerType const& pidcut, - std::vector const& vSpecies, int nSpecies, float nSigma, - const std::vector& vNsigma, - const kDetector iDet = kDetector::kTPC) +bool isPIDSelected(aod::femtodreamparticle::cutContainerType pidcut, + int vSpecies, + int nSpecies, + float nSigma, + std::vector vNsigma, + kDetector iDet) { - bool pidSelection = true; int iNsigma = getPIDselection(nSigma, vNsigma); - for (auto iSpecies : vSpecies) { - int bit_to_check = nSpecies * kDetector::kNdetectors * iNsigma + iSpecies * kDetector::kNdetectors + iDet; - if (!(pidcut & (1UL << bit_to_check))) { - pidSelection = false; - } - } - return pidSelection; + int nDet = static_cast(kDetector::kNdetectors); + int bit_to_check = 1 + (vNsigma.size() - (iNsigma + 1)) * nDet * nSpecies + (nSpecies - (vSpecies + 1)) * nSpecies + (nDet - 1 - iDet); + return ((pidcut >> (bit_to_check)) & 1) == 1; }; /// function that checks whether the PID selection specified in the vectors is fulfilled, depending on the momentum TPC or TPC+TOF PID is conducted @@ -77,10 +76,13 @@ bool isPIDSelected(aod::femtodreamparticle::cutContainerType const& pidcut, /// \param nSigmaTPCTOF Number of TPC+TOF sigmas for selection (circular selection) /// \return Whether the PID selection is fulfilled bool isFullPIDSelected(aod::femtodreamparticle::cutContainerType const& pidCut, - float const momentum, float const pidThresh, - std::vector const& vSpecies, int nSpecies, - const std::vector& vNsigma, const float nSigmaTPC, - const float nSigmaTPCTOF) + float momentum, + float pidThresh, + int vSpecies, + int nSpecies, + std::vector vNsigma, + float nSigmaTPC, + float nSigmaTPCTOF) { bool pidSelection = true; if (momentum < pidThresh) { @@ -97,29 +99,36 @@ int checkDaughterType(o2::aod::femtodreamparticle::ParticleType partType, int mo { int partOrigin = 0; if (partType == o2::aod::femtodreamparticle::ParticleType::kTrack) { - switch (abs(motherPDG)) { case 3122: - partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kDaughterLambda; + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondaryDaughterLambda; break; case 3222: - partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kDaughterSigmaplus; + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondaryDaughterSigmaplus; break; default: - partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kDaughter; + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondary; } // switch } else if (partType == o2::aod::femtodreamparticle::ParticleType::kV0) { - partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kDaughter; + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondary; } else if (partType == o2::aod::femtodreamparticle::ParticleType::kV0Child) { - partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kDaughter; + switch (abs(motherPDG)) { + case 3122: + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondaryDaughterLambda; + break; + case 3222: + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondaryDaughterSigmaplus; + break; + default: + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondary; + } // switch } else if (partType == o2::aod::femtodreamparticle::ParticleType::kCascade) { - partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kDaughter; - + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondary; } else if (partType == o2::aod::femtodreamparticle::ParticleType::kCascadeBachelor) { - partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kDaughter; + partOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kSecondary; } return partOrigin; }; diff --git a/PWGCF/FemtoDream/femtoDreamCutCulator.cxx b/PWGCF/FemtoDream/femtoDreamCutCulator.cxx index 26501797a7b..b5b5cc63ebc 100644 --- a/PWGCF/FemtoDream/femtoDreamCutCulator.cxx +++ b/PWGCF/FemtoDream/femtoDreamCutCulator.cxx @@ -36,19 +36,19 @@ int main(int argc, char* argv[]) cut.init(argv[1]); std::cout - << "Do you want to work with tracks or V0s (T/V)?"; + << "Do you want to work with tracks or V0s (T/V)? >"; std::string choice; std::cin >> choice; if (choice == std::string("T")) { cut.setTrackSelectionFromFile("ConfTrk"); - cut.setPIDSelectionFromFile("ConfPIDTrk", "ConfTrk"); + cut.setPIDSelectionFromFile("ConfTrk"); } else if (choice == std::string("V")) { - std::cout << "Do you want to select V0s or one of its children (V/T)?"; + std::cout << "Do you want to select V0s or one of its children (V/T)? >"; std::cin >> choice; cut.setV0SelectionFromFile("ConfV0"); cut.setTrackSelectionFromFile("ConfChild"); - cut.setPIDSelectionFromFile("ConfPIDChild", "ConfChild"); + cut.setPIDSelectionFromFile("ConfChild"); } else { std::cout << "Option not recognized. Break..."; return 2; @@ -58,7 +58,7 @@ int main(int argc, char* argv[]) /// femtoDreamSelection::kAbsUpperLimit, "ConfTrk"); std::cout << "Do you want to manually select cuts or create systematic " - "variations(M/V)?"; + "variations(M/V)? >"; std::string manual; std::cin >> manual; @@ -68,7 +68,7 @@ int main(int argc, char* argv[]) std::ofstream out("CutCulator.txt"); std::streambuf* coutbuf = std::cout.rdbuf(); // save old buf std::cout.rdbuf(out.rdbuf()); // redirect std::cout to out.txt! - for (int i = 0; i < 20; i++) { + for (int i = 0; i < 1000; i++) { cut.analyseCuts(choice, true, 1); } std::cout.rdbuf(coutbuf); // reset to standard output again diff --git a/PWGCF/FemtoDream/femtoDreamDebugTrack.cxx b/PWGCF/FemtoDream/femtoDreamDebugTrack.cxx index 1caddcce473..a1845090d9d 100644 --- a/PWGCF/FemtoDream/femtoDreamDebugTrack.cxx +++ b/PWGCF/FemtoDream/femtoDreamDebugTrack.cxx @@ -48,10 +48,15 @@ struct femtoDreamDebugTrack { Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; - Configurable> ConfPIDPartOne{"ConfPIDPartOne", std::vector{1}, "Particle 1 - Read from cutCulator"}; + Configurable ConfPIDPartOne{"ConfPIDPartOne", 1, "Particle 1 - Read from cutCulator"}; Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{3.5f, 3.f, 2.5f}, "This configurable needs to be the same as the one used in the producer task"}; - ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; - ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarBins{"ConfTempFitVarBins", {300, -0.15, 0.15}, "Binning of the TempFitVar"}; + ConfigurableAxis ConfNsigmaTPCBins{"ConfNsigmaTPCBins", {1600, -8, 8}, "Binning of Nsigma TPC plot"}; + ConfigurableAxis ConfNsigmaTOFBins{"ConfNsigmaTOFBins", {3000, -15, 15}, "Binning of the Nsigma TOF plot"}; + ConfigurableAxis ConfNsigmaTPCTOFBins{"ConfNsigmaTPCTOFBins", {1000, 0, 10}, "Binning of the Nsigma TPC+TOF plot"}; + ConfigurableAxis ConfTempFitVarMomentumBins{"ConfMomentumBins", {20, 0.5, 4.05}, "pT/p_reco/p_tpc binning of the Momentum vs. TempFitVar/Nsigma plot"}; + Configurable ConfTempFitVarMomentum{"ConfTempFitVarMomentum", 0, "Momentum used for binning: 0 -> pt; 1 -> preco; 2 -> ptpc"}; + ConfigurableAxis ConfDummy{"ConfDummy", {1, 0, 1}, "Dummy axis for inv mass"}; using FemtoFullParticles = soa::Join; Partition partsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartOne) == ConfCutPartOne); @@ -67,7 +72,7 @@ struct femtoDreamDebugTrack { FemtoDreamParticleHisto trackHisto; /// The configurables need to be passed to an std::vector - std::vector vPIDPartOne; + int vPIDPartOne; std::vector kNsigma; /// Histogram output @@ -76,7 +81,7 @@ struct femtoDreamDebugTrack { void init(InitContext&) { eventHisto.init(&qaRegistry); - trackHisto.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfIsMC, ConfPDGCodePartOne.value, true); + trackHisto.init(&qaRegistry, ConfTempFitVarMomentumBins, ConfTempFitVarBins, ConfNsigmaTPCBins, ConfNsigmaTOFBins, ConfNsigmaTPCTOFBins, ConfDummy, ConfIsMC, ConfPDGCodePartOne.value, true); vPIDPartOne = ConfPIDPartOne.value; kNsigma = ConfTrkPIDnSigmaMax.value; } @@ -93,7 +98,7 @@ struct femtoDreamDebugTrack { if (!isFullPIDSelected(part.pidcut(), part.p(), ConfCutTable->get("PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfCutTable->get("nSigmaTPC"), ConfCutTable->get("nSigmaTPCTOF"))) { continue; } - trackHisto.fillQA(part); + trackHisto.fillQA(part, static_cast(ConfTempFitVarMomentum.value)); } } diff --git a/PWGCF/FemtoDream/femtoDreamDebugV0.cxx b/PWGCF/FemtoDream/femtoDreamDebugV0.cxx index 85ee80e9d3b..d193bfe05ec 100644 --- a/PWGCF/FemtoDream/femtoDreamDebugV0.cxx +++ b/PWGCF/FemtoDream/femtoDreamDebugV0.cxx @@ -44,7 +44,16 @@ struct femtoDreamDebugV0 { Configurable ConfPDGCodeChildNeg{"ConfPDGCodeChildNeg", 211, "Negative Child- PDG code"}; Configurable ConfCutV0{"ConfCutV0", 338, "V0 - Selection bit from cutCulator"}; ConfigurableAxis ConfV0TempFitVarBins{"ConfV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; - ConfigurableAxis ConfV0TempFitVarpTBins{"ConfV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfV0TempFitVarMomentumBins{"ConfV0TempFitVarMomentumBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + + Configurable ConfTempFitVarMomentum{"ConfTempFitVarMomentum", 0, "Momentum used for binning: 0 -> pt; 1 -> preco; 2 -> ptpc"}; + + ConfigurableAxis ConfV0InvMassBins{"ConfV0InvMassBins", {200, 1, 1.2}, "V0: InvMass binning"}; + + ConfigurableAxis ConfChildTempFitVarMomentumBins{"ConfChildTempFitVarMomentumBins", {600, 0, 6}, "p binning for the p vs Nsigma TPC/TOF plot"}; + ConfigurableAxis ConfChildNsigmaTPCBins{"ConfChildNsigmaTPCBins", {1600, -8, 8}, "binning of Nsigma TPC plot"}; + ConfigurableAxis ConfChildNsigmaTOFBins{"ConfChildNsigmaTOFBins", {3000, -15, 15}, "binning of the Nsigma TOF plot"}; + ConfigurableAxis ConfChildNsigmaTPCTOFBins{"ConfChildNsigmaTPCTOFBins", {1000, 0, 10}, "binning of the Nsigma TPC+TOF plot"}; Configurable ConfCutChildPos{"ConfCutChildPos", 150, "Positive Child of V0 - Selection bit from cutCulator"}; Configurable ConfCutChildNeg{"ConfCutChildNeg", 149, "Negative Child of V0 - Selection bit from cutCulator"}; @@ -74,9 +83,9 @@ struct femtoDreamDebugV0 { void init(InitContext&) { eventHisto.init(&EventRegistry); - posChildHistos.init(&V0Registry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, ConfPDGCodeChildPos.value, true); - negChildHistos.init(&V0Registry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, ConfPDGCodeChildNeg, true); - V0Histos.init(&V0Registry, ConfV0TempFitVarpTBins, ConfV0TempFitVarBins, false, ConfPDGCodeV0.value, true); + posChildHistos.init(&V0Registry, ConfChildTempFitVarMomentumBins, ConfChildTempFitVarBins, ConfChildNsigmaTPCBins, ConfChildNsigmaTOFBins, ConfChildNsigmaTPCTOFBins, ConfV0InvMassBins, false, ConfPDGCodeChildPos.value, true); + negChildHistos.init(&V0Registry, ConfChildTempFitVarMomentumBins, ConfChildTempFitVarBins, ConfChildNsigmaTPCBins, ConfChildNsigmaTOFBins, ConfChildNsigmaTPCTOFBins, ConfV0InvMassBins, false, ConfPDGCodeChildNeg, true); + V0Histos.init(&V0Registry, ConfV0TempFitVarMomentumBins, ConfV0TempFitVarBins, ConfChildNsigmaTPCBins, ConfChildNsigmaTOFBins, ConfChildNsigmaTPCTOFBins, ConfV0InvMassBins, false, ConfPDGCodeV0.value, true); } /// Porduce QA plots for V0 selection in FemtoDream framework @@ -97,11 +106,10 @@ struct femtoDreamDebugV0 { // check cuts on V0 children if ((posChild.partType() == uint8_t(aod::femtodreamparticle::ParticleType::kV0Child) && (posChild.cut() & ConfCutChildPos) == ConfCutChildPos) && (negChild.partType() == uint8_t(aod::femtodreamparticle::ParticleType::kV0Child) && (negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) && - isFullPIDSelected(posChild.pidcut(), 0.f, 1.f, std::vector(ConfChildPosIndex.value), ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfChildPosPidnSigmaMax.value, 1.f) && - isFullPIDSelected(negChild.pidcut(), 0.f, 1.f, std::vector(ConfChildNegIndex.value), ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfChildNegPidnSigmaMax.value, 1.f)) { - V0Histos.fillQA(part); - posChildHistos.fillQA(posChild); - negChildHistos.fillQA(negChild); + isFullPIDSelected(posChild.pidcut(), posChild.p(), 999.f, ConfChildPosIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfChildPosPidnSigmaMax.value, 1.f) && isFullPIDSelected(negChild.pidcut(), negChild.p(), 999.f, ConfChildNegIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfChildNegPidnSigmaMax.value, 1.f)) { + V0Histos.fillQA(part, static_cast(ConfTempFitVarMomentum.value)); + posChildHistos.fillQA(posChild, static_cast(ConfTempFitVarMomentum.value)); + negChildHistos.fillQA(negChild, static_cast(ConfTempFitVarMomentum.value)); } } } diff --git a/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrack.cxx b/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrack.cxx index 91363ad6e51..c37ff38d813 100644 --- a/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrack.cxx +++ b/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrack.cxx @@ -62,11 +62,13 @@ struct femtoDreamPairTaskTrackTrack { Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable ConfExtendedPlots{"ConfExtendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; + Configurable ConfHighkstarCut{"ConfHighkstarCut", 6., "Set a cut for high k*, above which the pairs are rejected. Set it to -1 to deactivate it"}; /// Particle 1 Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; - Configurable> ConfPIDPartOne{"ConfPIDPartOne", std::vector{2}, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + Configurable ConfPIDPartOne{"ConfPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> /// Partition for particle 1 Partition partsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPartOne) == ConfCutPartOne); @@ -79,7 +81,7 @@ struct femtoDreamPairTaskTrackTrack { Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 2212, "Particle 2 - PDG code"}; Configurable ConfCutPartTwo{"ConfCutPartTwo", 5542474, "Particle 2 - Selection bit"}; - Configurable> ConfPIDPartTwo{"ConfPIDPartTwo", std::vector{2}, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + Configurable ConfPIDPartTwo{"ConfPIDPartTwo", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> /// Partition for particle 2 Partition partsTwo = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && @@ -95,7 +97,7 @@ struct femtoDreamPairTaskTrackTrack { FemtoDreamEventHisto eventHisto; /// The configurables need to be passed to an std::vector - std::vector vPIDPartOne, vPIDPartTwo; + int vPIDPartOne, vPIDPartTwo; std::vector kNsigma; /// particle part @@ -120,6 +122,7 @@ struct femtoDreamPairTaskTrackTrack { Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + ConfigurableAxis ConfDummy{"ConfDummy", {1, 0, 1}, "Dummy axis"}; FemtoDreamContainer sameEventCont; FemtoDreamContainer mixedEventCont; @@ -132,17 +135,18 @@ struct femtoDreamPairTaskTrackTrack { void init(InitContext&) { + eventHisto.init(&qaRegistry); - trackHistoPartOne.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfIsMC, ConfPDGCodePartOne); + trackHistoPartOne.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePartOne); if (!ConfIsSame) { - trackHistoPartTwo.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfIsMC, ConfPDGCodePartTwo); + trackHistoPartTwo.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePartTwo); } MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); - sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D); - mixedEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D); + sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D, ConfExtendedPlots, ConfHighkstarCut); + mixedEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D, ConfExtendedPlots, ConfHighkstarCut); sameEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); mixedEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); pairCleaner.init(&qaRegistry); @@ -150,9 +154,9 @@ struct femtoDreamPairTaskTrackTrack { pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); } - vPIDPartOne = ConfPIDPartOne; - vPIDPartTwo = ConfPIDPartTwo; - kNsigma = ConfTrkPIDnSigmaMax; + vPIDPartOne = ConfPIDPartOne.value; + vPIDPartTwo = ConfPIDPartTwo.value; + kNsigma = ConfTrkPIDnSigmaMax.value; } template @@ -192,7 +196,7 @@ struct femtoDreamPairTaskTrackTrack { continue; } - trackHistoPartOne.fillQA(part); + trackHistoPartOne.fillQA(part, aod::femtodreamparticle::kPt); } if (!ConfIsSame) { @@ -210,7 +214,7 @@ struct femtoDreamPairTaskTrackTrack { ConfCutTable->get("PartTwo", "nSigmaTPCTOF"))) { continue; } - trackHistoPartTwo.fillQA(part); + trackHistoPartTwo.fillQA(part, aod::femtodreamparticle::kPt); } } /// Now build the combinations @@ -247,7 +251,7 @@ struct femtoDreamPairTaskTrackTrack { if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; } - sameEventCont.setPair(p1, p2, multCol, ConfUse3D); + sameEventCont.setPair(p1, p2, multCol, ConfUse3D, ConfExtendedPlots); } } @@ -326,7 +330,7 @@ struct femtoDreamPairTaskTrackTrack { } } - mixedEventCont.setPair(p1, p2, multCol, ConfUse3D); + mixedEventCont.setPair(p1, p2, multCol, ConfUse3D, ConfExtendedPlots); } } diff --git a/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrackTrack.cxx b/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrackTrack.cxx new file mode 100644 index 00000000000..589cafc9e38 --- /dev/null +++ b/PWGCF/FemtoDream/femtoDreamPairTaskTrackTrackTrack.cxx @@ -0,0 +1,421 @@ +// 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 femtoDreamPairTaskTrackTrackTrack.cxx +/// \brief Tasks that reads the track tables and creates track triplets; should be currently used only for identical tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "TDatabasePDG.h" + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "FemtoDreamParticleHisto.h" +#include "FemtoDreamEventHisto.h" +#include "FemtoDreamPairCleaner.h" +#include "FemtoDreamContainerThreeBody.h" +#include "FemtoDreamDetaDphiStar.h" +#include "FemtoUtils.h" + +using namespace o2; +using namespace o2::analysis::femtoDream; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int nPart = 3; +static constexpr int nCuts = 5; +static const std::vector partNames{"PartOne", "PartTwo", "PartThree"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[nPart][nCuts]{ + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}}; +} // namespace + +struct femtoDreamPairTaskTrackTrackTrack { + SliceCache cache; + Preslice perCol = aod::femtodreamparticle::fdCollisionId; + + /// Particle selection part + + /// Table for both particles + Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; + Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; + Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + + // Which particles to analyse; currently support only for same species and cuts triplets + Configurable ConfPDGCodePart{"ConfPDGCodePart", 2212, "Particle PDG code"}; + Configurable ConfPIDPart{"ConfPIDPart", 2, "Particles - Read from cutCulator"}; + Configurable ConfCutPart{"ConfCutPart", 5542474, "Particles - Selection bit from cutCulator"}; + + // Keep this format as next code update will include also different particle species and cuts: + + /// Particle 1 + + /// Partition for particle 1 + Partition partsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPart) == ConfCutPart); + Partition> partsOneMC = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfCutPart) == ConfCutPart); + + /// Histogramming for particle 1 + FemtoDreamParticleHisto trackHistoPartOne; + + /// Particle 2 + + /// Partition for particle 2 + Partition partsTwo = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + // (aod::femtodreamparticle::pt < cfgCutTable->get("PartTwo", "MaxPt")) && + ((aod::femtodreamparticle::cut & ConfCutPart) == ConfCutPart); + Partition> partsTwoMC = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + ((aod::femtodreamparticle::cut & ConfCutPart) == ConfCutPart); + + /// Particle 3 + + /// Partition for particle 3 + Partition partsThree = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + // (aod::femtodreamparticle::pt < cfgCutTable->get("PartTwo", "MaxPt")) && + ((aod::femtodreamparticle::cut & ConfCutPart) == ConfCutPart); + Partition> partsThreeMC = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + ((aod::femtodreamparticle::cut & ConfCutPart) == ConfCutPart); + + /// Histogramming for Event + FemtoDreamEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + int vPIDPart; + std::vector kNsigma; + + /// particle part + ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + /// Correlation part + // ConfigurableAxis 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 + ConfigurableAxis ConfMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + 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"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + ConfigurableAxis ConfQ3Bins{"ConfQ3Bins", {2000, 0., 8.}, "binning Q3"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + ConfigurableAxis ConfDummy{"ConfDummy", {1, 0, 1}, "Dummy axis"}; + + FemtoDreamContainerThreeBody sameEventCont; + FemtoDreamContainerThreeBody mixedEventCont; + FemtoDreamPairCleaner pairCleaner; + FemtoDreamDetaDphiStar pairCloseRejection; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePart); + + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + sameEventCont.init(&resultRegistry, ConfQ3Bins, ConfMultBins, ConfIsMC); + mixedEventCont.init(&resultRegistry, ConfQ3Bins, ConfMultBins, ConfIsMC); + sameEventCont.setPDGCodes(ConfPDGCodePart, ConfPDGCodePart, ConfPDGCodePart); + mixedEventCont.setPDGCodes(ConfPDGCodePart, ConfPDGCodePart, ConfPDGCodePart); + pairCleaner.init(&qaRegistry); // SERKSNYTE : later check if init should be updated to have 3 separate histos + if (ConfIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); + } + + // CURRENTLY do only for one species + vPIDPart = ConfPIDPart.value; + kNsigma = ConfTrkPIDnSigmaMax.value; + } + + template + void fillCollision(CollisionType col) + { + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsOne partition for the first particle passed by the process function + /// @param groupPartsTwo partition for the second particle passed by the process function + /// @param parts femtoDreamParticles table (in case of Monte Carlo joined with FemtoDreamMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartitionType groupPartsThree, PartType parts, float magFieldTesla, int multCol) + { + /// Histogramming same event + int NGoodTracks = 0; + for (auto& part : groupPartsOne) { + if (part.p() > ConfCutTable->get("PartOne", "MaxP") || part.pt() > ConfCutTable->get("PartOne", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(part.pidcut(), + part.p(), + ConfCutTable->get("PartOne", "PIDthr"), + vPIDPart, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartOne", "nSigmaTPC"), + ConfCutTable->get("PartOne", "nSigmaTPCTOF"))) { + continue; + } + NGoodTracks++; + + trackHistoPartOne.fillQA(part, aod::femtodreamparticle::kPt); + } + + /// Now build the combinations + for (auto& [p1, p2, p3] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsTwo, groupPartsThree))) { + if (p1.p() > ConfCutTable->get("PartOne", "MaxP") || p1.pt() > ConfCutTable->get("PartOne", "MaxPt") || p2.p() > ConfCutTable->get("PartTwo", "MaxP") || p2.pt() > ConfCutTable->get("PartTwo", "MaxPt") || p3.p() > ConfCutTable->get("PartThree", "MaxP") || p3.pt() > ConfCutTable->get("PartThree", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(p1.pidcut(), + p1.p(), + ConfCutTable->get("PartOne", "PIDthr"), + vPIDPart, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartOne", "nSigmaTPC"), + ConfCutTable->get("PartOne", "nSigmaTPCTOF")) || + !isFullPIDSelected(p2.pidcut(), + p2.p(), + ConfCutTable->get("PartTwo", "PIDthr"), + vPIDPart, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartTwo", "nSigmaTPC"), + ConfCutTable->get("PartTwo", "nSigmaTPCTOF")) || + !isFullPIDSelected(p3.pidcut(), + p3.p(), + ConfCutTable->get("PartThree", "PIDthr"), + vPIDPart, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartThree", "nSigmaTPC"), + ConfCutTable->get("PartThree", "nSigmaTPCTOF"))) { + continue; + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + if (pairCloseRejection.isClosePair(p2, p3, parts, magFieldTesla)) { + continue; + } + if (pairCloseRejection.isClosePair(p1, p3, parts, magFieldTesla)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + if (!pairCleaner.isCleanPair(p2, p3, parts)) { + continue; + } + if (!pairCleaner.isCleanPair(p1, p3, parts)) { + continue; + } + sameEventCont.setTriplet(p1, p2, p3, multCol); + } + } + + /// process function to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoDreamParticleTable + void processSameEvent(o2::aod::FDCollision& col, + o2::aod::FDParticles& parts) + { + fillCollision(col); + + auto thegroupPartsOne = partsOne->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsThree = partsThree->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsOne, thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoDreamPairTaskTrackTrackTrack, processSameEvent, "Enable processing same event", true); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// \param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processSameEventMC(o2::aod::FDCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + + auto thegroupPartsOne = partsOneMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwoMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsThree = partsThreeMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsOne, thegroupPartsTwo, thegroupPartsThree, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoDreamPairTaskTrackTrackTrack, processSameEventMC, "Enable processing same event for Monte Carlo", false); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param groupPartsThree partition for the third particle passed by the process function + /// \param parts femtoDreamParticles table (in case of Monte Carlo joined with FemtoDreamMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartitionType groupPartsThree, PartType parts, float magFieldTesla, int multCol) + { + for (auto& [p1, p2, p3] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo, groupPartsThree))) { + if (p1.p() > ConfCutTable->get("PartOne", "MaxP") || p1.pt() > ConfCutTable->get("PartOne", "MaxPt") || p2.p() > ConfCutTable->get("PartTwo", "MaxP") || p2.pt() > ConfCutTable->get("PartTwo", "MaxPt") || p3.p() > ConfCutTable->get("PartThree", "MaxP") || p3.pt() > ConfCutTable->get("PartThree", "MaxPt")) { + continue; + } + + if (!isFullPIDSelected(p1.pidcut(), + p1.p(), + ConfCutTable->get("PartOne", "PIDthr"), + vPIDPart, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartOne", "nSigmaTPC"), + ConfCutTable->get("PartOne", "nSigmaTPCTOF")) || + !isFullPIDSelected(p2.pidcut(), + p2.p(), + ConfCutTable->get("PartTwo", "PIDthr"), + vPIDPart, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartTwo", "nSigmaTPC"), + ConfCutTable->get("PartTwo", "nSigmaTPCTOF")) || + !isFullPIDSelected(p3.pidcut(), + p3.p(), + ConfCutTable->get("PartThree", "PIDthr"), + vPIDPart, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartThree", "nSigmaTPC"), + ConfCutTable->get("PartThree", "nSigmaTPCTOF"))) { + continue; + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + if (pairCloseRejection.isClosePair(p2, p3, parts, magFieldTesla)) { + continue; + } + + if (pairCloseRejection.isClosePair(p1, p3, parts, magFieldTesla)) { + continue; + } + } + mixedEventCont.setTriplet(p1, p2, p3, multCol); + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoDreamParticleTable + void processMixedEvent(o2::aod::FDCollisions& cols, + o2::aod::FDParticles& parts) + { + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, 5, -1, cols, cols, cols)) { + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = partsThree->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + // CONSIDER testing different strategies to which events to use + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamPairTaskTrackTrackTrack, processMixedEvent, "Enable processing mixed events", true); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// @param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMC(o2::aod::FDCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, 5, -1, cols, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = partsThreeMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + // CONSIDER testing different strategies to which events to use + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamPairTaskTrackTrackTrack, processMixedEventMC, "Enable processing mixed events MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoDream/femtoDreamPairTaskTrackV0.cxx b/PWGCF/FemtoDream/femtoDreamPairTaskTrackV0.cxx index 0ef7eb72ca6..6473d80f0c0 100644 --- a/PWGCF/FemtoDream/femtoDreamPairTaskTrackV0.cxx +++ b/PWGCF/FemtoDream/femtoDreamPairTaskTrackV0.cxx @@ -57,7 +57,7 @@ struct femtoDreamPairTaskTrackV0 { Configurable> ConfTrkCutTable{"ConfTrkCutTable", {cutsTableTrack[0], nTrack, nCuts, TrackName, cutNames}, "Particle selections"}; Configurable ConfTrkPDGCodePartOne{"ConfTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"}; Configurable ConfTrkCutPartOne{"ConfTrkCutPartOne", 5542474, "Particle 1 (Track) - Selection bit from cutCulator"}; - Configurable> ConfTrkPIDPartOne{"ConfTrkPIDPartOne", std::vector{2}, "Particle 1 - Read from cutCulator"}; + Configurable ConfTrkPIDPartOne{"ConfTrkPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; ConfigurableAxis ConfTrkTempFitVarBins{"ConfTrkDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; @@ -65,6 +65,7 @@ struct femtoDreamPairTaskTrackV0 { /// Partition for particle 1 Partition partsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfTrkCutPartOne) == ConfTrkCutPartOne); + Partition> partsOneMC = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && ((aod::femtodreamparticle::cut & ConfTrkCutPartOne) == ConfTrkCutPartOne); /// Histogramming for particle 1 FemtoDreamParticleHisto trackHistoPartOne; @@ -75,6 +76,7 @@ struct femtoDreamPairTaskTrackV0 { Configurable ConfV0CutPartTwo{"ConfV0CutPartTwo", 338, "Particle 2 (V0) - Selection bit"}; ConfigurableAxis ConfV0TempFitVarBins{"ConfV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; ConfigurableAxis ConfV0TempFitVarpTBins{"ConfV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfV0TempFitVarInvMassBins{"ConfV0TempFitVarInvMassBins", {200, 1, 1.2}, "V0: InvMass binning"}; Configurable ConfCutChildPos{"ConfCutChildPos", 150, "Positive Child of V0 - Selection bit from cutCulator"}; Configurable ConfCutChildNeg{"ConfCutChildNeg", 149, "Negative Child of V0 - Selection bit from cutCulator"}; @@ -87,6 +89,7 @@ struct femtoDreamPairTaskTrackV0 { /// Partition for particle 2 Partition partsTwo = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)) && ((aod::femtodreamparticle::cut & ConfV0CutPartTwo) == ConfV0CutPartTwo); + Partition> partsTwoMC = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)) && ((aod::femtodreamparticle::cut & ConfV0CutPartTwo) == ConfV0CutPartTwo); /// Histogramming for particle 2 FemtoDreamParticleHisto trackHistoPartTwo; @@ -96,13 +99,15 @@ struct femtoDreamPairTaskTrackV0 { /// Histogramming for Event FemtoDreamEventHisto eventHisto; - /// The configurables need to be passed to an std::vector - std::vector vPIDPartOne; + int vPIDPartOne; std::vector kNsigma; /// Correlation part Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable ConfExtendedPlots{"ConfExtendedPlots", false, "Enable additional three dimensional histogramms. High memory consumption. Use for debugging"}; + Configurable ConfHighkstarCut{"ConfHighkstarCut", 6., "Set a cut for high k*, above which the pairs are rejected. Set it to -1 to deactivate it"}; + ConfigurableAxis ConfMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; @@ -116,6 +121,9 @@ struct femtoDreamPairTaskTrackV0 { ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; ConfigurableAxis ConfmultBins3D{"ConfMultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis ConfDummy{"ConfDummy", {1, 0, 1}, "Dummy axis"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; FemtoDreamContainer sameEventCont; FemtoDreamContainer mixedEventCont; @@ -128,14 +136,14 @@ struct femtoDreamPairTaskTrackV0 { void init(InitContext&) { eventHisto.init(&qaRegistry); - trackHistoPartOne.init(&qaRegistry, ConfTrkTempFitVarpTBins, ConfTrkTempFitVarBins, ConfIsMC, ConfTrkPDGCodePartOne); - trackHistoPartTwo.init(&qaRegistry, ConfV0TempFitVarpTBins, ConfV0TempFitVarBins, ConfIsMC, ConfV0PDGCodePartTwo); - posChildHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, false); - negChildHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, false); + trackHistoPartOne.init(&qaRegistry, ConfTrkTempFitVarpTBins, ConfTrkTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfTrkPDGCodePartOne); + trackHistoPartTwo.init(&qaRegistry, ConfV0TempFitVarpTBins, ConfV0TempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfV0TempFitVarInvMassBins, ConfIsMC, ConfV0PDGCodePartTwo); + posChildHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, false, false); + negChildHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, false, false); - sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D); + sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D, ConfExtendedPlots, ConfHighkstarCut); sameEventCont.setPDGCodes(ConfTrkPDGCodePartOne, ConfV0PDGCodePartTwo); - mixedEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D); + mixedEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D, ConfExtendedPlots, ConfHighkstarCut); mixedEventCont.setPDGCodes(ConfTrkPDGCodePartOne, ConfV0PDGCodePartTwo); pairCleaner.init(&qaRegistry); if (ConfIsCPR.value) { @@ -147,15 +155,9 @@ struct femtoDreamPairTaskTrackV0 { /// This function processes the same event and takes care of all the histogramming /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... - void processSameEvent(o2::aod::FDCollision& col, o2::aod::FDParticles& parts) + template + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol) { - const auto& magFieldTesla = col.magField(); - - auto groupPartsOne = partsOne->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - const int multCol = col.multNtr(); - - eventHisto.fillQA(col); /// Histogramming same event for (auto& part : groupPartsOne) { @@ -163,21 +165,20 @@ struct femtoDreamPairTaskTrackV0 { !isFullPIDSelected(part.pidcut(), part.p(), ConfTrkCutTable->get("Track", "PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfTrkCutTable->get("Track", "nSigmaTPC"), ConfTrkCutTable->get("Track", "nSigmaTPCTOF"))) { continue; } - trackHistoPartOne.fillQA(part); + trackHistoPartOne.fillQA(part, aod::femtodreamparticle::kPt); } - for (auto& part : groupPartsTwo) { const auto& posChild = parts.iteratorAt(part.index() - 2); const auto& negChild = parts.iteratorAt(part.index() - 1); // check cuts on V0 children if (!((posChild.cut() & ConfCutChildPos) == ConfCutChildPos) || !((negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) || - !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), std::vector(ConfChildPosIndex.value), ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || - !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), std::vector(ConfChildNegIndex.value), ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { + !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildPosIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || + !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildNegIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { continue; } - trackHistoPartTwo.fillQA(part); - posChildHistos.fillQA(posChild); - negChildHistos.fillQA(negChild); + trackHistoPartTwo.fillQA(part, aod::femtodreamparticle::kPt); + posChildHistos.fillQA(posChild, aod::femtodreamparticle::kPt); + negChildHistos.fillQA(negChild, aod::femtodreamparticle::kPt); } /// Now build the combinations @@ -190,8 +191,8 @@ struct femtoDreamPairTaskTrackV0 { const auto& negChild = parts.iteratorAt(p2.index() - 1); // check cuts on V0 children if (!((posChild.cut() & ConfCutChildPos) == ConfCutChildPos) || !((negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) || - !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), std::vector(ConfChildPosIndex.value), ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || - !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), std::vector(ConfChildNegIndex.value), ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { + !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildPosIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || + !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildNegIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { continue; } if (ConfIsCPR.value) { @@ -203,20 +204,67 @@ struct femtoDreamPairTaskTrackV0 { if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; } - sameEventCont.setPair(p1, p2, multCol, ConfUse3D); + sameEventCont.setPair(p1, p2, multCol, ConfUse3D, ConfExtendedPlots); } } + void processSameEvent(o2::aod::FDCollision& col, + o2::aod::FDParticles& parts) + { + eventHisto.fillQA(col); + + auto thegroupPartsOne = partsOne->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr()); + } PROCESS_SWITCH(femtoDreamPairTaskTrackV0, processSameEvent, "Enable processing same event", true); + void processSameEventMC(o2::aod::FDCollision& col, soa::Join& parts, o2::aod::FDMCParticles&) + { + eventHisto.fillQA(col); + auto thegroupPartsOne = partsOneMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwoMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoDreamPairTaskTrackV0, processSameEventMC, "Enable processing same event MC", false); + /// This function processes the mixed event /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... - void processMixedEvent(o2::aod::FDCollisions& cols, o2::aod::FDParticles& parts) + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol) { - ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; - for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (p1.p() > ConfTrkCutTable->get("Track", "MaxP") || p1.pt() > ConfTrkCutTable->get("Track", "MaxPt") || + !isFullPIDSelected(p1.pidcut(), p1.p(), ConfTrkCutTable->get("Track", "PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfTrkCutTable->get("Track", "nSigmaTPC"), ConfTrkCutTable->get("Track", "nSigmaTPCTOF"))) { + continue; + } + const auto& posChild = parts.iteratorAt(p2.index() - 2); + const auto& negChild = parts.iteratorAt(p2.index() - 1); + // check cuts on V0 children + if (!((posChild.cut() & ConfCutChildPos) == ConfCutChildPos) || !((negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) || + !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildPosIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || + !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildNegIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { + continue; + } + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + mixedEventCont.setPair(p1, p2, multCol, ConfUse3D, ConfExtendedPlots); + } + } + void processMixedEvent(o2::aod::FDCollisions& cols, + o2::aod::FDParticles& parts) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { const int multCol = collision1.multNtr(); auto groupPartsOne = partsOne->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); @@ -229,34 +277,30 @@ struct femtoDreamPairTaskTrackV0 { continue; } - for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { - if (p1.p() > ConfTrkCutTable->get("Track", "MaxP") || p1.pt() > ConfTrkCutTable->get("Track", "MaxPt") || - !isFullPIDSelected(p1.pidcut(), p1.p(), ConfTrkCutTable->get("Track", "PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfTrkCutTable->get("Track", "nSigmaTPC"), ConfTrkCutTable->get("Track", "nSigmaTPCTOF"))) { - continue; - } - const auto& posChild = parts.iteratorAt(p2.index() - 2); - const auto& negChild = parts.iteratorAt(p2.index() - 1); - // check cuts on V0 children - if (!((posChild.cut() & ConfCutChildPos) == ConfCutChildPos) || !((negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) || - !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), std::vector(ConfChildPosIndex.value), ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || - !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), std::vector(ConfChildNegIndex.value), ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { - continue; - } - if (ConfIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1)) { - continue; - } - } - // track cleaning - if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; - } - mixedEventCont.setPair(p1, p2, multCol, ConfUse3D); - } + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multCol); } } - PROCESS_SWITCH(femtoDreamPairTaskTrackV0, processMixedEvent, "Enable processing mixed events", true); + + void processMixedEventMC(o2::aod::FDCollisions& cols, soa::Join& parts, o2::aod::FDMCParticles&) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + const int multCol = collision1.multNtr(); + + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multCol); + } + } + PROCESS_SWITCH(femtoDreamPairTaskTrackV0, processMixedEventMC, "Enable processing mixed events MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoDream/femtoDreamProducerReducedTask.cxx b/PWGCF/FemtoDream/femtoDreamProducerReducedTask.cxx index 26656a938d0..cb809110cf9 100644 --- a/PWGCF/FemtoDream/femtoDreamProducerReducedTask.cxx +++ b/PWGCF/FemtoDream/femtoDreamProducerReducedTask.cxx @@ -54,10 +54,10 @@ using FemtoFullCollisionMC = soa::Join::iterator; using FemtoFullTracks = soa::Join; + aod::pidTPCFullEl, aod::pidTPCFullMu, aod::pidTPCFullPi, + aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullDe, + aod::pidTOFFullEl, aod::pidTOFFullMu, aod::pidTOFFullPi, + aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullDe>; } // namespace o2::aod struct femtoDreamProducerReducedTask { @@ -69,28 +69,25 @@ struct femtoDreamProducerReducedTask { Produces outputPartsMCLabels; Produces outputDebugPartsMC; - Configurable ConfDebugOutput{"ConfDebugOutput", true, "Debug output"}; - Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; // Choose if filtering or skimming version is run - Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or Run2"}; // Choose if running on converted data or Run3 - Configurable ConfIsMC{"ConfIsMC", false, "Running on MC; implemented only for Run3"}; + Configurable ConfIsDebug{"ConfIsDebug", true, "Enable Debug tables"}; + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or Run2"}; // Choose if running on converted data or Run3 + 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; - Configurable ConfUseTPCmult{"ConfUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; + Configurable ConfEvtUseTPCmult{"ConfEvtUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; 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 ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; - Configurable ConfRejectITSHitandTOFMissing{"ConfRejectITSHitandTOFMissing", false, "True: reject if neither ITS hit nor TOF timing satisfied"}; + Configurable ConfTrkRejectNotPropagated{"ConfTrkRejectNotPropagated", false, "True: reject not propagated tracks"}; - Configurable ConfForceGRP{"ConfForceGRP", 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)"}; - Configurable ConfPDGCodeTrack{"ConfPDGCodeTrack", 2212, "PDG code of the selected track for Monte Carlo truth"}; + Configurable ConfTrkPDGCode{"ConfTrkPDGCode", 2212, "PDG code of the selected track for Monte Carlo truth"}; // Track cuts FemtoDreamTrackSelection trackCuts; 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.4f, 0.6f, 0.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kpTMin, "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: ")}; @@ -103,11 +100,12 @@ struct femtoDreamProducerReducedTask { 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, "Conf"), std::vector{3.5f, 3.f, 2.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Track selection: ")}; // off set the center of the nsigma distribution to deal with bad TPC/TOF calibration - Configurable ConfPIDnSigmaOffsetTPC{"ConfPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; - Configurable ConfPIDnSigmaOffsetTOF{"ConfPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; - Configurable> ConfPIDspecies{"ConfPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton, o2::track::PID::Deuteron}, "Trk sel: Particles species for PID"}; + Configurable ConfTrkPIDnSigmaOffsetTPC{"ConfTrkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; + 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"}; HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry Registry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; int mRunNumber; float mMagField; @@ -115,7 +113,11 @@ struct femtoDreamProducerReducedTask { void init(InitContext&) { - colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3); + + int CutBits = 8 * sizeof(o2::aod::femtodreamparticle::cutContainerType); + Registry.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{CutBits + 1, -0.5, CutBits + 0.5}}); + + colCuts.setCuts(ConfEvtZvtx.value, ConfEvtTriggerCheck.value, ConfEvtTriggerSel.value, ConfEvtOfflineCheck.value, ConfIsRun3.value); colCuts.init(&qaRegistry); trackCuts.setSelection(ConfTrkCharge, femtoDreamTrackSelection::kSign, femtoDreamSelection::kEqual); @@ -131,11 +133,11 @@ struct femtoDreamProducerReducedTask { trackCuts.setSelection(ConfTrkDCAxyMax, femtoDreamTrackSelection::kDCAxyMax, femtoDreamSelection::kAbsUpperLimit); trackCuts.setSelection(ConfTrkDCAzMax, femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); trackCuts.setSelection(ConfTrkPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); - trackCuts.setPIDSpecies(ConfPIDspecies); - trackCuts.setnSigmaPIDOffset(ConfPIDnSigmaOffsetTPC, ConfPIDnSigmaOffsetTOF); + trackCuts.setPIDSpecies(ConfTrkPIDspecies); + trackCuts.setnSigmaPIDOffset(ConfTrkPIDnSigmaOffsetTPC, ConfTrkPIDnSigmaOffsetTOF); trackCuts.init(&qaRegistry); + aod::femtodreamparticle::cutContainerType>(&qaRegistry, &Registry); mRunNumber = 0; mMagField = 0.0; /// Initializing CCDB @@ -157,7 +159,7 @@ struct femtoDreamProducerReducedTask { auto timestamp = bc.timestamp(); float output = -999; - if (ConfIsRun3 && !ConfForceGRP) { + if (ConfIsRun3 && !ConfIsForceGRP) { static o2::parameters::GRPMagField* grpo = nullptr; grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); if (grpo == nullptr) { @@ -195,7 +197,7 @@ struct femtoDreamProducerReducedTask { int particleOrigin = 99; auto motherparticleMC = particleMC.template mothers_as().front(); - if (abs(pdgCode) == abs(ConfPDGCodeTrack.value)) { + if (abs(pdgCode) == abs(ConfTrkPDGCode.value)) { if (particleMC.isPhysicalPrimary()) { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kPrimary; @@ -234,18 +236,16 @@ struct femtoDreamProducerReducedTask { mult = 0.5 * (col.multFV0M()); /// For benchmarking on Run 2, V0M in FemtoDreamRun2 is defined V0M/2 multNtr = col.multTracklets(); } - if (ConfUseTPCmult) { + if (ConfEvtUseTPCmult) { multNtr = col.multTPC(); } /// First thing to do is to check whether the basic event selection criteria are fulfilled - // If the basic selection is NOT fulfilled: - // in case of skimming run - don't store such collisions - // in case of trigger run - store such collisions but don't store any particle candidates for such collisions - if (!colCuts.isSelected(col)) { - if (ConfIsTrigger) { - outputCollision(vtxZ, mult, multNtr, colCuts.computeSphericity(col, tracks), mMagField); - } + /// That includes checking if there are any usable tracks in a collision + if (!colCuts.isSelectedCollision(col)) { + return; + } + if (colCuts.isEmptyCollision(col, tracks, trackCuts)) { return; } @@ -275,12 +275,11 @@ struct femtoDreamProducerReducedTask { cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kCuts), cutContainer.at(femtoDreamTrackSelection::TrackContainerPosition::kPID), track.dcaXY(), childIDs, 0, 0); - if constexpr (isMC) { fillMCParticle(track, o2::aod::femtodreamparticle::ParticleType::kTrack); } - if (ConfDebugOutput) { + if (ConfIsDebug) { outputDebugParts(track.sign(), (uint8_t)track.tpcNClsFound(), track.tpcNClsFindable(), @@ -292,27 +291,23 @@ struct femtoDreamProducerReducedTask { track.dcaXY(), track.dcaZ(), track.tpcSignal(), - track.tpcNSigmaStoreEl(), - track.tpcNSigmaStorePi(), - track.tpcNSigmaStoreKa(), - track.tpcNSigmaStorePr(), - track.tpcNSigmaStoreDe(), - track.tofNSigmaStoreEl(), - track.tofNSigmaStorePi(), - track.tofNSigmaStoreKa(), - track.tofNSigmaStorePr(), - track.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999.); + track.tpcNSigmaEl(), + track.tpcNSigmaPi(), + track.tpcNSigmaKa(), + track.tpcNSigmaPr(), + track.tpcNSigmaDe(), + track.tofNSigmaEl(), + track.tofNSigmaPi(), + track.tofNSigmaKa(), + track.tofNSigmaPr(), + track.tofNSigmaDe(), + -999., -999., -999., -999., -999., -999.); } } } - void processData(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) + void + processData(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) { // get magnetic field for run getMagneticFieldTesla(col.bc_as()); diff --git a/PWGCF/FemtoDream/femtoDreamProducerTask.cxx b/PWGCF/FemtoDream/femtoDreamProducerTask.cxx index 1d0c56ae0d8..033d9590f2e 100644 --- a/PWGCF/FemtoDream/femtoDreamProducerTask.cxx +++ b/PWGCF/FemtoDream/femtoDreamProducerTask.cxx @@ -49,23 +49,11 @@ using FemtoFullCollision = using FemtoFullCollisionMC = soa::Join::iterator; using FemtoFullTracks = - soa::Join; - -// using FilteredFullV0s = soa::Filtered; /// predefined Join -// table for o2::aod::V0s = soa::Join -// to be used when we add v0Filter + soa::Join; } // namespace o2::aod -/// \todo fix how to pass array to setSelection, getRow() passing a different -/// type! -// static constexpr float arrayV0Sel[3][3] = {{100.f, 100.f, 100.f}, {0.2f, -// 0.2f, 0.2f}, {100.f, 100.f, 100.f}}; unsigned int rows = sizeof(arrayV0Sel) / -// sizeof(arrayV0Sel[0]); unsigned int columns = sizeof(arrayV0Sel[0]) / -// sizeof(arrayV0Sel[0][0]); - template int getRowDaughters(int daughID, T const& vecID) { @@ -88,42 +76,26 @@ struct femtoDreamProducerTask { Produces outputPartsMCLabels; Produces outputDebugPartsMC; - Configurable ConfDebugOutput{"ConfDebugOutput", true, "Debug output"}; - - // Choose if filtering or skimming version is run - - Configurable ConfIsTrigger{"ConfIsTrigger", false, - "Store all collisions"}; - - // Choose if running on converted data or Run3 / Pilot - Configurable ConfIsRun3{"ConfIsRun3", false, - "Running on Run3 or pilot"}; - Configurable ConfIsMC{"ConfIsMC", false, - "Running on MC; implemented only for Run3"}; - - Configurable ConfForceGRP{"ConfForceGRP", 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)"}; + Configurable ConfIsDebug{"ConfIsDebug", true, "Enable Debug tables"}; + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; + 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; - Configurable ConfUseTPCmult{"ConfUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; + Configurable ConfEvtUseTPCmult{"ConfEvtUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; 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 ConfStoreV0{"ConfStoreV0", true, "True: store V0 table"}; - // just sanity check to make sure in case there are problems in conversion or - // MC production it does not affect results - Configurable ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; - // Configurable ConfRejectITSHitandTOFMissing{ - // "ConfRejectITSHitandTOFMissing", false, - // "True: reject if neither ITS hit nor TOF timing satisfied"}; - - Configurable ConfPDGCodeTrack{"ConfPDGCodeTrack", 2212, "PDG code of the selected track for Monte Carlo truth"}; + Configurable ConfIsActivateV0{"ConfIsActivateV0", true, "Activate filling of V0 into femtodream 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; 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.4f, 0.6f, 0.5f}, 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> 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: ")}; @@ -132,16 +104,13 @@ struct femtoDreamProducerTask { 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: ")}; /// \todo Reintegrate PID to the general selection container + 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 ConfPIDnSigmaOffsetTPC{"ConfPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; - Configurable ConfPIDnSigmaOffsetTOF{"ConfPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; - Configurable> ConfPIDTrkspecies{"ConfPIDTrkspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton, o2::track::PID::Deuteron}, "Trk sel: Particles species for PID"}; + Configurable ConfTrkPIDnSigmaOffsetTPC{"ConfTrkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; + 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"}; FemtoDreamV0Selection v0Cuts; - // TrackSelection *o2PhysicsTrackSelection; - /// \todo Labeled array (see Track-Track task) - 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: ")}; @@ -152,19 +121,18 @@ struct femtoDreamProducerTask { 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> ConfPIDChildspecies{"ConfPIDChildspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Child sel: Particles species for PID"}; - - Configurable ConfV0InvMassLowLimit{"ConfInvV0MassLowLimit", 1.05, "Lower limit of the V0 invariant mass"}; - Configurable ConfV0InvMassUpLimit{"ConfInvV0MassUpLimit", 1.30, "Upper limit of the V0 invariant mass"}; - - Configurable ConfV0RejectKaons{"ConfRejectKaons", false, "Switch to reject kaons"}; - Configurable ConfV0InvKaonMassLowLimit{"ConfInvKaonMassLowLimit", 0.48, "Lower limit of the V0 invariant mass for Kaon rejection"}; - Configurable ConfV0InvKaonMassUpLimit{"ConfInvKaonMassUpLimit", 0.515, "Upper limit of the V0 invariant mass for Kaon rejection"}; + Configurable> ConfChildPIDspecies{"ConfChildPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Child sel: Particles species for PID"}; /// \todo should we add filter on min value pT/eta of V0 and daughters? /*Filter v0Filter = (nabs(aod::v0data::x) < V0DecVtxMax.value) && @@ -174,6 +142,8 @@ struct femtoDreamProducerTask { // for now do not know why HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry TrackRegistry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry V0Registry{"V0", {}, OutputObjHandlingPolicy::AnalysisObject}; int mRunNumber; float mMagField; @@ -190,6 +160,10 @@ struct femtoDreamProducerTask { "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}}); + V0Registry.add("AnalysisQA/CutCounter", "; Bit; Counter", kTH1F, {{CutBits + 1, -0.5, CutBits + 0.5}}); + colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3); colCuts.init(&qaRegistry); @@ -206,15 +180,15 @@ struct femtoDreamProducerTask { trackCuts.setSelection(ConfTrkDCAxyMax, femtoDreamTrackSelection::kDCAxyMax, femtoDreamSelection::kAbsUpperLimit); trackCuts.setSelection(ConfTrkDCAzMax, femtoDreamTrackSelection::kDCAzMax, femtoDreamSelection::kAbsUpperLimit); trackCuts.setSelection(ConfTrkPIDnSigmaMax, femtoDreamTrackSelection::kPIDnSigmaMax, femtoDreamSelection::kAbsUpperLimit); - trackCuts.setPIDSpecies(ConfPIDTrkspecies); - trackCuts.setnSigmaPIDOffset(ConfPIDnSigmaOffsetTPC, ConfPIDnSigmaOffsetTOF); - trackCuts.init(&qaRegistry); + trackCuts.setPIDSpecies(ConfTrkPIDspecies); + trackCuts.setnSigmaPIDOffset(ConfTrkPIDnSigmaOffsetTPC, 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 (ConfStoreV0) { + if (ConfIsActivateV0) { v0Cuts.setSelection(ConfV0Sign, femtoDreamV0Selection::kV0Sign, femtoDreamSelection::kEqual); v0Cuts.setSelection(ConfV0PtMin, femtoDreamV0Selection::kV0pTMin, femtoDreamSelection::kLowerLimit); v0Cuts.setSelection(ConfV0PtMax, femtoDreamV0Selection::kV0pTMax, femtoDreamSelection::kUpperLimit); @@ -234,26 +208,21 @@ struct femtoDreamProducerTask { 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, ConfPIDChildspecies); - v0Cuts.setChildPIDSpecies(femtoDreamV0Selection::kNegTrack, ConfPIDChildspecies); - v0Cuts.init(&qaRegistry); + v0Cuts.setChildPIDSpecies(femtoDreamV0Selection::kPosTrack, ConfChildPIDspecies); + v0Cuts.setChildPIDSpecies(femtoDreamV0Selection::kNegTrack, ConfChildPIDspecies); + v0Cuts.init(&qaRegistry, &V0Registry); v0Cuts.setInvMassLimits(ConfV0InvMassLowLimit, ConfV0InvMassUpLimit); - v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kPosTrack, ConfRejectNotPropagatedTracks); - v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kNegTrack, ConfRejectNotPropagatedTracks); + v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kPosTrack, ConfTrkRejectNotPropagated); + v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kNegTrack, ConfTrkRejectNotPropagated); - v0Cuts.setnSigmaPIDOffsetTPC(ConfPIDnSigmaOffsetTPC); - v0Cuts.setChildnSigmaPIDOffset(femtoDreamV0Selection::kPosTrack, ConfPIDnSigmaOffsetTPC, ConfPIDnSigmaOffsetTOF); - v0Cuts.setChildnSigmaPIDOffset(femtoDreamV0Selection::kNegTrack, ConfPIDnSigmaOffsetTPC, ConfPIDnSigmaOffsetTOF); + v0Cuts.setnSigmaPIDOffsetTPC(ConfTrkPIDnSigmaOffsetTPC); + v0Cuts.setChildnSigmaPIDOffset(femtoDreamV0Selection::kPosTrack, ConfTrkPIDnSigmaOffsetTPC, ConfTrkPIDnSigmaOffsetTOF); + v0Cuts.setChildnSigmaPIDOffset(femtoDreamV0Selection::kNegTrack, ConfTrkPIDnSigmaOffsetTPC, ConfTrkPIDnSigmaOffsetTOF); if (ConfV0RejectKaons) { v0Cuts.setKaonInvMassLimits(ConfV0InvKaonMassLowLimit, ConfV0InvKaonMassUpLimit); } - // if (ConfRejectITSHitandTOFMissing) { - // o2PhysicsTrackSelection = new - // TrackSelection(getGlobalTrackSelection()); - // o2PhysicsTrackSelection->SetRequireHitsInITSLayers(1, {0, 1, 2, 3}); - // } } mRunNumber = 0; @@ -277,7 +246,7 @@ struct femtoDreamProducerTask { auto timestamp = bc.timestamp(); float output = -999; - if (ConfIsRun3 && !ConfForceGRP) { + if (ConfIsRun3 && !ConfIsForceGRP) { static o2::parameters::GRPMagField* grpo = nullptr; grpo = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); if (grpo == nullptr) { @@ -308,25 +277,38 @@ struct femtoDreamProducerTask { void fillDebugParticle(ParticleType const& particle) { if constexpr (isTrackOrV0) { - outputDebugParts(particle.sign(), (uint8_t)particle.tpcNClsFound(), + 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.tpcNSigmaStoreEl(), particle.tpcNSigmaStorePi(), - particle.tpcNSigmaStoreKa(), particle.tpcNSigmaStorePr(), - particle.tpcNSigmaStoreDe(), particle.tofNSigmaStoreEl(), - particle.tofNSigmaStorePi(), particle.tofNSigmaStoreKa(), - particle.tofNSigmaStorePr(), particle.tofNSigmaStoreDe(), + 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.tofNSigmaEl(), + particle.tofNSigmaPi(), + particle.tofNSigmaKa(), + particle.tofNSigmaPr(), + particle.tofNSigmaDe(), -999., -999., -999., -999., -999., -999.); } else { outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., - particle.dcaV0daughters(), particle.v0radius(), - particle.x(), particle.y(), particle.z(), - particle.mK0Short()); // QA for v0 + particle.dcaV0daughters(), + particle.v0radius(), + particle.x(), + particle.y(), + particle.z(), + particle.mK0Short()); } } @@ -340,7 +322,7 @@ struct femtoDreamProducerTask { int particleOrigin = 99; auto motherparticleMC = particleMC.template mothers_as().front(); - if (abs(pdgCode) == abs(ConfPDGCodeTrack.value)) { + if (abs(pdgCode) == abs(ConfTrkPDGCode.value)) { if (particleMC.isPhysicalPrimary()) { particleOrigin = aod::femtodreamMCparticle::ParticleOriginMCTruth::kPrimary; } else if (motherparticleMC.producedByGenerator()) { @@ -359,8 +341,7 @@ struct femtoDreamProducerTask { } } - template + template void fillCollisionsAndTracksAndV0(CollisionType const& col, TrackType const& tracks, V0Type const& fullV0s) { @@ -376,21 +357,24 @@ struct femtoDreamProducerTask { /// FemtoDreamRun2 is defined V0M/2 multNtr = col.multTracklets(); } - if (ConfUseTPCmult) { + if (ConfEvtUseTPCmult) { multNtr = col.multTPC(); } // check whether the basic event selection criteria are fulfilled - // if the basic selection is NOT fulfilled: - // in case of skimming run - don't store such collisions - // in case of trigger run - store such collisions but don't store any - // particle candidates for such collisions - if (!colCuts.isSelected(col)) { - if (ConfIsTrigger) { - outputCollision(vtxZ, mult, multNtr, spher, mMagField); - } + // 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; + } + } colCuts.fillQA(col); outputCollision(vtxZ, mult, multNtr, spher, mMagField); @@ -404,21 +388,21 @@ struct femtoDreamProducerTask { if (!trackCuts.isSelectedMinimal(track)) { continue; } - trackCuts.fillQA(track); + trackCuts.fillQA(track); // the bit-wise container of the systematic variations is obtained auto cutContainer = trackCuts.getCutContainer(track); // 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), + 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 (ConfDebugOutput) { + if (ConfIsDebug.value) { fillDebugParticle(track); } @@ -427,7 +411,7 @@ struct femtoDreamProducerTask { } } - if (ConfStoreV0) { + if (ConfIsActivateV0.value) { for (auto& v0 : fullV0s) { auto postrack = v0.template posTrack_as(); auto negtrack = v0.template negTrack_as(); @@ -503,7 +487,7 @@ struct femtoDreamProducerTask { indexChildID, v0.mLambda(), v0.mAntiLambda()); - if (ConfDebugOutput) { + if (ConfIsDebug) { fillDebugParticle(postrack); // QA for positive daughter fillDebugParticle(negtrack); // QA for negative daughter fillDebugParticle(v0); // QA for v0 @@ -529,13 +513,12 @@ struct femtoDreamProducerTask { PROCESS_SWITCH(femtoDreamProducerTask, processData, "Provide experimental data", true); - void - processMC(aod::FemtoFullCollisionMC const& col, - aod::BCsWithTimestamps const&, - soa::Join const& tracks, - aod::McCollisions const& mcCollisions, - aod::McParticles const& mcParticles, - soa::Join const& fullV0s) /// \todo with FilteredFullV0s + void processMC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::McCollisions const& mcCollisions, + aod::McParticles const& mcParticles, + soa::Join const& fullV0s) /// \todo with FilteredFullV0s { // get magnetic field for run getMagneticFieldTesla(col.bc_as()); diff --git a/PWGCF/FemtoDream/femtoDreamProducerTaskV0Only.cxx b/PWGCF/FemtoDream/femtoDreamProducerTaskV0Only.cxx index 4dfc1c862b7..be711d73065 100644 --- a/PWGCF/FemtoDream/femtoDreamProducerTaskV0Only.cxx +++ b/PWGCF/FemtoDream/femtoDreamProducerTaskV0Only.cxx @@ -81,12 +81,6 @@ struct femtoDreamProducerTaskV0Only { Produces outputDebugParts; Configurable ConfDebugOutput{"ConfDebugOutput", true, "Debug output"}; - - // Choose if filtering or skimming version is run - - Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; - - // Choose if running on converted data or Run3 / Pilot Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; Configurable ConfIsMC{"ConfIsMC", false, "Running on MC; implemented only for Run3"}; @@ -202,10 +196,8 @@ struct femtoDreamProducerTaskV0Only { // (aod::v0data::v0radius > V0TranRadV0Min.value); to be added, not working // for now do not know why - HistogramRegistry qaRegistry{ - "QAHistos", - {}, - OutputObjHandlingPolicy::QAObject}; + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry Registry{"Producer", {}, OutputObjHandlingPolicy::AnalysisObject}; int mRunNumber; float mMagField; @@ -276,7 +268,7 @@ struct femtoDreamProducerTaskV0Only { ConfV0DaughTPIDspecies); v0Cuts.init(&qaRegistry); + aod::femtodreamparticle::cutContainerType>(&qaRegistry, &Registry); v0Cuts.setInvMassLimits(ConfInvMassLowLimit, ConfInvMassUpLimit); v0Cuts.setChildRejectNotPropagatedTracks(femtoDreamV0Selection::kPosTrack, ConfRejectNotPropagatedTracks); @@ -374,16 +366,12 @@ struct femtoDreamProducerTaskV0Only { multNtr = col.multTPC(); } - /// First thing to do is to check whether the basic event selection criteria - /// are fulfilled - // If the basic selection is NOT fulfilled: - // in case of skimming run - don't store such collisions - // in case of trigger run - store such collisions but don't store any - // particle candidates for such collisions - if (!colCuts.isSelected(col)) { - if (ConfIsTrigger) { - outputCollision(vtxZ, mult, multNtr, spher, mMagField); - } + /// First thing to do is to check whether the basic event selection criteria are fullfilled + /// that includes checking if there is at least one usable V0 in the collision + if (!colCuts.isSelectedCollision(col)) { + return; + } + if (colCuts.isEmptyCollision(col, fullV0s, v0Cuts, tracks)) { return; } @@ -397,13 +385,9 @@ struct femtoDreamProducerTaskV0Only { // track table row <-> aod::track table global index if (ConfStoreV0) { - for (auto& v0 : fullV0s) { - auto postrack = v0.posTrack_as(); - auto negtrack = - v0.negTrack_as(); ///\tocheck funnily enough - /// if we apply the filter - /// the sign of Pos and Neg - /// track is always negative + for (auto const& v0 : fullV0s) { + const auto postrack = v0.posTrack_as(); + const auto negtrack = v0.negTrack_as(); // const auto dcaXYpos = postrack.dcaXY(); // const auto dcaZpos = postrack.dcaZ(); // const auto dcapos = std::sqrt(pow(dcaXYpos, 2.) + pow(dcaZpos, 2.)); diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h new file mode 100644 index 00000000000..0e888a0cb2e --- /dev/null +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h @@ -0,0 +1,246 @@ +// 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 FemtoUniverseAngularContainer.h +/// \brief Definition of the FemtoUniverseAngularContainer +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Valentina Mantovani Sarti, valentina.mantovani-sarti@tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEANGULARCONTAINER_H_ +#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEANGULARCONTAINER_H_ + +#include +#include +#include + +#include "Framework/HistogramRegistry.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" + +#include "Math/Vector4D.h" +#include "TMath.h" +#include "TDatabasePDG.h" + +using namespace o2::framework; + +namespace o2::analysis::femtoUniverse +{ + +namespace femtoUniverseAngularContainer +{ +/// Femtoscopic observable to be computed +enum Observable { kstar ///< kstar +}; + +/// Type of the event processind +enum EventType { same, ///< Pair from same event + mixed ///< Pair from mixed event +}; +}; // namespace femtoUniverseAngularContainer + +/// \class FemtoUniverseAngularContainer +/// \brief Container for all histogramming related to the correlation function. The two +/// particles of the pair are passed here, and the correlation function and QA histograms +/// are filled according to the specified observable +/// \tparam eventType Type of the event (same/mixed) +/// \tparam obs Observable to be computed (k*/Q_inv/...) +template +class FemtoUniverseAngularContainer +{ + public: + /// Destructor + virtual ~FemtoUniverseAngularContainer() = default; + + /// Initializes histograms for the task + /// Called by init both in case of reconstructed data/ Monte Carlo, and for Monte Carlo Truth + /// \tparam T type of the axis Object + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) + /// \param femtoObs Title of the femto observable axis + /// \param femtoObsAxis axis object for the femto observable axis + /// \param multAxis axis object for the multiplicity axis + /// \param kTAxis axis object for the kT axis + /// \param mTAxis axis object for the mT axis + template + void init_base(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis, T kTAxis, T mTAxis, T multAxis3D, T mTAxis3D, T etaAxis, T phiAxis, bool use3dplots) + { + mHistogramRegistry->add((folderName + "/DeltaEtaDeltaPhi").c_str(), "; #Delta#varphi (rad); #Delta#eta", kTH2F, {phiAxis, etaAxis}); + if (use3dplots) { + // use 3d plots + } + } + + /// Initializes specialized Monte Carlo truth histograms for the task + /// internal function called by init only in case of Monte Carlo truth + /// \tparam T type of the xxis Object + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) + /// \param femtoObsAxis axis object for the femto observable axis + template + void init_MC(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis, T mTAxis) + { + } + + /// Templated function to initialize the histograms for the task + /// Always calls init_base to initialize the histograms for data/ Monte Carlo reconstructed + /// In case of Monte Carlo, calls init_base again for Monte Carlo truth and the specialized function init_MC for additional histogramms + /// \tparam T type of the configurable for the axis configuration + /// \param registry Histogram registry to be passed + /// \param kstarBins k* binning for the histograms + /// \param multBins multiplicity binning for the histograms + /// \param kTBins kT binning for the histograms + /// \param mTBins mT binning for the histograms + /// \param etaBins eta binning for the histograms + /// \param phiBins phi binning for the histograms + /// \param isMC add Monte Carlo truth histograms to the output file + template + void init(HistogramRegistry* registry, T& kstarBins, T& multBins, T& kTBins, T& mTBins, T& multBins3D, T& mTBins3D, P& etaBins, P& phiBins, bool isMC, bool use3dplots) + { + mHistogramRegistry = registry; + std::string femtoObs; + if constexpr (mFemtoObs == femtoUniverseAngularContainer::Observable::kstar) { + femtoObs = "#it{k*} (GeV/#it{c})"; + } + + std::vector tmpVecMult = multBins; + framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; + framework::AxisSpec femtoObsAxis = {kstarBins, femtoObs.c_str()}; + framework::AxisSpec kTAxis = {kTBins, "#it{k}_{T} (GeV/#it{c})"}; + framework::AxisSpec mTAxis = {mTBins, "#it{m}_{T} (GeV/#it{c}^{2})"}; + + framework::AxisSpec multAxis3D = {multBins3D, "Multiplicity"}; + framework::AxisSpec mTAxis3D = {mTBins3D, "#it{m}_{T} (GeV/#it{c})"}; + + // angular correlations + mPhiLow = (-static_cast(phiBins / 4) + 0.5) * 2. * o2::constants::math::PI / phiBins; + mPhiHigh = 2 * o2::constants::math::PI + (-static_cast(phiBins / 4) + 0.5) * 2. * o2::constants::math::PI / phiBins; + framework::AxisSpec phiAxis = {phiBins, mPhiLow, mPhiHigh}; + framework::AxisSpec etaAxis = {etaBins, -2.0, 2.0}; + + std::string folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kRecon]); + + init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, etaAxis, phiAxis, use3dplots); + if (isMC) { + folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]); + init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, etaAxis, phiAxis, use3dplots); + init_MC(folderName, femtoObs, femtoObsAxis, multAxis, mTAxis); + } + } + + /// Set the PDG codes of the two particles involved + /// \param pdg1 PDG code of particle one + /// \param pdg2 PDG code of particle two + void setPDGCodes(const int pdg1, const int pdg2) + { + mMassOne = TDatabasePDG::Instance()->GetParticle(pdg1)->Mass(); + mMassTwo = TDatabasePDG::Instance()->GetParticle(pdg2)->Mass(); + mPDGOne = pdg1; + mPDGTwo = pdg2; + } + + /// Pass a pair to the container and compute all the relevant observables + /// Called by setPair both in case of data/ and Monte Carlo reconstructed and for Monte Carlo truth + /// \tparam T type of the femtouniverseparticle + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + template + void setPair_base(const float femtoObs, const float mT, T const& part1, T const& part2, const int mult, bool use3dplots) + { + delta_eta = part1.eta() - part2.eta(); + delta_phi = part1.phi() - part2.phi(); + + while (delta_phi < mPhiLow) { + delta_phi += o2::constants::math::TwoPI; + } + while (delta_phi > mPhiHigh) { + delta_phi -= o2::constants::math::TwoPI; + } + + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/DeltaEtaDeltaPhi"), delta_phi, delta_eta); + if (use3dplots) { + // use 3d plots + } + } + + /// Called by setPair only in case of Monte Carlo truth + /// Fills MC truth specific histogramms: + /// - kstar distribution plots with RECONSTRUCTED information but ONLY for non-fake candidates; needed for purity calculations of tracks + /// - kstar resolution matrix + /// Note: Standard histogramms with MC truth information are filled with the setPair_base function + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + void setPair_MC(const float femtoObsMC, const float femtoObs, const float mT, const int mult) + { + if (mHistogramRegistry) { + // Fill the kstar distributions with the reconstructed information but only for particles with the right PDG code + } + } + + /// Templated function to handle data/ Monte Carlo reconstructed and Monte Carlo truth + /// Always calls setPair_base to compute the observables with reconstructed data + /// In case of Monte Carlo, calls setPair_base with MC info and specialized function setPair_MC for additional histogramms + /// \tparam T type of the femtouniverseparticle + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + template + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots) + { + float femtoObs, femtoObsMC; + // Calculate femto observable and the mT with reconstructed information + if constexpr (mFemtoObs == femtoUniverseAngularContainer::Observable::kstar) { + femtoObs = FemtoUniverseMath::getkstar(part1, mMassOne, part2, mMassTwo); + } + const float mT = FemtoUniverseMath::getmT(part1, mMassOne, part2, mMassTwo); + + if (mHistogramRegistry) { + setPair_base(femtoObs, mT, part1, part2, mult, use3dplots); + + if constexpr (isMC) { + if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { + // calculate the femto observable and the mT with MC truth information + if constexpr (mFemtoObs == femtoUniverseAngularContainer::Observable::kstar) { + femtoObsMC = FemtoUniverseMath::getkstar(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + } + const float mTMC = FemtoUniverseMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + + if (abs(part1.fdMCParticle().pdgMCTruth()) == abs(mPDGOne) && abs(part2.fdMCParticle().pdgMCTruth()) == abs(mPDGTwo)) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots); + setPair_MC(femtoObsMC, femtoObs, mT, mult); + } else { + } + + } else { + } + } + } + } + + protected: + HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output + static constexpr std::string_view mFolderSuffix[2] = {"SameEvent", "MixedEvent"}; ///< Folder naming for the output according to mEventType + static constexpr femtoUniverseAngularContainer::Observable mFemtoObs = obs; ///< Femtoscopic observable to be computed (according to femtoUniverseAngularContainer::Observable) + static constexpr int mEventType = eventType; ///< Type of the event (same/mixed, according to femtoUniverseAngularContainer::EventType) + float mMassOne = 0.f; ///< PDG mass of particle 1 + float mMassTwo = 0.f; ///< PDG mass of particle 2 + int mPDGOne = 0; ///< PDG code of particle 1 + int mPDGTwo = 0; ///< PDG code of particle 2 + double mPhiLow; + double mPhiHigh; + double delta_eta; + double delta_phi; +}; + +} // namespace o2::analysis::femtoUniverse + +#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEANGULARCONTAINER_H_ diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h index 93f23d8368d..5aa132eb963 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -12,14 +12,13 @@ /// \file FemtoUniverseCollisionSelection.h /// \brief FemtoUniverseCollisionSelection - event selection within the o2femtouniverse framework /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECOLLISIONSELECTION_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECOLLISIONSELECTION_H_ #include #include - #include "Common/CCDB/TriggerAliases.h" #include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" @@ -61,14 +60,21 @@ class FemtoUniverseCollisionSelection } mHistogramRegistry = registry; mHistogramRegistry->add("Event/zvtxhist", "; vtx_{z} (cm); Entries", kTH1F, {{300, -12.5, 12.5}}); - mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{600, 0, 600}}); - mHistogramRegistry->add("Event/MultT0M", "; vMultT0M; Entries", kTH1F, {{600, 0, 600}}); + mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{16384, 0, 32768}}); + mHistogramRegistry->add("Event/MultT0M", "; vMultT0M; Entries", kTH1F, {{4096, 0, 8192}}); + mHistogramRegistry->add("Event/MultNTracksPV", "; vMultNTracksPV; Entries", kTH1F, {{120, 0, 120}}); + mHistogramRegistry->add("Event/MultNTracklets", "; vMultNTrackslets; Entries", kTH1F, {{300, 0, 300}}); + mHistogramRegistry->add("Event/MultTPC", "; vMultTPC; Entries", kTH1I, {{600, 0, 600}}); } /// Print some debug information void printCuts() { - LOGF(info, "Debug information for FemtoUniverseCollisionSelection \n Max. z-vertex: %f \n Check trigger: %B \n Trigger: %i \n Check offline: %B ", mZvtxMax, mCheckTrigger, mTrigger, mCheckOffline); + LOG(info) << "Debug information for FemtoUniverseCollisionSelection"; + LOG(info) << "Max. z-vertex: " << mZvtxMax; + LOG(info) << "Check trigger: " << mCheckTrigger; + LOG(info) << "Trigger: " << mTrigger; + LOG(info) << " Check offline: " << mCheckOffline; } /// Check whether the collisions fulfills the specified selections @@ -104,8 +110,15 @@ class FemtoUniverseCollisionSelection { if (mHistogramRegistry) { mHistogramRegistry->fill(HIST("Event/zvtxhist"), col.posZ()); - mHistogramRegistry->fill(HIST("Event/MultV0M"), col.multFV0M()); mHistogramRegistry->fill(HIST("Event/MultT0M"), col.multFT0M()); + mHistogramRegistry->fill(HIST("Event/MultNTracksPV"), col.multNTracksPV()); + mHistogramRegistry->fill(HIST("Event/MultNTracklets"), col.multTracklets()); + mHistogramRegistry->fill(HIST("Event/MultTPC"), col.multTPC()); + if (mCheckIsRun3) { + mHistogramRegistry->fill(HIST("Event/MultV0M"), col.multFV0M()); + } else { + mHistogramRegistry->fill(HIST("Event/MultV0M"), 0.5 * (col.multFV0M())); // in AliPhysics, the VOM was defined by (V0A + V0C)/2. + } } } diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h index 3e5ac65b000..c54bd819589 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -13,11 +13,14 @@ /// \brief Definition of the FemtoUniverseContainer /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de /// \author Valentina Mantovani Sarti, valentina.mantovani-sarti@tum.de -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch NOWE +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECONTAINER_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECONTAINER_H_ +#include #include #include @@ -28,11 +31,7 @@ #include "TMath.h" #include "TDatabasePDG.h" -#include "TLorentzVector.h" -#include "CommonConstants/MathConstants.h" - using namespace o2::framework; -using namespace o2::constants::math; namespace o2::analysis::femtoUniverse { @@ -63,7 +62,53 @@ class FemtoUniverseContainer virtual ~FemtoUniverseContainer() = default; /// Initializes histograms for the task - /// \tparam T Type of the configurable for the axis configuration + /// Called by init both in case of reconstructed data/ Monte Carlo, and for Monte Carlo Truth + /// \tparam T type of the axis Object + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) + /// \param femtoObs Title of the femto observable axis + /// \param femtoObsAxis axis object for the femto observable axis + /// \param multAxis axis object for the multiplicity axis + /// \param kTAxis axis object for the kT axis + /// \param mTAxis axis object for the mT axis + template + void init_base(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis, T kTAxis, T mTAxis, T multAxis3D, T mTAxis3D, T etaAxis, T phiAxis, bool use3dplots) + { + mHistogramRegistry->add((folderName + "/relPairDist").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); + mHistogramRegistry->add((folderName + "/relPairkT").c_str(), "; #it{k}_{T} (GeV/#it{c}); Entries", kTH1F, {kTAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarkT").c_str(), ("; " + femtoObs + "; #it{k}_{T} (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, kTAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarmT").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2})").c_str(), kTH2F, {femtoObsAxis, mTAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarMult").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); + mHistogramRegistry->add((folderName + "/kstarPtPart1").c_str(), ("; " + femtoObs + "; #it{p} _{T} Particle 1 (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, {375, 0., 7.5}}); + mHistogramRegistry->add((folderName + "/kstarPtPart2").c_str(), ("; " + femtoObs + "; #it{p} _{T} Particle 2 (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, {375, 0., 7.5}}); + mHistogramRegistry->add((folderName + "/MultPtPart1").c_str(), "; #it{p} _{T} Particle 1 (GeV/#it{c}); Multiplicity", kTH2F, {{375, 0., 7.5}, multAxis}); + mHistogramRegistry->add((folderName + "/MultPtPart2").c_str(), "; #it{p} _{T} Particle 2 (GeV/#it{c}); Multiplicity", kTH2F, {{375, 0., 7.5}, multAxis}); + mHistogramRegistry->add((folderName + "/PtPart1PtPart2").c_str(), "; #it{p} _{T} Particle 1 (GeV/#it{c}); #it{p} _{T} Particle 2 (GeV/#it{c})", kTH2F, {{375, 0., 7.5}, {375, 0., 7.5}}); + mHistogramRegistry->add((folderName + "/DeltaEtaDeltaPhi").c_str(), "; #Delta#varphi (rad); #Delta#eta", kTH2F, {phiAxis, etaAxis}); + if (use3dplots) { + mHistogramRegistry->add((folderName + "/relPairkstarmTMult").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2}); Multiplicity").c_str(), kTH3F, {femtoObsAxis, mTAxis3D, multAxis3D}); + } + } + + /// Initializes specialized Monte Carlo truth histograms for the task + /// internal function called by init only in case of Monte Carlo truth + /// \tparam T type of the xxis Object + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) + /// \param femtoObsAxis axis object for the femto observable axis + template + void init_MC(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis, T mTAxis) + { + mHistogramRegistry->add((folderName + "/relPairDist_ReconNoFake").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarmT_ReconNoFake").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2})").c_str(), kTH2F, {femtoObsAxis, mTAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarMult_ReconNoFake").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); + mHistogramRegistry->add((folderName + "/hNoMCtruthPairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + mHistogramRegistry->add((folderName + "/hFakePairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + mHistogramRegistry->add((folderName + "/kstar_resolution").c_str(), "; #it{k} _{T} reconstructed (GeV/#it{c}); #it{k} _{T} truth (GeV/#it{c})", kTH2F, {femtoObsAxis, femtoObsAxis}); + } + + /// Templated function to initialize the histograms for the task + /// Always calls init_base to initialize the histograms for data/ Monte Carlo reconstructed + /// In case of Monte Carlo, calls init_base again for Monte Carlo truth and the specialized function init_MC for additional histogramms + /// \tparam T type of the configurable for the axis configuration /// \param registry Histogram registry to be passed /// \param kstarBins k* binning for the histograms /// \param multBins multiplicity binning for the histograms @@ -71,10 +116,9 @@ class FemtoUniverseContainer /// \param mTBins mT binning for the histograms /// \param etaBins eta binning for the histograms /// \param phiBins phi binning for the histograms - /// \param mInvBins invariant mass binning for the histograms - - template - void init(HistogramRegistry* registry, T1& kstarBins, T1& multBins, T1& kTBins, T1& mTBins, T2& phiBins, T2& etaBins, T2& mInvBins) + /// \param isMC add Monte Carlo truth histograms to the output file + template + void init(HistogramRegistry* registry, T& kstarBins, T& multBins, T& kTBins, T& mTBins, T& multBins3D, T& mTBins3D, P& etaBins, P& phiBins, bool isMC, bool use3dplots) { mHistogramRegistry = registry; std::string femtoObs; @@ -87,26 +131,23 @@ class FemtoUniverseContainer framework::AxisSpec kTAxis = {kTBins, "#it{k}_{T} (GeV/#it{c})"}; framework::AxisSpec mTAxis = {mTBins, "#it{m}_{T} (GeV/#it{c}^{2})"}; - mPhiLow = (-(static_cast)(phiBins / 4) + 0.5) * 2. * PI / phiBins; - mPhiHigh = 2 * PI + (-(static_cast)(phiBins / 4) + 0.5) * 2. * PI / phiBins; + framework::AxisSpec multAxis3D = {multBins3D, "Multiplicity"}; + framework::AxisSpec mTAxis3D = {mTBins3D, "#it{m}_{T} (GeV/#it{c})"}; + // angular correlations + mPhiLow = (-static_cast(phiBins / 4) + 0.5) * 2. * o2::constants::math::PI / phiBins; + mPhiHigh = 2 * o2::constants::math::PI + (-static_cast(phiBins / 4) + 0.5) * 2. * o2::constants::math::PI / phiBins; framework::AxisSpec phiAxis = {phiBins, mPhiLow, mPhiHigh}; framework::AxisSpec etaAxis = {etaBins, -2.0, 2.0}; - framework::AxisSpec mInvAxis = {mInvBins, 0.0, 10.0}; - - std::string folderName = static_cast(mFolderSuffix[mEventType]); - mHistogramRegistry->add((folderName + "relPairDist").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); - mHistogramRegistry->add((folderName + "relPairkT").c_str(), "; #it{k}_{T} (GeV/#it{c}); Entries", kTH1F, {kTAxis}); - mHistogramRegistry->add((folderName + "relPairkstarkT").c_str(), ("; " + femtoObs + "; #it{k}_{T} (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, kTAxis}); - mHistogramRegistry->add((folderName + "relPairkstarmT").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2})").c_str(), kTH2F, {femtoObsAxis, mTAxis}); - mHistogramRegistry->add((folderName + "relPairkstarMult").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); - mHistogramRegistry->add((folderName + "kstarPtPart1").c_str(), ("; " + femtoObs + "; #it{p} _{T} Particle 1 (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, {375, 0., 7.5}}); - mHistogramRegistry->add((folderName + "kstarPtPart2").c_str(), ("; " + femtoObs + "; #it{p} _{T} Particle 2 (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, {375, 0., 7.5}}); - mHistogramRegistry->add((folderName + "MultPtPart1").c_str(), "; #it{p} _{T} Particle 1 (GeV/#it{c}); Multiplicity", kTH2F, {{375, 0., 7.5}, multAxis}); - mHistogramRegistry->add((folderName + "MultPtPart2").c_str(), "; #it{p} _{T} Particle 2 (GeV/#it{c}); Multiplicity", kTH2F, {{375, 0., 7.5}, multAxis}); - mHistogramRegistry->add((folderName + "PtPart1PtPart2").c_str(), "; #it{p} _{T} Particle 1 (GeV/#it{c}); #it{p} _{T} Particle 2 (GeV/#it{c})", kTH2F, {{375, 0., 7.5}, {375, 0., 7.5}}); - mHistogramRegistry->add((folderName + "relPairDetaDphi").c_str(), "; #Delta#varphi (rad); #Delta#eta", kTH2D, {phiAxis, etaAxis}); - mHistogramRegistry->add((folderName + "relPairInvariantMass").c_str(), ";M_{K^{+}K^{-}} (GeV/#it{c}^{2});", kTH1D, {mInvAxis}); + + std::string folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kRecon]); + + init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, etaAxis, phiAxis, use3dplots); + if (isMC) { + folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]); + init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, etaAxis, phiAxis, use3dplots); + init_MC(folderName, femtoObs, femtoObsAxis, multAxis, mTAxis); + } } /// Set the PDG codes of the two particles involved @@ -116,65 +157,121 @@ class FemtoUniverseContainer { mMassOne = TDatabasePDG::Instance()->GetParticle(pdg1)->Mass(); mMassTwo = TDatabasePDG::Instance()->GetParticle(pdg2)->Mass(); + mPDGOne = pdg1; + mPDGTwo = pdg2; } /// Pass a pair to the container and compute all the relevant observables + /// Called by setPair both in case of data/ and Monte Carlo reconstructed and for Monte Carlo truth /// \tparam T type of the femtouniverseparticle /// \param part1 Particle one /// \param part2 Particle two /// \param mult Multiplicity of the event - template - void setPair(T const& part1, T const& part2, const int mult) + template + void setPair_base(const float femtoObs, const float mT, T const& part1, T const& part2, const int mult, bool use3dplots) { - float femtoObs; - if constexpr (mFemtoObs == femtoUniverseContainer::Observable::kstar) { - femtoObs = FemtoUniverseMath::getkstar(part1, mMassOne, part2, mMassTwo); - } const float kT = FemtoUniverseMath::getkT(part1, mMassOne, part2, mMassTwo); - const float mT = FemtoUniverseMath::getmT(part1, mMassOne, part2, mMassTwo); - - double delta_eta = part1.eta() - part2.eta(); - double delta_phi = part1.phi() - part2.phi(); + delta_eta = part1.eta() - part2.eta(); + delta_phi = part1.phi() - part2.phi(); while (delta_phi < mPhiLow) { - delta_phi += TwoPI; + delta_phi += o2::constants::math::TwoPI; } while (delta_phi > mPhiHigh) { - delta_phi -= TwoPI; + delta_phi -= o2::constants::math::TwoPI; + } + + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairDist"), femtoObs); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkT"), kT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarkT"), femtoObs, kT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmT"), femtoObs, mT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarMult"), femtoObs, mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/kstarPtPart1"), femtoObs, part1.pt()); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/kstarPtPart2"), femtoObs, part2.pt()); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/MultPtPart1"), part1.pt(), mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/MultPtPart2"), part2.pt(), mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/PtPart1PtPart2"), part1.pt(), part2.pt()); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/DeltaEtaDeltaPhi"), delta_phi, delta_eta); + if (use3dplots) { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmTMult"), femtoObs, mT, mult); } - TLorentzVector part1Vec; - part1Vec.SetPtEtaPhiM(part1.pt(), part1.eta(), part1.phi(), mMassOne); - TLorentzVector part2Vec; - part2Vec.SetPtEtaPhiM(part2.pt(), part2.eta(), part2.phi(), mMassTwo); + } - TLorentzVector sumVec(part1Vec); - sumVec += part2Vec; + /// Called by setPair only in case of Monte Carlo truth + /// Fills MC truth specific histogramms: + /// - kstar distribution plots with RECONSTRUCTED information but ONLY for non-fake candidates; needed for purity calculations of tracks + /// - kstar resolution matrix + /// Note: Standard histogramms with MC truth information are filled with the setPair_base function + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + void setPair_MC(const float femtoObsMC, const float femtoObs, const float mT, const int mult) + { + if (mHistogramRegistry) { + // Fill the kstar distributions with the reconstructed information but only for particles with the right PDG code + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/relPairDist_ReconNoFake"), femtoObs); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/relPairkstarmT_ReconNoFake"), femtoObs, mT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/relPairkstarMult_ReconNoFake"), femtoObs, mult); + + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/kstar_resolution"), femtoObsMC, femtoObs); + } + } + + /// Templated function to handle data/ Monte Carlo reconstructed and Monte Carlo truth + /// Always calls setPair_base to compute the observables with reconstructed data + /// In case of Monte Carlo, calls setPair_base with MC info and specialized function setPair_MC for additional histogramms + /// \tparam T type of the femtouniverseparticle + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + template + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots) + { + float femtoObs, femtoObsMC; + // Calculate femto observable and the mT with reconstructed information + if constexpr (mFemtoObs == femtoUniverseContainer::Observable::kstar) { + femtoObs = FemtoUniverseMath::getkstar(part1, mMassOne, part2, mMassTwo); + } + const float mT = FemtoUniverseMath::getmT(part1, mMassOne, part2, mMassTwo); if (mHistogramRegistry) { - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairDist"), femtoObs); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairkT"), kT); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairkstarkT"), femtoObs, kT); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairkstarmT"), femtoObs, mT); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairkstarMult"), femtoObs, mult); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("kstarPtPart1"), femtoObs, part1.pt()); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("kstarPtPart2"), femtoObs, part2.pt()); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("MultPtPart1"), part1.pt(), mult); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("MultPtPart2"), part2.pt(), mult); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("PtPart1PtPart2"), part1.pt(), part2.pt()); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairDetaDphi"), delta_phi, delta_eta); - mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST("relPairInvariantMass"), sumVec.M()); + setPair_base(femtoObs, mT, part1, part2, mult, use3dplots); + + if constexpr (isMC) { + if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { + // calculate the femto observable and the mT with MC truth information + if constexpr (mFemtoObs == femtoUniverseContainer::Observable::kstar) { + femtoObsMC = FemtoUniverseMath::getkstar(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + } + const float mTMC = FemtoUniverseMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + + if (abs(part1.fdMCParticle().pdgMCTruth()) == abs(mPDGOne) && abs(part2.fdMCParticle().pdgMCTruth()) == abs(mPDGTwo)) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots); + setPair_MC(femtoObsMC, femtoObs, mT, mult); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); + } + + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/hNoMCtruthPairsCounter"), 0); + } + } } } protected: - HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output - static constexpr std::string_view mFolderSuffix[2] = {"SameEvent/", "MixedEvent/"}; ///< Folder naming for the output according to mEventType - static constexpr femtoUniverseContainer::Observable mFemtoObs = obs; ///< Femtoscopic observable to be computed (according to femtoUniverseContainer::Observable) - static constexpr int mEventType = eventType; ///< Type of the event (same/mixed, according to femtoUniverseContainer::EventType) - float mMassOne = 0.f; ///< PDG mass of particle 1 - float mMassTwo = 0.f; ///< PDG mass of particle 2 + HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output + static constexpr std::string_view mFolderSuffix[2] = {"SameEvent", "MixedEvent"}; ///< Folder naming for the output according to mEventType + static constexpr femtoUniverseContainer::Observable mFemtoObs = obs; ///< Femtoscopic observable to be computed (according to femtoUniverseContainer::Observable) + static constexpr int mEventType = eventType; ///< Type of the event (same/mixed, according to femtoUniverseContainer::EventType) + float mMassOne = 0.f; ///< PDG mass of particle 1 + float mMassTwo = 0.f; ///< PDG mass of particle 2 + int mPDGOne = 0; ///< PDG code of particle 1 + int mPDGTwo = 0; ///< PDG code of particle 2 double mPhiLow; double mPhiHigh; + double delta_eta; + double delta_phi; }; } // namespace o2::analysis::femtoUniverse diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseCutculator.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseCutculator.h new file mode 100644 index 00000000000..b22697f4d02 --- /dev/null +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseCutculator.h @@ -0,0 +1,362 @@ +// 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 FemtoUniverseCutculator.h +/// \brief FemtoUniverseCutculator - small class to match bit-wise encoding and actual physics cuts +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECUTCULATOR_H_ +#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECUTCULATOR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h" + +namespace o2::analysis::femtoUniverse +{ + +/// \class FemtoUniverseCutculator +/// \brief Small class to match bit-wise encoding and actual physics cuts +class FemtoUniverseCutculator +{ + public: + /// Initializes boost ptree + /// \param configFile Path to the dpl-config.json file from the + /// femtouniverse-producer task + void init(const char* configFile) + { + std::cout << "Welcome to the CutCulator!" << std::endl; + + boost::property_tree::ptree root; + try { + boost::property_tree::read_json(configFile, root); + } catch (const boost::property_tree::ptree_error& e) { + std::cout + << "Failed to read JSON config file " << configFile << " (" + << e.what() << ")" << std::endl; + } + + // check the config file for all known producer task + std::vector ProducerTasks = { + "femto-universe-producer-task"}; + for (auto& Producer : ProducerTasks) { + if (root.count(Producer) > 0) { + mConfigTree = root.get_child(Producer); + std::cout << "Found " << Producer << " in " << configFile << std::endl; + break; + } + } + }; + + /// Generic function that retrieves a given selection from the boost ptree and + /// returns an std::vector in the proper format \param name Name of the + /// selection in the dpl-config.json \return std::vector that can be directly + /// passed to the FemtoUniverseTrack/V0/../Selection + std::vector setSelection(std::string name) + { + try { + boost::property_tree::ptree& selections = mConfigTree.get_child(name); + boost::property_tree::ptree& selectionsValues = + selections.get_child("values"); + std::vector tmpVec; + for (boost::property_tree::ptree::value_type& val : selectionsValues) { + tmpVec.push_back(std::stof(val.second.data())); + } + return tmpVec; + } catch (const boost::property_tree::ptree_error& e) { + std::cout << "Selection " << name << " not available (" << e.what() << ")" + << std::endl; + return {}; + } + } + + /// Specialization of the setSelection function for tracks + + /// 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 setTrackSelection(femtoUniverseTrackSelection::TrackSel obs, + femtoUniverseSelection::SelectionType type, + const char* prefix) + { + auto tmpVec = + setSelection(FemtoUniverseTrackSelection::getSelectionName(obs, prefix)); + if (tmpVec.size() > 0) { + mTrackSel.setSelection(tmpVec, obs, type); + } + } + + /// Automatically retrieves track selections from the dpl-config.json + /// \param prefix Prefix which is added to the name of the Configurable + void setTrackSelectionFromFile(const char* prefix) + { + for (const auto& sel : mConfigTree) { + std::string sel_name = sel.first; + femtoUniverseTrackSelection::TrackSel obs; + if (sel_name.find(prefix) != std::string::npos) { + int index = FemtoUniverseTrackSelection::findSelectionIndex( + std::string_view(sel_name), prefix); + if (index >= 0) { + obs = femtoUniverseTrackSelection::TrackSel(index); + } else { + continue; + } + if (obs == femtoUniverseTrackSelection::TrackSel::kPIDnSigmaMax) + continue; // kPIDnSigmaMax is a special case + setTrackSelection(obs, FemtoUniverseTrackSelection::getSelectionType(obs), + prefix); + } + } + } + + /// Automatically retrieves track PID from the dpl-config.json + /// \param prefix Prefix which is added to the name of the Configurable + void setPIDSelectionFromFile(const char* prefix) + { + 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()))); + } + 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())); + } + } catch (const boost::property_tree::ptree_error& e) { + std::cout << "PID selection not avalible for these skimmed data." + << std::endl; + } + } + + /// Specialization of the setSelection function for V0 + + /// 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 setV0Selection(femtoUniverseV0Selection::V0Sel obs, + femtoUniverseSelection::SelectionType type, + const char* prefix) + { + auto tmpVec = + setSelection(FemtoUniverseV0Selection::getSelectionName(obs, prefix)); + if (tmpVec.size() > 0) { + mV0Sel.setSelection(tmpVec, obs, type); + } + } + + /// Automatically retrieves V0 selections from the dpl-config.json + /// \param prefix Prefix which is added to the name of the Configurable + void setV0SelectionFromFile(const char* prefix) + { + for (const auto& sel : mConfigTree) { + std::string sel_name = sel.first; + femtoUniverseV0Selection::V0Sel obs; + if (sel_name.find(prefix) != std::string::npos) { + int index = FemtoUniverseV0Selection::findSelectionIndex( + std::string_view(sel_name), prefix); + if (index >= 0) { + obs = femtoUniverseV0Selection::V0Sel(index); + } else { + continue; + } + setV0Selection(obs, FemtoUniverseV0Selection::getSelectionType(obs), + prefix); + } + } + } + + /// This function investigates a given selection criterion. The available + /// options are displayed in the terminal and the bit-wise container is put + /// together according to the user input \tparam T1 Selection class under + /// investigation \param T2 Selection type under investigation \param output + /// Bit-wise container for the systematic variations \param counter Current + /// position in the bit-wise container to modify \tparam objectSelection + /// Selection class under investigation (FemtoUniverseTrack/V0/../Selection) + /// \param selectionType Selection type under investigation, as defined in the + /// selection class + template + void checkForSelection(aod::femtouniverseparticle::cutContainerType& output, + size_t& counter, T1 objectSelection, T2 selectionType, + bool SysChecks, float sign) + { + /// Output of the available selections and user input + std::cout << "Selection: " + << objectSelection.getSelectionHelper(selectionType) << " - ("; + auto selVec = objectSelection.getSelections(selectionType); + for (auto selIt : selVec) { + std::cout << selIt.getSelectionValue() << " "; + } + std::cout << ")" << std::endl + << " > "; + std::string in; + std::vector out; + float input; + + if (SysChecks) { + if (objectSelection.getSelectionHelper(selectionType) == std::string("Sign of the track")) { + input = sign; + std::cout << sign << std::endl; + } else { + // Seed the random number generator + std::random_device rd; + std::mt19937 rng(rd()); + // Select a random element + std::uniform_int_distribution uni(0, selVec.size() - 1); + int randomIndex = uni(rng); + input = selVec[randomIndex].getSelectionValue(); + std::cout << input << std::endl; + } + } else { + if (selVec.size() == 1) { + input = selVec[0].getSelectionValue(); + std::cout << input << std::endl; + } else { + std::cin >> in; + input = std::stof(in); + } + } + + /// First we check whether the input is actually contained within the + /// options + bool inputSane = false; + for (auto sel : selVec) { + if (std::abs(sel.getSelectionValue() - input) <= + std::abs(1.e-6 * input)) { + inputSane = true; + } + } + + /// If the input is sane, the selection bit is put together + if (inputSane) { + int internal_index = 0; + for (auto sel : selVec) { + double signOffset; + switch (sel.getSelectionType()) { + case femtoUniverseSelection::SelectionType::kEqual: + signOffset = 0.; + break; + case (femtoUniverseSelection::SelectionType::kLowerLimit): + case (femtoUniverseSelection::SelectionType::kAbsLowerLimit): + signOffset = 1.; + break; + case (femtoUniverseSelection::SelectionType::kUpperLimit): + case (femtoUniverseSelection::SelectionType::kAbsUpperLimit): + signOffset = -1.; + break; + } + + /// for upper and lower limit we have to subtract/add an epsilon so that + /// the cut is actually fulfilled + if (sel.isSelected(input + signOffset * 1.e-6 * input)) { + output |= 1UL << counter; + for (int i = internal_index; i > 0; i--) { + output &= ~(1UL << (counter - i)); + } + } + ++counter; + ++internal_index; + } + } else { + std::cout << "Choice " << in << " not recognized - repeating" + << std::endl; + checkForSelection(output, counter, objectSelection, selectionType, SysChecks, sign); + } + } + + /// This function iterates over all selection types of a given class and puts + /// together the bit-wise container \tparam T1 Selection class under + /// investigation \tparam objectSelection Selection class under investigation + /// (FemtoUniverseTrack/V0/../Selection) \return the full selection bit-wise + /// container that will be put to the user task incorporating the user choice + /// of selections + template + aod::femtouniverseparticle::cutContainerType iterateSelection(T objectSelection, + bool SysChecks, float sign) + { + aod::femtouniverseparticle::cutContainerType output = 0; + size_t counter = 0; + auto selectionVariables = objectSelection.getSelectionVariables(); + for (auto selVarIt : selectionVariables) { + checkForSelection(output, counter, objectSelection, selVarIt, SysChecks, sign); + } + return output; + } + + /// This is the function called by the executable that then outputs the full + /// selection bit-wise container incorporating the user choice of selections + void analyseCuts(std::string choice, bool SysChecks = false, float sign = 1) + { + aod::femtouniverseparticle::cutContainerType output = -1; + if (choice == std::string("T")) { + output = iterateSelection(mTrackSel, SysChecks, sign); + } else if (choice == std::string("V")) { + output = iterateSelection(mV0Sel, SysChecks, sign); + } else { + std::cout << "Option " << choice + << " not recognized - available options are (T/V)" << std::endl; + return; + } + std::bitset<8 * sizeof(aod::femtouniverseparticle::cutContainerType)> + bitOutput = output; + std::cout << "+++++++++++++++++++++++++++++++++" << std::endl; + std::cout << "CutCulator has spoken - your selection bit is" << std::endl; + std::cout << bitOutput << " (bitwise)" << std::endl; + std::cout << output << " (number representation)" << std::endl; + std::cout << "PID for these species is stored:" << std::endl; + int index = 0; + for (auto id : mPIDspecies) { + std::cout << o2::track::PID::getName(id) << " : " << index++ << std::endl; + if (SysChecks) { + // Seed the random number generator + std::random_device rd; + std::mt19937 rng(rd()); + // Select a random element + std::uniform_int_distribution uni(0, mPIDValues.size() - 1); + int randomIndex = uni(rng); + std::cout << "Nsigma: " << mPIDValues[randomIndex] << std::endl; + } + } + } + + private: + boost::property_tree::ptree + mConfigTree; ///< the dpl-config.json buffered into a ptree + FemtoUniverseTrackSelection + mTrackSel; ///< for setting up the bit-wise selection container for tracks + FemtoUniverseV0Selection + mV0Sel; ///< for setting up the bit-wise selection container for V0s + std::vector + mPIDspecies; ///< list of particle species for which PID is stored + std::vector + mPIDValues; ///< list of nsigma values for which PID is stored +}; +} // namespace o2::analysis::femtoUniverse + +#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECUTCULATOR_H_ */ diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h index 5d231f61470..3438b1726ad 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -12,18 +12,20 @@ /// \file FemtoUniverseDetaDphiStar.h /// \brief FemtoUniverseDetaDphiStar - Checks particles for the close pair rejection. /// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEDETADPHISTAR_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEDETADPHISTAR_H_ +#include #include #include -#include - -#include "PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" #include "Framework/HistogramRegistry.h" +using namespace o2; +using namespace o2::framework; + namespace o2::analysis { namespace femtoUniverse @@ -71,6 +73,16 @@ class FemtoUniverseDetaDphiStar } } if constexpr (mPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kPhi) { + for (int i = 0; i < 2; i++) { + std::string dirName = static_cast(dirNames[2]); + histdetadpi[i][0] = mHistogramRegistry->add((dirName + static_cast(histNames[0][i])).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])).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])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + } + } + } } } /// Check if pair is close or not @@ -120,7 +132,26 @@ class FemtoUniverseDetaDphiStar return pass; } else if constexpr (mPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kPhi) { /// Track-Phi combination - return true; + // check if provided particles are in agreement with the class instantiation + if (part1.partType() != o2::aod::femtouniverseparticle::ParticleType::kTrack || part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kPhi) { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar instantiation! Please provide kTrack,kPhi candidates."; + return false; + } + + bool pass = false; + for (int i = 0; i < 2; i++) { + auto indexOfDaughter = part2.index() - 2 + i; + auto daughter = particles.begin() + indexOfDaughter; + auto deta = part1.eta() - daughter.eta(); + auto dphiAvg = AveragePhiStar(part1, *daughter, i); + histdetadpi[i][0]->Fill(deta, dphiAvg); + if (pow(dphiAvg, 2) / pow(deltaPhiMax, 2) + pow(deta, 2) / pow(deltaEtaMax, 2) < 1.) { + pass = true; + } else { + histdetadpi[i][1]->Fill(deta, dphiAvg); + } + } + return pass; } else { LOG(fatal) << "FemtoUniversePairCleaner: Combination of objects not defined - quitting!"; return false; @@ -130,7 +161,7 @@ class FemtoUniverseDetaDphiStar private: HistogramRegistry* mHistogramRegistry = nullptr; ///< For main output HistogramRegistry* mHistogramRegistryQA = nullptr; ///< For QA output - static constexpr std::string_view dirNames[2] = {"kTrack_kTrack/", "kTrack_kV0/"}; + static constexpr std::string_view dirNames[3] = {"kTrack_kTrack/", "kTrack_kV0/", "kTrack_kPhi/"}; static constexpr std::string_view histNames[2][2] = {{"detadphidetadphi0Before_0", "detadphidetadphi0Before_1"}, {"detadphidetadphi0After_0", "detadphidetadphi0After_1"}}; @@ -191,7 +222,7 @@ class FemtoUniverseDetaDphiStar std::vector tmpVec2; PhiAtRadiiTPC(part1, tmpVec1); PhiAtRadiiTPC(part2, tmpVec2); - const int num = tmpVec1.size(); + int num = tmpVec1.size(); float dPhiAvg = 0; for (int i = 0; i < num; i++) { float dphi = tmpVec1.at(i) - tmpVec2.at(i); @@ -201,7 +232,7 @@ class FemtoUniverseDetaDphiStar histdetadpiRadii[iHist][i]->Fill(part1.eta() - part2.eta(), dphi); } } - return (dPhiAvg / (static_cast)num); + return dPhiAvg / num; } }; diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h index bfe972357f4..83d23b3b5cf 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -12,12 +12,12 @@ /// \file FemtoUniverseEventHisto.h /// \brief FemtoUniverseEventHisto - Histogram class for tracks, V0s and cascades /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEVENTHISTO_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEVENTHISTO_H_ -#include "PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" #include "Framework/HistogramRegistry.h" using namespace o2::framework; @@ -36,7 +36,8 @@ class FemtoUniverseEventHisto { mHistogramRegistry = registry; mHistogramRegistry->add("Event/zvtxhist", "; vtx_{z} (cm); Entries", kTH1F, {{300, -12.5, 12.5}}); - mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{600, 0, 600}}); + mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{16384, 0, 32768}}); + mHistogramRegistry->add("Event/MultNTr", "; vMultNTr; Entries", kTH1F, {{200, 0, 200}}); } /// Some basic QA of the event @@ -48,6 +49,7 @@ class FemtoUniverseEventHisto if (mHistogramRegistry) { mHistogramRegistry->fill(HIST("Event/zvtxhist"), col.posZ()); mHistogramRegistry->fill(HIST("Event/MultV0M"), col.multV0M()); + mHistogramRegistry->fill(HIST("Event/MultNTr"), col.multNtr()); } } diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h new file mode 100644 index 00000000000..f92c92ecff5 --- /dev/null +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h @@ -0,0 +1,256 @@ +// 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 FemtoUniverseFemtoContainer.h +/// \brief Definition of the FemtoUniverseFemtoContainer +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Valentina Mantovani Sarti, valentina.mantovani-sarti@tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEFEMTOCONTAINER_H_ +#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEFEMTOCONTAINER_H_ + +#include +#include +#include + +#include "Framework/HistogramRegistry.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" + +#include "Math/Vector4D.h" +#include "TMath.h" +#include "TDatabasePDG.h" + +using namespace o2::framework; + +namespace o2::analysis::femtoUniverse +{ + +namespace femtoUniverseFemtoContainer +{ +/// Femtoscopic observable to be computed +enum Observable { kstar ///< kstar +}; + +/// Type of the event processind +enum EventType { same, ///< Pair from same event + mixed ///< Pair from mixed event +}; +}; // namespace femtoUniverseFemtoContainer + +/// \class FemtoUniverseFemtoContainer +/// \brief Container for all histogramming related to the correlation function. The two +/// particles of the pair are passed here, and the correlation function and QA histograms +/// are filled according to the specified observable +/// \tparam eventType Type of the event (same/mixed) +/// \tparam obs Observable to be computed (k*/Q_inv/...) +template +class FemtoUniverseFemtoContainer +{ + public: + /// Destructor + virtual ~FemtoUniverseFemtoContainer() = default; + + /// Initializes histograms for the task + /// Called by init both in case of reconstructed data/ Monte Carlo, and for Monte Carlo Truth + /// \tparam T type of the axis Object + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) + /// \param femtoObs Title of the femto observable axis + /// \param femtoObsAxis axis object for the femto observable axis + /// \param multAxis axis object for the multiplicity axis + /// \param kTAxis axis object for the kT axis + /// \param mTAxis axis object for the mT axis + template + void init_base(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis, T kTAxis, T mTAxis, T multAxis3D, T mTAxis3D, bool use3dplots) + { + mHistogramRegistry->add((folderName + "/relPairDist").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); + mHistogramRegistry->add((folderName + "/relPairkT").c_str(), "; #it{k}_{T} (GeV/#it{c}); Entries", kTH1F, {kTAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarkT").c_str(), ("; " + femtoObs + "; #it{k}_{T} (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, kTAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarmT").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2})").c_str(), kTH2F, {femtoObsAxis, mTAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarMult").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); + mHistogramRegistry->add((folderName + "/kstarPtPart1").c_str(), ("; " + femtoObs + "; #it{p} _{T} Particle 1 (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, {375, 0., 7.5}}); + mHistogramRegistry->add((folderName + "/kstarPtPart2").c_str(), ("; " + femtoObs + "; #it{p} _{T} Particle 2 (GeV/#it{c})").c_str(), kTH2F, {femtoObsAxis, {375, 0., 7.5}}); + mHistogramRegistry->add((folderName + "/MultPtPart1").c_str(), "; #it{p} _{T} Particle 1 (GeV/#it{c}); Multiplicity", kTH2F, {{375, 0., 7.5}, multAxis}); + mHistogramRegistry->add((folderName + "/MultPtPart2").c_str(), "; #it{p} _{T} Particle 2 (GeV/#it{c}); Multiplicity", kTH2F, {{375, 0., 7.5}, multAxis}); + mHistogramRegistry->add((folderName + "/PtPart1PtPart2").c_str(), "; #it{p} _{T} Particle 1 (GeV/#it{c}); #it{p} _{T} Particle 2 (GeV/#it{c})", kTH2F, {{375, 0., 7.5}, {375, 0., 7.5}}); + if (use3dplots) { + mHistogramRegistry->add((folderName + "/relPairkstarmTMult").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2}); Multiplicity").c_str(), kTH3F, {femtoObsAxis, mTAxis3D, multAxis3D}); + } + } + + /// Initializes specialized Monte Carlo truth histograms for the task + /// internal function called by init only in case of Monte Carlo truth + /// \tparam T type of the xxis Object + /// \param folderName Name of the directory in the output file (no suffix for reconstructed data/ Monte Carlo; "_MC" for Monte Carlo Truth) + /// \param femtoObsAxis axis object for the femto observable axis + template + void init_MC(std::string folderName, std::string femtoObs, T femtoObsAxis, T multAxis, T mTAxis) + { + mHistogramRegistry->add((folderName + "/relPairDist_ReconNoFake").c_str(), ("; " + femtoObs + "; Entries").c_str(), kTH1F, {femtoObsAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarmT_ReconNoFake").c_str(), ("; " + femtoObs + "; #it{m}_{T} (GeV/#it{c}^{2})").c_str(), kTH2F, {femtoObsAxis, mTAxis}); + mHistogramRegistry->add((folderName + "/relPairkstarMult_ReconNoFake").c_str(), ("; " + femtoObs + "; Multiplicity").c_str(), kTH2F, {femtoObsAxis, multAxis}); + mHistogramRegistry->add((folderName + "/hNoMCtruthPairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + mHistogramRegistry->add((folderName + "/hFakePairsCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + mHistogramRegistry->add((folderName + "/kstar_resolution").c_str(), "; #it{k} _{T} reconstructed (GeV/#it{c}); #it{k} _{T} truth (GeV/#it{c})", kTH2F, {femtoObsAxis, femtoObsAxis}); + } + + /// Templated function to initialize the histograms for the task + /// Always calls init_base to initialize the histograms for data/ Monte Carlo reconstructed + /// In case of Monte Carlo, calls init_base again for Monte Carlo truth and the specialized function init_MC for additional histogramms + /// \tparam T type of the configurable for the axis configuration + /// \param registry Histogram registry to be passed + /// \param kstarBins k* binning for the histograms + /// \param multBins multiplicity binning for the histograms + /// \param kTBins kT binning for the histograms + /// \param mTBins mT binning for the histograms + /// \param isMC add Monte Carlo truth histograms to the output file + template + void init(HistogramRegistry* registry, T& kstarBins, T& multBins, T& kTBins, T& mTBins, T& multBins3D, T& mTBins3D, bool isMC, bool use3dplots) + { + mHistogramRegistry = registry; + std::string femtoObs; + if constexpr (mFemtoObs == femtoUniverseFemtoContainer::Observable::kstar) { + femtoObs = "#it{k*} (GeV/#it{c})"; + } + std::vector tmpVecMult = multBins; + framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; + framework::AxisSpec femtoObsAxis = {kstarBins, femtoObs.c_str()}; + framework::AxisSpec kTAxis = {kTBins, "#it{k}_{T} (GeV/#it{c})"}; + framework::AxisSpec mTAxis = {mTBins, "#it{m}_{T} (GeV/#it{c}^{2})"}; + + framework::AxisSpec multAxis3D = {multBins3D, "Multiplicity"}; + framework::AxisSpec mTAxis3D = {mTBins3D, "#it{m}_{T} (GeV/#it{c})"}; + + std::string folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kRecon]); + + init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, use3dplots); + if (isMC) { + folderName = static_cast(mFolderSuffix[mEventType]) + static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]); + init_base(folderName, femtoObs, femtoObsAxis, multAxis, kTAxis, mTAxis, multAxis3D, mTAxis3D, use3dplots); + init_MC(folderName, femtoObs, femtoObsAxis, multAxis, mTAxis); + } + } + + /// Set the PDG codes of the two particles involved + /// \param pdg1 PDG code of particle one + /// \param pdg2 PDG code of particle two + void setPDGCodes(const int pdg1, const int pdg2) + { + mMassOne = TDatabasePDG::Instance()->GetParticle(pdg1)->Mass(); + mMassTwo = TDatabasePDG::Instance()->GetParticle(pdg2)->Mass(); + mPDGOne = pdg1; + mPDGTwo = pdg2; + } + + /// Pass a pair to the container and compute all the relevant observables + /// Called by setPair both in case of data/ and Monte Carlo reconstructed and for Monte Carlo truth + /// \tparam T type of the femtouniverseparticle + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + template + void setPair_base(const float femtoObs, const float mT, T const& part1, T const& part2, const int mult, bool use3dplots) + { + const float kT = FemtoUniverseMath::getkT(part1, mMassOne, part2, mMassTwo); + + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairDist"), femtoObs); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkT"), kT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarkT"), femtoObs, kT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmT"), femtoObs, mT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarMult"), femtoObs, mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/kstarPtPart1"), femtoObs, part1.pt()); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/kstarPtPart2"), femtoObs, part2.pt()); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/MultPtPart1"), part1.pt(), mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/MultPtPart2"), part2.pt(), mult); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/PtPart1PtPart2"), part1.pt(), part2.pt()); + if (use3dplots) { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmTMult"), femtoObs, mT, mult); + } + } + + /// Called by setPair only in case of Monte Carlo truth + /// Fills MC truth specific histogramms: + /// - kstar distribution plots with RECONSTRUCTED information but ONLY for non-fake candidates; needed for purity calculations of tracks + /// - kstar resolution matrix + /// Note: Standard histogramms with MC truth information are filled with the setPair_base function + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + void setPair_MC(const float femtoObsMC, const float femtoObs, const float mT, const int mult) + { + if (mHistogramRegistry) { + // Fill the kstar distributions with the reconstructed information but only for particles with the right PDG code + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/relPairDist_ReconNoFake"), femtoObs); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/relPairkstarmT_ReconNoFake"), femtoObs, mT); + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/relPairkstarMult_ReconNoFake"), femtoObs, mult); + + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/kstar_resolution"), femtoObsMC, femtoObs); + } + } + + /// Templated function to handle data/ Monte Carlo reconstructed and Monte Carlo truth + /// Always calls setPair_base to compute the observables with reconstructed data + /// In case of Monte Carlo, calls setPair_base with MC info and specialized function setPair_MC for additional histogramms + /// \tparam T type of the femtouniverseparticle + /// \param part1 Particle one + /// \param part2 Particle two + /// \param mult Multiplicity of the event + template + void setPair(T const& part1, T const& part2, const int mult, bool use3dplots) + { + float femtoObs, femtoObsMC; + // Calculate femto observable and the mT with reconstructed information + if constexpr (mFemtoObs == femtoUniverseFemtoContainer::Observable::kstar) { + femtoObs = FemtoUniverseMath::getkstar(part1, mMassOne, part2, mMassTwo); + } + const float mT = FemtoUniverseMath::getmT(part1, mMassOne, part2, mMassTwo); + + if (mHistogramRegistry) { + setPair_base(femtoObs, mT, part1, part2, mult, use3dplots); + + if constexpr (isMC) { + if (part1.has_fdMCParticle() && part2.has_fdMCParticle()) { + // calculate the femto observable and the mT with MC truth information + if constexpr (mFemtoObs == femtoUniverseFemtoContainer::Observable::kstar) { + femtoObsMC = FemtoUniverseMath::getkstar(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + } + const float mTMC = FemtoUniverseMath::getmT(part1.fdMCParticle(), mMassOne, part2.fdMCParticle(), mMassTwo); + + if (abs(part1.fdMCParticle().pdgMCTruth()) == abs(mPDGOne) && abs(part2.fdMCParticle().pdgMCTruth()) == abs(mPDGTwo)) { // Note: all pair-histogramms are filled with MC truth information ONLY in case of non-fake candidates + setPair_base(femtoObsMC, mTMC, part1.fdMCParticle(), part2.fdMCParticle(), mult, use3dplots); + setPair_MC(femtoObsMC, femtoObs, mT, mult); + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/hFakePairsCounter"), 0); + } + + } else { + mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]) + HIST("/hNoMCtruthPairsCounter"), 0); + } + } + } + } + + protected: + HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output + static constexpr std::string_view mFolderSuffix[2] = {"SameEvent", "MixedEvent"}; ///< Folder naming for the output according to mEventType + static constexpr femtoUniverseFemtoContainer::Observable mFemtoObs = obs; ///< Femtoscopic observable to be computed (according to femtoUniverseFemtoContainer::Observable) + static constexpr int mEventType = eventType; ///< Type of the event (same/mixed, according to femtoUniverseFemtoContainer::EventType) + float mMassOne = 0.f; ///< PDG mass of particle 1 + float mMassTwo = 0.f; ///< PDG mass of particle 2 + int mPDGOne = 0; ///< PDG code of particle 1 + int mPDGTwo = 0; ///< PDG code of particle 2 +}; + +} // namespace o2::analysis::femtoUniverse + +#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEFEMTOCONTAINER_H_ diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h index 4590a9879d4..f0243942279 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -11,8 +11,9 @@ /// \file FemtoUniverseMath.h /// \brief Definition of the FemtoUniverseMath Container for math calculations of quantities related to pairs -/// \author Valentina Mantovani Sarti, TU München, valentina.mantovani-sarti@tum.de, Laura Serksnyte, TU München, laura.serksnyte@cern.ch -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Valentina Mantovani Sarti, TU München, valentina.mantovani-sarti@tum.de +/// \author Laura Serksnyte, TU München, laura.serksnyte@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEMATH_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEMATH_H_ @@ -140,4 +141,4 @@ class FemtoUniverseMath } // namespace o2::analysis::femtoUniverse -#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEMATH_H_" +#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEMATH_H_ diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h index 40833551458..ec91b1ca7ea 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -12,18 +12,21 @@ /// \file FemtoUniverseObjectSelection.h /// \brief FemtoUniverseObjectSelection - Parent class of all selections /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEOBJECTSELECTION_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEOBJECTSELECTION_H_ #include -#include #include +#include #include "PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h" #include "ReconstructionDataFormats/PID.h" #include "Framework/HistogramRegistry.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +using namespace o2; using namespace o2::framework; namespace o2::analysis @@ -49,6 +52,7 @@ class FemtoUniverseObjectSelection void fillSelectionHistogram() { int nBins = mSelections.size(); + LOGF(info, "%s", (static_cast(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + "/cuthist").c_str()); mHistogramRegistry->add((static_cast(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + "/cuthist").c_str(), "; Cut; Value", kTH1F, {{nBins, 0, static_cast(nBins)}}); auto hist = mHistogramRegistry->get(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/cuthist")); for (size_t i = 0; i < mSelections.size(); ++i) { @@ -95,7 +99,7 @@ class FemtoUniverseObjectSelection } /// Then, the sorted selections are added to the overall container of cuts - for (const auto& sel : sels) { + for (auto& sel : sels) { mSelections.push_back(sel); } } diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h b/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h index c0dceb69ee9..b8fb1afce44 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -11,13 +11,14 @@ /// \file FemtoUniversePairCleaner.h /// \brief FemtoUniversePairCleaner - Makes sure only proper candidates are paired -/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de, Laura Serksnyte , TU München -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Laura Serksnyte, TU München,laura.serksnyte@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPAIRCLEANER_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPAIRCLEANER_H_ -#include "PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" #include "Framework/HistogramRegistry.h" using namespace o2::framework; @@ -63,22 +64,40 @@ class FemtoUniversePairCleaner return false; } return part1.globalIndex() != part2.globalIndex(); + } else if constexpr (mPartOneType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack && mPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + /// Track-Track combination + if (part1.partType() != o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack || part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + LOG(fatal) << "FemtoUniversePairCleaner: passed arguments don't agree with FemtoUniversePairCleaner instantiation! Please provide kMCTruthTrack,kMCTruthTrack candidates."; + return false; + } + return part1.globalIndex() != part2.globalIndex(); } else if constexpr (mPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kV0) { /// Track-V0 combination if (part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kV0) { LOG(fatal) << "FemtoUniversePairCleaner: passed arguments don't agree with FemtoUniversePairCleaner instantiation! Please provide second argument kV0 candidate."; return false; } - uint64_t id1 = part2.index() - 2; - uint64_t id2 = part2.index() - 1; - auto daughter1 = particles.begin() + id1; - auto daughter2 = particles.begin() + id2; - if ((*daughter1).indices()[0] <= 0 && (*daughter1).indices()[1] <= 0 && (*daughter2).indices()[0] <= 0 && (*daughter2).indices()[1] <= 0) { + const auto& posChild = particles.iteratorAt(part2.index() - 2); + const auto& negChild = particles.iteratorAt(part2.index() - 1); + if (part1.globalIndex() != posChild.globalIndex() && part2.globalIndex() != negChild.globalIndex()) { return true; } return false; } else if constexpr (mPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kPhi) { - return true; + /// Track-Phi combination part1 is Phi and part 2 is hadron + if (part1.partType() != o2::aod::femtouniverseparticle::ParticleType::kTrack || part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kPhi) { + LOG(fatal) << "FemtoUniversePairCleaner: passed arguments don't agree with FemtoUniversePairCleaner instantiation! Please provide second argument kPhi candidate."; + return false; + } + + // getting Phi (part1) children + const auto& posChild = particles.iteratorAt(part2.index() - 2); + const auto& negChild = particles.iteratorAt(part2.index() - 1); + + if (part1.globalIndex() != posChild.globalIndex() && part1.globalIndex() != negChild.globalIndex()) { + return true; + } + return false; } else { LOG(fatal) << "FemtoUniversePairCleaner: Combination of objects not defined - quitting!"; return false; diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniversePairWithCentMultKt.h b/PWGCF/FemtoUniverse/Core/FemtoUniversePairWithCentMultKt.h new file mode 100644 index 00000000000..d4c449041cc --- /dev/null +++ b/PWGCF/FemtoUniverse/Core/FemtoUniversePairWithCentMultKt.h @@ -0,0 +1,181 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// \author Deependra Sharma, IITB, deependra.sharma@cern.ch +/// \author Alicja Płachta, WUT Warsaw, alicja.plachta.stud@pw.edu.pl + +#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPAIRWITHCENTMULTKT_H_ +#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPAIRWITHCENTMULTKT_H_ + +#include +#include +#include +#include "Framework/HistogramRegistry.h" + +using namespace o2; +using namespace o2::framework; + +namespace o2::analysis::femtoUniverse +{ +class PairWithCentMultKt +{ + public: + virtual ~PairWithCentMultKt() = default; + /// @brief + /// @tparam t1 + /// @param registry + /// @param kstarbins + /// @param centmultbins + template + void init(HistogramRegistry* registry, t1& kstarbins, t1& centmultbins, t1& ktbins, bool processKT) + { + PairWithCentMultKtRegistry = registry; + AxisSpec kstarAxis = {kstarbins, "#it{k*} (GeV/#it{c})"}; + CentMultBins = centmultbins; + KtBins = ktbins; + KtBins.erase(KtBins.begin()); + CentMultBins.erase(CentMultBins.begin()); + UseKt = processKT; + + for (int i = 0; i < static_cast(CentMultBins.size() - 1); i++) { + int lowBin = static_cast((CentMultBins[i])); + int highBin = static_cast((CentMultBins[i + 1])); + std::string HistTitle = "mult_" + std::to_string(lowBin) + "-" + std::to_string(highBin); + std::string HistSuffix1 = static_cast(HistSuffix[i]); + std::string HistSuffix2 = static_cast(HistSuffix[i + 1]); + std::string HistFolderMult = "mult_" + HistSuffix1 + "_" + HistSuffix2; + std::string HistName = HistFolderMult + "/kstar"; + PairWithCentMultKtRegistry->add(HistName.c_str(), HistTitle.c_str(), HistType::kTH1F, {kstarAxis}); + if (UseKt) { + for (int i = 0; i < static_cast(KtBins.size() - 1); i++) { + std::string kt_bin1_string = std::to_string(KtBins[i]); + std::replace(kt_bin1_string.begin(), kt_bin1_string.end(), '.', '_'); + std::string kt_bin2_string = std::to_string(KtBins[i + 1]); + std::replace(kt_bin2_string.begin(), kt_bin2_string.end(), '.', '_'); + kt_bin1_string.resize(4); + kt_bin2_string.resize(4); + std::string HistTitleKt = "kt_" + kt_bin1_string + "-" + kt_bin2_string; + std::string HistSuffix1Kt = static_cast(HistSuffix[i]); + std::string HistSuffix2Kt = static_cast(HistSuffix[i + 1]); + std::string HistNameKt = HistFolderMult + "/kstar_kt_" + HistSuffix1Kt + "_" + HistSuffix2Kt; + PairWithCentMultKtRegistry->add(HistNameKt.c_str(), HistTitleKt.c_str(), HistType::kTH1F, {kstarAxis}); + } + } + } + PairWithCentMultKtRegistry->add("Beyond_Max", "Beyond_Max", HistType::kTH1F, {kstarAxis}); + } + + /// @brief + /// @tparam t1 + /// @param kstar_value + /// @param cent_mult_value + template + void fill(t1 kstar_value, t1 cent_mult_value, t1 kt_value) + { + + if (cent_mult_value > CentMultBins[CentMultBins.size() - 1] || cent_mult_value < CentMultBins[0]) { + PairWithCentMultKtRegistry->fill(HIST("Beyond_Max"), kstar_value); + } else if (cent_mult_value <= CentMultBins[1]) { + PairWithCentMultKtRegistry->fill(HIST("mult_0_1/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_0_1/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } else if (cent_mult_value <= CentMultBins[2]) { + PairWithCentMultKtRegistry->fill(HIST("mult_1_2/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_1_2/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } else if (cent_mult_value <= CentMultBins[3]) { + PairWithCentMultKtRegistry->fill(HIST("mult_2_3/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_2_3/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } else if (cent_mult_value <= CentMultBins[4]) { + PairWithCentMultKtRegistry->fill(HIST("mult_3_4/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_3_4/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } else if (cent_mult_value <= CentMultBins[5]) { + PairWithCentMultKtRegistry->fill(HIST("mult_4_5/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_4_5/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } else if (cent_mult_value <= CentMultBins[6]) { + PairWithCentMultKtRegistry->fill(HIST("mult_5_6/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_5_6/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } else if (cent_mult_value <= CentMultBins[7]) { + PairWithCentMultKtRegistry->fill(HIST("mult_6_7/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_6_7/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } else if (cent_mult_value <= CentMultBins[8]) { + PairWithCentMultKtRegistry->fill(HIST("mult_7_8/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_7_8/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } else if (cent_mult_value <= CentMultBins[9]) { + PairWithCentMultKtRegistry->fill(HIST("mult_8_9/kstar"), kstar_value); + if (UseKt) { + auto histMultFolder = HIST("mult_8_9/"); + fill_kT(kstar_value, kt_value, histMultFolder); + } + } + } + + /// @brief + /// @tparam t1 + /// @tparam t2 + /// @param kstar_value + /// @param kt_value + /// @param folder + template + void fill_kT(t1 kstar_value, t1 kt_value, t2 folder) + { + if (kt_value <= KtBins[1]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_0_1"), kstar_value); + } else if (kt_value <= KtBins[2]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_1_2"), kstar_value); + } else if (kt_value <= KtBins[3]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_2_3"), kstar_value); + } else if (kt_value <= KtBins[4]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_3_4"), kstar_value); + } else if (kt_value <= KtBins[5]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_4_5"), kstar_value); + } else if (kt_value <= KtBins[6]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_5_6"), kstar_value); + } else if (kt_value <= KtBins[7]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_6_7"), kstar_value); + } else if (kt_value <= KtBins[8]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_7_8"), kstar_value); + } else if (kt_value <= KtBins[9]) { + PairWithCentMultKtRegistry->fill(folder + HIST("kstar_kt_8_9"), kstar_value); + } + } + + protected: + HistogramRegistry* PairWithCentMultKtRegistry = nullptr; + std::vector CentMultBins; + std::vector KtBins; + bool UseKt = false; + static constexpr std::string_view HistSuffix[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; +}; +} // namespace o2::analysis::femtoUniverse + +#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPAIRWITHCENTMULTKT_H_ diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h index 7d054278df6..40c1cac7a7f 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -12,24 +12,25 @@ /// \file FemtoUniverseParticleHisto.h /// \brief FemtoUniverseParticleHisto - Histogram class for tracks, V0s and cascades /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPARTICLEHISTO_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPARTICLEHISTO_H_ #include -#include "PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" #include "Framework/HistogramRegistry.h" using namespace o2::framework; -// using namespace o2::aod::o2::aod; namespace o2::analysis::femtoUniverse { /// \class FemtoUniverseParticleHisto /// \brief Class for histogramming particle properties -/// \tparam particleType Type of the particle (Track/V0/Cascade/...) +/// \tparam particleType Type of the particle (Track/V0/Cascade/Phi/...) /// \tparam suffixType (optional) Takes care of the suffix for the folder name in case of analyses of pairs of the same kind (T-T, V-V, C-C) template class FemtoUniverseParticleHisto @@ -38,87 +39,322 @@ class FemtoUniverseParticleHisto /// Destructor virtual ~FemtoUniverseParticleHisto() = default; - /// Initialization of the QA histograms - /// \param registry HistogramRegistry - void init(HistogramRegistry* registry) + /// Initializes particle histograms + /// Called by init both in case of reconstructed data/ Monte Carlo, and for Monte Carlo Truth + /// \tparam T type of the axis Object + /// \tparam mc enum object to get the suffix ("" for data/ Monte Cartlo reconstructed, "_MC" for Monte Carlo truth) for the folder in the output file + /// \param folderName base path of the directory in the output file, in which to store the histograms + /// \param tempFitVarAxisTitle Title of the axis of the tempFitVar (DCA_xy in case of tracks, CPA in case of V0s, etc.) + /// \param tempFitVarpTAxis axis object for the pT axis in the pT vs. tempFitVar plots + /// \param tempFitVarAxis axis object for the tempFitVar axis + template + void init_base(std::string folderName, std::string tempFitVarAxisTitle, T& tempFitVarpTAxis, T& tempFitVarAxis) { + std::string folderSuffix = static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[mc]).c_str(); + /// Histograms of the kinematic properties + mHistogramRegistry->add((folderName + folderSuffix + "/hPt").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hEta").c_str(), "; #eta; Entries", kTH1F, {{200, -1.5, 1.5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{200, 0, 2. * M_PI}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hPhiEta").c_str(), "; #phi; #eta", kTH2F, {{200, 0, 2. * M_PI}, {200, -1.5, 1.5}}); + + /// particle specific histogramms for the TempFitVar column in FemtoUniverseParticles + if constexpr (o2::aod::femtouniverseMCparticle::MCType::kRecon == mc) { + mHistogramRegistry->add((folderName + folderSuffix + static_cast(o2::aod::femtouniverseparticle::TempFitVarName[mParticleType])).c_str(), ("; #it{p}_{T} (GeV/#it{c}); " + tempFitVarAxisTitle).c_str(), kTH2F, {{tempFitVarpTAxis}, {tempFitVarAxis}}); + } + } + + // comment + template + void init_debug(std::string folderName) + { + std::string folderSuffix = static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[mc]).c_str(); + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + 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; 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 + "/hTPCfindableVsCrossed").c_str(), ";TPC findable clusters ; TPC crossed rows;", kTH2F, {{163, -0.5, 162.5}, {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 + "/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}_{T} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {{100, 0, 10}, {500, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCA").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA (cm)", kTH2F, {{100, 0, 10}, {301, 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_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTPC_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TPC}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{e}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{#pi}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{K}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{p}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaTOF_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{TOF}^{d}", kTH2F, {{100, 0, 10}, {100, -5, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_el").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{e}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_pi").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{#pi}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_K").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{K}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_p").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{p}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); + mHistogramRegistry->add((folderName + folderSuffix + "/nSigmaComb_d").c_str(), "; #it{p} (GeV/#it{c}); n#sigma_{comb}^{d}", kTH2F, {{100, 0, 10}, {100, 0, 5}}); + } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0) { + mHistogramRegistry->add((folderName + folderSuffix + "/hDaughDCA").c_str(), "; DCA^{daugh} (cm); Entries", kTH1F, {{1000, 0, 10}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hTransRadius").c_str(), "; #it{r}_{xy} (cm); Entries", kTH1F, {{1500, 0, 150}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDecayVtxX").c_str(), "; #it{Vtx}_{x} (cm); Entries", kTH1F, {{2000, 0, 200}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDecayVtxY").c_str(), "; #it{Vtx}_{y} (cm)); Entries", kTH1F, {{2000, 0, 200}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDecayVtxZ").c_str(), "; #it{Vtx}_{z} (cm); Entries", kTH1F, {{2000, 0, 200}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassLambda").c_str(), "; M_{#Lambda}; Entries", kTH1F, {{2000, 1.f, 3.f}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassAntiLambda").c_str(), "; M_{#bar{#Lambda}}; Entries", kTH1F, {{2000, 1.f, 3.f}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hInvMassLambdaAntiLambda").c_str(), "; M_{#Lambda}; M_{#bar{#Lambda}}", kTH2F, {{2000, 1.f, 3.f}, {2000, 1.f, 3.f}}); + } + } + + /// Initializes specialized Monte Carlo particle histograms + /// internal function called by init only in case of Monte Carlo truth + /// \tparam T type of the axis Object + /// \param folderName base path of the directory in the output file, in which to store the histograms + /// \param tempFitVarAxisTitle Title of the axis of the tempFitVar (DCA_xy in case of tracks, CPA in case of V0s, etc.) + /// \param tempFitVarpTAxis axis object for the pT axis in the pT vs. tempFitVar plots + /// \param tempFitVarAxis axis object for the tempFitVar axis + template + void init_MC(std::string folderName, std::string tempFitVarAxisTitle, T& tempFitVarpTAxis, T& tempFitVarAxis) + { + /// Particle-type specific histograms + std::string folderSuffix = static_cast(o2::aod::femtouniverseMCparticle::MCTypeName[o2::aod::femtouniverseMCparticle::MCType::kTruth]).c_str(); + + mHistogramRegistry->add((folderName + folderSuffix + "/hPt_ReconNoFake").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); + + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + /// Track histograms + mHistogramRegistry->add((folderName + folderSuffix + "/hPDG").c_str(), "; PDG; Entries", kTH1I, {{6001, -3000, 3000}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hOrigin_MC").c_str(), "; Origin; Entries", kTH1I, {{7, 0, 7}}); + mHistogramRegistry->add((folderName + folderSuffix + "/hNoMCtruthCounter").c_str(), "; Counter; Entries", kTH1I, {{1, 0, 1}}); + // DCA plots + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Material").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Fake").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_DaughterLambda").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_DaughterSigmaplus").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Primary").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + mHistogramRegistry->add((folderName + folderSuffix + "/hDCAxy_Daughter").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {tempFitVarpTAxis, tempFitVarAxis}); + } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0) { + /// V0 histograms + /// to be implemented + } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascade) { + /// Cascade histograms + /// to be implemented + } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kPhi) { + // Phi histograms + } else { + LOG(fatal) << "FemtoUniverseParticleHisto: Histogramming for requested object not defined - quitting!"; + } + } + + /// Templated function for the initialization of the QA histograms + /// Always calls init_base to initialize the histograms with data/ Monte Carlo reconstructed + /// In case of Monte Carlo, calls init_base again for Monte Carlo truth and the specialized function init_MC for additional Monte Carlo histogramms + /// \tparam T type of the axis binning + /// \param registry Histogram registry to be passed + /// \param tempFitVarpTBins binning of the pT axis in the pT vs. tempFitVar + /// \param tempFitVarBins binning of the tempFitVar (DCA_xy in case of tracks, CPA in case of V0s, etc.) + /// \param isMC add Monte Carlo truth histograms to the output file + template + void init(HistogramRegistry* registry, T& tempFitVarpTBins, T& tempFitVarBins, bool isMC, int pdgCode, bool isDebug = false) + { + mPDG = pdgCode; if (registry) { mHistogramRegistry = registry; /// The folder names are defined by the type of the object and the suffix (if applicable) - std::string folderName = static_cast(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]); - folderName += static_cast(mFolderSuffix[mFolderSuffixType]); - - /// Histograms of the kinematic properties - mHistogramRegistry->add((folderName + "/hPt").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{240, 0, 6}}); - mHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", kTH1F, {{200, -1.5, 1.5}}); - mHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{200, 0, 2. * M_PI}}); - mHistogramRegistry->add((folderName + "/dEdxTPCVsMomentum").c_str(), "; #it{p} (GeV/#it{c}); dE/dx (keV/cm)", kTH2F, {{200, 0., 5.}, {250, 0., 500.}}); - mHistogramRegistry->add((folderName + "/TOFBetaVsMomentum").c_str(), "; #it{p} (GeV/#it{c}); TOF #beta", kTH2F, {{200, 0., 5.}, {250, 0.4, 1.1}}); - - /// Particle-type specific histograms - if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack) { + std::string tempFitVarAxisTitle; + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child) { /// Track histograms - mHistogramRegistry->add((folderName + "/hDCAxy").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{20, 0.5, 4.05}, {500, -5, 5}}); - mHistogramRegistry->add((folderName + "/hDCAz").c_str(), "; #it{p}_{T} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {{20, 0.5, 4.05}, {500, -5, 5}}); + tempFitVarAxisTitle = "DCA_{xy} (cm)"; + } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + /// MC Truth Track histograms + tempFitVarAxisTitle = "PDG code"; } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0) { /// V0 histograms - mHistogramRegistry->add((folderName + "/hCPA").c_str(), "; #it{p}_{T} (GeV/#it{c}); cos#alpha", kTH2F, {{8, 0.3, 4.3}, {1000, 0.9, 1}}); + tempFitVarAxisTitle = "cos#alpha"; } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascade) { /// Cascade histograms + tempFitVarAxisTitle = "cos#alpha"; } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kPhi) { - /// Phi histograms - int mInvBins = 1000; - framework::AxisSpec mInvAxis = {mInvBins, 0.5, 1.5}; - mHistogramRegistry->add((folderName + "/InvariantMass").c_str(), ";M_{K^{+}K^{-}} (GeV/#it{c}^{2});", kTH1D, {mInvAxis}); - } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kPhiChild) { - /// Phi daughters histograms + // Phi histograms + tempFitVarAxisTitle = "#Phi invariant mass"; } else { LOG(fatal) << "FemtoUniverseParticleHisto: Histogramming for requested object not defined - quitting!"; } + + framework::AxisSpec tempFitVarpTAxis = {tempFitVarpTBins, "#it{p}_{T} (GeV/#it{c})"}; // the pT binning may vary + framework::AxisSpec tempFitVarAxis = {tempFitVarBins, tempFitVarAxisTitle}; + + std::string folderName = (static_cast(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]).c_str() + static_cast(mFolderSuffix[mFolderSuffixType])).c_str(); + + // Fill here the actual histogramms by calling init_base and init_MC + init_base(folderName, tempFitVarAxisTitle, tempFitVarpTAxis, tempFitVarAxis); + if (isDebug) { + init_debug(folderName); + } + if (isMC) { + init_base(folderName, tempFitVarAxisTitle, tempFitVarpTAxis, tempFitVarAxis); + init_MC(folderName, tempFitVarAxisTitle, tempFitVarpTAxis, tempFitVarAxis); + } } } /// Filling of the histograms + /// Called by init both in case of reconstructed data/ Monte Carlo, and for Monte Carlo Truth /// \tparam T Data type of the particle /// \param part Particle + template + void fillQA_base(T const& part) + { + /// Histograms of the kinematic properties + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hPt"), part.pt()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hEta"), part.eta()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hPhi"), part.phi()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hPhiEta"), part.phi(), part.eta()); + + /// particle specific histogramms for the TempFitVar column in FemtoUniverseParticles + if constexpr (mc == o2::aod::femtouniverseMCparticle::MCType::kRecon) { + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST(o2::aod::femtouniverseparticle::TempFitVarName[mParticleType]), part.pt(), part.tempFitVar()); + } + } + + template + void fillQA_debug(T const& part) + { + // Histograms holding further debug information + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hCharge"), part.sign()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCfindable"), part.tpcNClsFindable()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCfound"), part.tpcNClsFound()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCcrossedOverFindable"), part.tpcCrossedRowsOverFindableCls()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCcrossedRows"), part.tpcNClsCrossedRows()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCfindableVsCrossed"), part.tpcNClsFindable(), part.tpcNClsCrossedRows()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCshared"), part.tpcNClsShared()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hITSclusters"), part.itsNCls()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hITSclustersIB"), part.itsNClsInnerBarrel()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hDCAz"), part.pt(), part.dcaZ()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hDCA"), part.pt(), std::sqrt(std::pow(part.dcaXY(), 2.) + std::pow(part.dcaZ(), 2.))); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTPCdEdX"), part.p(), part.tpcSignal()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_el"), part.p(), part.tpcNSigmaEl()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_pi"), part.p(), part.tpcNSigmaPi()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_K"), part.p(), part.tpcNSigmaKa()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_p"), part.p(), part.tpcNSigmaPr()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTPC_d"), part.p(), part.tpcNSigmaDe()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_el"), part.p(), part.tofNSigmaEl()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_pi"), part.p(), part.tofNSigmaPi()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_K"), part.p(), part.tofNSigmaKa()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_p"), part.p(), part.tofNSigmaPr()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaTOF_d"), part.p(), part.tofNSigmaDe()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_el"), part.p(), std::sqrt(part.tpcNSigmaEl() * part.tpcNSigmaEl() + part.tofNSigmaEl() * part.tofNSigmaEl())); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_pi"), part.p(), std::sqrt(part.tpcNSigmaPi() * part.tpcNSigmaPi() + part.tofNSigmaPi() * part.tofNSigmaPi())); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_K"), part.p(), std::sqrt(part.tpcNSigmaKa() * part.tpcNSigmaKa() + part.tofNSigmaKa() * part.tofNSigmaKa())); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_p"), part.p(), std::sqrt(part.tpcNSigmaPr() * part.tpcNSigmaPr() + part.tofNSigmaPr() * part.tofNSigmaPr())); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/nSigmaComb_d"), part.p(), std::sqrt(part.tpcNSigmaDe() * part.tpcNSigmaDe() + part.tofNSigmaDe() * part.tofNSigmaDe())); + } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0) { + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hDaughDCA"), part.daughDCA()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hTransRadius"), part.transRadius()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hDecayVtxX"), part.decayVtxX()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hDecayVtxY"), part.decayVtxY()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hDecayVtxZ"), part.decayVtxZ()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hInvMassLambda"), part.mLambda()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hInvMassAntiLambda"), part.mAntiLambda()); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST(o2::aod::femtouniverseMCparticle::MCTypeName[mc]) + HIST("/hInvMassLambdaAntiLambda"), part.mLambda(), part.mAntiLambda()); + } + } + + /// 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 + /// \tparam TMC Data typ of the Monte Carlo Particle + /// \param part Particle + /// \param mctruthorigin Origin of the associated mc Truth particle + /// \param pdgcode PDG of the associated mc Truth particle associated to the reconstructed particle part template - void fillQA(T const& part) + void fillQA_MC(T const& part, int mctruthorigin, int pdgcode) { if (mHistogramRegistry) { - /// Histograms of the kinematic properties - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hPt"), part.pt()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hEta"), part.eta()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hPhi"), part.phi()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/dEdxTPCVsMomentum"), part.p(), part.tpcSignal()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/TOFBetaVsMomentum"), part.p(), part.beta()); - - /// Particle-type specific histograms - if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack) { + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hPDG"), pdgcode); + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hOrigin_MC"), mctruthorigin); + + if (abs(pdgcode) == mPDG) { // fill this histogramm only for TRUE protons (independently of their origin) for the track purity estimation + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hPt_ReconNoFake"), part.pt()); + } + + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kTrack || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0Child || mParticleType == o2::aod::femtouniverseparticle::ParticleType::kMCTruthTrack) { /// Track histograms - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hDCAxy"), part.pt(), part.tempFitVar()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hDCAz"), part.pt(), part.dcaZ()); + switch (mctruthorigin) { + case (o2::aod::femtouniverseMCparticle::kPrimary): + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_Primary"), + part.pt(), part.tempFitVar()); + break; + case (o2::aod::femtouniverseMCparticle::kDaughter): + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_Daughter"), + part.pt(), part.tempFitVar()); + break; + case (o2::aod::femtouniverseMCparticle::kMaterial): + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_Material"), + part.pt(), part.tempFitVar()); + break; + case (o2::aod::femtouniverseMCparticle::kFake): + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_Fake"), + part.pt(), part.tempFitVar()); + break; + case (o2::aod::femtouniverseMCparticle::kDaughterLambda): + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_DaughterLambda"), + part.pt(), part.tempFitVar()); + break; + case (o2::aod::femtouniverseMCparticle::kDaughterSigmaplus): + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hDCAxy_DaughterSigmaplus"), + part.pt(), part.tempFitVar()); + break; + default: + LOG(fatal) << "femtouniverseparticleMC: not known value for ParticleOriginMCTruth - please check. Quitting!"; + } } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kV0) { /// V0 histograms - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("/hCPA"), - part.pt(), part.tempFitVar()); } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascade) { /// Cascade histograms } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kPhi) { - /// Phi histograms - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST("/InvariantMass"), part.mass()); - } else if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kPhiChild) { - /// Phi daughters histograms + // Phi histograms } else { LOG(fatal) << "FemtoUniverseParticleHisto: Histogramming for requested object not defined - quitting!"; } } } + /// Templated function to fill particle histograms for data/ Monte Carlo reconstructed and Monte Carlo truth + /// Always calls fillQA_base fill histogramms with data/ Monte Carlo reconstructed + /// In case of Monte Carlo, calls fillQA_base with Monte Carlo truth info and specialized function fillQA_MC for additional histogramms + /// \tparam T particle type + /// \tparam isMC fills the additional histograms for Monte Carlo truth + /// \param part particle for which the histograms should be filled + template + void fillQA(T const& part) + { + std::string tempFitVarName; + if (mHistogramRegistry) { + fillQA_base(part); + if constexpr (isDebug) { + fillQA_debug(part); + } + if constexpr (isMC) { + if (part.has_fdMCParticle()) { + fillQA_base(part.fdMCParticle()); + fillQA_MC(part, (part.fdMCParticle()).partOriginMCTruth(), (part.fdMCParticle()).pdgMCTruth()); + } else { + mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[mParticleType]) + HIST(mFolderSuffix[mFolderSuffixType]) + HIST("_MC/hNoMCtruthCounter"), 0); + } + } + } + } + private: - HistogramRegistry* mHistogramRegistry; ///< For QA output - static constexpr o2::aod::femtouniverseparticle::ParticleType mParticleType = particleType; ///< Type of the particle under analysis - static constexpr int mFolderSuffixType = suffixType; ///< Counter for the folder suffix specified below - static constexpr std::string_view mFolderSuffix[5] = {"", "_one", "_one_rejected", "_two", "two_rejected"}; ///< Suffix for the folder name in case of analyses of pairs of the same kind (T-T, V-V, C-C) + HistogramRegistry* mHistogramRegistry; ///< For QA output + static constexpr o2::aod::femtouniverseparticle::ParticleType mParticleType = particleType; ///< Type of the particle under analysis + static constexpr int mFolderSuffixType = suffixType; ///< Counter for the folder suffix specified below + static constexpr std::string_view mFolderSuffix[5] = {"", "_one", "_two", "_pos", "_neg"}; ///< Suffix for the folder name in case of analyses of pairs of the same kind (T-T, V-V, C-C) + int mPDG = 0; ///< PDG code of the selected particle }; } // namespace o2::analysis::femtoUniverse diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h index 851b60f2992..1b028579ed2 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -14,21 +14,22 @@ /// \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 -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPHISELECTION_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPHISELECTION_H_ +#include #include #include #include "PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" -#include "ReconstructionDataFormats/PID.h" #include "Common/Core/RecoDecay.h" #include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" #include "TLorentzVector.h" using namespace o2::framework; @@ -38,17 +39,20 @@ namespace o2::analysis::femtoUniverse namespace femtoUniversePhiSelection { /// The different selections this task is capable of doing -enum PhiSel { kPhiSign, ///< +1 particle, -1 antiparticle - kpTPhiMin, - kpTPhiMax, - kDCAPhiDaughMax, - kCPAPhiMin, - kTranRadPhiMin, - kTranRadPhiMax, - kDecVtxMax }; - -enum ChildTrackType { kPosTrackPhi, - kNegTrackPhi }; +enum PhiSel { + kPhiSign, ///< +1 particle, -1 antiparticle + kPhipTMin, + kPhipTMax, + kPhietaMax, + kPhiDCADaughMax, + kPhiCPAMin, + kPhiTranRadMin, + kPhiTranRadMax, + kPhiDecVtxMax +}; + +enum ChildTrackType { kPosTrack, + kNegTrack }; enum PhiContainerPosition { kPhi, @@ -62,69 +66,55 @@ enum PhiContainerPosition { /// \class FemtoUniversePhiSelection /// \brief Cut class to contain and execute all cuts applied to Phis -class FemtoUniversePhiSelection : public FemtoUniverseObjectSelection +class FemtoUniversePhiSelection + : public FemtoUniverseObjectSelection { public: - FemtoUniversePhiSelection() : nPtPhiMinSel(0), - nPtPhiMaxSel(0), - nDCAPhiDaughMax(0), - nCPAPhiMin(0), - nTranRadPhiMin(0), - nTranRadPhiMax(0), - nDecVtxMax(0), - pTPhiMin(9999999.), - pTPhiMax(-9999999.), - DCAPhiDaughMax(-9999999.), - CPAPhiMin(9999999.), - TranRadPhiMin(9999999.), - TranRadPhiMax(-9999999.), - DecVtxMax(-9999999.), - fInvMassLowLimit(1.05), - fInvMassUpLimit(1.3), - fRejectKaon(false), - fInvMassKaonLowLimit(0.48), - fInvMassKaonUpLimit(0.515) {} + FemtoUniversePhiSelection() + : nPtPhiMinSel(0), nPtPhiMaxSel(0), nEtaPhiMaxSel(0), nDCAPhiDaughMax(0), nCPAPhiMin(0), nTranRadPhiMin(0), nTranRadPhiMax(0), nDecVtxMax(0), pTPhiMin(9999999.), pTPhiMax(-9999999.), etaPhiMax(-9999999.), DCAPhiDaughMax(-9999999.), CPAPhiMin(9999999.), TranRadPhiMin(9999999.), TranRadPhiMax(-9999999.), DecVtxMax(-9999999.), fInvMassLowLimit(1.05), fInvMassUpLimit(1.3), fRejectKaon(false), fInvMassKaonLowLimit(0.48), fInvMassKaonUpLimit(0.515), nSigmaPIDOffsetTPC(0.) {} /// Initializes histograms for the task - template + template void init(HistogramRegistry* registry); - template - void initPhi(HistogramRegistry* registry); - template - bool isSelectedMinimal(C const& col, V const& v0, T const& posTrack, T const& negTrack); + bool isSelectedMinimal(C const& col, V const& phi, T const& posTrack, + T const& negTrack); template - void fillPhiQA(C const& col, V const& v0, T const& posTrack, T const& negTrack); - - template - void fillPhiQAMass(C const& col, V const& v0, T const& posTrack, T const& negTrack, P const& ConfInvMassLowLimit, P const& ConfInvMassUpLimit); - - /// \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, T const& posTrack, T const& negTrack); + void fillLambdaQA(C const& col, V const& phi, T const& posTrack, + T const& negTrack); - template - void fillQA(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& phi, + T const& posTrack, + T const& negTrack); - template - void fillQAPhi(C const& col, V const& v0, T const& posTrack, T const& negTrack); + template + void fillQA(C const& col, V const& phi, T const& posTrack, T const& negTrack, Q const& posPID, Q const& negPID); template - void setChildCuts(femtoUniversePhiSelection::ChildTrackType child, T1 selVal, T2 selVar, femtoUniverseSelection::SelectionType selType) + void setChildCuts(femtoUniversePhiSelection::ChildTrackType child, T1 selVal, + T2 selVar, femtoUniverseSelection::SelectionType selType) { - if (child == femtoUniversePhiSelection::kPosTrackPhi) { + if (child == femtoUniversePhiSelection::kPosTrack) { PosDaughTrack.setSelection(selVal, selVar, selType); - } else if (child == femtoUniversePhiSelection::kNegTrackPhi) { + } else if (child == femtoUniversePhiSelection::kNegTrack) { NegDaughTrack.setSelection(selVal, selVar, selType); } } template - void setChildPIDSpecies(femtoUniversePhiSelection::ChildTrackType child, T& pids) + void setChildPIDSpecies(femtoUniversePhiSelection::ChildTrackType child, + T& pids) { - if (child == femtoUniversePhiSelection::kPosTrackPhi) { + if (child == femtoUniversePhiSelection::kPosTrack) { PosDaughTrack.setPIDSpecies(pids); - } else if (child == femtoUniversePhiSelection::kNegTrackPhi) { + } else if (child == femtoUniversePhiSelection::kNegTrack) { NegDaughTrack.setPIDSpecies(pids); } } @@ -133,7 +123,9 @@ class FemtoUniversePhiSelection : public FemtoUniverseObjectSelection(prefix); outString += static_cast(mSelectionNames[iSel]); @@ -144,10 +136,12 @@ class FemtoUniversePhiSelection : public FemtoUniverseObjectSelection(prefix) + static_cast(mSelectionNames[index]); + for (int index = 0; index < kNphiSelection; index++) { + std::string comp = static_cast(prefix) + + static_cast(mSelectionNames[index]); std::string_view cmp{comp}; if (obs.compare(cmp) == 0) return index; @@ -158,15 +152,18 @@ class FemtoUniversePhiSelection : public FemtoUniverseObjectSelection(prefix); outString += static_cast(mSelectionHelper[iSel]); @@ -192,18 +189,33 @@ class FemtoUniversePhiSelection : public FemtoUniverseObjectSelection +template void FemtoUniversePhiSelection::init(HistogramRegistry* registry) { - if (registry) { - mHistogramRegistry = registry; - fillSelectionHistogram(); - fillSelectionHistogram(); - - AxisSpec massAxisPhi = {60000, 0.0f, 3.0f, "m_{#Phi} (GeV/#it{c}^{2})"}; - AxisSpec massAxisAntiPhi = {60000, 0.0f, 3.0f, "m_{#bar{#Phi}} (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) << "FemtoUniversePhiCuts: Number of selections to large for your container - quitting!"; - } - std::string folderName = static_cast(o2::aod::femtouniverseparticle::ParticleTypeName[part]); - /// \todo initialize histograms for children tracks of v0s - mHistogramRegistry->add((folderName + "/hPt").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{1000, 0, 10}}); - mHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", kTH1F, {{1000, -1, 1}}); - mHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{1000, 0, 2. * M_PI}}); - // mHistogramRegistry->add((folderName + "/hDaughDCA").c_str(), "; DCA^{daugh} (cm); Entries", kTH1F, {{1000, 0, 10}}); - // mHistogramRegistry->add((folderName + "/hTransRadius").c_str(), "; #it{r}_{xy} (cm); Entries", kTH1F, {{1500, 0, 150}}); - // mHistogramRegistry->add((folderName + "/hDecayVtxX").c_str(), "; #it{Vtx}_{x} (cm); Entries", kTH1F, {{2000, 0, 200}}); - // mHistogramRegistry->add((folderName + "/hDecayVtxY").c_str(), "; #it{Vtx}_{y} (cm)); Entries", kTH1F, {{2000, 0, 200}}); - // mHistogramRegistry->add((folderName + "/hDecayVtxZ").c_str(), "; #it{Vtx}_{z} (cm); Entries", kTH1F, {{2000, 0, 200}}); - // mHistogramRegistry->add((folderName + "/hCPA").c_str(), "; #it{cos #theta_{p}}; Entries", kTH1F, {{1000, 0.9, 1.}}); - // mHistogramRegistry->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.}}); - mHistogramRegistry->add((folderName + "/hInvMassPhi").c_str(), "", kTH1F, {massAxisPhi}); - // mHistogramRegistry->add((folderName + "/hInvMassAntiPhi").c_str(), "", kTH1F, {massAxisAntiPhi}); - // mHistogramRegistry->add((folderName + "/hInvMassPhiPhi").c_str(), "", kTH2F, {massAxisPhi, massAxisPhi}); - - PosDaughTrack.init(mHistogramRegistry); - NegDaughTrack.init(mHistogramRegistry); - - mHistogramRegistry->add("PhiQA/hInvMassPhiNoCuts", "No cuts Phi", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiInvMassCut", "Invariant mass cut Phi", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiPtMin", "Minimum Pt cut", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiPtMax", "Maximum Pt cut", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiDCAPhiDaugh", "Phi-daughters DCA cut", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiCPA", "CPA cut", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiTranRadMin", "Minimum transverse radius cut", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiTranRadMax", "Maximum transverse radius cut", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiDecVtxMax", "Maximum distance on decay vertex cut", kTH1F, {massAxisPhi}); - } - /// check whether the most open cuts are fulfilled - most of this should have already be done by the filters - nPtPhiMinSel = getNSelections(femtoUniversePhiSelection::kpTPhiMin); - nPtPhiMaxSel = getNSelections(femtoUniversePhiSelection::kpTPhiMax); - nDCAPhiDaughMax = getNSelections(femtoUniversePhiSelection::kDCAPhiDaughMax); - nCPAPhiMin = getNSelections(femtoUniversePhiSelection::kCPAPhiMin); - nTranRadPhiMin = getNSelections(femtoUniversePhiSelection::kTranRadPhiMin); - nTranRadPhiMax = getNSelections(femtoUniversePhiSelection::kTranRadPhiMax); - nDecVtxMax = getNSelections(femtoUniversePhiSelection::kDecVtxMax); - - pTPhiMin = getMinimalSelection(femtoUniversePhiSelection::kpTPhiMin, femtoUniverseSelection::kLowerLimit); - pTPhiMax = getMinimalSelection(femtoUniversePhiSelection::kpTPhiMax, femtoUniverseSelection::kUpperLimit); - DCAPhiDaughMax = getMinimalSelection(femtoUniversePhiSelection::kDCAPhiDaughMax, femtoUniverseSelection::kUpperLimit); - CPAPhiMin = getMinimalSelection(femtoUniversePhiSelection::kCPAPhiMin, femtoUniverseSelection::kLowerLimit); - TranRadPhiMin = getMinimalSelection(femtoUniversePhiSelection::kTranRadPhiMin, femtoUniverseSelection::kLowerLimit); - TranRadPhiMax = getMinimalSelection(femtoUniversePhiSelection::kTranRadPhiMax, femtoUniverseSelection::kUpperLimit); - DecVtxMax = getMinimalSelection(femtoUniversePhiSelection::kDecVtxMax, femtoUniverseSelection::kAbsUpperLimit); -} - -// Phi initialization -template -void FemtoUniversePhiSelection::initPhi(HistogramRegistry* registry) -{ if (registry) { mHistogramRegistry = registry; fillSelectionHistogram(); fillSelectionHistogram(); - AxisSpec massAxisPhi = {60000, 0.0f, 3.0f, "m_{#Phi} (GeV/#it{c}^{2})"}; - // AxisSpec massAxisAntiPhi = {600, 0.0f, 3.0f, "m_{#bar{#Phi}} (GeV/#it{c}^{2})"}; + AxisSpec massAxisPhi = {6000, 0.9f, 3.0f, "m_{#Phi} (GeV/#it{c}^{2})"}; + AxisSpec massAxisLambda = {600, 0.0f, 3.0f, "m_{#Lambda} (GeV/#it{c}^{2})"}; + 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 + /// \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) << "FemtoUniversePhiCuts: Number of selections to large for your container - quitting!"; + LOG(fatal) << "FemtoUniversePhiCuts: Number of selections to large for your " + "container - quitting!"; } - std::string folderName = static_cast(o2::aod::femtouniverseparticle::ParticleTypeName[part]); - /// \todo initialize histograms for children tracks of v0s - mHistogramRegistry->add((folderName + "/hPtPhi").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{1000, 0, 10}}); - mHistogramRegistry->add((folderName + "/hEtaPhi").c_str(), "; #eta; Entries", kTH1F, {{1000, -1, 1}}); - mHistogramRegistry->add((folderName + "/hPhiPhi").c_str(), "; #phi; Entries", kTH1F, {{1000, 0, 2. * M_PI}}); - // mHistogramRegistry->add((folderName + "/hDaughDCA").c_str(), "; DCA^{daugh} (cm); Entries", kTH1F, {{1000, 0, 10}}); - // mHistogramRegistry->add((folderName + "/hTransRadius").c_str(), "; #it{r}_{xy} (cm); Entries", kTH1F, {{1500, 0, 150}}); - // mHistogramRegistry->add((folderName + "/hDecayVtxX").c_str(), "; #it{Vtx}_{x} (cm); Entries", kTH1F, {{2000, 0, 200}}); - // mHistogramRegistry->add((folderName + "/hDecayVtxY").c_str(), "; #it{Vtx}_{y} (cm)); Entries", kTH1F, {{2000, 0, 200}}); - // mHistogramRegistry->add((folderName + "/hDecayVtxZ").c_str(), "; #it{Vtx}_{z} (cm); Entries", kTH1F, {{2000, 0, 200}}); - // mHistogramRegistry->add((folderName + "/hCPA").c_str(), "; #it{cos #theta_{p}}; Entries", kTH1F, {{1000, 0.9, 1.}}); - // mHistogramRegistry->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.}}); - mHistogramRegistry->add((folderName + "/hInvMassPhi").c_str(), "", kTH1F, {massAxisPhi}); - PosDaughTrack.init(mHistogramRegistry); - NegDaughTrack.init(mHistogramRegistry); - - mHistogramRegistry->add("PhiQA/hInvMasPhiNoCuts", "No cuts", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiInvMassCut", "Invariant mass cut", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiPtMin", "Minimum Pt cut", kTH1F, {massAxisPhi}); - mHistogramRegistry->add("PhiQA/hInvMassPhiPtMax", "Maximum Pt cut", kTH1F, {massAxisPhi}); - // mHistogramRegistry->add("PhiQA/hInvMassPhiDCAPhiDaugh", "Phi-daughters DCA cut", kTH1F, {massAxisPhi}); - // mHistogramRegistry->add("PhiQA/hInvMassPhiCPA", "CPA cut", kTH1F, {massAxisPhi}); - // mHistogramRegistry->add("PhiQA/hInvMassPhiTranRadMin", "Minimum transverse radius cut", kTH1F, {massAxisPhi}); - // mHistogramRegistry->add("PhiQA/hInvMassPhiTranRadMax", "Maximum transverse radius cut", kTH1F, {massAxisPhi}); - // mHistogramRegistry->add("PhiQA/hInvMassPhiDecVtxMax", "Maximum distance on decay vertex cut", kTH1F, {massAxisPhi}); - } - /// check whether the most open cuts are fulfilled - most of this should have already be done by the filters - nPtPhiMinSel = getNSelections(femtoUniversePhiSelection::kpTPhiMin); - nPtPhiMaxSel = getNSelections(femtoUniversePhiSelection::kpTPhiMax); - nDCAPhiDaughMax = getNSelections(femtoUniversePhiSelection::kDCAPhiDaughMax); - nCPAPhiMin = getNSelections(femtoUniversePhiSelection::kCPAPhiMin); - nTranRadPhiMin = getNSelections(femtoUniversePhiSelection::kTranRadPhiMin); - nTranRadPhiMax = getNSelections(femtoUniversePhiSelection::kTranRadPhiMax); - nDecVtxMax = getNSelections(femtoUniversePhiSelection::kDecVtxMax); - - pTPhiMin = getMinimalSelection(femtoUniversePhiSelection::kpTPhiMin, femtoUniverseSelection::kLowerLimit); - pTPhiMax = getMinimalSelection(femtoUniversePhiSelection::kpTPhiMax, femtoUniverseSelection::kUpperLimit); - DCAPhiDaughMax = getMinimalSelection(femtoUniversePhiSelection::kDCAPhiDaughMax, femtoUniverseSelection::kUpperLimit); - CPAPhiMin = getMinimalSelection(femtoUniversePhiSelection::kCPAPhiMin, femtoUniverseSelection::kLowerLimit); - TranRadPhiMin = getMinimalSelection(femtoUniversePhiSelection::kTranRadPhiMin, femtoUniverseSelection::kLowerLimit); - TranRadPhiMax = getMinimalSelection(femtoUniversePhiSelection::kTranRadPhiMax, femtoUniverseSelection::kUpperLimit); - DecVtxMax = getMinimalSelection(femtoUniversePhiSelection::kDecVtxMax, femtoUniverseSelection::kAbsUpperLimit); + std::string folderName = static_cast( + o2::aod::femtouniverseparticle::ParticleTypeName[part]); + /// \todo initialize histograms for children tracks of phis + mHistogramRegistry->add((folderName + "/hPt").c_str(), + "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, + {{1000, 0, 10}}); + mHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", + kTH1F, {{1000, -1, 1}}); + mHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", + kTH1F, {{1000, 0, 2. * M_PI}}); + mHistogramRegistry->add((folderName + "/hInvMassPhi").c_str(), "", kTH1F, + {massAxisPhi}); + + PosDaughTrack.init( + mHistogramRegistry); + NegDaughTrack.init( + mHistogramRegistry); + + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaNoCuts", "No cuts", kTH1F, + // {massAxisLambda}); + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaInvMassCut", + // "Invariant mass cut", kTH1F, {massAxisLambda}); + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMin", "Minimum Pt cut", + // kTH1F, {massAxisLambda}); + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMax", "Maximum Pt cut", + // kTH1F, {massAxisLambda}); + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaEtaMax", "Maximum Eta cut", + // kTH1F, {massAxisLambda}); + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaDCAPhiDaugh", + // "Phi-daughters DCA cut", kTH1F, {massAxisLambda}); + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaCPA", "CPA cut", kTH1F, + // {massAxisLambda}); + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMin", + // "Minimum transverse radius cut", kTH1F, + // {massAxisLambda}); + // mHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMax", + // "Maximum transverse radius cut", kTH1F, + // {massAxisLambda}); + // mHistogramRegistry->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 + nPtPhiMinSel = getNSelections(femtoUniversePhiSelection::kPhipTMin); + nPtPhiMaxSel = getNSelections(femtoUniversePhiSelection::kPhipTMax); + nEtaPhiMaxSel = getNSelections(femtoUniversePhiSelection::kPhietaMax); + nDCAPhiDaughMax = getNSelections(femtoUniversePhiSelection::kPhiDCADaughMax); + nCPAPhiMin = getNSelections(femtoUniversePhiSelection::kPhiCPAMin); + nTranRadPhiMin = getNSelections(femtoUniversePhiSelection::kPhiTranRadMin); + nTranRadPhiMax = getNSelections(femtoUniversePhiSelection::kPhiTranRadMax); + nDecVtxMax = getNSelections(femtoUniversePhiSelection::kPhiDecVtxMax); + + pTPhiMin = getMinimalSelection(femtoUniversePhiSelection::kPhipTMin, + femtoUniverseSelection::kLowerLimit); + pTPhiMax = getMinimalSelection(femtoUniversePhiSelection::kPhipTMax, + femtoUniverseSelection::kUpperLimit); + etaPhiMax = getMinimalSelection(femtoUniversePhiSelection::kPhietaMax, + femtoUniverseSelection::kAbsUpperLimit); + DCAPhiDaughMax = getMinimalSelection(femtoUniversePhiSelection::kPhiDCADaughMax, + femtoUniverseSelection::kUpperLimit); + CPAPhiMin = getMinimalSelection(femtoUniversePhiSelection::kPhiCPAMin, + femtoUniverseSelection::kLowerLimit); + TranRadPhiMin = getMinimalSelection(femtoUniversePhiSelection::kPhiTranRadMin, + femtoUniverseSelection::kLowerLimit); + TranRadPhiMax = getMinimalSelection(femtoUniversePhiSelection::kPhiTranRadMax, + femtoUniverseSelection::kUpperLimit); + DecVtxMax = getMinimalSelection(femtoUniversePhiSelection::kPhiDecVtxMax, + femtoUniverseSelection::kAbsUpperLimit); } template -bool FemtoUniversePhiSelection::isSelectedMinimal(C const& col, V const& v0, T const& posTrack, T const& negTrack) +bool FemtoUniversePhiSelection::isSelectedMinimal(C const& col, V const& phi, + T const& posTrack, + T const& negTrack) { const auto signPos = posTrack.sign(); const auto signNeg = negTrack.sign(); if (signPos < 0 || signNeg > 0) { - LOGF(error, "-Something wrong in isSelectedMinimal--\n"); - LOGF(error, "ERROR - Wrong sign for Phi daughters\n"); - } - const float pT = v0.pt(); - const std::vector decVtx = {v0.x(), v0.y(), v0.z()}; - const float tranRad = v0.v0radius(); - const float dcaDaughv0 = v0.dcaPhidaughters(); - const float cpav0 = v0.v0cosPA(col.posX(), col.posY(), col.posZ()); - - const float invMassPhi = v0.mPhi(); - const float invMassAntiPhi = v0.mAntiPhi(); - - if (((invMassPhi < fInvMassLowLimit) || (invMassPhi > fInvMassUpLimit)) && ((invMassAntiPhi < fInvMassLowLimit) || (invMassAntiPhi > fInvMassUpLimit))) { + LOG(warn) << "Something wrong in isSelectedMinimal"; + LOG(warn) << "ERROR - Wrong sign for Phi daughters"; + } + // asfaf + const float pT = phi.pt(); + const float eta = phi.eta(); + const std::vector decVtx = {phi.x(), phi.y(), phi.z()}; + const float tranRad = phi.phiradius(); + const float dcaDaughphi = phi.dcaPhidaughters(); + const float cpaphi = phi.phicosPA(col.posX(), col.posY(), col.posZ()); + + const float invMassLambda = phi.mLambda(); + const float invMassAntiLambda = phi.mAntiLambda(); + + if ((invMassLambda < fInvMassLowLimit || invMassLambda > fInvMassUpLimit) && + (invMassAntiLambda < fInvMassLowLimit || + invMassAntiLambda > fInvMassUpLimit)) { return false; } if (fRejectKaon) { - const float invMassKaon = v0.mK0Short(); - if (invMassKaon > fInvMassKaonLowLimit && invMassKaon < fInvMassKaonUpLimit) { + const float invMassKaon = phi.mK0Short(); + if (invMassKaon > fInvMassKaonLowLimit && + invMassKaon < fInvMassKaonUpLimit) { return false; } } @@ -418,10 +414,13 @@ bool FemtoUniversePhiSelection::isSelectedMinimal(C const& col, V const& v0, T c if (nPtPhiMaxSel > 0 && pT > pTPhiMax) { return false; } - if (nDCAPhiDaughMax > 0 && dcaDaughv0 > DCAPhiDaughMax) { + if (nEtaPhiMaxSel > 0 && std::abs(eta) > etaPhiMax) { + return false; + } + if (nDCAPhiDaughMax > 0 && dcaDaughphi > DCAPhiDaughMax) { return false; } - if (nCPAPhiMin > 0 && cpav0 < CPAPhiMin) { + if (nCPAPhiMin > 0 && cpaphi < CPAPhiMin) { return false; } if (nTranRadPhiMin > 0 && tranRad < TranRadPhiMin) { @@ -447,10 +446,13 @@ bool FemtoUniversePhiSelection::isSelectedMinimal(C const& col, V const& v0, T c // antiPhi auto nSigmaPrNeg = negTrack.tpcNSigmaPr(); auto nSigmaPiPos = posTrack.tpcNSigmaPi(); - // v0 + // phi auto nSigmaPiNeg = negTrack.tpcNSigmaPi(); auto nSigmaPrPos = posTrack.tpcNSigmaPr(); - if (!((abs(nSigmaPrNeg) < nSigmaPIDMax) && (abs(nSigmaPiPos) < nSigmaPIDMax)) && !((abs(nSigmaPrPos) < nSigmaPIDMax) && (abs(nSigmaPiNeg) < nSigmaPIDMax))) { + if (!(abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax) && + !(abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax)) { return false; } @@ -458,81 +460,84 @@ bool FemtoUniversePhiSelection::isSelectedMinimal(C const& col, V const& v0, T c } template -void FemtoUniversePhiSelection::fillPhiQA(C const& col, V const& v0, T const& posTrack, T const& negTrack) +void FemtoUniversePhiSelection::fillLambdaQA(C const& col, V const& phi, + T const& posTrack, T const& negTrack) { const auto signPos = posTrack.sign(); const auto signNeg = negTrack.sign(); if (signPos < 0 || signNeg > 0) { - LOGF(error, "-Something wrong in isSelectedMinimal--\n"); - LOGF(error, "ERROR - Wrong sign for Phi daughters\n"); + LOG(warn) << "Something wrong in isSelectedMinimal"; + LOG(warn) << "ERROR - Wrong sign for Phi daughters"; } - const float pT = v0.pt(); - const std::vector decVtx = {v0.x(), v0.y(), v0.z()}; - const float tranRad = v0.v0radius(); - const float dcaDaughv0 = v0.dcaPhidaughters(); - const float cpav0 = v0.v0cosPA(col.posX(), col.posY(), col.posZ()); + const float pT = phi.pt(); + const float eta = phi.eta(); + const std::vector decVtx = {phi.x(), phi.y(), phi.z()}; + const float tranRad = phi.phiradius(); + const float dcaDaughphi = phi.dcaPhidaughters(); + const float cpaphi = phi.phicosPA(col.posX(), col.posY(), col.posZ()); - const float invMassPhi = v0.mPhi(); + const float invMassLambda = phi.mLambda(); - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiNoCuts"), v0.mPhi()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaNoCuts"), phi.mLambda()); - if ((invMassPhi > fInvMassLowLimit) && (invMassPhi < fInvMassUpLimit)) { - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiInvMassCut"), v0.mPhi()); + if (invMassLambda > fInvMassLowLimit && invMassLambda < fInvMassUpLimit) { + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaInvMassCut"), + phi.mLambda()); } if (pT > pTPhiMin) { - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiPtMin"), v0.mPhi()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMin"), + phi.mLambda()); } if (pT < pTPhiMax) { - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiPtMax"), v0.mPhi()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMax"), + phi.mLambda()); } - if (dcaDaughv0 < DCAPhiDaughMax) { - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiDCAPhiDaugh"), v0.mPhi()); + if (std::abs(eta) < etaPhiMax) { + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaEtaMax"), + phi.mLambda()); } - if (cpav0 > CPAPhiMin) { - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiCPA"), v0.mPhi()); + if (dcaDaughphi < DCAPhiDaughMax) { + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDCAPhiDaugh"), + phi.mLambda()); + } + if (cpaphi > CPAPhiMin) { + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaCPA"), phi.mLambda()); } if (tranRad > TranRadPhiMin) { - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiTranRadMin"), v0.mPhi()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMin"), + phi.mLambda()); } if (tranRad < TranRadPhiMax) { - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiTranRadMax"), v0.mPhi()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMax"), + phi.mLambda()); } bool write = true; for (size_t i = 0; i < decVtx.size(); i++) { write = write && (decVtx.at(i) < DecVtxMax); } if (write) { - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiDecVtxMax"), v0.mPhi()); - } -} - -template -void FemtoUniversePhiSelection::fillPhiQAMass(C const& col, V const& MassPhi, T const& posTrack, T const& negTrack, P const& ConfInvMassLowLimit, P const& ConfInvMassUpLimit) -{ - const auto signPos = posTrack.sign(); - const auto signNeg = negTrack.sign(); - if (signPos < 0 || signNeg > 0) { - LOGF(error, "-Something wrong in isSelectedMinimal--\n"); - LOGF(error, "ERROR - Wrong sign for Phi daughters\n"); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDecVtxMax"), + phi.mLambda()); } - mHistogramRegistry->fill(HIST("PhiQA/hInvMassPhiNoCuts"), MassPhi); } -/// the CosPA of Phi needs as argument the posXYZ of collisions vertex so we need to pass the collsion as well -template -std::array FemtoUniversePhiSelection::getCutContainer(C const& col, T const& posTrack, T const& negTrack) +/// the CosPA of Phi needs as argument the posXYZ of collisions vertex so we need +/// to pass the collsion as well +template +std::array + FemtoUniversePhiSelection::getCutContainer(C const& col, V const& phi, T const& posTrack, T const& negTrack) { auto outputPosTrack = PosDaughTrack.getCutContainer(posTrack); auto outputNegTrack = NegDaughTrack.getCutContainer(negTrack); cutContainerType output = 0; size_t counter = 0; - // auto lambdaMassNominal = TDatabasePDG::Instance()->GetParticle(321)->Mass(); - // auto lambdaMassHypothesis = v0.mPhi(); - // auto antiPhiMassHypothesis = v0.mAntiPhi(); - // auto diffPhi = abs(lambdaMassNominal - lambdaMassHypothesis); - // auto diffAntiPhi = abs(antiPhiMassHypothesis - lambdaMassHypothesis); + auto lambdaMassNominal = TDatabasePDG::Instance()->GetParticle(3122)->Mass(); + auto lambdaMassHypothesis = phi.mLambda(); + auto antiLambdaMassHypothesis = phi.mAntiLambda(); + auto diffLambda = abs(lambdaMassNominal - lambdaMassHypothesis); + auto diffAntiLambda = abs(antiLambdaMassHypothesis - lambdaMassHypothesis); float sign = 0.; int nSigmaPIDMax = PosDaughTrack.getSigmaPIDMax(); @@ -541,41 +546,30 @@ std::array FemtoUniversePhiSelection::getCutContainer(C con auto nSigmaPiNeg = negTrack.tpcNSigmaPi(); auto nSigmaPrPos = posTrack.tpcNSigmaPr(); // check the mass and the PID of daughters - if (abs(nSigmaPrNeg) < nSigmaPIDMax && abs(nSigmaPiPos) < nSigmaPIDMax) { + if (abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && diffAntiLambda > diffLambda) { sign = -1.; - } else if (abs(nSigmaPrPos) < nSigmaPIDMax && abs(nSigmaPiNeg) < nSigmaPIDMax) { + } else if (abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && diffAntiLambda < diffLambda) { sign = 1.; - } else { // if it happens that none of these are true, ignore the invariant mass - if (abs(nSigmaPrNeg) < nSigmaPIDMax && abs(nSigmaPiPos) < nSigmaPIDMax) { + } else { + // if it happens that none of these are true, ignore the invariant mass + if (abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax) { sign = -1.; - } else if (abs(nSigmaPrPos) < nSigmaPIDMax && abs(nSigmaPiNeg) < nSigmaPIDMax) { + } else if (abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax) { sign = 1.; } } - TLorentzVector part1Vec; - TLorentzVector part2Vec; - Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 321, "Particle 1 - PDG code"}; - Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 321, "Particle 2 - PDG code"}; - float mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartOne)->Mass(); - float mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartTwo)->Mass(); - part1Vec.SetPtEtaPhiM(posTrack.pt(), posTrack.eta(), posTrack.phi(), mMassOne); - part2Vec.SetPtEtaPhiM(negTrack.pt(), negTrack.eta(), negTrack.phi(), mMassTwo); - - TLorentzVector sumVec(part1Vec); - sumVec += part2Vec; - - const auto pT = sumVec.Pt(); - // const auto tranRad = v0.v0radius(); - // const auto dcaDaughv0 = v0.dcaPhidaughters(); - // const auto cpav0 = v0.v0cosPA(col.posX(), col.posY(), col.posZ()); - const std::vector decVtx = {posTrack.x(), posTrack.y(), posTrack.z()}; + const auto pT = phi.pt(); + const auto eta = phi.eta(); + const auto tranRad = phi.phiradius(); + const auto dcaDaughphi = phi.dcaPhidaughters(); + const auto cpaphi = phi.phicosPA(col.posX(), col.posY(), col.posZ()); + const std::vector decVtx = {phi.x(), phi.y(), phi.z()}; float observable = 0.; for (auto& sel : mSelections) { const auto selVariable = sel.getSelectionVariable(); - - if (selVariable == femtoUniversePhiSelection::kDecVtxMax) { + if (selVariable == femtoUniversePhiSelection::kPhiDecVtxMax) { for (size_t i = 0; i < decVtx.size(); ++i) { auto decVtxValue = decVtx.at(i); sel.checkSelectionSetBit(decVtxValue, output, counter); @@ -585,91 +579,93 @@ std::array FemtoUniversePhiSelection::getCutContainer(C con case (femtoUniversePhiSelection::kPhiSign): observable = sign; break; - case (femtoUniversePhiSelection::kpTPhiMin): - case (femtoUniversePhiSelection::kpTPhiMax): + case (femtoUniversePhiSelection::kPhipTMin): + observable = pT; + break; + case (femtoUniversePhiSelection::kPhipTMax): observable = pT; break; - case (femtoUniversePhiSelection::kDCAPhiDaughMax): - // observable = dcaDaughv0; + case (femtoUniversePhiSelection::kPhietaMax): + observable = eta; + break; + case (femtoUniversePhiSelection::kPhiDCADaughMax): + observable = dcaDaughphi; break; - case (femtoUniversePhiSelection::kCPAPhiMin): - // observable = cpav0; + case (femtoUniversePhiSelection::kPhiCPAMin): + observable = cpaphi; break; - case (femtoUniversePhiSelection::kTranRadPhiMin): - case (femtoUniversePhiSelection::kTranRadPhiMax): - // observable = tranRad; + case (femtoUniversePhiSelection::kPhiTranRadMin): + observable = tranRad; break; - case (femtoUniversePhiSelection::kDecVtxMax): + case (femtoUniversePhiSelection::kPhiTranRadMax): + observable = tranRad; + break; + case (femtoUniversePhiSelection::kPhiDecVtxMax): break; } sel.checkSelectionSetBit(observable, output, counter); } } - return {output, outputPosTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), - outputPosTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID), - outputNegTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), - outputNegTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID)}; + return { + output, + outputPosTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), + outputPosTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID), + outputNegTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), + outputNegTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID)}; } -template -void FemtoUniversePhiSelection::fillQA(C const& col, V const& v0, T const& posTrack, T const& negTrack) +template +void FemtoUniversePhiSelection::fillQA(C const& col, V const& phi, T const& posTrack, + T const& negTrack, Q const& posPID, Q const& negPID) { if (mHistogramRegistry) { TLorentzVector part1Vec; TLorentzVector part2Vec; - Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 321, "Particle 1 - PDG code"}; - Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 321, "Particle 2 - PDG code"}; - float mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartOne)->Mass(); - float mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartTwo)->Mass(); + float mMassOne = TDatabasePDG::Instance()->GetParticle(321)->Mass(); + float mMassTwo = TDatabasePDG::Instance()->GetParticle(321)->Mass(); + part1Vec.SetPtEtaPhiM(posTrack.pt(), posTrack.eta(), posTrack.phi(), mMassOne); part2Vec.SetPtEtaPhiM(negTrack.pt(), negTrack.eta(), negTrack.phi(), mMassTwo); TLorentzVector sumVec(part1Vec); sumVec += part2Vec; - float phiEta = sumVec.Eta(); - float phiPhi = sumVec.Phi(); float phiPt = sumVec.Pt(); - float phiInvMass = sumVec.M(); - - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hPt"), phiPt); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hEta"), phiEta); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hPhi"), phiPhi); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDaughDCA"), v0.dcaPhidaughters()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hTransRadius"), v0.v0radius()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxX"), v0.x()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxY"), v0.y()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxZ"), v0.z()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassPhi"), phiInvMass); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassAntiPhi"), v0.mAntiPhi()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassPhiPhi"), v0.mPhi(), v0.mPhi()); - } - - PosDaughTrack.fillQA(posTrack); - NegDaughTrack.fillQA(negTrack); -} + // float phiP = sumVec.P(); + float phiPhi = sumVec.Phi(); + if (sumVec.Phi() < 0) { + phiPhi = sumVec.Phi() + 2 * o2::constants::math::PI; + } else if (sumVec.Phi() >= 0) { + phiPhi = sumVec.Phi(); + } -template -void FemtoUniversePhiSelection::fillQAPhi(C const& col, V const& v0, T const& posTrack, T const& negTrack) -{ - if (mHistogramRegistry) { - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hPtPhi"), v0.pt()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hEtaPhi"), v0.eta()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hPhiPhi"), v0.phi()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDaughDCA"), v0.dcaPhidaughters()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hTransRadius"), v0.v0radius()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxX"), v0.x()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxY"), v0.y()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxZ"), v0.z()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hCPA"), v0.v0cosPA(col.posX(), col.posY(), col.posZ())); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hCPAvsPt"), v0.pt(), v0.v0cosPA(col.posX(), col.posY(), col.posZ())); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassPhi"), v0.mPhi()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassAntiPhi"), v0.mAntiPhi()); - // mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassPhiAntiPhi"), v0.mPhi(), v0.mAntiPhi()); - } - - PosDaughTrack.fillQA(posTrack); - NegDaughTrack.fillQA(negTrack); + float phiM = sumVec.M(); + + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hPt"), + phiPt); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hEta"), + phiEta); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hPhi"), + phiPhi); + + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hInvMassPhi"), + phiM); + } + + PosDaughTrack.fillQA(posTrack); + NegDaughTrack.fillQA(negTrack); } } // namespace o2::analysis::femtoUniverse diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h index b3f14fda7a7..ce368276d4b 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -12,10 +12,13 @@ /// \file FemtoUniverseSelection.h /// \brief FemtoUniverseSelection - small generic class to do selections /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSESELECTION_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSESELECTION_H_ +#include + namespace o2::analysis::femtoUniverse { @@ -107,6 +110,18 @@ class FemtoUniverseSelection ++counter; } + template + void checkSelectionSetBitPID(selValDataType observable, T& cutContainer) + { + /// If the selection is fulfilled the bit at the specified position (counter) within the bit-wise container is set to 1 + if (isSelected(observable)) { + cutContainer |= 1UL; + } else { + cutContainer |= 0UL; + } + cutContainer <<= 1; + } + private: selValDataType mSelVal{0.f}; ///< Value used for the selection selVariableDataType mSelVar; ///< Variable used for the selection diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h index f6e3102c642..8494da318b9 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -13,23 +13,21 @@ /// \brief Definition of the FemtoUniverseTrackCuts /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de /// \author Luca Barioglio, TU München, luca.barioglio@cern.ch -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSETRACKSELECTION_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSETRACKSELECTION_H_ +#include +#include #include #include -#include -#include - -#include "PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" - +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h" #include "ReconstructionDataFormats/PID.h" #include "Framework/HistogramRegistry.h" @@ -92,7 +90,9 @@ class FemtoUniverseTrackSelection : public FemtoUniverseObjectSelection 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", @@ -368,9 +374,9 @@ template auto FemtoUniverseTrackSelection::getNsigmaTOF(T const& track, o2::track::PID pid) { /// skip tracks without TOF signal - if (!track.hasTOF()) { - return 999.f; - } + // if (!track.hasTOF()) { + // return 999.f; + // } return o2::aod::pidutils::tofNSigma(pid, track); } @@ -440,7 +446,7 @@ bool FemtoUniverseTrackSelection::isSelectedMinimal(T const& track) bool isFulfilled = false; for (size_t i = 0; i < pidTPC.size(); ++i) { auto pidTPCVal = pidTPC.at(i); - if (std::abs(pidTPCVal) < nSigmaPIDMax) { + if (std::abs(pidTPCVal - nSigmaPIDOffsetTPC) < nSigmaPIDMax) { isFulfilled = true; } } @@ -457,7 +463,6 @@ std::array FemtoUniverseTrackSelection::getCutContainer(T c cutContainerType output = 0; size_t counter = 0; cutContainerType outputPID = 0; - size_t counterPID = 0; const auto sign = track.sign(); const auto pT = track.pt(); const auto eta = track.eta(); @@ -482,12 +487,12 @@ std::array FemtoUniverseTrackSelection::getCutContainer(T c const auto selVariable = sel.getSelectionVariable(); if (selVariable == femtoUniverseTrackSelection::kPIDnSigmaMax) { /// PID needs to be handled a bit differently since we may need more than one species - for (size_t i = 0; i < pidTPC.size(); ++i) { - auto pidTPCVal = pidTPC.at(i); - auto pidTOFVal = pidTOF.at(i); - sel.checkSelectionSetBit(pidTPCVal, outputPID, counterPID); + for (size_t i = 0; i < mPIDspecies.size(); ++i) { + auto pidTPCVal = pidTPC.at(i) - nSigmaPIDOffsetTPC; + auto pidTOFVal = pidTOF.at(i) - nSigmaPIDOffsetTOF; auto pidComb = std::sqrt(pidTPCVal * pidTPCVal + pidTOFVal * pidTOFVal); - sel.checkSelectionSetBit(pidComb, outputPID, counterPID); + sel.checkSelectionSetBitPID(pidTPCVal, outputPID); + sel.checkSelectionSetBitPID(pidComb, outputPID); } } else { diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseUtils.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseUtils.h deleted file mode 100644 index 174c9769815..00000000000 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseUtils.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file CFFilter.cxx -/// \brief Utilities for the FemtoUniverse framework -/// -/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch - -#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEUTILS_H_ -#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEUTILS_H_ - -#include -#include -#include "Framework/ASoAHelpers.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h" - -namespace o2::analysis::femtoUniverse -{ - -enum kPIDselection { - k3d5sigma = 0, - k3sigma = 1, - k2d5sigma = 2 -}; - -enum kDetector { - kTPC = 0, - kTPCTOF = 1, - kNdetectors = 2 -}; - -/// internal function that returns the kPIDselection element corresponding to a specifica n-sigma value -/// \param nSigma number of sigmas for PID -/// \param vNsigma vector with the number of sigmas of interest -/// \return kPIDselection corresponding to n-sigma -kPIDselection getPIDselection(const float nSigma, const std::vector& vNsigma) -{ - for (int i = 0; i < (static_cast)vNsigma.size(); i++) { - if (abs(nSigma - vNsigma[i]) < 1e-3) { - return static_cast(i); - } - } - LOG(info) << "Invalid value of nSigma: " << nSigma << ". Standard 3 sigma returned." << std::endl; - return kPIDselection::k3sigma; -} - -/// function that checks whether the PID selection specified in the vectors is fulfilled -/// \param pidcut Bit-wise container for the PID -/// \param vSpecies vector with ID corresponding to the selected species (output from cutculator) -/// \param nSpecies number of available selected species (output from cutculator) -/// \param nSigma number of sigma selection fo PID -/// \param vNsigma vector with available n-sigma selections for PID -/// \param kDetector enum corresponding to the PID technique -/// \return Whether the PID selection specified in the vectors is fulfilled -bool isPIDSelected(aod::femtouniverseparticle::cutContainerType const& pidcut, std::vector const& vSpecies, int nSpecies, float nSigma, const std::vector& vNsigma, const kDetector iDet = kDetector::kTPC) -{ - bool pidSelection = true; - kPIDselection iNsigma = getPIDselection(nSigma, vNsigma); - for (auto iSpecies : vSpecies) { - //\todo we also need the possibility to specify whether the bit is true/false ->std>>vector> - // if (!((pidcut >> it.first) & it.second)) { - int bit_to_check = nSpecies * kDetector::kNdetectors * iNsigma + iSpecies * kDetector::kNdetectors + iDet; - if (!(pidcut & (1UL << bit_to_check))) { - pidSelection = false; - } - } - return pidSelection; -}; - -/// function that checks whether the PID selection specified in the vectors is fulfilled, depending on the momentum TPC or TPC+TOF PID is conducted -/// \param pidcut Bit-wise container for the PID -/// \param momentum Momentum of the track -/// \param pidThresh Momentum threshold that separates between TPC and TPC+TOF PID -/// \param vSpecies Vector with the species of interest (number returned by the CutCulator) -/// \param nSpecies number of available selected species (output from cutculator) -/// \param nSigmaTPC Number of TPC sigmas for selection -/// \param nSigmaTPCTOF Number of TPC+TOF sigmas for selection (circular selection) -/// \return Whether the PID selection is fulfilled -bool isFullPIDSelected(aod::femtouniverseparticle::cutContainerType const& pidCut, float const momentum, float const pidThresh, std::vector const& vSpecies, int nSpecies, const std::vector& vNsigma = {3.5, 3., 2.5}, const float nSigmaTPC = 3.5, const float nSigmaTPCTOF = 3.5) -{ - bool pidSelection = true; - if (momentum < pidThresh) { - /// TPC PID only - pidSelection = isPIDSelected(pidCut, vSpecies, nSpecies, nSigmaTPC, vNsigma, kDetector::kTPC); - } else { - /// TPC + TOF PID - pidSelection = isPIDSelected(pidCut, vSpecies, nSpecies, nSigmaTPCTOF, vNsigma, kDetector::kTPCTOF); - } - return pidSelection; -}; - -} // namespace o2::analysis::femtoUniverse -#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEUTILS_H_ diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h index 66dea5e4e12..0389624d534 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -14,21 +14,22 @@ /// \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 -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEV0SELECTION_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEV0SELECTION_H_ -#include +#include #include +#include #include "PWGCF/FemtoUniverse/Core/FemtoUniverseObjectSelection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" -#include "ReconstructionDataFormats/PID.h" #include "Common/Core/RecoDecay.h" #include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/PID.h" using namespace o2::framework; @@ -37,14 +38,17 @@ namespace o2::analysis::femtoUniverse namespace femtoUniverseV0Selection { /// The different selections this task is capable of doing -enum V0Sel { kV0Sign, ///< +1 particle, -1 antiparticle - kpTV0Min, - kpTV0Max, - kDCAV0DaughMax, - kCPAV0Min, - kTranRadV0Min, - kTranRadV0Max, - kDecVtxMax }; +enum V0Sel { + kV0Sign, ///< +1 particle, -1 antiparticle + kV0pTMin, + kV0pTMax, + kV0etaMax, + kV0DCADaughMax, + kV0CPAMin, + kV0TranRadMin, + kV0TranRadMax, + kV0DecVtxMax +}; enum ChildTrackType { kPosTrack, kNegTrack }; @@ -61,51 +65,41 @@ enum V0ContainerPosition { /// \class FemtoUniverseV0Selection /// \brief Cut class to contain and execute all cuts applied to V0s -class FemtoUniverseV0Selection : public FemtoUniverseObjectSelection +class FemtoUniverseV0Selection + : public FemtoUniverseObjectSelection { public: - FemtoUniverseV0Selection() : nPtV0MinSel(0), - nPtV0MaxSel(0), - nDCAV0DaughMax(0), - nCPAV0Min(0), - nTranRadV0Min(0), - nTranRadV0Max(0), - nDecVtxMax(0), - pTV0Min(9999999.), - pTV0Max(-9999999.), - DCAV0DaughMax(-9999999.), - CPAV0Min(9999999.), - TranRadV0Min(9999999.), - TranRadV0Max(-9999999.), - DecVtxMax(-9999999.), - fInvMassLowLimit(1.05), - fInvMassUpLimit(1.3), - fRejectKaon(false), - fInvMassKaonLowLimit(0.48), - fInvMassKaonUpLimit(0.515) {} + FemtoUniverseV0Selection() + : 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), fInvMassKaonLowLimit(0.48), fInvMassKaonUpLimit(0.515), nSigmaPIDOffsetTPC(0.) {} /// Initializes histograms for the task - template + template void init(HistogramRegistry* registry); template - bool isSelectedMinimal(C const& col, V const& v0, T const& posTrack, T const& negTrack); + 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); + 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? + /// \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); - - // for getting colision of the phi candidate - // template - // std::array getCutContainerPhi(C const& col, V const& v0, T const& posTrack, T const& negTrack); + std::array getCutContainer(C const& col, V const& v0, + T const& posTrack, + T const& negTrack); - template + template void fillQA(C const& col, V const& v0, T const& posTrack, T const& negTrack); template - void setChildCuts(femtoUniverseV0Selection::ChildTrackType child, T1 selVal, T2 selVar, femtoUniverseSelection::SelectionType selType) + void setChildCuts(femtoUniverseV0Selection::ChildTrackType child, T1 selVal, + T2 selVar, femtoUniverseSelection::SelectionType selType) { if (child == femtoUniverseV0Selection::kPosTrack) { PosDaughTrack.setSelection(selVal, selVar, selType); @@ -114,7 +108,8 @@ class FemtoUniverseV0Selection : public FemtoUniverseObjectSelection - void setChildPIDSpecies(femtoUniverseV0Selection::ChildTrackType child, T& pids) + void setChildPIDSpecies(femtoUniverseV0Selection::ChildTrackType child, + T& pids) { if (child == femtoUniverseV0Selection::kPosTrack) { PosDaughTrack.setPIDSpecies(pids); @@ -127,7 +122,9 @@ class FemtoUniverseV0Selection : public FemtoUniverseObjectSelection(prefix); outString += static_cast(mSelectionNames[iSel]); @@ -138,10 +135,12 @@ class FemtoUniverseV0Selection : public FemtoUniverseObjectSelection(prefix) + static_cast(mSelectionNames[index]); + std::string comp = static_cast(prefix) + + static_cast(mSelectionNames[index]); std::string_view cmp{comp}; if (obs.compare(cmp) == 0) return index; @@ -152,15 +151,18 @@ class FemtoUniverseV0Selection : public FemtoUniverseObjectSelection(prefix); outString += static_cast(mSelectionHelper[iSel]); @@ -186,6 +188,11 @@ class FemtoUniverseV0Selection : public FemtoUniverseObjectSelection +template void FemtoUniverseV0Selection::init(HistogramRegistry* registry) { if (registry) { @@ -264,70 +286,130 @@ void FemtoUniverseV0Selection::init(HistogramRegistry* registry) fillSelectionHistogram(); AxisSpec massAxisLambda = {600, 0.0f, 3.0f, "m_{#Lambda} (GeV/#it{c}^{2})"}; - AxisSpec massAxisAntiLambda = {600, 0.0f, 3.0f, "m_{#bar{#Lambda}} (GeV/#it{c}^{2})"}; + 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 + /// \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) << "FemtoUniverseV0Cuts: Number of selections to large for your container - quitting!"; + LOG(fatal) << "FemtoUniverseV0Cuts: Number of selections to large for your " + "container - quitting!"; } - std::string folderName = static_cast(o2::aod::femtouniverseparticle::ParticleTypeName[part]); + std::string folderName = static_cast( + o2::aod::femtouniverseparticle::ParticleTypeName[part]); /// \todo initialize histograms for children tracks of v0s - mHistogramRegistry->add((folderName + "/hPt").c_str(), "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, {{1000, 0, 10}}); - mHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", kTH1F, {{1000, -1, 1}}); - mHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", kTH1F, {{1000, 0, 2. * M_PI}}); - mHistogramRegistry->add((folderName + "/hDaughDCA").c_str(), "; DCA^{daugh} (cm); Entries", kTH1F, {{1000, 0, 10}}); - mHistogramRegistry->add((folderName + "/hTransRadius").c_str(), "; #it{r}_{xy} (cm); Entries", kTH1F, {{1500, 0, 150}}); - mHistogramRegistry->add((folderName + "/hDecayVtxX").c_str(), "; #it{Vtx}_{x} (cm); Entries", kTH1F, {{2000, 0, 200}}); - mHistogramRegistry->add((folderName + "/hDecayVtxY").c_str(), "; #it{Vtx}_{y} (cm)); Entries", kTH1F, {{2000, 0, 200}}); - mHistogramRegistry->add((folderName + "/hDecayVtxZ").c_str(), "; #it{Vtx}_{z} (cm); Entries", kTH1F, {{2000, 0, 200}}); - mHistogramRegistry->add((folderName + "/hCPA").c_str(), "; #it{cos #theta_{p}}; Entries", kTH1F, {{1000, 0.9, 1.}}); - mHistogramRegistry->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.}}); - mHistogramRegistry->add((folderName + "/hInvMassLambda").c_str(), "", kTH1F, {massAxisLambda}); - mHistogramRegistry->add((folderName + "/hInvMassAntiLambda").c_str(), "", kTH1F, {massAxisAntiLambda}); - mHistogramRegistry->add((folderName + "/hInvMassLambdaAntiLambda").c_str(), "", kTH2F, {massAxisLambda, massAxisAntiLambda}); - - PosDaughTrack.init(mHistogramRegistry); - NegDaughTrack.init(mHistogramRegistry); - - mHistogramRegistry->add("LambdaQA/hInvMassLambdaNoCuts", "No cuts", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaInvMassCut", "Invariant mass cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMin", "Minimum Pt cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMax", "Maximum Pt cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaDCAV0Daugh", "V0-daughters DCA cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaCPA", "CPA cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMin", "Minimum transverse radius cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMax", "Maximum transverse radius cut", kTH1F, {massAxisLambda}); - mHistogramRegistry->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(femtoUniverseV0Selection::kpTV0Min); - nPtV0MaxSel = getNSelections(femtoUniverseV0Selection::kpTV0Max); - nDCAV0DaughMax = getNSelections(femtoUniverseV0Selection::kDCAV0DaughMax); - nCPAV0Min = getNSelections(femtoUniverseV0Selection::kCPAV0Min); - nTranRadV0Min = getNSelections(femtoUniverseV0Selection::kTranRadV0Min); - nTranRadV0Max = getNSelections(femtoUniverseV0Selection::kTranRadV0Max); - nDecVtxMax = getNSelections(femtoUniverseV0Selection::kDecVtxMax); - - pTV0Min = getMinimalSelection(femtoUniverseV0Selection::kpTV0Min, femtoUniverseSelection::kLowerLimit); - pTV0Max = getMinimalSelection(femtoUniverseV0Selection::kpTV0Max, femtoUniverseSelection::kUpperLimit); - DCAV0DaughMax = getMinimalSelection(femtoUniverseV0Selection::kDCAV0DaughMax, femtoUniverseSelection::kUpperLimit); - CPAV0Min = getMinimalSelection(femtoUniverseV0Selection::kCPAV0Min, femtoUniverseSelection::kLowerLimit); - TranRadV0Min = getMinimalSelection(femtoUniverseV0Selection::kTranRadV0Min, femtoUniverseSelection::kLowerLimit); - TranRadV0Max = getMinimalSelection(femtoUniverseV0Selection::kTranRadV0Max, femtoUniverseSelection::kUpperLimit); - DecVtxMax = getMinimalSelection(femtoUniverseV0Selection::kDecVtxMax, femtoUniverseSelection::kAbsUpperLimit); + mHistogramRegistry->add((folderName + "/hPt").c_str(), + "; #it{p}_{T} (GeV/#it{c}); Entries", kTH1F, + {{1000, 0, 10}}); + mHistogramRegistry->add((folderName + "/hEta").c_str(), "; #eta; Entries", + kTH1F, {{1000, -1, 1}}); + mHistogramRegistry->add((folderName + "/hPhi").c_str(), "; #phi; Entries", + kTH1F, {{1000, 0, 2. * M_PI}}); + mHistogramRegistry->add((folderName + "/hDaughDCA").c_str(), + "; DCA^{daugh} (cm); Entries", kTH1F, + {{1000, 0, 10}}); + mHistogramRegistry->add((folderName + "/hTransRadius").c_str(), + "; #it{r}_{xy} (cm); Entries", kTH1F, + {{1500, 0, 150}}); + mHistogramRegistry->add((folderName + "/hDecayVtxX").c_str(), + "; #it{Vtx}_{x} (cm); Entries", kTH1F, + {{2000, 0, 200}}); + mHistogramRegistry->add((folderName + "/hDecayVtxY").c_str(), + "; #it{Vtx}_{y} (cm)); Entries", kTH1F, + {{2000, 0, 200}}); + mHistogramRegistry->add((folderName + "/hDecayVtxZ").c_str(), + "; #it{Vtx}_{z} (cm); Entries", kTH1F, + {{2000, 0, 200}}); + mHistogramRegistry->add((folderName + "/hCPA").c_str(), + "; #it{cos #theta_{p}}; Entries", kTH1F, + {{1000, 0.9, 1.}}); + mHistogramRegistry->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.}}); + mHistogramRegistry->add((folderName + "/hInvMassLambda").c_str(), "", kTH1F, + {massAxisLambda}); + mHistogramRegistry->add((folderName + "/hInvMassAntiLambda").c_str(), "", + kTH1F, {massAxisAntiLambda}); + mHistogramRegistry->add((folderName + "/hInvMassLambdaAntiLambda").c_str(), + "", kTH2F, {massAxisLambda, massAxisAntiLambda}); + + PosDaughTrack.init( + mHistogramRegistry); + NegDaughTrack.init( + mHistogramRegistry); + + mHistogramRegistry->add("LambdaQA/hInvMassLambdaNoCuts", "No cuts", kTH1F, + {massAxisLambda}); + mHistogramRegistry->add("LambdaQA/hInvMassLambdaInvMassCut", + "Invariant mass cut", kTH1F, {massAxisLambda}); + mHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMin", "Minimum Pt cut", + kTH1F, {massAxisLambda}); + mHistogramRegistry->add("LambdaQA/hInvMassLambdaPtMax", "Maximum Pt cut", + kTH1F, {massAxisLambda}); + mHistogramRegistry->add("LambdaQA/hInvMassLambdaEtaMax", "Maximum Eta cut", + kTH1F, {massAxisLambda}); + mHistogramRegistry->add("LambdaQA/hInvMassLambdaDCAV0Daugh", + "V0-daughters DCA cut", kTH1F, {massAxisLambda}); + mHistogramRegistry->add("LambdaQA/hInvMassLambdaCPA", "CPA cut", kTH1F, + {massAxisLambda}); + mHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMin", + "Minimum transverse radius cut", kTH1F, + {massAxisLambda}); + mHistogramRegistry->add("LambdaQA/hInvMassLambdaTranRadMax", + "Maximum transverse radius cut", kTH1F, + {massAxisLambda}); + mHistogramRegistry->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(femtoUniverseV0Selection::kV0pTMin); + nPtV0MaxSel = getNSelections(femtoUniverseV0Selection::kV0pTMax); + nEtaV0MaxSel = getNSelections(femtoUniverseV0Selection::kV0etaMax); + nDCAV0DaughMax = getNSelections(femtoUniverseV0Selection::kV0DCADaughMax); + nCPAV0Min = getNSelections(femtoUniverseV0Selection::kV0CPAMin); + nTranRadV0Min = getNSelections(femtoUniverseV0Selection::kV0TranRadMin); + nTranRadV0Max = getNSelections(femtoUniverseV0Selection::kV0TranRadMax); + nDecVtxMax = getNSelections(femtoUniverseV0Selection::kV0DecVtxMax); + + pTV0Min = getMinimalSelection(femtoUniverseV0Selection::kV0pTMin, + femtoUniverseSelection::kLowerLimit); + pTV0Max = getMinimalSelection(femtoUniverseV0Selection::kV0pTMax, + femtoUniverseSelection::kUpperLimit); + etaV0Max = getMinimalSelection(femtoUniverseV0Selection::kV0etaMax, + femtoUniverseSelection::kAbsUpperLimit); + DCAV0DaughMax = getMinimalSelection(femtoUniverseV0Selection::kV0DCADaughMax, + femtoUniverseSelection::kUpperLimit); + CPAV0Min = getMinimalSelection(femtoUniverseV0Selection::kV0CPAMin, + femtoUniverseSelection::kLowerLimit); + TranRadV0Min = getMinimalSelection(femtoUniverseV0Selection::kV0TranRadMin, + femtoUniverseSelection::kLowerLimit); + TranRadV0Max = getMinimalSelection(femtoUniverseV0Selection::kV0TranRadMax, + femtoUniverseSelection::kUpperLimit); + DecVtxMax = getMinimalSelection(femtoUniverseV0Selection::kV0DecVtxMax, + femtoUniverseSelection::kAbsUpperLimit); } template -bool FemtoUniverseV0Selection::isSelectedMinimal(C const& col, V const& v0, T const& posTrack, T const& negTrack) +bool FemtoUniverseV0Selection::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) { - LOGF(error, "-Something wrong in isSelectedMinimal--\n"); - LOGF(error, "ERROR - Wrong sign for V0 daughters\n"); + 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(); @@ -336,12 +418,15 @@ bool FemtoUniverseV0Selection::isSelectedMinimal(C const& col, V const& v0, T co const float invMassLambda = v0.mLambda(); const float invMassAntiLambda = v0.mAntiLambda(); - if (((invMassLambda < fInvMassLowLimit) || (invMassLambda > fInvMassUpLimit)) && ((invMassAntiLambda < fInvMassLowLimit) || (invMassAntiLambda > fInvMassUpLimit))) { + if ((invMassLambda < fInvMassLowLimit || invMassLambda > fInvMassUpLimit) && + (invMassAntiLambda < fInvMassLowLimit || + invMassAntiLambda > fInvMassUpLimit)) { return false; } if (fRejectKaon) { const float invMassKaon = v0.mK0Short(); - if (invMassKaon > fInvMassKaonLowLimit && invMassKaon < fInvMassKaonUpLimit) { + if (invMassKaon > fInvMassKaonLowLimit && + invMassKaon < fInvMassKaonUpLimit) { return false; } } @@ -351,6 +436,9 @@ bool FemtoUniverseV0Selection::isSelectedMinimal(C const& col, V const& v0, T co if (nPtV0MaxSel > 0 && pT > pTV0Max) { return false; } + if (nEtaV0MaxSel > 0 && std::abs(eta) > etaV0Max) { + return false; + } if (nDCAV0DaughMax > 0 && dcaDaughv0 > DCAV0DaughMax) { return false; } @@ -383,7 +471,10 @@ bool FemtoUniverseV0Selection::isSelectedMinimal(C const& col, V const& v0, T co // v0 auto nSigmaPiNeg = negTrack.tpcNSigmaPi(); auto nSigmaPrPos = posTrack.tpcNSigmaPr(); - if (!((abs(nSigmaPrNeg) < nSigmaPIDMax) && (abs(nSigmaPiPos) < nSigmaPIDMax)) && !((abs(nSigmaPrPos) < nSigmaPIDMax) && (abs(nSigmaPiNeg) < nSigmaPIDMax))) { + if (!(abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax) && + !(abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && + abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax)) { return false; } @@ -391,15 +482,17 @@ bool FemtoUniverseV0Selection::isSelectedMinimal(C const& col, V const& v0, T co } template -void FemtoUniverseV0Selection::fillLambdaQA(C const& col, V const& v0, T const& posTrack, T const& negTrack) +void FemtoUniverseV0Selection::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) { - LOGF(error, "-Something wrong in isSelectedMinimal--\n"); - LOGF(error, "ERROR - Wrong sign for V0 daughters\n"); + 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(); @@ -409,40 +502,53 @@ void FemtoUniverseV0Selection::fillLambdaQA(C const& col, V const& v0, T const& mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaNoCuts"), v0.mLambda()); - if ((invMassLambda > fInvMassLowLimit) && (invMassLambda < fInvMassUpLimit)) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaInvMassCut"), v0.mLambda()); + if (invMassLambda > fInvMassLowLimit && invMassLambda < fInvMassUpLimit) { + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaInvMassCut"), + v0.mLambda()); } if (pT > pTV0Min) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMin"), v0.mLambda()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMin"), + v0.mLambda()); } if (pT < pTV0Max) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMax"), v0.mLambda()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaPtMax"), + v0.mLambda()); + } + if (std::abs(eta) < etaV0Max) { + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaEtaMax"), + v0.mLambda()); } if (dcaDaughv0 < DCAV0DaughMax) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDCAV0Daugh"), v0.mLambda()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDCAV0Daugh"), + v0.mLambda()); } if (cpav0 > CPAV0Min) { mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaCPA"), v0.mLambda()); } if (tranRad > TranRadV0Min) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMin"), v0.mLambda()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMin"), + v0.mLambda()); } if (tranRad < TranRadV0Max) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMax"), v0.mLambda()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaTranRadMax"), + v0.mLambda()); } bool write = true; for (size_t i = 0; i < decVtx.size(); i++) { write = write && (decVtx.at(i) < DecVtxMax); } if (write) { - mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDecVtxMax"), v0.mLambda()); + mHistogramRegistry->fill(HIST("LambdaQA/hInvMassLambdaDecVtxMax"), + v0.mLambda()); } } -/// the CosPA of V0 needs as argument the posXYZ of collisions vertex so we need to pass the collsion as well +/// the CosPA of V0 needs as argument the posXYZ of collisions vertex so we need +/// to pass the collsion as well template -std::array FemtoUniverseV0Selection::getCutContainer(C const& col, V const& v0, T const& posTrack, T const& negTrack) +std::array + FemtoUniverseV0Selection::getCutContainer(C const& col, V const& v0, T const& posTrack, T const& negTrack) { auto outputPosTrack = PosDaughTrack.getCutContainer(posTrack); auto outputNegTrack = NegDaughTrack.getCutContainer(negTrack); @@ -462,19 +568,21 @@ std::array FemtoUniverseV0Selection::getCutContainer(C cons auto nSigmaPiNeg = negTrack.tpcNSigmaPi(); auto nSigmaPrPos = posTrack.tpcNSigmaPr(); // check the mass and the PID of daughters - if (abs(nSigmaPrNeg) < nSigmaPIDMax && abs(nSigmaPiPos) < nSigmaPIDMax && diffAntiLambda > diffLambda) { + if (abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && diffAntiLambda > diffLambda) { sign = -1.; - } else if (abs(nSigmaPrPos) < nSigmaPIDMax && abs(nSigmaPiNeg) < nSigmaPIDMax && diffAntiLambda < diffLambda) { + } else if (abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && diffAntiLambda < diffLambda) { sign = 1.; - } else { // if it happens that none of these are true, ignore the invariant mass - if (abs(nSigmaPrNeg) < nSigmaPIDMax && abs(nSigmaPiPos) < nSigmaPIDMax) { + } else { + // if it happens that none of these are true, ignore the invariant mass + if (abs(nSigmaPrNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax && abs(nSigmaPiPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax) { sign = -1.; - } else if (abs(nSigmaPrPos) < nSigmaPIDMax && abs(nSigmaPiNeg) < nSigmaPIDMax) { + } else if (abs(nSigmaPrPos - nSigmaPIDOffsetTPC) < nSigmaPIDMax && abs(nSigmaPiNeg - nSigmaPIDOffsetTPC) < nSigmaPIDMax) { sign = 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(col.posX(), col.posY(), col.posZ()); @@ -483,8 +591,7 @@ std::array FemtoUniverseV0Selection::getCutContainer(C cons float observable = 0.; for (auto& sel : mSelections) { const auto selVariable = sel.getSelectionVariable(); - - if (selVariable == femtoUniverseV0Selection::kDecVtxMax) { + if (selVariable == femtoUniverseV0Selection::kV0DecVtxMax) { for (size_t i = 0; i < decVtx.size(); ++i) { auto decVtxValue = decVtx.at(i); sel.checkSelectionSetBit(decVtxValue, output, counter); @@ -494,53 +601,106 @@ std::array FemtoUniverseV0Selection::getCutContainer(C cons case (femtoUniverseV0Selection::kV0Sign): observable = sign; break; - case (femtoUniverseV0Selection::kpTV0Min): - case (femtoUniverseV0Selection::kpTV0Max): + case (femtoUniverseV0Selection::kV0pTMin): + observable = pT; + break; + case (femtoUniverseV0Selection::kV0pTMax): observable = pT; break; - case (femtoUniverseV0Selection::kDCAV0DaughMax): + case (femtoUniverseV0Selection::kV0etaMax): + observable = eta; + break; + case (femtoUniverseV0Selection::kV0DCADaughMax): observable = dcaDaughv0; break; - case (femtoUniverseV0Selection::kCPAV0Min): + case (femtoUniverseV0Selection::kV0CPAMin): observable = cpav0; break; - case (femtoUniverseV0Selection::kTranRadV0Min): - case (femtoUniverseV0Selection::kTranRadV0Max): + case (femtoUniverseV0Selection::kV0TranRadMin): + observable = tranRad; + break; + case (femtoUniverseV0Selection::kV0TranRadMax): observable = tranRad; break; - case (femtoUniverseV0Selection::kDecVtxMax): + case (femtoUniverseV0Selection::kV0DecVtxMax): break; } sel.checkSelectionSetBit(observable, output, counter); } } - return {output, outputPosTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), - outputPosTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID), - outputNegTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), - outputNegTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID)}; + return { + output, + outputPosTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), + outputPosTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID), + outputNegTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), + outputNegTrack.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID)}; } -template -void FemtoUniverseV0Selection::fillQA(C const& col, V const& v0, T const& posTrack, T const& negTrack) +template +void FemtoUniverseV0Selection::fillQA(C const& col, V const& v0, T const& posTrack, + T const& negTrack) { if (mHistogramRegistry) { - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hPt"), v0.pt()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hEta"), v0.eta()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hPhi"), v0.phi()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDaughDCA"), v0.dcaV0daughters()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hTransRadius"), v0.v0radius()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxX"), v0.x()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxY"), v0.y()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hDecayVtxZ"), v0.z()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hCPA"), v0.v0cosPA(col.posX(), col.posY(), col.posZ())); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hCPAvsPt"), v0.pt(), v0.v0cosPA(col.posX(), col.posY(), col.posZ())); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassLambda"), v0.mLambda()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassAntiLambda"), v0.mAntiLambda()); - mHistogramRegistry->fill(HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + HIST("/hInvMassLambdaAntiLambda"), v0.mLambda(), v0.mAntiLambda()); - } - - PosDaughTrack.fillQA(posTrack); - NegDaughTrack.fillQA(negTrack); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hPt"), + v0.pt()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hEta"), + v0.eta()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hPhi"), + v0.phi()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hDaughDCA"), + v0.dcaV0daughters()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hTransRadius"), + v0.v0radius()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hDecayVtxX"), + v0.x()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hDecayVtxY"), + v0.y()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hDecayVtxZ"), + v0.z()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hCPA"), + v0.v0cosPA(col.posX(), col.posY(), col.posZ())); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hCPAvsPt"), + v0.pt(), v0.v0cosPA(col.posX(), col.posY(), col.posZ())); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hInvMassLambda"), + v0.mLambda()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hInvMassAntiLambda"), + v0.mAntiLambda()); + mHistogramRegistry->fill( + HIST(o2::aod::femtouniverseparticle::ParticleTypeName[part]) + + HIST("/hInvMassLambdaAntiLambda"), + v0.mLambda(), v0.mAntiLambda()); + } + + PosDaughTrack.fillQA(posTrack); + NegDaughTrack.fillQA(negTrack); } } // namespace o2::analysis::femtoUniverse diff --git a/PWGCF/FemtoUniverse/Core/FemtoUtils.h b/PWGCF/FemtoUniverse/Core/FemtoUtils.h new file mode 100644 index 00000000000..0a907474ec2 --- /dev/null +++ b/PWGCF/FemtoUniverse/Core/FemtoUtils.h @@ -0,0 +1,131 @@ +// 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 FemtoUtils.h +/// \brief Utilities for the FemtoUniverse framework +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUTILS_H_ +#define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUTILS_H_ + +#include +#include +#include +#include "Framework/ASoAHelpers.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +namespace o2::analysis::femtoUniverse +{ + +enum kDetector { kTPC, + kTPCTOF, + kNdetectors }; + +/// internal function that returns the kPIDselection element corresponding to a +/// specifica n-sigma value \param nSigma number of sigmas for PID +/// \param vNsigma vector with the number of sigmas of interest +/// \return kPIDselection corresponding to n-sigma +int getPIDselection(float nSigma, std::vector vNsigma) +{ + std::sort(vNsigma.begin(), vNsigma.end(), std::greater<>()); + auto it = std::find(vNsigma.begin(), vNsigma.end(), nSigma); + if (it == vNsigma.end()) { + LOG(warn) << "Invalid value of nSigma: " << nSigma << ". Return the largest value of the vector: " << *it; + } + return std::distance(vNsigma.begin(), it); +} + +/// function that checks whether the PID selection specified in the vectors is +/// fulfilled +/// \param pidcut Bit-wise container for the PID +/// \param vSpecies number (ID) of the species of interest (as returned by the CutCulator), e.g. 0 / 1 / 2, usually 0 if only one particle species in the skimmed data +/// \param nSpecies number of available selected species (output from cutculator), i.e. how many particle types were saved in the skimmed data +/// \param nSigma Nsigma selection for PID (e.g. 3, for NsigmaTPC < 3 or NsigmaTPCTOF < 3) +/// \param vNsigma vector with available n-sigma selections for PID (to check if chosen nSigma value is avialable + size to get the bit number) +/// \param kDetector enum corresponding to the PID technique +/// \return Whether the PID selection specified in the vectors is fulfilled +bool isPIDSelected(aod::femtouniverseparticle::cutContainerType pidcut, + int vSpecies, + int nSpecies, + float nSigma, + std::vector vNsigma, + kDetector iDet) +{ + int iNsigma = getPIDselection(nSigma, vNsigma); + int nDet = static_cast(kDetector::kNdetectors); + int bit_to_check = 1 + (vNsigma.size() - (iNsigma + 1)) * nDet * nSpecies + (nSpecies - (vSpecies + 1)) * nSpecies + (nDet - 1 - iDet); + return ((pidcut >> (bit_to_check)) & 1) == 1; +}; + +/// function that checks whether the PID selection specified in the vectors is fulfilled, depending on the momentum TPC or TPC+TOF PID is conducted +/// \param pidcut Bit-wise container for the PID +/// \param momentum Momentum of the track +/// \param pidThresh Momentum threshold that separates between TPC and TPC+TOF PID +/// \param vSpecies number (ID) of the species of interest (as returned by the CutCulator), e.g. 0 / 1 / 2, usually 0 if only one particle specie in the skimmed data +/// \param nSpecies number of available selected species (output from cutculator), i.e. how many particle types were saved in the skimmed data +/// \param vNsigma vector with available n-sigma selections for PID +/// \param nSigmaTPC Number of TPC sigmas for selection +/// \param nSigmaTPCTOF Number of TPC+TOF sigmas for selection (circular selection) +/// \return Whether the PID selection is fulfilled +bool isFullPIDSelected(aod::femtouniverseparticle::cutContainerType const& pidCut, + float momentum, + float pidThresh, + int vSpecies, + int nSpecies, + std::vector vNsigma, + float nSigmaTPC, + float nSigmaTPCTOF) +{ + bool pidSelection = true; + if (momentum < pidThresh) { + /// TPC PID only + pidSelection = isPIDSelected(pidCut, vSpecies, nSpecies, nSigmaTPC, vNsigma, kDetector::kTPC); + } else { + /// TPC + TOF PID + pidSelection = isPIDSelected(pidCut, vSpecies, nSpecies, nSigmaTPCTOF, vNsigma, kDetector::kTPCTOF); + } + return pidSelection; +}; + +int checkDaughterType(o2::aod::femtouniverseparticle::ParticleType partType, int motherPDG) +{ + int partOrigin = 0; + if (partType == o2::aod::femtouniverseparticle::ParticleType::kTrack) { + + switch (abs(motherPDG)) { + case 3122: + partOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kDaughterLambda; + break; + case 3222: + partOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kDaughterSigmaplus; + break; + default: + partOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kDaughter; + } // switch + + } else if (partType == o2::aod::femtouniverseparticle::ParticleType::kV0) { + partOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kDaughter; + + } else if (partType == o2::aod::femtouniverseparticle::ParticleType::kV0Child) { + partOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kDaughter; + + } else if (partType == o2::aod::femtouniverseparticle::ParticleType::kCascade) { + partOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kDaughter; + + } else if (partType == o2::aod::femtouniverseparticle::ParticleType::kCascadeBachelor) { + partOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kDaughter; + } + return partOrigin; +}; + +} // namespace o2::analysis::femtoUniverse +#endif // PWGCF_FEMTOUNIVERSE_CORE_FEMTOUTILS_H_ diff --git a/PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h similarity index 58% rename from PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h rename to PWGCF/FemtoUniverse/DataModel/FemtoDerived.h index 12f6a8e9185..f9a33a18fcc 100644 --- a/PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h +++ b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -9,11 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef PWGCF_FEMTOUNIVERSE_DATAMODEL_FEMTOUNIVERSEDERIVED_H_ -#define PWGCF_FEMTOUNIVERSE_DATAMODEL_FEMTOUNIVERSEDERIVED_H_ +#ifndef PWGCF_FEMTOUNIVERSE_DATAMODEL_FEMTODERIVED_H_ +#define PWGCF_FEMTOUNIVERSE_DATAMODEL_FEMTODERIVED_H_ #include - #include "Framework/ASoA.h" #include "MathUtils/Utils.h" #include "Framework/DataTypes.h" @@ -29,18 +28,20 @@ namespace o2::aod namespace femtouniversecollision { DECLARE_SOA_COLUMN(MultV0M, multV0M, float); //! V0M multiplicity +DECLARE_SOA_COLUMN(MultNtr, multNtr, int); //! multiplicity of charged tracks as defined in the producer DECLARE_SOA_COLUMN(Sphericity, sphericity, float); //! Sphericity of the event -DECLARE_SOA_COLUMN(MagField, magField, float); //! Sphericity of the event +DECLARE_SOA_COLUMN(MagField, magField, float); //! Magnetic field of the event } // namespace femtouniversecollision -DECLARE_SOA_TABLE(FemtoUniverseCollisions, "AOD", "FEMTOUNICOLS", +DECLARE_SOA_TABLE(FDCollisions, "AOD", "FDCOLLISION", o2::soa::Index<>, o2::aod::collision::PosZ, femtouniversecollision::MultV0M, + femtouniversecollision::MultNtr, femtouniversecollision::Sphericity, femtouniversecollision::MagField); -using FemtoUniverseCollision = FemtoUniverseCollisions::iterator; +using FDCollision = FDCollisions::iterator; /// FemtoUniverseTrack namespace femtouniverseparticle @@ -48,17 +49,18 @@ namespace femtouniverseparticle /// Distinuishes the different particle types enum ParticleType { kTrack, //! Track + kMCTruthTrack, //! MC Truth Track kV0, //! V0 kV0Child, //! Child track of a V0 - kPhi, // PhiCandidate type - kPhiChild, // PhiCandidate type kCascade, //! Cascade kCascadeBachelor, //! Bachelor track of a cascade + kPhi, //! Phi meson + kPhiChild, //! Child track of a Phi meson kNParticleTypes //! Number of particle types - }; -static constexpr std::string_view ParticleTypeName[kNParticleTypes] = {"Tracks", "V0", "V0Child", "Phi", "PhiChild", "Cascade", "CascadeBachelor"}; //! Naming of the different particle types +static constexpr std::string_view ParticleTypeName[kNParticleTypes] = {"Tracks", "MCTruthTracks", "V0", "V0Child", "Cascade", "CascadeBachelor", "Phi", "PhiChild"}; //! Naming of the different particle types +static constexpr std::string_view TempFitVarName[kNParticleTypes] = {"/hDCAxy", "/hPDGvspT", "/hCPA", "/hDCAxy", "/hCPA", "/hDCAxy", "/hInvMass", "/hDCAxy"}; using cutContainerType = uint32_t; //! Definition of the data type for the bit-wise container for the different selection criteria @@ -71,18 +73,17 @@ enum TrackType { static constexpr std::string_view TrackTypeName[kNTrackTypes] = {"Trk", "Pos", "Neg"}; //! Naming of the different particle types -DECLARE_SOA_INDEX_COLUMN(FemtoUniverseCollision, femtoUniverseCollision); -DECLARE_SOA_COLUMN(Pt, pt, float); //! p_T (GeV/c) -DECLARE_SOA_COLUMN(Eta, eta, float); //! Eta -DECLARE_SOA_COLUMN(Phi, phi, float); //! Phi -DECLARE_SOA_COLUMN(Mass, mass, float); //! Mass of the particle -DECLARE_SOA_COLUMN(PartType, partType, uint8_t); //! Type of the particle, according to femtouniverseparticle::ParticleType -DECLARE_SOA_COLUMN(Cut, cut, cutContainerType); //! Bit-wise container for the different selection criteria -DECLARE_SOA_COLUMN(PIDCut, pidcut, cutContainerType); //! Bit-wise container for the different PID selection criteria \todo since bit-masking cannot be done yet with filters we use a second field for the PID -DECLARE_SOA_COLUMN(TempFitVar, tempFitVar, float); //! Observable for the template fitting (Track: DCA_xy, V0: CPA) -DECLARE_SOA_COLUMN(Indices, indices, int[2]); //! Field for the track indices to remove auto-correlations -DECLARE_SOA_COLUMN(MLambda, mLambda, float); //! The invariant mass of V0 candidate, assuming lambda -DECLARE_SOA_COLUMN(MAntiLambda, mAntiLambda, float); //! The invariant mass of V0 candidate, assuming antilambda +DECLARE_SOA_INDEX_COLUMN(FDCollision, fdCollision); +DECLARE_SOA_COLUMN(Pt, pt, float); //! p_T (GeV/c) +DECLARE_SOA_COLUMN(Eta, eta, float); //! Eta +DECLARE_SOA_COLUMN(Phi, phi, float); //! Phi +DECLARE_SOA_COLUMN(PartType, partType, uint8_t); //! Type of the particle, according to femtouniverseparticle::ParticleType +DECLARE_SOA_COLUMN(Cut, cut, cutContainerType); //! Bit-wise container for the different selection criteria +DECLARE_SOA_COLUMN(PIDCut, pidcut, cutContainerType); //! Bit-wise container for the different PID selection criteria \todo since bit-masking cannot be done yet with filters we use a second field for the PID +DECLARE_SOA_COLUMN(TempFitVar, tempFitVar, float); //! Observable for the template fitting (Track: DCA_xy, V0: CPA) +DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(Children, children); //! Field for the track indices to remove auto-correlations +DECLARE_SOA_COLUMN(MLambda, mLambda, float); //! The invariant mass of V0 candidate, assuming lambda +DECLARE_SOA_COLUMN(MAntiLambda, mAntiLambda, float); //! The invariant mass of V0 candidate, assuming antilambda DECLARE_SOA_DYNAMIC_COLUMN(Theta, theta, //! Compute the theta of the track [](float eta) -> float { @@ -100,21 +101,20 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, //! Compute the momentum in z in GeV/c [](float pt, float eta) -> float { return pt * std::sinh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! Compute the overall momentum in GeV/c + [](float pt, float eta) -> float { + return pt * std::cosh(eta); + }); +// debug variables DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign of the track charge -DECLARE_SOA_COLUMN(Beta, beta, float); //! TOF Beta signal -DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, float); //! Chi2 / cluster for the ITS track segment -DECLARE_SOA_COLUMN(TPCChi2NCl, tpcChi2NCl, float); //! Chi2 / cluster for the TPC track segment DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, uint8_t); //! Number of TPC clusters DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, uint8_t); //! Number of TPC crossed rows -DECLARE_SOA_COLUMN(TPCNSigmaKaon, tpcNSigmaKaon, float); //! TPCNSigmaKaon -DECLARE_SOA_COLUMN(TOFNSigmaKaon, tofNSigmaKaon, float); //! TOFNSigmaKaon DECLARE_SOA_COLUMN(ITSNCls, itsNCls, uint8_t); //! Number of ITS clusters DECLARE_SOA_COLUMN(ITSNClsInnerBarrel, itsNClsInnerBarrel, uint8_t); //! Number of ITS clusters in the inner barrel //! TPC signal DECLARE_SOA_DYNAMIC_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, //! Compute the number of crossed rows over findable TPC clusters [](uint8_t tpcNClsFindable, uint8_t tpcNClsCrossedRows) -> float { return (float)tpcNClsCrossedRows / (float)tpcNClsFindable; }); -// DECLARE_SOA_COLUMN(TPCNSigmaStoreKa, tpcNSigmaStoreKa, binning::binned_t); DECLARE_SOA_COLUMN(DaughDCA, daughDCA, float); //! DCA between daughters DECLARE_SOA_COLUMN(TransRadius, transRadius, float); //! Transverse radius of the decay vertex DECLARE_SOA_COLUMN(DecayVtxX, decayVtxX, float); //! X position of the decay vertex @@ -123,32 +123,28 @@ DECLARE_SOA_COLUMN(DecayVtxZ, decayVtxZ, float); //! Z position of the decay DECLARE_SOA_COLUMN(MKaon, mKaon, float); //! The invariant mass of V0 candidate, assuming kaon } // namespace femtouniverseparticle - -DECLARE_SOA_TABLE(FemtoUniverseParticles, "AOD", "FEMTOUNIPARTS", +DECLARE_SOA_TABLE(FDParticles, "AOD", "FDPARTICLE", o2::soa::Index<>, - femtouniverseparticle::FemtoUniverseCollisionId, + femtouniverseparticle::FDCollisionId, femtouniverseparticle::Pt, femtouniverseparticle::Eta, femtouniverseparticle::Phi, - track::P, - femtouniverseparticle::Mass, femtouniverseparticle::PartType, femtouniverseparticle::Cut, femtouniverseparticle::PIDCut, femtouniverseparticle::TempFitVar, - femtouniverseparticle::Indices, + femtouniverseparticle::ChildrenIds, femtouniverseparticle::MLambda, femtouniverseparticle::MAntiLambda, femtouniverseparticle::Theta, femtouniverseparticle::Px, femtouniverseparticle::Py, femtouniverseparticle::Pz, + femtouniverseparticle::P); +using FDParticle = FDParticles::iterator; + +DECLARE_SOA_TABLE(FDExtParticles, "AOD", "FDEXTPARTICLE", femtouniverseparticle::Sign, - pidtofbeta::Beta, - femtouniverseparticle::ITSChi2NCl, - femtouniverseparticle::TPCChi2NCl, - femtouniverseparticle::TPCNSigmaKaon, - femtouniverseparticle::TOFNSigmaKaon, femtouniverseparticle::TPCNClsFound, track::TPCNClsFindable, femtouniverseparticle::TPCNClsCrossedRows, @@ -186,14 +182,77 @@ DECLARE_SOA_TABLE(FemtoUniverseParticles, "AOD", "FEMTOUNIPARTS", pidtof_tiny::TOFNSigmaKa, pidtof_tiny::TOFNSigmaPr, pidtof_tiny::TOFNSigmaDe); -using FemtoUniverseParticle = FemtoUniverseParticles::iterator; +using FDFullParticle = FDExtParticles::iterator; -namespace femtohash +/// FemtoUniverseTrackMC +namespace femtouniverseMCparticle { -DECLARE_SOA_COLUMN(FemtoBin, bin, int); //! Hash for the event mixing -} // namespace femtohash -DECLARE_SOA_TABLE(FemtoHashes, "AOD", "HASH", femtohash::FemtoBin); -using FemtoHash = FemtoHashes::iterator; +/// Distinuishes the different particle origins +enum ParticleOriginMCTruth { + kPrimary, //! Primary track or V0 + kDaughter, //! Particle from a decay + kMaterial, //! Particle from a material + kNotPrimary, //! Not primary particles (kept for compatibility reasons with the FullProducer task. will be removed, since we look at "non primaries" more differentially now) + kFake, //! particle, that has NOT the PDG code of the current analysed particle + kDaughterLambda, //! Daughter from a Lambda decay + kDaughterSigmaplus, //! Daughter from a Sigma^plus decay + kNOriginMCTruthTypes +}; + +//! Naming of the different OriginMCTruth types +static constexpr std::string_view ParticleOriginMCTruthName[kNOriginMCTruthTypes] = { + "_Primary", + "_Daughter", + "_Material", + "_NotPrimary", + "_Fake", + "_DaughterLambda", + "DaughterSigmaPlus"}; + +/// Distinguished between reconstructed and truth +enum MCType { + kRecon, //! Reconstructed in case of MC and used as default in case of data + kTruth, //! MC truth + kNMCTypes +}; + +static constexpr std::string_view MCTypeName[kNMCTypes] = {"", "_MC"}; + +DECLARE_SOA_COLUMN(PartOriginMCTruth, partOriginMCTruth, uint8_t); //! Origin of the particle, according to femtouniverseparticle::ParticleOriginMCTruth +DECLARE_SOA_COLUMN(PDGMCTruth, pdgMCTruth, int); //! Particle PDG + +// debug variables +DECLARE_SOA_COLUMN(MotherPDG, motherPDG, int); //! Checks mother PDG, where mother is the primary particle for that decay chain +} // namespace femtouniverseMCparticle + +DECLARE_SOA_TABLE(FDMCParticles, "AOD", "FDMCPARTICLE", + o2::soa::Index<>, + femtouniverseMCparticle::PartOriginMCTruth, + femtouniverseMCparticle::PDGMCTruth, + femtouniverseparticle::Pt, + femtouniverseparticle::Eta, + femtouniverseparticle::Phi); +using FDMCParticle = FDMCParticles::iterator; + +DECLARE_SOA_TABLE(FDExtMCParticles, "AOD", "FDEXTMCPARTICLE", + femtouniverseMCparticle::MotherPDG); +using FDExtMCParticle = FDExtMCParticles::iterator; + +namespace mcfdlabel +{ +DECLARE_SOA_INDEX_COLUMN(FDMCParticle, fdMCParticle); //! MC particle for femtouniverseparticle +} // namespace mcfdlabel +DECLARE_SOA_TABLE(FDMCLabels, "AOD", "FDMCLabel", //! Table joinable to FemtoUniverseParticle containing the MC labels + mcfdlabel::FDMCParticleId); + +/// Hash +namespace hash +{ +DECLARE_SOA_COLUMN(Bin, bin, int); //! Hash for the event mixing +} // namespace hash +DECLARE_SOA_TABLE(Hashes, "AOD", "HASH", hash::Bin); +using Hash = Hashes::iterator; } // namespace o2::aod -#endif // PWGCF_FEMTOUNIVERSE_DATAMODEL_FEMTOUNIVERSEDERIVED_H_ + +#endif // PWGCF_FEMTOUNIVERSE_DATAMODEL_FEMTODERIVED_H_ diff --git a/PWGCF/FemtoUniverse/TableProducer/CMakeLists.txt b/PWGCF/FemtoUniverse/TableProducer/CMakeLists.txt index cf8298fbf1e..ecbb6e46873 100644 --- a/PWGCF/FemtoUniverse/TableProducer/CMakeLists.txt +++ b/PWGCF/FemtoUniverse/TableProducer/CMakeLists.txt @@ -9,7 +9,22 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2physics_add_dpl_workflow(femto-universe-producer - SOURCES femtoUniverseProducerTask.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtouniverse-producer + SOURCES femtoUniverseProducerTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(femtouniverse-mctruth-producer + SOURCES femtoUniverseProducerMCTruthTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-producer-reduced + SOURCES femtoUniverseProducerReducedTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-producer-v0 + SOURCES femtoUniverseProducerTaskV0Only.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerMCTruthTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerMCTruthTask.cxx new file mode 100644 index 00000000000..cfb516f02d9 --- /dev/null +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerMCTruthTask.cxx @@ -0,0 +1,251 @@ +// 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 femtoUniverseProducerMCTruthTask.cxx +/// \brief Tasks that produces the track tables used for the pairing +/// \author Malgorzata Janik, WUT Warsaw, majanik@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Math/Vector4D.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "ReconstructionDataFormats/Track.h" +#include "TMath.h" +#include "TLorentzVector.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ + +using FemtoFullCollisionMC = soa::Join::iterator; + +} // namespace o2::aod + +/// \todo fix how to pass array to setSelection, getRow() passing a different +/// type! +// static constexpr float arrayV0Sel[3][3] = {{100.f, 100.f, 100.f}, {0.2f, +// 0.2f, 0.2f}, {100.f, 100.f, 100.f}}; unsigned int rows = sizeof(arrayV0Sel) / +// sizeof(arrayV0Sel[0]); unsigned int columns = sizeof(arrayV0Sel[0]) / +// sizeof(arrayV0Sel[0][0]); + +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 femtoUniverseProducerMCTruthTask { + int evCount = 0; + int mRunNumber; + float mMagField; + Service ccdb; /// Accessing the CCDB + + // Tables being produced + Produces outputCollision; + Produces outputParts; + + // Analysis configs + Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; // Choose if filtering or skimming version is run + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; + Configurable ConfIsMC{"ConfIsMC", false, "Running on MC; implemented only for Run3"}; + 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)"}; + Configurable ConfIsActivateV0{"ConfIsActivateV0", true, "Activate filling of V0 into femtouniverse tables"}; + Configurable ConfIsActivatePhi{"ConfIsActivatePhi", true, "Activate filling of Phi into femtouniverse tables"}; + Configurable> ConfPDGCodes{"ConfPDGCodes", std::vector{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"}; + Configurable ConfAnalysisWithPID{"ConfAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles"}; + + /// Event cuts + Configurable ConfEvtUseTPCmult{"ConfEvtUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; + 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"}; + + // Track cuts + struct : o2::framework::ConfigurableGroup { + Configurable ConfPtLowFilterCut{"ConfPtLowFilterCut", 0.14, "Lower limit for Pt for the filtering tracks"}; // pT low + Configurable ConfPtHighFilterCut{"ConfPtHighFilterCut", 5.0, "Higher limit for Pt for the filtering tracks"}; // pT high + Configurable ConfEtaFilterCut{"ConfEtaFilterCut", 0.8, "Eta cut for the filtering tracks"}; + } ConfFilteringTracks; + + FemtoUniverseCollisionSelection colCuts; + FemtoUniverseTrackSelection trackCuts; + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; + + void init(InitContext&) + { + if ((doprocessTrackMC) == false) { + LOGF(fatal, "Neither processFullData nor processFullMC enabled. Please choose one."); + } + + colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3); + + colCuts.init(&qaRegistry); + trackCuts.init(&qaRegistry); + + 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); + } + + template + void fillCollisions(CollisionType const& col, TrackType const& tracks) + { + const auto vtxZ = col.posZ(); + const auto spher = 0; // colCuts.computeSphericity(col, tracks); + int mult = 0; + int multNtr = 0; + if (ConfIsRun3) { + mult = col.multFV0M(); + multNtr = col.multNTracksPV(); + } else { + mult = 0.5 * (col.multFV0M()); /// For benchmarking on Run 2, V0M in + /// FemtoUniverseRun2 is defined V0M/2 + multNtr = col.multTracklets(); + } + if (ConfEvtUseTPCmult) { + multNtr = col.multTPC(); + } + + // check whether the basic event selection criteria are fulfilled + // if the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any + // particle candidates for such collisions + + // CHECK WHAT CUTS SHOULD BE USED FOR MC TRUTH + // if (!colCuts.isSelected(col)) { + // if (ConfIsTrigger) { + // outputCollision(vtxZ, mult, multNtr, spher, mMagField); + // } + // return; + // } + + colCuts.fillQA(col); + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + } + + template + void fillParticles(TrackType const& tracks) + { + std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children + + for (auto& particle : tracks) { + /// if the most open selection criteria are not fulfilled there is no + /// point looking further at the track + + if (particle.eta() < -ConfFilteringTracks.ConfEtaFilterCut || particle.eta() > ConfFilteringTracks.ConfEtaFilterCut) + continue; + if (particle.pt() < ConfFilteringTracks.ConfPtLowFilterCut || particle.pt() > ConfFilteringTracks.ConfPtHighFilterCut) + continue; + + uint32_t pdgCode = (uint32_t)particle.pdgCode(); + + if (ConfAnalysisWithPID) { + bool pass = false; + std::vector tmpPDGCodes = ConfPDGCodes; // necessary due to some features of the Configurable + for (uint32_t pdg : tmpPDGCodes) { + if (static_cast(pdg) == static_cast(pdgCode)) { + if (pdgCode == 333) { // ATTENTION: workaround for now, because all Phi mesons are NOT primary particles for now. + pass = true; + } else { + if (particle.isPhysicalPrimary()) + pass = true; + } + } + } + if (!pass) + continue; + } + + // we cannot use isSelectedMinimal since it takes Ncls + // if (!trackCuts.isSelectedMinimal(track)) { + // continue; + // } + + // trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // auto cutContainer = trackCuts.getCutContainer(track); + // instead of the bitmask, the PDG of the particle is stored as uint32_t + + // now the table is filled + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + pdgCode, + pdgCode, + childIDs, + 0, + 0); + } + } + + void + processTrackMC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + aod::McCollisions const& mcCollisions, + aod::McParticles const& mcParticles) + { + if (evCount > 30) + return; + evCount++; + // magnetic field for run not needed for mc truth + // fill the tables + fillCollisions(col, mcParticles); + fillParticles(mcParticles); + } + PROCESS_SWITCH(femtoUniverseProducerMCTruthTask, processTrackMC, "Provide MC data for track analysis", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerReducedTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerReducedTask.cxx new file mode 100644 index 00000000000..fe46d7509ba --- /dev/null +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerReducedTask.cxx @@ -0,0 +1,342 @@ +// 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 femtoUniverseProducerReducedTask.cxx +/// \brief Tasks that produces the track tables used for the pairing (tracks only) +/// \author Luca Barioglio, TU München, andreas.mathis@ph.tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include "TMath.h" +#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "Math/Vector4D.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ + +using FemtoFullCollision = soa::Join::iterator; +using FemtoFullCollisionMC = soa::Join::iterator; + +using FemtoFullTracks = soa::Join; +} // namespace o2::aod + +struct femtoUniverseProducerReducedTask { + + Produces outputCollision; + Produces outputParts; + Produces outputPartsMC; + Produces outputDebugParts; + Produces outputPartsMCLabels; + Produces outputDebugPartsMC; + + Configurable ConfDebugOutput{"ConfDebugOutput", true, "Debug output"}; + Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; // Choose if filtering or skimming version is run + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or Run2"}; // Choose if running on converted data or Run3 + Configurable ConfIsMC{"ConfIsMC", false, "Running on MC; implemented only for Run3"}; + + // Event cuts + FemtoUniverseCollisionSelection colCuts; + Configurable ConfUseTPCmult{"ConfUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; + 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 ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; + Configurable ConfRejectITSHitandTOFMissing{"ConfRejectITSHitandTOFMissing", false, "True: reject if neither ITS hit nor TOF timing satisfied"}; + + Configurable ConfForceGRP{"ConfForceGRP", 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)"}; + Configurable ConfPDGCodeTrack{"ConfPDGCodeTrack", 2212, "PDG code of the selected track for Monte Carlo truth"}; + // Track cuts + FemtoUniverseTrackSelection trackCuts; + Configurable> ConfTrkCharge{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kSign, "ConfTrk"), std::vector{-1, 1}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kSign, "Track selection: ")}; + Configurable> ConfTrkPtmin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kpTMin, "ConfTrk"), std::vector{0.4f, 0.6f, 0.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kpTMin, "Track selection: ")}; + Configurable> ConfTrkPtmax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kpTMax, "ConfTrk"), std::vector{5.4f, 5.6f, 5.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kpTMax, "Track selection: ")}; + Configurable> ConfTrkEta{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kEtaMax, "ConfTrk"), std::vector{0.8f, 0.7f, 0.9f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kEtaMax, "Track selection: ")}; + Configurable> ConfTrkTPCnclsMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCnClsMin, "ConfTrk"), std::vector{80.f, 70.f, 60.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCnClsMin, "Track selection: ")}; + Configurable> ConfTrkTPCfCls{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCfClsMin, "ConfTrk"), std::vector{0.7f, 0.83f, 0.9f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCfClsMin, "Track selection: ")}; + Configurable> ConfTrkTPCcRowsMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCcRowsMin, "ConfTrk"), std::vector{70.f, 60.f, 80.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCcRowsMin, "Track selection: ")}; + Configurable> ConfTrkTPCsCls{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCsClsMax, "ConfTrk"), std::vector{0.1f, 160.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCsClsMax, "Track selection: ")}; + Configurable> ConfTrkITSnclsMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kITSnClsMin, "ConfTrk"), std::vector{-1.f, 2.f, 4.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kITSnClsMin, "Track selection: ")}; + Configurable> ConfTrkITSnclsIbMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kITSnClsIbMin, "ConfTrk"), std::vector{-1.f, 1.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kITSnClsIbMin, "Track selection: ")}; + Configurable> ConfTrkDCAxyMax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kDCAxyMax, "ConfTrk"), std::vector{0.1f, 0.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kDCAxyMax, "Track selection: ")}; /// here we need an open cut to do the DCA fits later on! + Configurable> ConfTrkDCAzMax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kDCAzMax, "ConfTrk"), std::vector{0.2f, 0.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kDCAzMax, "Track selection: ")}; + Configurable> ConfTrkPIDnSigmaMax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kPIDnSigmaMax, "Conf"), std::vector{3.5f, 3.f, 2.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kPIDnSigmaMax, "Track selection: ")}; + // off set the center of the nsigma distribution to deal with bad TPC/TOF calibration + Configurable ConfPIDnSigmaOffsetTPC{"ConfPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; + Configurable ConfPIDnSigmaOffsetTOF{"ConfPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; + Configurable> ConfPIDspecies{"ConfPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton, o2::track::PID::Deuteron}, "Trk sel: Particles species for PID"}; + + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; + + int mRunNumber; + float mMagField; + Service ccdb; /// Accessing the CCDB + + void init(InitContext&) + { + colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3); + colCuts.init(&qaRegistry); + + trackCuts.setSelection(ConfTrkCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); + trackCuts.setSelection(ConfTrkPtmin, femtoUniverseTrackSelection::kpTMin, femtoUniverseSelection::kLowerLimit); + trackCuts.setSelection(ConfTrkPtmax, femtoUniverseTrackSelection::kpTMax, femtoUniverseSelection::kUpperLimit); + trackCuts.setSelection(ConfTrkEta, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); + trackCuts.setSelection(ConfTrkTPCnclsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); + trackCuts.setSelection(ConfTrkTPCfCls, femtoUniverseTrackSelection::kTPCfClsMin, femtoUniverseSelection::kLowerLimit); + trackCuts.setSelection(ConfTrkTPCcRowsMin, femtoUniverseTrackSelection::kTPCcRowsMin, femtoUniverseSelection::kLowerLimit); + trackCuts.setSelection(ConfTrkTPCsCls, femtoUniverseTrackSelection::kTPCsClsMax, femtoUniverseSelection::kUpperLimit); + trackCuts.setSelection(ConfTrkITSnclsMin, femtoUniverseTrackSelection::kITSnClsMin, femtoUniverseSelection::kLowerLimit); + trackCuts.setSelection(ConfTrkITSnclsIbMin, femtoUniverseTrackSelection::kITSnClsIbMin, femtoUniverseSelection::kLowerLimit); + trackCuts.setSelection(ConfTrkDCAxyMax, femtoUniverseTrackSelection::kDCAxyMax, femtoUniverseSelection::kAbsUpperLimit); + trackCuts.setSelection(ConfTrkDCAzMax, femtoUniverseTrackSelection::kDCAzMax, femtoUniverseSelection::kAbsUpperLimit); + trackCuts.setSelection(ConfTrkPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); + trackCuts.setPIDSpecies(ConfPIDspecies); + trackCuts.setnSigmaPIDOffset(ConfPIDnSigmaOffsetTPC, ConfPIDnSigmaOffsetTOF); + trackCuts.init(&qaRegistry); + 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 getMagneticFieldTesla(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 && !ConfForceGRP) { + 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(); + } + + template + void fillMCParticle(CandidateType const& candidate, o2::aod::femtouniverseparticle::ParticleType fdparttype) + { + if (candidate.has_mcParticle()) { + // get corresponding MC particle and its info + auto particleMC = candidate.mcParticle(); + auto pdgCode = particleMC.pdgCode(); + + int particleOrigin = 99; + auto motherparticleMC = particleMC.template mothers_as().front(); + + if (abs(pdgCode) == abs(ConfPDGCodeTrack.value)) { + + if (particleMC.isPhysicalPrimary()) { + particleOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kPrimary; + } else if (motherparticleMC.producedByGenerator()) { + particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); + } else { + particleOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kMaterial; + } + + } else { + + particleOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kFake; + } + + outputPartsMC(particleOrigin, pdgCode, particleMC.pt(), particleMC.eta(), particleMC.phi()); + outputPartsMCLabels(outputPartsMC.lastIndex()); + } else { + outputPartsMCLabels(-1); + } + } + + template + void fillCollisionsAndTracks(CollisionType const& col, TrackType const& tracks) /// \todo with FilteredFullV0s + { + // get magnetic field for run + + const auto vtxZ = col.posZ(); + const auto spher = colCuts.computeSphericity(col, tracks); + + int mult = 0; + int multNtr = 0; + if (ConfIsRun3) { + mult = col.multFV0M(); + multNtr = col.multNTracksPV(); + } else { + mult = 0.5 * (col.multFV0M()); /// For benchmarking on Run 2, V0M in FemtoUniverseRun2 is defined V0M/2 + multNtr = col.multTracklets(); + } + if (ConfUseTPCmult) { + multNtr = col.multTPC(); + } + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(vtxZ, mult, multNtr, colCuts.computeSphericity(col, tracks), mMagField); + } + return; + } + + colCuts.fillQA(col); + // now the table is filled + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + + // these IDs are necessary to keep track of the children + // since this producer only produces the tables for tracks, there are no children + std::vector childIDs = {0, 0}; + for (auto& track : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // an array of two bit-wise containers of the systematic variations is obtained + // one container for the track quality cuts and one for the PID cuts + auto cutContainer = trackCuts.getCutContainer(track); + + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + aod::femtouniverseparticle::ParticleType::kTrack, + cutContainer.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), + cutContainer.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), childIDs, 0, 0); + + if constexpr (isMC) { + fillMCParticle(track, o2::aod::femtouniverseparticle::ParticleType::kTrack); + } + + if (ConfDebugOutput) { + outputDebugParts(track.sign(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaStoreEl(), + track.tpcNSigmaStorePi(), + track.tpcNSigmaStoreKa(), + track.tpcNSigmaStorePr(), + track.tpcNSigmaStoreDe(), + track.tofNSigmaStoreEl(), + track.tofNSigmaStorePi(), + track.tofNSigmaStoreKa(), + track.tofNSigmaStorePr(), + track.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999.); + } + } + } + + void processData(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisionsAndTracks(col, tracks); + } + PROCESS_SWITCH(femtoUniverseProducerReducedTask, processData, "Provide experimental data", true); + + void processMC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisionsAndTracks(col, tracks); + } + PROCESS_SWITCH(femtoUniverseProducerReducedTask, processMC, "Provide MC data", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index e9fbc7d355e..3f95a44f8ea 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 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. // @@ -11,33 +11,34 @@ /// \file femtoUniverseProducerTask.cxx /// \brief Tasks that produces the track tables used for the pairing -/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de -/// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch +/// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl +/// \author Malgorzata Janik, WUT Warsaw, majanik@cern.ch -#include "CCDB/BasicCCDBManager.h" +#include +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoUniverseDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" - -#include "TLorentzVector.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "DataFormatsParameters/GRPObject.h" +#include "Framework/runDataProcessing.h" #include "Math/Vector4D.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "ReconstructionDataFormats/Track.h" #include "TMath.h" +#include "TLorentzVector.h" using namespace o2; using namespace o2::analysis::femtoUniverse; @@ -47,27 +48,27 @@ using namespace o2::framework::expressions; namespace o2::aod { -using FemtoFullCollision = soa::Join::iterator; -using FemtoFullTracks = soa::Join; -using FemtoPhiTracks = soa::Join; +using FemtoFullCollision = + soa::Join::iterator; +using FemtoFullCollisionMC = soa::Join::iterator; + +using FemtoFullTracks = + soa::Join; + +// using FilteredFullV0s = soa::Filtered; /// predefined Join +// table for o2::aod::V0s = soa::Join +// to be used when we add v0Filter } // namespace o2::aod -/// \todo fix how to pass array to setSelection, getRow() passing a different type! -// static constexpr float arrayV0Sel[3][3] = {{100.f, 100.f, 100.f}, {0.2f, 0.2f, 0.2f}, {100.f, 100.f, 100.f}}; -// unsigned int rows = sizeof(arrayV0Sel) / sizeof(arrayV0Sel[0]); -// unsigned int columns = sizeof(arrayV0Sel[0]) / sizeof(arrayV0Sel[0][0]); +/// \todo fix how to pass array to setSelection, getRow() passing a different +/// type! +// static constexpr float arrayV0Sel[3][3] = {{100.f, 100.f, 100.f}, {0.2f, +// 0.2f, 0.2f}, {100.f, 100.f, 100.f}}; unsigned int rows = sizeof(arrayV0Sel) / +// sizeof(arrayV0Sel[0]); unsigned int columns = sizeof(arrayV0Sel[0]) / +// sizeof(arrayV0Sel[0][0]); template int getRowDaughters(int daughID, T const& vecID) @@ -83,141 +84,199 @@ int getRowDaughters(int daughID, T const& vecID) } struct femtoUniverseProducerTask { - - Produces outputCollision; - Produces outputParts; - // Produces outputPhiCan; - // Produces outputDebugParts; - - Configurable ConfDebugOutput{"ConfDebugOutput", true, "Debug output"}; - + Produces outputCollision; + Produces outputParts; + Produces outputPartsMC; + Produces outputDebugParts; + Produces outputPartsMCLabels; + Produces outputDebugPartsMC; + + Configurable ConfIsDebug{"ConfIsDebug", true, "Enable Debug tables"}; // Choose if filtering or skimming version is run - Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; + // Choose if running on converted data or Run3 / Pilot + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; + Configurable ConfIsMC{"ConfIsMC", false, "Running on MC; implemented only for Run3"}; - // Choose if running on converted data or pilot beam - Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Pilot beam"}; + 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 FemtoUniverseCollisionSelection colCuts; + Configurable ConfEvtUseTPCmult{"ConfEvtUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; 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 ConfIsActivateV0{"ConfIsActivateV0", true, "Activate filling of V0 into femtouniverse tables"}; + Configurable ConfIsActivatePhi{"ConfIsActivatePhi", true, "Activate filling of Phi into femtouniverse tables"}; + Configurable ConfMCTruthAnalysisWithPID{"ConfMCTruthAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles (for MC Truth)"}; + Configurable> ConfMCTruthPDGCodes{"ConfMCTruthPDGCodes", std::vector{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"}; + + // just sanity check to make sure in case there are problems in conversion or + // MC production it does not affect results + 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"}; // only for checking the particle origin (particles for which PDG does not match are marked as "Fake") + FemtoUniverseTrackSelection trackCuts; - Configurable ConfStoreV0{"ConfStoreV0", true, "True: store V0 table"}; - Configurable ConfStorePhi{"ConfStorePhi", true, "True: store Phi table"}; - // just sanity check to make sure in case there are problems in conversion or MC production it does not affect results - Configurable ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; - Configurable ConfRejectITSHitandTOFMissing{"ConfRejectITSHitandTOFMissing", false, "True: reject if neither ITS hit nor TOF timing satisfied"}; + struct : o2::framework::ConfigurableGroup { + Configurable ConfPtLowFilterCut{"ConfPtLowFilterCut", 0.14, "Lower limit for Pt for the global track"}; // pT low + Configurable ConfPtHighFilterCut{"ConfPtHighFilterCut", 5.0, "Higher limit for Pt for the global track"}; // pT high + Configurable ConfEtaFilterCut{"ConfEtaFilterCut", 0.8, "Eta cut for the global track"}; // eta + Configurable ConfDcaXYFilterCut{"ConfDcaXYFilterCut", 2.4, "Value for DCA_XY for the global track"}; // max dca to vertex XY + Configurable ConfDcaZFilterCut{"ConfDcaZFilterCut", 3.2, "Value for DCA_Z for the global track"}; // max dca to vertex Z + } ConfFilterCuts; - FemtoUniverseTrackSelection trackCuts; Configurable> ConfTrkCharge{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kSign, "ConfTrk"), std::vector{-1, 1}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kSign, "Track selection: ")}; - Configurable> ConfTrkPtmin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kpTMin, "ConfTrk"), std::vector{0.4f, 0.6f, 0.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kpTMin, "Track selection: ")}; + Configurable> ConfTrkPtmin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kpTMin, "ConfTrk"), std::vector{0.5f, 0.4f, 0.6f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kpTMin, "Track selection: ")}; + Configurable> ConfTrkPtmax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kpTMax, "ConfTrk"), std::vector{5.4f, 5.6f, 5.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kpTMax, "Track selection: ")}; Configurable> ConfTrkEta{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kEtaMax, "ConfTrk"), std::vector{0.8f, 0.7f, 0.9f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kEtaMax, "Track selection: ")}; - Configurable> ConfTrkTPCnclsMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCnClsMin, "ConfTrk"), std::vector{80.f, 70.f, 60.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCnClsMin, "Track selection: ")}; - Configurable> ConfTrkTPCfCls{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCfClsMin, "ConfTrk"), std::vector{0.7f, 0.83f, 0.9f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCfClsMin, "Track selection: ")}; + Configurable> ConfTrkTPCnclsMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCnClsMin, "ConfTrk"), std::vector{70.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCnClsMin, "Track selection: ")}; + Configurable> ConfTrkTPCfCls{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCfClsMin, "ConfTrk"), std::vector{0.83f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCfClsMin, "Track selection: ")}; Configurable> ConfTrkTPCcRowsMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCcRowsMin, "ConfTrk"), std::vector{70.f, 60.f, 80.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCcRowsMin, "Track selection: ")}; Configurable> ConfTrkTPCsCls{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kTPCsClsMax, "ConfTrk"), std::vector{0.1f, 160.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kTPCsClsMax, "Track selection: ")}; Configurable> ConfTrkITSnclsMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kITSnClsMin, "ConfTrk"), std::vector{-1.f, 2.f, 4.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kITSnClsMin, "Track selection: ")}; Configurable> ConfTrkITSnclsIbMin{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kITSnClsIbMin, "ConfTrk"), std::vector{-1.f, 1.f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kITSnClsIbMin, "Track selection: ")}; - Configurable> ConfTrkDCAxyMax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kDCAxyMax, "ConfTrk"), std::vector{0.1f, 3.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kDCAxyMax, "Track selection: ")}; /// here we need an open cut to do the DCA fits later on! - Configurable> ConfTrkDCAzMax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kDCAzMax, "ConfTrk"), std::vector{0.2f, 3.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kDCAzMax, "Track selection: ")}; - /// \todo Reintegrate PID to the general selection container + Configurable> ConfTrkDCAxyMax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kDCAxyMax, "ConfTrk"), std::vector{0.1f, 3.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kDCAxyMax, "Track selection: ")}; + Configurable> ConfTrkDCAzMax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kDCAzMax, "ConfTrk"), std::vector{0.2f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kDCAzMax, "Track selection: ")}; /// \todo Reintegrate PID to the general selection container Configurable> ConfTrkPIDnSigmaMax{FemtoUniverseTrackSelection::getSelectionName(femtoUniverseTrackSelection::kPIDnSigmaMax, "ConfTrk"), std::vector{3.5f, 3.f, 2.5f}, FemtoUniverseTrackSelection::getSelectionHelper(femtoUniverseTrackSelection::kPIDnSigmaMax, "Track selection: ")}; - Configurable> ConfTrkTPIDspecies{"ConfTrkTPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton, o2::track::PID::Deuteron}, "Trk sel: Particles species for PID"}; + Configurable ConfTrkPIDnSigmaOffsetTPC{"ConfTrkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; + 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"}; + // Numbers from ~/alice/O2/DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h //static constexpr ID Pion = 2; static constexpr ID Kaon = 3; static constexpr ID Proton = 4; static constexpr ID Deuteron = 5; - FemtoUniverseV0Selection v0Cuts; - TrackSelection* o2PhysicsTrackSelection; + // TrackSelection *o2PhysicsTrackSelection; /// \todo Labeled array (see Track-Track task) - /// V0 + + // V0 + FemtoUniverseV0Selection v0Cuts; Configurable> ConfV0Sign{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0Sign, "ConfV0"), std::vector{-1, 1}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0Sign, "V0 selection: ")}; - Configurable> ConfV0PtMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kpTV0Min, "ConfV0"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kpTV0Min, "V0 selection: ")}; - Configurable> ConfDCAV0DaughMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kDCAV0DaughMax, "ConfV0"), std::vector{1.2f, 1.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kDCAV0DaughMax, "V0 selection: ")}; - Configurable> ConfCPAV0Min{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kCPAV0Min, "ConfV0"), std::vector{0.99f, 0.995f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kCPAV0Min, "V0 selection: ")}; - - Configurable> V0TranRadV0Min{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kTranRadV0Min, "ConfV0"), std::vector{0.2f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kTranRadV0Min, "V0 selection: ")}; - Configurable> V0TranRadV0Max{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kTranRadV0Max, "ConfV0"), std::vector{100.f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kTranRadV0Max, "V0 selection: ")}; - Configurable> V0DecVtxMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kDecVtxMax, "ConfV0"), std::vector{100.f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kDecVtxMax, "V0 selection: ")}; - - Configurable> ConfV0DaughCharge{"ConfV0DaughCharge", std::vector{-1, 1}, "V0 Daugh sel: Charge"}; - Configurable> ConfDaughEta{"ConfDaughEta", std::vector{0.8f}, "V0 Daugh sel: max eta"}; - Configurable> ConfV0DaughTPCnclsMin{"ConfV0DaughTPCnclsMin", std::vector{80.f, 70.f, 60.f}, "V0 Daugh sel: Min. nCls TPC"}; - Configurable> ConfV0DaughDCAMin{"ConfV0DaughDCAMin", std::vector{0.05f, 0.06f}, "V0 Daugh sel: Max. DCA Daugh to PV (cm)"}; - Configurable> ConfV0DaughPIDnSigmaMax{"ConfV0DaughPIDnSigmaMax", std::vector{5.f, 4.f}, "V0 Daugh sel: Max. PID nSigma TPC"}; - - Configurable> ConfV0DaughTPIDspecies{"ConfV0DaughTPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "V0 Daugh sel: Particles species for PID"}; - - Configurable ConfInvMassLowLimit{"ConfInvMassLowLimit", 1.005, "Lower limit of the V0 invariant mass"}; - Configurable ConfInvMassUpLimit{"ConfInvMassUpLimit", 1.035, "Upper limit of the V0 invariant mass"}; - - Configurable ConfRejectKaons{"ConfRejectKaons", false, "Switch to reject kaons"}; - Configurable ConfInvKaonMassLowLimit{"ConfInvKaonMassLowLimit", 0.48, "Lower limit of the V0 invariant mass for Kaon rejection"}; - Configurable ConfInvKaonMassUpLimit{"ConfInvKaonMassUpLimit", 0.515, "Upper limit of the V0 invariant mass for Kaon rejection"}; - - // PHI Daughters (Kaons) - Configurable ConfInvMassLowLimitPhi{"ConfInvMassLowLimitPhi", 1.011, "Lower limit of the Phi invariant mass"}; // change that to do invariant mass cut - Configurable ConfInvMassUpLimitPhi{"ConfInvMassUpLimitPhi", 1.027, "Upper limit of the Phi invariant mass"}; - Configurable ConfRejectKaonsPhi{"ConfRejectKaonsPhi", false, "Switch to reject kaons"}; - Configurable ConfInvKaonMassLowLimitPhi{"ConfInvKaonMassLowLimitPhi", 0.48, "Lower limit of the Phi invariant mass for Kaon rejection"}; - Configurable ConfInvKaonMassUpLimitPhi{"ConfInvKaonMassUpLimitPhi", 0.515, "Upper limit of the Phi invariant mass for Kaon rejection"}; - Configurable ConfNsigmaTPCTOFKaon{"ConfNsigmaTPCTOFKaon", true, "Use TPC and TOF for PID of Kaons"}; - Configurable ConfNsigmaCombinedKaon{"ConfNsigmaCombinedKaon", 5.0, "TPC and TOF Kaon Sigma (combined) for momentum > 0.4"}; - Configurable ConfNsigmaTPCKaon{"ConfNsigmaTPCKaon", 5.0, "TPC Kaon Sigma for momentum < 0.4"}; - // For Phi (daughter 1) - Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 321, "Particle 1 - PDG code"}; - Configurable cfgPtLowPart1{"cfgPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; - Configurable cfgPtHighPart1{"cfgPtHighPart1", 4.0, "Higher limit for Pt for the first particle"}; - Configurable cfgPLowPart1{"cfgPLowPart1", 0.14, "Lower limit for P for the first particle"}; - Configurable cfgPHighPart1{"cfgPHighPart1", 1.5, "Higher limit for P for the first particle"}; - Configurable cfgEtaLowPart1{"cfgEtaLowPart1", -0.8, "Lower limit for Eta for the first particle"}; - Configurable cfgEtaHighPart1{"cfgEtaHighPart1", 0.8, "Higher limit for Eta for the first particle"}; - Configurable cfgDcaXYPart1{"cfgDcaXYPart1", 2.4, "Value for DCA_XY for the first particle"}; - Configurable cfgDcaZPart1{"cfgDcaZPart1", 3.2, "Value for DCA_Z for the first particle"}; - Configurable cfgTpcClPart1{"cfgTpcClPart1", 88, "Number of tpc clasters for the first particle"}; // min number of found TPC clusters - Configurable cfgTpcCrosRoPart1{"cfgTpcCrosRoPart1", 70, "Number of tpc crossed rows for the first particle"}; // min number of crossed rows - Configurable cfgChi2TpcPart1{"cfgChi2TpcPart1", 4.0, "Chi2 / cluster for the TPC track segment for the first particle"}; - Configurable cfgChi2ItsPart1{"cfgChi2ItsPart1", 36.0, "Chi2 / cluster for the ITS track segment for the first particle"}; - - // For Phi (daughter 2) - Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 321, "Particle 2 - PDG code"}; - Configurable cfgPtLowPart2{"cfgPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; - Configurable cfgPtHighPart2{"cfgPtHighPart2", 4.0, "Higher limit for Pt for the second particle"}; - Configurable cfgPLowPart2{"cfgPLowPart2", 0.14, "Lower limit for P for the second particle"}; - Configurable cfgPHighPart2{"cfgPHighPart2", 1.5, "Higher limit for P for the second particle"}; - Configurable cfgEtaLowPart2{"cfgEtaLowPart2", -0.8, "Lower limit for Eta for the second particle"}; - Configurable cfgEtaHighPart2{"cfgEtaHighPart2", 0.8, "Higher limit for Eta for the second particle"}; - Configurable cfgDcaXYPart2{"cfgDcaXYPart2", 2.4, "Value for DCA_XY for the second particle"}; - Configurable cfgDcaZPart2{"cfgDcaZPart2", 3.2, "Value for DCA_Z for the second particle"}; - Configurable cfgTpcClPart2{"cfgTpcClPart2", 88, "Number of tpc clasters for the second particle"}; // min number of found TPC clusters - Configurable cfgTpcCrosRoPart2{"cfgTpcCrosRoPart2", 70, "Number of tpc crossed rows for the second particle"}; // min number of crossed rows - Configurable cfgChi2TpcPart2{"cfgChi2TpcPart2", 4.0, "Chi2 / cluster for the TPC track segment for the second particle"}; - Configurable cfgChi2ItsPart2{"cfgChi2ItsPart2", 36.0, "Chi2 / cluster for the ITS track segment for the second particle"}; - - // PHI Candidates - FemtoUniversePhiSelection PhiCuts; - Configurable> ConfPhiSign{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiSign, "ConfPhi"), std::vector{-1, 1}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiSign, "Phi selection: ")}; - Configurable> ConfPhiPtMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kpTPhiMin, "ConfPhi"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kpTPhiMin, "Phi selection: ")}; - // Configurable> ConfDCAPhiDaughMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kDCAPhiDaughMax, "ConfPhi"), std::vector{1.2f, 1.5f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kDCAPhiDaughMax, "Phi selection: ")}; - // Configurable> ConfCPAPhiMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kCPAPhiMin, "ConfPhi"), std::vector{0.99f, 0.995f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kCPAPhiMin, "Phi selection: ")}; - - // Configurable> PhiTranRadPhiMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kTranRadPhiMin, "ConfPhi"), std::vector{0.2f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kTranRadPhiMin, "Phi selection: ")}; - // Configurable> PhiTranRadPhiMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kTranRadPhiMax, "ConfPhi"), std::vector{100.f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kTranRadPhiMax, "Phi selection: ")}; - // Configurable> PhiDecVtxMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kDecVtxMax, "ConfPhi"), std::vector{100.f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kDecVtxMax, "Phi selection: ")}; - - /*Configurable> ConfPhiDaughCharge{"ConfPhiDaughCharge", std::vector{-1, 1}, "Phi Daugh sel: Charge"}; - Configurable> ConfPhiDaughEta{"ConfPhiDaughEta", std::vector{0.8f}, "Phi Daugh sel: max eta"}; - Configurable> ConfPhiDaughTPCnclsMin{"ConfPhiDaughTPCnclsMin", std::vector{80.f, 70.f, 60.f}, "Phi Daugh sel: Min. nCls TPC"}; - Configurable> ConfPhiDaughDCAMin{"ConfPhiDaughDCAMin", std::vector{0.05f, 0.06f}, "Phi Daugh sel: Max. DCA Daugh to PV (cm)"}; - Configurable> ConfPhiDaughPIDnSigmaMax{"ConfPhiDaughPIDnSigmaMax", std::vector{5.f, 4.f}, "Phi Daugh sel: Max. PID nSigma TPC"}; - Configurable> ConfPhiDaughTPIDspecies{"ConfPhiDaughTPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "Phi Daugh sel: Particles species for PID"};*/ - // Configurable> ConfPhiSign{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0Sign, "ConfV0"), std::vector{-1, 1}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0Sign, "V0 selection: ")}; + Configurable> ConfV0PtMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0pTMin, "ConfV0"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0pTMin, "V0 selection: ")}; + Configurable> ConfV0PtMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0pTMax, "ConfV0"), std::vector{3.3f, 3.4f, 3.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0pTMax, "V0 selection: ")}; + Configurable> ConfV0EtaMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0etaMax, "ConfV0"), std::vector{0.8f, 0.7f, 0.9f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0etaMax, "V0 selection: ")}; + Configurable> ConfV0DCADaughMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0DCADaughMax, "ConfV0"), std::vector{1.2f, 1.5f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0DCADaughMax, "V0 selection: ")}; + Configurable> ConfV0CPAMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0CPAMin, "ConfV0"), std::vector{0.99f, 0.995f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0CPAMin, "V0 selection: ")}; + Configurable> ConfV0TranRadMin{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0TranRadMin, "ConfV0"), std::vector{0.2f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0TranRadMin, "V0 selection: ")}; + Configurable> ConfV0TranRadMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0TranRadMax, "ConfV0"), std::vector{100.f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0TranRadMax, "V0 selection: ")}; + Configurable> ConfV0DecVtxMax{FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0DecVtxMax, "ConfV0"), std::vector{100.f}, FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0DecVtxMax, "V0 selection: ")}; + + 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"}; + + 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"}; + + Filter GlobalCutFilter = requireGlobalTrackInFilter(); + + Filter CustomTrackFilter = (aod::track::pt > ConfFilterCuts.ConfPtLowFilterCut) && + (aod::track::pt < ConfFilterCuts.ConfPtHighFilterCut) && + (nabs(aod::track::eta) < ConfFilterCuts.ConfEtaFilterCut) && + (aod::track::dcaXY < ConfFilterCuts.ConfDcaXYFilterCut) && + (aod::track::dcaZ < ConfFilterCuts.ConfDcaZFilterCut); + + // PHI + FemtoUniversePhiSelection phiCuts; + struct : o2::framework::ConfigurableGroup { + Configurable> ConfPhiSign{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiSign, "ConfPhi"), std::vector{-1, 1}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiSign, "Phi selection: ")}; + Configurable> ConfPhiPtMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhipTMin, "ConfPhi"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhipTMin, "Phi selection: ")}; + Configurable> ConfPhiPtMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhipTMax, "ConfPhi"), std::vector{3.3f, 3.4f, 3.5f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhipTMax, "Phi selection: ")}; + Configurable> ConfPhiEtaMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhietaMax, "ConfPhi"), std::vector{0.8f, 0.7f, 0.9f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhietaMax, "Phi selection: ")}; + Configurable> ConfPhiDCADaughMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiDCADaughMax, "ConfPhi"), std::vector{1.2f, 1.5f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiDCADaughMax, "Phi selection: ")}; + Configurable> ConfPhiCPAMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiCPAMin, "ConfPhi"), std::vector{0.99f, 0.995f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiCPAMin, "Phi selection: ")}; + Configurable> ConfPhiTranRadMin{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiTranRadMin, "ConfPhi"), std::vector{0.2f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiTranRadMin, "Phi selection: ")}; + Configurable> ConfPhiTranRadMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiTranRadMax, "ConfPhi"), std::vector{100.f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiTranRadMax, "Phi selection: ")}; + Configurable> ConfPhiDecVtxMax{FemtoUniversePhiSelection::getSelectionName(femtoUniversePhiSelection::kPhiDecVtxMax, "ConfPhi"), std::vector{100.f}, FemtoUniversePhiSelection::getSelectionHelper(femtoUniversePhiSelection::kPhiDecVtxMax, "Phi selection: ")}; + } ConfPhiSelection; + + struct : o2::framework::ConfigurableGroup { + Configurable> ConfPhiChildCharge{"ConfPhiChildSign", std::vector{-1, 1}, "Phi Child sel: Charge"}; + Configurable> ConfPhiChildEtaMax{"ConfPhiChildEtaMax", std::vector{0.8f}, "Phi Child sel: max eta"}; + Configurable> ConfPhiChildTPCnClsMin{"ConfPhiChildTPCnClsMin", std::vector{80.f, 70.f, 60.f}, "Phi Child sel: Min. nCls TPC"}; + Configurable> ConfPhiChildDCAMin{"ConfPhiChildDCAMin", std::vector{0.05f, 0.06f}, "Phi Child sel: Max. DCA Daugh to PV (cm)"}; + Configurable> ConfPhiChildPIDnSigmaMax{"ConfPhiChildPIDnSigmaMax", std::vector{5.f, 4.f}, "Phi Child sel: Max. PID nSigma TPC"}; + Configurable> ConfPhiChildPIDspecies{"ConfPhiChildPIDspecies", std::vector{o2::track::PID::Kaon, o2::track::PID::Kaon}, "Phi Child sel: Particles species for PID"}; + } ConfPhiChildSelection; + + struct : o2::framework::ConfigurableGroup { + Configurable ConfNsigmaCombinedKaon{"ConfNsigmaCombinedKaon", 3.0, "TPC and TOF Kaon Sigma (combined) for momentum > 0.4"}; + Configurable ConfNsigmaTPCKaon{"ConfNsigmaTPCKaon", 3.0, "TPC Kaon Sigma for momentum < 0.4"}; + Configurable ConfNsigmaTPCTOFKaon{"ConfNsigmaTPCTOFKaon", true, "Use TPC and TOF for PID of Kaons"}; + Configurable ConfInvMassLowLimitPhi{"ConfInvMassLowLimitPhi", 1.011, "Lower limit of the Phi invariant mass"}; // change that to do invariant mass cut + Configurable ConfInvMassUpLimitPhi{"ConfInvMassUpLimitPhi", 1.027, "Upper limit of the Phi invariant mass"}; + } ConfPhiCommon; + // PHI child one + struct : o2::framework::ConfigurableGroup { + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 321, "Particle 1 - PDG code"}; + } ConfPhiChildOne; + // PHI child two + struct : o2::framework::ConfigurableGroup { + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 321, "Particle 2 - PDG code"}; + } ConfPhiChildTwo; + + bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + //|nsigma_TPC| < 5 for p < 0.4 GeV/c + //|nsigma_combined| < 5 for p > 0.4 + + // using configurables: + // ConfNsigmaTPCTOFKaon -> are we doing TPC TOF PID for Kaons? (boolean) + // ConfNsigmaTPCKaon -> TPC Kaon Sigma for momentum < 0.4 + // ConfNsigmaCombinedKaon -> TPC and TOF Kaon Sigma (combined) for momentum > 0.4 + + if (mom < 0.3) { // 0.0-0.3 + if (TMath::Abs(nsigmaTPCK) < 3.0) { + return true; + } else { + return false; + } + } else if (mom < 0.45) { // 0.30 - 0.45 + if (TMath::Abs(nsigmaTPCK) < 2.0) { + return true; + } else { + return false; + } + } else if (mom < 0.55) { // 0.45-0.55 + if (TMath::Abs(nsigmaTPCK) < 1.0) { + return true; + } else { + return false; + } + } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) + if ((TMath::Abs(nsigmaTOFK) < 3.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + { + return true; + } + } else { + return false; + } + } else if (mom > 1.5) { // 1.5 - + if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + return true; + } else { + return false; + } + } else { + return false; + } + } /// \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 + // (aod::v0data::v0radius > V0TranRadV0Min.value); to be added, not working + // for now do not know why HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; @@ -227,11 +286,21 @@ struct femtoUniverseProducerTask { void init(InitContext&) { + if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData) == false && (doprocessFullMC || doprocessTrackMC) == false) { + LOGF(fatal, "Neither processFullData nor processFullMC enabled. Please choose one."); + } + if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData) == true && (doprocessFullMC || doprocessTrackMC) == true) { + LOGF(fatal, + "Cannot enable process Data and process MC at the same time. " + "Please choose one."); + } + colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3); colCuts.init(&qaRegistry); trackCuts.setSelection(ConfTrkCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); trackCuts.setSelection(ConfTrkPtmin, femtoUniverseTrackSelection::kpTMin, femtoUniverseSelection::kLowerLimit); + trackCuts.setSelection(ConfTrkPtmax, femtoUniverseTrackSelection::kpTMax, femtoUniverseSelection::kUpperLimit); trackCuts.setSelection(ConfTrkEta, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); trackCuts.setSelection(ConfTrkTPCnclsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); trackCuts.setSelection(ConfTrkTPCfCls, femtoUniverseTrackSelection::kTPCfClsMin, femtoUniverseSelection::kLowerLimit); @@ -242,53 +311,62 @@ struct femtoUniverseProducerTask { trackCuts.setSelection(ConfTrkDCAxyMax, femtoUniverseTrackSelection::kDCAxyMax, femtoUniverseSelection::kAbsUpperLimit); trackCuts.setSelection(ConfTrkDCAzMax, femtoUniverseTrackSelection::kDCAzMax, femtoUniverseSelection::kAbsUpperLimit); trackCuts.setSelection(ConfTrkPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); - trackCuts.setPIDSpecies(ConfTrkTPIDspecies); + trackCuts.setPIDSpecies(ConfTrkPIDspecies); + trackCuts.setnSigmaPIDOffset(ConfTrkPIDnSigmaOffsetTPC, ConfTrkPIDnSigmaOffsetTOF); trackCuts.init(&qaRegistry); - /// \todo fix how to pass array to setSelection, getRow() passing a different type! - // v0Cuts.setSelection(ConfV0Selection->getRow(0), femtoUniverseV0Selection::kDecVtxMax, femtoUniverseSelection::kAbsUpperLimit); - if (ConfStoreV0) { + /// \todo fix how to pass array to setSelection, getRow() passing a + /// different type! + // v0Cuts.setSelection(ConfV0Selection->getRow(0), + // femtoUniverseV0Selection::kDecVtxMax, femtoUniverseSelection::kAbsUpperLimit); + if (ConfIsActivateV0) { + // initializing for V0 v0Cuts.setSelection(ConfV0Sign, femtoUniverseV0Selection::kV0Sign, femtoUniverseSelection::kEqual); - v0Cuts.setSelection(ConfV0PtMin, femtoUniverseV0Selection::kpTV0Min, femtoUniverseSelection::kLowerLimit); - v0Cuts.setSelection(ConfDCAV0DaughMax, femtoUniverseV0Selection::kDCAV0DaughMax, femtoUniverseSelection::kUpperLimit); - v0Cuts.setSelection(ConfCPAV0Min, femtoUniverseV0Selection::kCPAV0Min, femtoUniverseSelection::kLowerLimit); - - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0DaughCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfDaughEta, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0DaughTPCnclsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0DaughDCAMin, femtoUniverseTrackSelection::kDCAMin, femtoUniverseSelection::kAbsLowerLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0DaughPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0DaughCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfDaughEta, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0DaughTPCnclsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0DaughDCAMin, femtoUniverseTrackSelection::kDCAMin, femtoUniverseSelection::kAbsLowerLimit); - v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0DaughPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); - v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kPosTrack, ConfV0DaughTPIDspecies); - v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kNegTrack, ConfV0DaughTPIDspecies); + v0Cuts.setSelection(ConfV0PtMin, femtoUniverseV0Selection::kV0pTMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0PtMax, femtoUniverseV0Selection::kV0pTMax, femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0EtaMax, femtoUniverseV0Selection::kV0etaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setSelection(ConfV0DCADaughMax, femtoUniverseV0Selection::kV0DCADaughMax, femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0CPAMin, femtoUniverseV0Selection::kV0CPAMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0TranRadMin, femtoUniverseV0Selection::kV0TranRadMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0TranRadMax, femtoUniverseV0Selection::kV0TranRadMax, femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0DecVtxMax, femtoUniverseV0Selection::kV0DecVtxMax, femtoUniverseSelection::kUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildDCAMin, femtoUniverseTrackSelection::kDCAMin, femtoUniverseSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildCharge, femtoUniverseTrackSelection::kSign, femtoUniverseSelection::kEqual); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildEtaMax, femtoUniverseTrackSelection::kEtaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildTPCnClsMin, femtoUniverseTrackSelection::kTPCnClsMin, femtoUniverseSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildDCAMin, femtoUniverseTrackSelection::kDCAMin, femtoUniverseSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfChildPIDnSigmaMax, femtoUniverseTrackSelection::kPIDnSigmaMax, femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kPosTrack, ConfChildPIDspecies); + v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kNegTrack, ConfChildPIDspecies); v0Cuts.init(&qaRegistry); - v0Cuts.setInvMassLimits(ConfInvMassLowLimit, ConfInvMassUpLimit); - v0Cuts.setChildRejectNotPropagatedTracks(femtoUniverseV0Selection::kPosTrack, ConfRejectNotPropagatedTracks); - v0Cuts.setChildRejectNotPropagatedTracks(femtoUniverseV0Selection::kNegTrack, ConfRejectNotPropagatedTracks); + v0Cuts.setInvMassLimits(ConfV0InvMassLowLimit, ConfV0InvMassUpLimit); - if (ConfRejectKaons) { - v0Cuts.setKaonInvMassLimits(ConfInvKaonMassLowLimit, ConfInvKaonMassUpLimit); - } - if (ConfRejectITSHitandTOFMissing) { - o2PhysicsTrackSelection = new TrackSelection(getGlobalTrackSelection()); - o2PhysicsTrackSelection->SetRequireHitsInITSLayers(1, {0, 1, 2, 3}); + v0Cuts.setChildRejectNotPropagatedTracks(femtoUniverseV0Selection::kPosTrack, ConfTrkRejectNotPropagated); + v0Cuts.setChildRejectNotPropagatedTracks(femtoUniverseV0Selection::kNegTrack, ConfTrkRejectNotPropagated); + + v0Cuts.setnSigmaPIDOffsetTPC(ConfTrkPIDnSigmaOffsetTPC); + v0Cuts.setChildnSigmaPIDOffset(femtoUniverseV0Selection::kPosTrack, ConfTrkPIDnSigmaOffsetTPC, ConfTrkPIDnSigmaOffsetTOF); + v0Cuts.setChildnSigmaPIDOffset(femtoUniverseV0Selection::kNegTrack, ConfTrkPIDnSigmaOffsetTPC, ConfTrkPIDnSigmaOffsetTOF); + + if (ConfV0RejectKaons) { + v0Cuts.setKaonInvMassLimits(ConfV0InvKaonMassLowLimit, ConfV0InvKaonMassUpLimit); } + // if (ConfRejectITSHitandTOFMissing) { + // o2PhysicsTrackSelection = new + // TrackSelection(getGlobalTrackSelection()); + // o2PhysicsTrackSelection->SetRequireHitsInITSLayers(1, {0, 1, 2, 3}); + // } } - if (ConfStorePhi) { - PhiCuts.init(&qaRegistry); - if (ConfRejectKaonsPhi) { - //! PhiCuts.setKaonInvMassLimits(ConfInvKaonMassLowLimitPhi, ConfInvKaonMassUpLimitPhi); - } - if (ConfRejectITSHitandTOFMissing) { - o2PhysicsTrackSelection = new TrackSelection(getGlobalTrackSelection()); - o2PhysicsTrackSelection->SetRequireHitsInITSLayers(1, {0, 1, 2, 3}); - } + if (ConfIsActivatePhi) { + // initializing for Phi meson + phiCuts.init(&qaRegistry); } + mRunNumber = 0; mMagField = 0.0; /// Initializing CCDB @@ -296,578 +374,576 @@ struct femtoUniverseProducerTask { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); - // changed long to float because of the MegaLinter int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); ccdb->setCreatedNotAfter(now); } - // PID - /* - bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + /// Function to retrieve the nominal magnetic field in kG (0.1T) and convert it directly to T + void getMagneticFieldTesla(aod::BCsWithTimestamps::iterator bc) { - bool fNsigmaTPCTOF = true; - double fNsigma = 3; - double fNsigma2 = 3; - if (fNsigmaTPCTOF) { - if (mom > 0.5) { - // if (TMath::Hypot( nsigmaTOFP, nsigmaTPCP )/TMath::Sqrt(2) < 3.0) - if (mom < 2.0) { - if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < fNsigma) { - return true; - } - } else if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < fNsigma2) { - return true; - } - } else { - if (TMath::Abs(nsigmaTPCK) < fNsigma) { - return true; - } + // 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 { - if (mom < 0.4) { - if (nsigmaTOFK < -999.) { - if (TMath::Abs(nsigmaTPCK) < 2.0) { - return true; - } - } else if (TMath::Abs(nsigmaTOFK) < 3.0 && TMath::Abs(nsigmaTPCK) < 3.0) { - return true; - } - } else if ((mom >= 0.4 && mom <= 0.45) || (mom >= 0.5 && mom <= 0.6)) { - if (nsigmaTOFK < -999.) { - if (TMath::Abs(nsigmaTPCK) < 2.0) { - return true; - } - } else if (TMath::Abs(nsigmaTOFK) < 3.0 && TMath::Abs(nsigmaTPCK) < 3.0) { - return true; - } - } else if ((mom >= 0.45 && mom <= 0.5)) { - if (ConfKaonChangePID == true) { // reducing contamination - return false; - } else { - return true; - } - } else if (nsigmaTOFK < -999.) { - return false; - } else if (TMath::Abs(nsigmaTOFK) < 3.0 && TMath::Abs(nsigmaTPCK) < 3.0) { - return true; + + 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()); } - return false; - }*/ - bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + mMagField = output; + mRunNumber = bc.runNumber(); + } + + template + void fillDebugParticle(ParticleType const& particle) { - //|nsigma_TPC| < 5 for p < 0.4 GeV/c - //|nsigma_combined| < 5 for p > 0.4 + if constexpr (isTrackOrV0) { + 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.tpcNSigmaStoreEl(), particle.tpcNSigmaStorePi(), + particle.tpcNSigmaStoreKa(), particle.tpcNSigmaStorePr(), + particle.tpcNSigmaStoreDe(), particle.tofNSigmaStoreEl(), + particle.tofNSigmaStorePi(), particle.tofNSigmaStoreKa(), + particle.tofNSigmaStorePr(), particle.tofNSigmaStoreDe(), + -999., -999., -999., -999., -999., -999.); + } else if constexpr (isPhi) { + outputDebugParts(-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.); // QA for phi + } else { + LOGF(info, "isTrack0orV0: %d, isPhi: %d", isTrackOrV0, isPhi); + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., + particle.dcaV0daughters(), particle.v0radius(), + particle.x(), particle.y(), particle.z(), + particle.mK0Short()); // QA for v0 + } + } - // using configurables: - // ConfNsigmaTPCTOFKaon -> are we doing TPC TOF PID for Kaons? (boolean) - // ConfNsigmaTPCKaon -> TPC Kaon Sigma for momentum < 0.4 - // ConfNsigmaCombinedKaon -> TPC and TOF Kaon Sigma (combined) for momentum > 0.4 - if (ConfNsigmaTPCTOFKaon) { - if (mom < 0.4) { - if (TMath::Abs(nsigmaTPCK) < ConfNsigmaTPCKaon) { - return true; - } else { - return false; - } - } else if (mom > 0.4) { - if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < ConfNsigmaCombinedKaon) { - return true; + template + void fillMCParticle(ParticleType const& particle, o2::aod::femtouniverseparticle::ParticleType fdparttype) + { + if (particle.has_mcParticle()) { + // get corresponding MC particle and its info + auto particleMC = particle.mcParticle(); + auto pdgCode = particleMC.pdgCode(); + int particleOrigin = 99; + auto motherparticleMC = particleMC.template mothers_as().front(); + + if (abs(pdgCode) == abs(ConfTrkPDGCode.value)) { + if (particleMC.isPhysicalPrimary()) { + particleOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kPrimary; + } else if (motherparticleMC.producedByGenerator()) { + particleOrigin = checkDaughterType(fdparttype, motherparticleMC.pdgCode()); } else { - return false; + particleOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kMaterial; } + } else { + particleOrigin = aod::femtouniverseMCparticle::ParticleOriginMCTruth::kFake; } + + outputPartsMC(particleOrigin, pdgCode, particleMC.pt(), particleMC.eta(), particleMC.phi()); + outputPartsMCLabels(outputPartsMC.lastIndex()); + } else { + outputPartsMCLabels(-1); } - return false; } - /// Function to retrieve the nominal mgnetic field in kG (0.1T) and convert it directly to T - float getMagneticFieldTesla(uint64_t timestamp) + template + void fillCollisions(CollisionType const& col, TrackType const& tracks) { - // TODO done only once (and not per run). Will be replaced by CCDBConfigurable - static o2::parameters::GRPObject* grpo = nullptr; - if (grpo == nullptr) { - grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", timestamp); - if (grpo == nullptr) { - LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); - return 0; - } - LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + const auto vtxZ = col.posZ(); + const auto spher = colCuts.computeSphericity(col, tracks); + int mult = 0; + int multNtr = 0; + if (ConfIsRun3) { + mult = col.multFV0M(); + multNtr = col.multNTracksPV(); + } else { + mult = 0.5 * (col.multFV0M()); /// For benchmarking on Run 2, V0M in + /// FemtoUniverseRun2 is defined V0M/2 + multNtr = col.multTracklets(); } - float output = 0.1 * (grpo->getNominalL3Field()); - return output; - } - - void processProd(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks, - o2::aod::V0Datas const& fullV0s) /// \todo with FilteredFullV0s - { - // get magnetic field for run - auto bc = col.bc_as(); - if (mRunNumber != bc.runNumber()) { - mMagField = getMagneticFieldTesla(bc.timestamp()); - mRunNumber = bc.runNumber(); + if (ConfEvtUseTPCmult) { + multNtr = col.multTPC(); } - /// First thing to do is to check whether the basic event selection criteria are fulfilled - // If the basic selection is NOT fulfilled: + // check whether the basic event selection criteria are fulfilled + // if the basic selection is NOT fulfilled: // in case of skimming run - don't store such collisions - // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + // in case of trigger run - store such collisions but don't store any + // particle candidates for such collisions if (!colCuts.isSelected(col)) { if (ConfIsTrigger) { - outputCollision(col.posZ(), col.multFV0M(), colCuts.computeSphericity(col, tracks), mMagField); + outputCollision(vtxZ, mult, multNtr, spher, mMagField); } return; } - const auto vtxZ = col.posZ(); - const auto mult = col.multFV0M(); - const auto spher = colCuts.computeSphericity(col, tracks); colCuts.fillQA(col); + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + } - // now the table is filled + template + void fillMCTruthCollisions(CollisionType const& col, TrackType const& tracks) + { + const auto vtxZ = col.posZ(); + const auto spher = 0; // colCuts.computeSphericity(col, tracks); + int mult = 0; + int multNtr = 0; if (ConfIsRun3) { - outputCollision(vtxZ, col.multFT0M(), spher, mMagField); + mult = col.multFV0M(); + multNtr = col.multNTracksPV(); } else { - outputCollision(vtxZ, mult, spher, mMagField); + mult = 0.5 * (col.multFV0M()); /// For benchmarking on Run 2, V0M in + /// FemtoUniverseRun2 is defined V0M/2 + multNtr = col.multTracklets(); } + if (ConfEvtUseTPCmult) { + multNtr = col.multTPC(); + } + + // check whether the basic event selection criteria are fulfilled + // if the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any + // particle candidates for such collisions + + // CHECK WHAT CUTS SHOULD BE USED FOR MC TRUTH + // if (!colCuts.isSelected(col)) { + // if (ConfIsTrigger) { + // outputCollision(vtxZ, mult, multNtr, spher, mMagField); + // } + // return; + // } + + colCuts.fillQA(col); + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + } - int childIDs[2] = {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 + template + void fillTracks(TrackType const& tracks) + { + 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 : tracks) { - /// if the most open selection criteria are not fulfilled there is no point looking further at the track + /// if the most open selection criteria are not fulfilled there is no + /// point looking further at the track if (!trackCuts.isSelectedMinimal(track)) { continue; } - trackCuts.fillQA(track); + + trackCuts.fillQA(track); // the bit-wise container of the systematic variations is obtained + auto cutContainer = trackCuts.getCutContainer(track); + // now the table is filled - outputParts(outputCollision.lastIndex(), - track.pt(), - track.eta(), - track.phi(), - track.p(), - 1, - aod::femtouniverseparticle::ParticleType::kTrack, - 0, // cutContainer.at(femtoUniverseTrackSelection::TrackContainerPosition::kCuts), - 0, // cutContainer.at(femtoUniverseTrackSelection::TrackContainerPosition::kPID), - track.dcaXY(), - childIDs, 0, 0, // początek nowej części - track.sign(), - track.beta(), - track.itsChi2NCl(), - track.tpcChi2NCl(), - track.tpcNSigmaKa(), - track.tofNSigmaKa(), - (uint8_t)track.tpcNClsFound(), - track.tpcNClsFindable(), - (uint8_t)track.tpcNClsCrossedRows(), - track.tpcNClsShared(), - track.tpcInnerParam(), - track.itsNCls(), - track.itsNClsInnerBarrel(), - track.dcaXY(), - track.dcaZ(), - track.tpcSignal(), - track.tpcNSigmaStoreEl(), - track.tpcNSigmaStorePi(), - track.tpcNSigmaStoreKa(), - track.tpcNSigmaStorePr(), - track.tpcNSigmaStoreDe(), - track.tofNSigmaStoreEl(), - track.tofNSigmaStorePi(), - track.tofNSigmaStoreKa(), - track.tofNSigmaStorePr(), - track.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999.); + outputParts(outputCollision.lastIndex(), track.pt(), track.eta(), + track.phi(), aod::femtouniverseparticle::ParticleType::kTrack, + cutContainer.at( + femtoUniverseTrackSelection::TrackContainerPosition::kCuts), + cutContainer.at( + femtoUniverseTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), childIDs, 0, 0); tmpIDtrack.push_back(track.globalIndex()); + if (ConfIsDebug) { + fillDebugParticle(track); + } + + if constexpr (isMC) { + fillMCParticle(track, o2::aod::femtouniverseparticle::ParticleType::kTrack); + } } + } - if (ConfStoreV0) { - for (auto& v0 : fullV0s) { - auto postrack = v0.posTrack_as(); - auto negtrack = v0.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); + template + void fillV0(CollisionType const& col, V0Type const& fullV0s, TrackType const& tracks) + { + 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& 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 (!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::femtouniverseparticle::ParticleType::kV0Child, + cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosCuts), + cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0); + const int rowOfPosTrack = outputParts.lastIndex(); + if constexpr (isMC) { + fillMCParticle(postrack, o2::aod::femtouniverseparticle::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::femtouniverseparticle::ParticleType::kV0Child, + cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegCuts), + cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegPID), + 0., + childIDs, + 0, + 0); + const int rowOfNegTrack = outputParts.lastIndex(); + if constexpr (isMC) { + fillMCParticle(negtrack, o2::aod::femtouniverseparticle::ParticleType::kV0Child); + } + std::vector indexChildID = {rowOfPosTrack, rowOfNegTrack}; + outputParts(outputCollision.lastIndex(), + v0.pt(), + v0.eta(), + v0.phi(), + aod::femtouniverseparticle::ParticleType::kV0, + cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kV0), + 0, + v0.v0cosPA(col.posX(), col.posY(), col.posZ()), + indexChildID, + v0.mLambda(), + v0.mAntiLambda()); + if (ConfIsDebug) { + fillDebugParticle(postrack); // QA for positive daughter + fillDebugParticle(negtrack); // QA for negative daughter + fillDebugParticle(v0); // QA for v0 + } + if constexpr (isMC) { + fillMCParticle(v0, o2::aod::femtouniverseparticle::ParticleType::kV0); + } + } + } - 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); - } + template + void fillPhi(CollisionType const& col, TrackType const& tracks) + { + 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 + // lorentz vectors and filling the tables + for (auto& [p1, p2] : combinations(soa::CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { + // implementing PID cuts for phi children + if (!(IsKaonNSigma(p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon)))) { + continue; + } + if (!(IsKaonNSigma(p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon)))) { + continue; + } else if ((!(p1.sign() == 1)) || (!(p2.sign() == -1))) { + continue; + } - v0Cuts.fillQA(col, v0, postrack, negtrack); ///\todo fill QA also for daughters - auto cutContainerV0 = v0Cuts.getCutContainer(col, v0, postrack, negtrack); - - if ((cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kV0) > 0) && (cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosCuts) > 0) && (cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegCuts) > 0)) { - 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(), - 0, // v0.p(), - 0, // mass - aod::femtouniverseparticle::ParticleType::kV0Child, - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosCuts), - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosPID), - 0., - childIDs, - 0, - 0, - postrack.sign(), - postrack.beta(), - postrack.itsChi2NCl(), - postrack.tpcChi2NCl(), - postrack.tpcNSigmaKa(), - postrack.tofNSigmaKa(), - (uint8_t)postrack.tpcNClsFound(), - postrack.tpcNClsFindable(), - (uint8_t)postrack.tpcNClsCrossedRows(), - postrack.tpcNClsShared(), - postrack.tpcInnerParam(), - postrack.itsNCls(), - postrack.itsNClsInnerBarrel(), - postrack.dcaXY(), - postrack.dcaZ(), - postrack.tpcSignal(), - postrack.tpcNSigmaStoreEl(), - postrack.tpcNSigmaStorePi(), - postrack.tpcNSigmaStoreKa(), - postrack.tpcNSigmaStorePr(), - postrack.tpcNSigmaStoreDe(), - postrack.tofNSigmaStoreEl(), - postrack.tofNSigmaStorePi(), - postrack.tofNSigmaStoreKa(), - postrack.tofNSigmaStorePr(), - postrack.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999.); - const int rowOfPosTrack = outputParts.lastIndex(); - 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(), - 0, // momentum - 0, // mass - aod::femtouniverseparticle::ParticleType::kV0Child, - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegCuts), - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegPID), - 0., - childIDs, - 0, - 0, - negtrack.sign(), - negtrack.beta(), - negtrack.itsChi2NCl(), - negtrack.tpcChi2NCl(), - negtrack.tpcNSigmaKa(), - negtrack.tofNSigmaKa(), - (uint8_t)negtrack.tpcNClsFound(), - negtrack.tpcNClsFindable(), - (uint8_t)negtrack.tpcNClsCrossedRows(), - negtrack.tpcNClsShared(), - negtrack.tpcInnerParam(), - negtrack.itsNCls(), - negtrack.itsNClsInnerBarrel(), - negtrack.dcaXY(), - negtrack.dcaZ(), - negtrack.tpcSignal(), - negtrack.tpcNSigmaStoreEl(), - negtrack.tpcNSigmaStorePi(), - negtrack.tpcNSigmaStoreKa(), - negtrack.tpcNSigmaStorePr(), - negtrack.tpcNSigmaStoreDe(), - negtrack.tofNSigmaStoreEl(), - negtrack.tofNSigmaStorePi(), - negtrack.tofNSigmaStoreKa(), - negtrack.tofNSigmaStorePr(), - negtrack.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999.); - const int rowOfNegTrack = outputParts.lastIndex(); - int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; - outputParts(outputCollision.lastIndex(), - v0.pt(), - v0.eta(), - v0.phi(), - 0, // momentum - 0, // mass - aod::femtouniverseparticle::ParticleType::kV0, - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kV0), - 0, - v0.v0cosPA(col.posX(), col.posY(), col.posZ()), - indexChildID, - v0.mLambda(), - v0.mAntiLambda(), - postrack.sign(), - postrack.beta(), - postrack.itsChi2NCl(), - postrack.tpcChi2NCl(), - postrack.tpcNSigmaKa(), - postrack.tofNSigmaKa(), - (uint8_t)postrack.tpcNClsFound(), - postrack.tpcNClsFindable(), - (uint8_t)postrack.tpcNClsCrossedRows(), - postrack.tpcNClsShared(), - postrack.tpcInnerParam(), - postrack.itsNCls(), - postrack.itsNClsInnerBarrel(), - postrack.dcaXY(), - postrack.dcaZ(), - postrack.tpcSignal(), - postrack.tpcNSigmaStoreEl(), - postrack.tpcNSigmaStorePi(), - postrack.tpcNSigmaStoreKa(), - postrack.tpcNSigmaStorePr(), - postrack.tpcNSigmaStoreDe(), - postrack.tofNSigmaStoreEl(), - postrack.tofNSigmaStorePi(), - postrack.tofNSigmaStoreKa(), - postrack.tofNSigmaStorePr(), - postrack.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999.); - } + TLorentzVector part1Vec; + TLorentzVector part2Vec; + + float mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPhiChildOne.ConfPDGCodePartOne)->Mass(); + float mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPhiChildTwo.ConfPDGCodePartTwo)->Mass(); + + part1Vec.SetPtEtaPhiM(p1.pt(), p1.eta(), p1.phi(), mMassOne); + part2Vec.SetPtEtaPhiM(p2.pt(), p2.eta(), p2.phi(), mMassTwo); + + TLorentzVector sumVec(part1Vec); + sumVec += part2Vec; + + float phiEta = sumVec.Eta(); + if (TMath::Abs(phiEta) > 0.8) { + continue; } - } - if (ConfStorePhi) { - for (auto& [p1, p2] : combinations(soa::CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { - if ((p1.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet) || (p2.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet)) { - continue; - } else if (p1.globalIndex() == p2.globalIndex()) { // checking not to correlate same particles - continue; - } else if ((p1.pt() < cfgPtLowPart1) || (p1.pt() > cfgPtHighPart1)) { // pT cuts for part1 - continue; - } else if ((p1.p() < cfgPLowPart1) || (p1.p() > cfgPHighPart1)) { // p cuts for part1 - continue; - } else if ((p1.eta() < cfgEtaLowPart1) || (p1.eta() > cfgEtaHighPart1)) { // eta cuts for part1 - continue; - } else if ((p2.pt() < cfgPtLowPart2) || (p2.pt() > cfgPtHighPart2)) { // pT cuts for part2 - continue; - } else if ((p2.p() < cfgPLowPart2) || (p2.p() > cfgPHighPart2)) { // p cuts for part2 - continue; - } else if ((p2.eta() < cfgEtaLowPart2) || (p2.eta() > cfgEtaHighPart2)) { // eta for part2 - continue; - } else if (!(IsKaonNSigma(p1.p(), p1.tpcNSigmaKa(), p1.tofNSigmaKa()))) { // PID for Kaons - continue; - } else if (!(IsKaonNSigma(p2.p(), p2.tpcNSigmaKa(), p2.tofNSigmaKa()))) { - continue; - } - TLorentzVector part1Vec; - TLorentzVector part2Vec; - float mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartOne)->Mass(); - float mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartTwo)->Mass(); + float phiPt = sumVec.Pt(); + if ((phiPt < 0.14) || (phiPt > 10.0)) { + continue; + } - part1Vec.SetPtEtaPhiM(p1.pt(), p1.eta(), p1.phi(), mMassOne); - part2Vec.SetPtEtaPhiM(p2.pt(), p2.eta(), p2.phi(), mMassTwo); + float phiPhi = sumVec.Phi(); + if (sumVec.Phi() < 0) { + phiPhi = sumVec.Phi() + 2 * o2::constants::math::PI; + } else if (sumVec.Phi() >= 0) { + phiPhi = sumVec.Phi(); + } + float phiM = sumVec.M(); - TLorentzVector sumVec(part1Vec); - sumVec += part2Vec; + if (((phiM < ConfPhiCommon.ConfInvMassLowLimitPhi) || (phiM > ConfPhiCommon.ConfInvMassUpLimitPhi))) { + continue; + } - float phiEta = sumVec.Eta(); - float phiPt = sumVec.Pt(); - float phiP = sumVec.P(); - float phiM = sumVec.M(); + phiCuts.fillQA(col, p1, p1, p2, ConfPhiChildOne.ConfPDGCodePartOne, ConfPhiChildTwo.ConfPDGCodePartTwo); ///\todo fill QA also for daughters + + int postrackID = p1.globalIndex(); + int rowInPrimaryTrackTablePos = -1; // does it do anything? + rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); + childIDs[0] = rowInPrimaryTrackTablePos; + childIDs[1] = 0; + + outputParts(outputCollision.lastIndex(), p1.pt(), + p1.eta(), p1.phi(), + aod::femtouniverseparticle::ParticleType::kPhiChild, + -999, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosCuts), + -999, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosPID), + p1.dcaXY(), + childIDs, + 0, + 0); + const int rowOfPosTrack = outputParts.lastIndex(); + if constexpr (isMC) { + fillMCParticle(p1, o2::aod::femtouniverseparticle::ParticleType::kPhiChild); + } + int negtrackID = p2.globalIndex(); + int rowInPrimaryTrackTableNeg = -1; + rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); + childIDs[0] = 0; + childIDs[1] = rowInPrimaryTrackTableNeg; + outputParts(outputCollision.lastIndex(), + p2.pt(), + p2.eta(), + p2.phi(), + aod::femtouniverseparticle::ParticleType::kPhiChild, + -999, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegCuts), + -999, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegPID), + p2.dcaXY(), + childIDs, + 0, + 0); + const int rowOfNegTrack = outputParts.lastIndex(); + if constexpr (isMC) { + fillMCParticle(p2, o2::aod::femtouniverseparticle::ParticleType::kPhiChild); + } + std::vector indexChildID = {rowOfPosTrack, rowOfNegTrack}; - if (((phiM < ConfInvMassLowLimitPhi) || (phiM > ConfInvMassUpLimitPhi))) { - continue; - } + outputParts(outputCollision.lastIndex(), + phiPt, + phiEta, + phiPhi, + aod::femtouniverseparticle::ParticleType::kPhi, + -999, // cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kV0), + 0, + phiM, // v0.v0cosPA(col.posX(), col.posY(), col.posZ()), + indexChildID, + phiM, // phi.mLambda(), //for now it will have a mLambda getter, maybe we will change it in the future so it's more logical + -999); // v0.mAntiLambda() + + if (ConfIsDebug) { + fillDebugParticle(p1); // QA for positive daughter + fillDebugParticle(p2); // QA for negative daughter + fillDebugParticle(p1); // QA for phi + } + // if constexpr (isMC) { + // fillMCParticle(v0, o2::aod::femtouniverseparticle::ParticleType::kV0); + // } + } + } + + template + void fillParticles(TrackType const& tracks) + { + std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children + + for (auto& particle : tracks) { + /// if the most open selection criteria are not fulfilled there is no + /// point looking further at the track + if (!particle.isPhysicalPrimary()) + continue; + + uint32_t pdgCode = (uint32_t)particle.pdgCode(); - PhiCuts.fillQA(col, p1, p1, p2); ///\todo fill QA also for daughters - auto cutContainerV0 = PhiCuts.getCutContainer(col, p1, p2); - if (true) { // temporary true value, we are doing simpler version first - int postrackID = p1.globalIndex(); - int rowInPrimaryTrackTablePos = -1; - rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); - childIDs[0] = rowInPrimaryTrackTablePos; - childIDs[1] = 0; - outputParts(outputCollision.lastIndex(), - p1.pt(), - p1.eta(), - p1.phi(), - p1.p(), - mMassOne, - aod::femtouniverseparticle::ParticleType::kPhiChild, - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosCuts), - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kPosPID), - 0., - childIDs, - 0, - 0, - p1.sign(), - p1.beta(), - p1.itsChi2NCl(), - p1.tpcChi2NCl(), - p1.tpcNSigmaKa(), - p1.tofNSigmaKa(), - (uint8_t)p1.tpcNClsFound(), - p1.tpcNClsFindable(), - (uint8_t)p1.tpcNClsCrossedRows(), - p1.tpcNClsShared(), - p1.tpcInnerParam(), - p1.itsNCls(), - p1.itsNClsInnerBarrel(), - p1.dcaXY(), - p1.dcaZ(), - p1.tpcSignal(), - p1.tpcNSigmaStoreEl(), - p1.tpcNSigmaStorePi(), - p1.tpcNSigmaStoreKa(), - p1.tpcNSigmaStorePr(), - p1.tpcNSigmaStoreDe(), - p1.tofNSigmaStoreEl(), - p1.tofNSigmaStorePi(), - p1.tofNSigmaStoreKa(), - p1.tofNSigmaStorePr(), - p1.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999.); - const int rowOfPosTrack = outputParts.lastIndex(); - int negtrackID = p2.globalIndex(); - int rowInPrimaryTrackTableNeg = -1; - rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); - childIDs[0] = 0; - childIDs[1] = rowInPrimaryTrackTableNeg; - outputParts(outputCollision.lastIndex(), - p2.pt(), - p2.eta(), - p2.phi(), - p2.p(), - mMassTwo, - aod::femtouniverseparticle::ParticleType::kPhiChild, - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegCuts), - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kNegPID), - 0., - childIDs, - 0, - 0, - p2.sign(), - p2.beta(), - p2.itsChi2NCl(), - p2.tpcChi2NCl(), - p2.tpcNSigmaKa(), - p2.tofNSigmaKa(), - (uint8_t)p2.tpcNClsFound(), - p2.tpcNClsFindable(), - (uint8_t)p2.tpcNClsCrossedRows(), - p2.tpcNClsShared(), - p2.tpcInnerParam(), - p2.itsNCls(), - p2.itsNClsInnerBarrel(), - p2.dcaXY(), - p2.dcaZ(), - p2.tpcSignal(), - p2.tpcNSigmaStoreEl(), - p2.tpcNSigmaStorePi(), - p2.tpcNSigmaStoreKa(), - p2.tpcNSigmaStorePr(), - p2.tpcNSigmaStoreDe(), - p2.tofNSigmaStoreEl(), - p2.tofNSigmaStorePi(), - p2.tofNSigmaStoreKa(), - p2.tofNSigmaStorePr(), - p2.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999.); - - const int rowOfNegTrack = outputParts.lastIndex(); - int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; - float phiPhi = sumVec.Phi(); - if (sumVec.Phi() < 0) { - phiPhi = sumVec.Phi() + 2 * o2::constants::math::PI; - } else if (sumVec.Phi() >= 0) { - phiPhi = sumVec.Phi(); + if (ConfMCTruthAnalysisWithPID) { + bool pass = false; + std::vector tmpPDGCodes = ConfMCTruthPDGCodes; // necessary due to some features of the Configurable + for (uint32_t pdg : tmpPDGCodes) { + if (static_cast(pdg) == static_cast(pdgCode)) { + pass = true; } - outputParts(outputCollision.lastIndex(), - phiPt, - phiEta, - phiPhi, - phiP, - phiM, - aod::femtouniverseparticle::ParticleType::kPhi, - cutContainerV0.at(femtoUniverseV0Selection::V0ContainerPosition::kV0), - 0, - 0, // p1.v0cosPA(col.posX(), col.posY(), col.posZ()), - indexChildID, - 0, // v0.mLambda(), - 0, // v0.mAntiLambda(), - p1.sign(), - p1.beta(), - p1.itsChi2NCl(), - p1.tpcChi2NCl(), - p1.tpcNSigmaKa(), - p1.tofNSigmaKa(), - (uint8_t)p1.tpcNClsFound(), - 0, // p1.tpcNClsFindable(), - 0, //(uint8_t)p1.tpcNClsCrossedRows(), - p1.tpcNClsShared(), - p1.tpcInnerParam(), - p1.itsNCls(), - p1.itsNClsInnerBarrel(), - 0, // p1.dcaXY(), - 0, // p1.dcaZ(), - p1.tpcSignal(), - p1.tpcNSigmaStoreEl(), - p1.tpcNSigmaStorePi(), - p1.tpcNSigmaStoreKa(), - p1.tpcNSigmaStorePr(), - p1.tpcNSigmaStoreDe(), - p1.tofNSigmaStoreEl(), - p1.tofNSigmaStorePi(), - p1.tofNSigmaStoreKa(), - p1.tofNSigmaStorePr(), - p1.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999.); } + if (!pass) + continue; } + + // we cannot use isSelectedMinimal since it takes Ncls + // if (!trackCuts.isSelectedMinimal(track)) { + // continue; + // } + + // trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // auto cutContainer = trackCuts.getCutContainer(track); + // instead of the bitmask, the PDG of the particle is stored as uint32_t + + // now the table is filled + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + pdgCode, + pdgCode, + childIDs, + 0, + 0); + } + } + + template + void fillCollisionsAndTracksAndV0AndPhi(CollisionType const& col, TrackType const& tracks, V0Type const& fullV0s) + { + fillCollisions(col, tracks); + fillTracks(tracks); + if (ConfIsActivateV0) { + fillV0(col, fullV0s, tracks); } + if (ConfIsActivatePhi) { + fillPhi(col, tracks); + } + } + + void + processFullData(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0AndPhi(col, tracks, fullV0s); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processFullData, + "Provide experimental data", false); + + void + processFullMC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::McCollisions const& mcCollisions, + aod::McParticles const& mcParticles, + soa::Join const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisionsAndTracksAndV0AndPhi(col, tracks, fullV0s); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processFullMC, "Provide MC data (tracks, V0, Phi)", false); + + void + processTrackMC(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + soa::Join const& tracks, + aod::McCollisions const& mcCollisions, + aod::McParticles const&) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisions(col, tracks); + fillTracks(tracks); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackMC, "Provide MC data for track analysis", false); + + void + processTrackData(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks) /// \todo with FilteredFullV0s + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisions(col, tracks); + fillTracks(tracks); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackData, + "Provide experimental data for track track", true); + + // using FilteredFemtoFullTracks = soa::Filtered; + void processTrackPhiData(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + soa::Filtered const& tracks) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + // fill the tables + fillCollisions(col, tracks); + fillTracks(tracks); + fillPhi(col, tracks); + } + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackPhiData, + "Provide experimental data for track phi", false); + + void + processTrackMCTruth(aod::FemtoFullCollisionMC const& col, + aod::BCsWithTimestamps const&, + aod::McCollisions const& mcCollisions, + aod::McParticles const& mcParticles) + { + // magnetic field for run not needed for mc truth + // fill the tables + fillMCTruthCollisions(col, mcParticles); + fillParticles(mcParticles); } - PROCESS_SWITCH(femtoUniverseProducerTask, processProd, "Produce Femto tables", true); + PROCESS_SWITCH(femtoUniverseProducerTask, processTrackMCTruth, "Provide MC data for MC truth track analysis", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTaskV0Only.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTaskV0Only.cxx new file mode 100644 index 00000000000..aa813a10080 --- /dev/null +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTaskV0Only.cxx @@ -0,0 +1,510 @@ +// 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 femtoUniverseProducerTaskV0Only.cxx +/// \brief Tasks that produces the track tables used for the pairing +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Math/Vector4D.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "ReconstructionDataFormats/Track.h" +#include "TMath.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ + +using FemtoFullCollision = + soa::Join::iterator; +using FemtoFullTracks = + soa::Join; +// using FilteredFullV0s = soa::Filtered; /// predefined Join +// table for o2::aod::V0s = soa::Join +// to be used when we add v0Filter +} // namespace o2::aod + +/// \todo fix how to pass array to setSelection, getRow() passing a different +/// type! +// static constexpr float arrayV0Sel[3][3] = {{100.f, 100.f, 100.f}, {0.2f, +// 0.2f, 0.2f}, {100.f, 100.f, 100.f}}; unsigned int rows = sizeof(arrayV0Sel) / +// sizeof(arrayV0Sel[0]); unsigned int columns = sizeof(arrayV0Sel[0]) / +// sizeof(arrayV0Sel[0][0]); + +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 femtoUniverseProducerTaskV0Only { + + Produces outputCollision; + Produces outputParts; + Produces outputDebugParts; + + Configurable ConfDebugOutput{"ConfDebugOutput", true, "Debug output"}; + + // Choose if filtering or skimming version is run + + Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; + + // Choose if running on converted data or Run3 / Pilot + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; + Configurable ConfIsMC{"ConfIsMC", false, "Running on MC; implemented only for Run3"}; + + /// Event cuts + FemtoUniverseCollisionSelection colCuts; + Configurable ConfUseTPCmult{"ConfUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; + 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 ConfStoreV0{"ConfStoreV0", true, "True: store V0 table"}; + // just sanity check to make sure in case there are problems in conversion or + // MC production it does not affect results + Configurable ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; + FemtoUniverseV0Selection v0Cuts; + /// \todo Labeled array (see Track-Track task) + + Configurable> ConfV0Sign{ + FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0Sign, + "ConfV0"), + std::vector{-1, 1}, + FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0Sign, + "V0 selection: ")}; + Configurable> ConfV0PtMin{ + FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0pTMin, + "ConfV0"), + std::vector{0.3f}, + FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0pTMin, + "V0 selection: ")}; + Configurable> ConfV0PtMax{ + FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0pTMax, + "ConfV0"), + std::vector{6.f}, + FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0pTMax, + "V0 selection: ")}; + Configurable> ConfV0EtaMax{ + FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0etaMax, + "ConfV0"), + std::vector{6.f}, + FemtoUniverseV0Selection::getSelectionHelper(femtoUniverseV0Selection::kV0etaMax, + "V0 selection: ")}; + Configurable> ConfDCAV0DaughMax{ + FemtoUniverseV0Selection::getSelectionName( + femtoUniverseV0Selection::kV0DCADaughMax, "ConfV0"), + std::vector{1.5f}, + FemtoUniverseV0Selection::getSelectionHelper( + femtoUniverseV0Selection::kV0DCADaughMax, "V0 selection: ")}; + Configurable> ConfCPAV0Min{ + FemtoUniverseV0Selection::getSelectionName(femtoUniverseV0Selection::kV0CPAMin, + "ConfV0"), + std::vector{0.99f}, + FemtoUniverseV0Selection::getSelectionHelper( + femtoUniverseV0Selection::kV0CPAMin, "V0 selection: ")}; + + Configurable> V0TranRadV0Min{ + FemtoUniverseV0Selection::getSelectionName( + femtoUniverseV0Selection::kV0TranRadMin, "ConfV0"), + std::vector{0.2f}, + FemtoUniverseV0Selection::getSelectionHelper( + femtoUniverseV0Selection::kV0TranRadMin, "V0 selection: ")}; + Configurable> V0TranRadV0Max{ + FemtoUniverseV0Selection::getSelectionName( + femtoUniverseV0Selection::kV0TranRadMax, "ConfV0"), + std::vector{100.f}, + FemtoUniverseV0Selection::getSelectionHelper( + femtoUniverseV0Selection::kV0TranRadMax, "V0 selection: ")}; + Configurable> V0DecVtxMax{ + FemtoUniverseV0Selection::getSelectionName( + femtoUniverseV0Selection::kV0DecVtxMax, "ConfV0"), + std::vector{100.f}, + FemtoUniverseV0Selection::getSelectionHelper( + femtoUniverseV0Selection::kV0DecVtxMax, "V0 selection: ")}; + + Configurable> ConfV0DaughCharge{ + "ConfV0DaughCharge", std::vector{-1, 1}, "V0 Daugh sel: Charge"}; + Configurable> ConfDaughEta{ + "ConfDaughEta", std::vector{0.8f}, "V0 Daugh sel: max eta"}; + Configurable> ConfV0DaughTPCnclsMin{ + "ConfV0DaughTPCnclsMin", std::vector{70.f}, + "V0 Daugh sel: Min. nCls TPC"}; + Configurable> ConfV0DaughDCAMin{ + "ConfV0DaughDCAMin", std::vector{0.05f}, + "V0 Daugh sel: Max. DCA Daugh to PV (cm)"}; + Configurable> ConfV0DaughPIDnSigmaMax{ + "ConfV0DaughPIDnSigmaMax", std::vector{5.f}, + "V0 Daugh sel: Max. PID nSigma TPC"}; + + Configurable> ConfV0DaughTPIDspecies{ + "ConfV0DaughTPIDspecies", + std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, + o2::track::PID::Proton}, + "V0 Daugh sel: Particles species for PID"}; + + Configurable ConfInvMassLowLimit{ + "ConfInvMassLowLimit", 1.05, "Lower limit of the V0 invariant mass"}; + Configurable ConfInvMassUpLimit{ + "ConfInvMassUpLimit", 1.30, "Upper limit of the V0 invariant mass"}; + + Configurable ConfRejectKaons{"ConfRejectKaons", false, + "Switch to reject kaons"}; + Configurable ConfInvKaonMassLowLimit{ + "ConfInvKaonMassLowLimit", 0.48, + "Lower limit of the V0 invariant mass for Kaon rejection"}; + Configurable ConfInvKaonMassUpLimit{ + "ConfInvKaonMassUpLimit", 0.515, + "Upper limit of the V0 invariant mass for Kaon rejection"}; + + /// \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 + + HistogramRegistry qaRegistry{ + "QAHistos", + {}, + OutputObjHandlingPolicy::QAObject}; + + int mRunNumber; + float mMagField; + Service ccdb; /// Accessing the CCDB + + void init(InitContext&) + { + colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, + ConfEvtOfflineCheck, ConfIsRun3); + colCuts.init(&qaRegistry); + + /// \todo fix how to pass array to setSelection, getRow() passing a + /// different type! + // v0Cuts.setSelection(ConfV0Selection->getRow(0), + // femtoUniverseV0Selection::kDecVtxMax, femtoUniverseSelection::kAbsUpperLimit); + if (ConfStoreV0) { + v0Cuts.setSelection(ConfV0Sign, femtoUniverseV0Selection::kV0Sign, + femtoUniverseSelection::kEqual); + v0Cuts.setSelection(ConfV0PtMin, femtoUniverseV0Selection::kV0pTMin, + femtoUniverseSelection::kLowerLimit); + v0Cuts.setSelection(ConfV0PtMax, femtoUniverseV0Selection::kV0pTMax, + femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfV0EtaMax, femtoUniverseV0Selection::kV0etaMax, + femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfDCAV0DaughMax, + femtoUniverseV0Selection::kV0DCADaughMax, + femtoUniverseSelection::kUpperLimit); + v0Cuts.setSelection(ConfCPAV0Min, femtoUniverseV0Selection::kV0CPAMin, + femtoUniverseSelection::kLowerLimit); + + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0DaughCharge, + femtoUniverseTrackSelection::kSign, + femtoUniverseSelection::kEqual); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfDaughEta, + femtoUniverseTrackSelection::kEtaMax, + femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, + ConfV0DaughTPCnclsMin, + femtoUniverseTrackSelection::kTPCnClsMin, + femtoUniverseSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, ConfV0DaughDCAMin, + femtoUniverseTrackSelection::kDCAMin, + femtoUniverseSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kPosTrack, + ConfV0DaughPIDnSigmaMax, + femtoUniverseTrackSelection::kPIDnSigmaMax, + femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0DaughCharge, + femtoUniverseTrackSelection::kSign, + femtoUniverseSelection::kEqual); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfDaughEta, + femtoUniverseTrackSelection::kEtaMax, + femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, + ConfV0DaughTPCnclsMin, + femtoUniverseTrackSelection::kTPCnClsMin, + femtoUniverseSelection::kLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, ConfV0DaughDCAMin, + femtoUniverseTrackSelection::kDCAMin, + femtoUniverseSelection::kAbsLowerLimit); + v0Cuts.setChildCuts(femtoUniverseV0Selection::kNegTrack, + ConfV0DaughPIDnSigmaMax, + femtoUniverseTrackSelection::kPIDnSigmaMax, + femtoUniverseSelection::kAbsUpperLimit); + v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kPosTrack, + ConfV0DaughTPIDspecies); + v0Cuts.setChildPIDSpecies(femtoUniverseV0Selection::kNegTrack, + ConfV0DaughTPIDspecies); + v0Cuts.init(&qaRegistry); + v0Cuts.setInvMassLimits(ConfInvMassLowLimit, ConfInvMassUpLimit); + v0Cuts.setChildRejectNotPropagatedTracks(femtoUniverseV0Selection::kPosTrack, + ConfRejectNotPropagatedTracks); + v0Cuts.setChildRejectNotPropagatedTracks(femtoUniverseV0Selection::kNegTrack, + ConfRejectNotPropagatedTracks); + if (ConfRejectKaons) { + v0Cuts.setKaonInvMassLimits(ConfInvKaonMassLowLimit, + ConfInvKaonMassUpLimit); + } + } + 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 mgnetic field in kG (0.1T) and convert it + /// directly to T + float getMagneticFieldTesla(uint64_t timestamp) + { + // TODO done only once (and not per run). Will be replaced by + // CCDBConfigurable + float output = -999; + + if (ConfIsRun3 && !ConfIsMC) { + static o2::parameters::GRPMagField* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp( + "GLO/Config/GRPMagField", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + 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); + } + + if (!ConfIsRun3 || (ConfIsRun3 && ConfIsMC)) { + static o2::parameters::GRPObject* grpo = nullptr; + if (grpo == nullptr) { + grpo = ccdb->getForTimeStamp("GLO/GRP/GRP", + timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object not found for timestamp %llu", timestamp); + return 0; + } + LOGF(info, + "Retrieved GRP for timestamp %llu with magnetic field of %d kG", + timestamp, grpo->getNominalL3Field()); + } + output = 0.1 * (grpo->getNominalL3Field()); + } + return output; + } + + void process(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) /// \todo with FilteredFullV0s + { + // get magnetic field for run + auto bc = col.bc_as(); + if (mRunNumber != bc.runNumber()) { + mMagField = getMagneticFieldTesla(bc.timestamp()); + mRunNumber = bc.runNumber(); + } + + const auto vtxZ = col.posZ(); + const auto spher = colCuts.computeSphericity(col, tracks); + + int mult = 0; + int multNtr = 0; + if (ConfIsRun3) { + mult = col.multFV0M(); + multNtr = col.multNTracksPV(); + } else { + mult = 0.5 * (col.multFV0M()); /// For benchmarking on Run 2, V0M in + /// FemtoUniverseRun2 is defined V0M/2 + multNtr = col.multTracklets(); + } + if (ConfUseTPCmult) { + multNtr = col.multTPC(); + } + + /// First thing to do is to check whether the basic event selection criteria + /// are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any + // particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + } + return; + } + + colCuts.fillQA(col); + // now the table is filled + outputCollision(vtxZ, mult, multNtr, spher, mMagField); + + 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 + + if (ConfStoreV0) { + for (auto& v0 : fullV0s) { + auto postrack = v0.posTrack_as(); + auto negtrack = + v0.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; + } + v0Cuts.fillQA( + col, v0, postrack, negtrack); ///\todo fill QA also for daughters + auto cutContainerV0 = + v0Cuts.getCutContainer( + col, v0, postrack, negtrack); + + if ((cutContainerV0.at( + femtoUniverseV0Selection::V0ContainerPosition::kV0) > 0) && + (cutContainerV0.at( + femtoUniverseV0Selection::V0ContainerPosition::kPosCuts) > 0) && + (cutContainerV0.at( + femtoUniverseV0Selection::V0ContainerPosition::kNegCuts) > 0)) { + 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::femtouniverseparticle::ParticleType::kV0Child, + cutContainerV0.at( + femtoUniverseV0Selection::V0ContainerPosition::kPosCuts), + cutContainerV0.at( + femtoUniverseV0Selection::V0ContainerPosition::kPosPID), + 0., childIDs, 0, 0); + const int rowOfPosTrack = outputParts.lastIndex(); + 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::femtouniverseparticle::ParticleType::kV0Child, + cutContainerV0.at( + femtoUniverseV0Selection::V0ContainerPosition::kNegCuts), + cutContainerV0.at( + femtoUniverseV0Selection::V0ContainerPosition::kNegPID), + 0., childIDs, 0, 0); + const int rowOfNegTrack = outputParts.lastIndex(); + std::vector indexChildID = {rowOfPosTrack, rowOfNegTrack}; + outputParts(outputCollision.lastIndex(), v0.pt(), v0.eta(), v0.phi(), + aod::femtouniverseparticle::ParticleType::kV0, + cutContainerV0.at( + femtoUniverseV0Selection::V0ContainerPosition::kV0), + 0, v0.v0cosPA(col.posX(), col.posY(), col.posZ()), + indexChildID, v0.mLambda(), v0.mAntiLambda()); + if (ConfDebugOutput) { + outputDebugParts( + postrack.sign(), (uint8_t)postrack.tpcNClsFound(), + postrack.tpcNClsFindable(), + (uint8_t)postrack.tpcNClsCrossedRows(), + postrack.tpcNClsShared(), postrack.tpcInnerParam(), + postrack.itsNCls(), postrack.itsNClsInnerBarrel(), + postrack.dcaXY(), postrack.dcaZ(), postrack.tpcSignal(), + postrack.tpcNSigmaStoreEl(), postrack.tpcNSigmaStorePi(), + postrack.tpcNSigmaStoreKa(), postrack.tpcNSigmaStorePr(), + postrack.tpcNSigmaStoreDe(), postrack.tofNSigmaStoreEl(), + postrack.tofNSigmaStorePi(), postrack.tofNSigmaStoreKa(), + postrack.tofNSigmaStorePr(), postrack.tofNSigmaStoreDe(), -999., + -999., -999., -999., -999., + -999.); // QA for positive daughter + outputDebugParts( + negtrack.sign(), (uint8_t)negtrack.tpcNClsFound(), + negtrack.tpcNClsFindable(), + (uint8_t)negtrack.tpcNClsCrossedRows(), + negtrack.tpcNClsShared(), negtrack.tpcInnerParam(), + negtrack.itsNCls(), negtrack.itsNClsInnerBarrel(), + negtrack.dcaXY(), negtrack.dcaZ(), negtrack.tpcSignal(), + negtrack.tpcNSigmaStoreEl(), negtrack.tpcNSigmaStorePi(), + negtrack.tpcNSigmaStoreKa(), negtrack.tpcNSigmaStorePr(), + negtrack.tpcNSigmaStoreDe(), negtrack.tofNSigmaStoreEl(), + negtrack.tofNSigmaStorePi(), negtrack.tofNSigmaStoreKa(), + negtrack.tofNSigmaStorePr(), negtrack.tofNSigmaStoreDe(), -999., + -999., -999., -999., -999., + -999.); // QA for negative daughter + outputDebugParts(-999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., + -999., -999., -999., -999., -999., -999., -999., + v0.dcaV0daughters(), v0.v0radius(), v0.x(), v0.y(), + v0.z(), + v0.mK0Short()); // QA for V0 + } + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt index eb3c7833d08..b93a111bf17 100644 --- a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt @@ -9,4 +9,52 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +o2physics_add_dpl_workflow(femtouniverse-pair-track-track + SOURCES femtoUniversePairTaskTrackTrack.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtouniverse-pair-track-track-mc-truth + SOURCES femtoUniversePairTaskTrackTrackMcTruth.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-pair-track-track-extended + SOURCES femtoUniversePairTaskTrackTrackExtended.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-pair-track-track-mult-kt + SOURCES femtoUniversePairTaskTrackTrackMultKt.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-debug-track + SOURCES femtoUniverseDebugTrack.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-pair-track-v0 + SOURCES femtoUniversePairTaskTrackV0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-pair-track-phi + SOURCES femtoUniversePairTaskTrackPhi.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-debug-v0 + SOURCES femtoUniverseDebugV0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femtouniverse-hash + SOURCES femtoUniverseHashTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_executable(femtouniverse-cutculator + SOURCES femtoUniverseCutCulator.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseCutCulator.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseCutCulator.cxx new file mode 100644 index 00000000000..d1d45372e36 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseCutCulator.cxx @@ -0,0 +1,87 @@ +// 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 femtoUniverseCutCulator.cxx +/// \brief Executable that encodes physical selection criteria in a bit-wise selection +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include +#include +#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCutculator.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +using namespace o2::analysis::femtoUniverse; + +/// The function takes the path to the dpl-config.json as a argument and the +/// does a Q&A session for the user to find the appropriate selection criteria +/// for the analysis task +int main(int argc, char* argv[]) +{ + std::string configFileName(argv[1]); + std::filesystem::path configFile{configFileName}; + + if (std::filesystem::exists(configFile)) { + FemtoUniverseCutculator cut; + cut.init(argv[1]); + + std::cout + << "Do you want to work with tracks or V0s (T/V)? >"; + std::string choice; + std::cin >> choice; + + if (choice == std::string("T")) { + cut.setTrackSelectionFromFile("ConfTrk"); + cut.setPIDSelectionFromFile("ConfTrk"); + } else if (choice == std::string("V")) { + std::cout << "Do you want to select V0s or one of its children (V/T)? >"; + std::cin >> choice; + cut.setV0SelectionFromFile("ConfV0"); + cut.setTrackSelectionFromFile("ConfChild"); + cut.setPIDSelectionFromFile("ConfChild"); + } else { + std::cout << "Option not recognized. Break..."; + return 2; + } + /// \todo factor out the pid here + /// cut.setTrackSelection(femtoUniverseTrackSelection::kPIDnSigmaMax, + /// femtoUniverseSelection::kAbsUpperLimit, "ConfTrk"); + + std::cout << "Do you want to manually select cuts or create systematic " + "variations(M/V)? >"; + std::string manual; + std::cin >> manual; + + if (manual == std::string("M")) { + cut.analyseCuts(choice); + } else if (manual == std::string("V")) { + std::ofstream out("CutCulator.txt"); + std::streambuf* coutbuf = std::cout.rdbuf(); // save old buf + std::cout.rdbuf(out.rdbuf()); // redirect std::cout to out.txt! + for (int i = 0; i < 20; i++) { + cut.analyseCuts(choice, true, 1); + } + std::cout.rdbuf(coutbuf); // reset to standard output again + } else { + std::cout << "Option not recognized. Break..."; + return 2; + } + + } else { + std::cout << "The configuration file " << configFileName + << " could not be found."; + } + + return 0; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx new file mode 100644 index 00000000000..118969b3a70 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugTrack.cxx @@ -0,0 +1,274 @@ +// 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 femtoUniverseDebugTrack.cxx +/// \brief Tasks that reads the particle tables and fills QA histograms for tracks +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#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 "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int nCuts = 5; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[1][nCuts] = {{4.05f, 0.75f, 3.f, 3.f, 100.f}}; + +} // namespace + +struct femtoUniverseDebugTrack { + SliceCache cache; + + Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nCuts, cutNames}, "Particle selections"}; + Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; + + struct : o2::framework::ConfigurableGroup { + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; + Configurable ConfIsTrackIdentified{"ConfIsTrackIdentified", true, "Enable PID for the track"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable ConfTrackChoicePartOne{"ConfTrackChoicePartOne", 1, "Type of particle (track1): {0:Proton, 1:Pion, 2:Kaon}"}; + Configurable ConfTrackSign{"ConfTrackSign", 1, "Track sign"}; + } trackonefilter; + + struct : o2::framework::ConfigurableGroup { + Configurable ConfNsigmaCombinedKaon{"ConfNsigmaCombinedKaon", 3.0, "TPC and TOF Kaon Sigma (combined) for momentum > 0.4"}; + Configurable ConfNsigmaTPCKaon{"ConfNsigmaTPCKaon", 3.0, "TPC Kaon Sigma for momentum < 0.4"}; + Configurable ConfNsigmaCombinedProton{"ConfNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined) for momentum > 0.5"}; + Configurable ConfNsigmaTPCProton{"ConfNsigmaTPCProton", 3.0, "TPC Proton Sigma for momentum < 0.5"}; + Configurable ConfNsigmaCombinedPion{"ConfNsigmaCombinedPion", 3.0, "TPC and TOF Pion Sigma (combined) for momentum > 0.5"}; + Configurable ConfNsigmaTPCPion{"ConfNsigmaTPCPion", 3.0, "TPC Pion Sigma for momentum < 0.5"}; + } generalPIDcuts; + + // Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; + Configurable ConfPIDPartOne{"ConfPIDPartOne", 1, "Particle 1 - Read from cutCulator"}; + Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{3.5f, 3.f, 2.5f}, "This configurable needs to be the same as the one used in the producer task"}; + ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + FemtoUniverseTrackSelection trackCuts; + + using FemtoFullParticles = soa::Join; + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(trackonefilter.ConfTrackSign)); // && ((aod::femtouniverseparticle::cut & ConfCutPartOne) == ConfCutPartOne); + Preslice perColReco = aod::femtouniverseparticle::fdCollisionId; + + using FemtoFullParticlesMC = soa::Join; + Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(trackonefilter.ConfTrackSign)); // && ((aod::femtouniverseparticle::cut & ConfCutPartOne) == ConfCutPartOne); + Preslice perColGen = aod::femtouniverseparticle::fdCollisionId; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + FemtoUniverseParticleHisto trackHisto; + + /// The configurables need to be passed to an std::vector + int vPIDPartOne; + std::vector kNsigma; + + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // PID for protons + bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfNsigmaTPCProton -> TPC Kaon Sigma for momentum < 0.5 + // ConfNsigmaCombinedProton -> TPC and TOF Kaon Sigma (combined) for momentum > 0.5 + + if (mom < 0.5) { + if (TMath::Abs(nsigmaTPCPr) < generalPIDcuts.ConfNsigmaTPCProton) { + return true; + } else { + return false; + } + } else if (mom > 0.5) { + if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < generalPIDcuts.ConfNsigmaCombinedProton) { + return true; + } else { + return false; + } + } + return false; + } + + bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfNsigmaTPCTOFKaon -> are we doing TPC TOF PID for Kaons? (boolean) + // ConfNsigmaTPCKaon -> TPC Kaon Sigma for momentum < 0.5 + // ConfNsigmaCombinedKaon -> TPC and TOF Kaon Sigma (combined) for momentum > 0.5 + if (mom < 0.3) { // 0.0-0.3 + if (TMath::Abs(nsigmaTPCK) < 3.0) { + return true; + } else { + return false; + } + } else if (mom < 0.45) { // 0.30 - 0.45 + if (TMath::Abs(nsigmaTPCK) < 2.0) { + return true; + } else { + return false; + } + } else if (mom < 0.55) { // 0.45-0.55 + if (TMath::Abs(nsigmaTPCK) < 1.0) { + return true; + } else { + return false; + } + } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) + if ((TMath::Abs(nsigmaTOFK) < 3.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + { + return true; + } + } else { + return false; + } + } else if (mom > 1.5) { // 1.5 - + if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + bool IsPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfNsigmaTPCPion -> TPC Kaon Sigma for momentum < 0.5 + // ConfNsigmaCombinedPion -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 + if (true) { + if (mom < 0.5) { + if (TMath::Abs(nsigmaTPCPi) < generalPIDcuts.ConfNsigmaTPCPion) { + return true; + } else { + return false; + } + } else if (mom > 0.5) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < generalPIDcuts.ConfNsigmaCombinedPion) { + return true; + } else { + return false; + } + } + } + return false; + } + + bool IsParticleNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + { + switch (trackonefilter.ConfPDGCodePartOne) { + case 2212: // Proton + case -2212: // anty Proton + return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion + case -211: // Pion- + case 111: // Pion 0 + return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + break; + case 321: // Kaon+ + case -321: // Kaon- + return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } + + void init(InitContext&) + { + eventHisto.init(&qaRegistry); + trackHisto.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, trackonefilter.ConfIsMC, trackonefilter.ConfPDGCodePartOne.value, true); + vPIDPartOne = ConfPIDPartOne.value; + kNsigma = ConfTrkPIDnSigmaMax.value; + } + + /// Porduce QA plots for sigle track selection in FemtoUniverse framework + template + void FillDebugHistos(o2::aod::FDCollision& col, PartitionType& groupPartsOne) + { + eventHisto.fillQA(col); + for (auto& part : groupPartsOne) { + // if (part.p() > ConfCutTable->get("MaxP") || part.pt() > ConfCutTable->get("MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(part.pidcut(), part.p(), ConfCutTable->get("PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfCutTable->get("nSigmaTPC"), ConfCutTable->get("nSigmaTPCTOF"))) { + // continue; + // } + if (trackonefilter.ConfIsTrackIdentified) { + if (!IsParticleNSigma(part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + } + trackHisto.fillQA(part); + } + } + + /// process function when runnning over data/ Monte Carlo reconstructed only + /// \param col subscribe to FemtoUniverseCollision table + /// \param parts subscribe to FemtoUniverseParticles table + void processData(o2::aod::FDCollision& col, FemtoFullParticles& parts) + { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + FillDebugHistos(col, groupPartsOne); + } + PROCESS_SWITCH(femtoUniverseDebugTrack, processData, "Enable Debug processing for Monte Carlo", true); + + /// process function when runnning over Monte Carlo with MC truth enabled + + /// \param col subscribe to FemtoUniverseCollision table + /// \param parts subscribe to the joined table of FemtoUniverseParticles and FemtoUniverseMCLabels table + /// \param FemtoDramMCParticles subscribe to the table containing the Monte Carlo Truth information + void processMC(o2::aod::FDCollision& col, FemtoFullParticlesMC& parts, o2::aod::FDMCParticles&) + { + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + FillDebugHistos(col, groupPartsOne); + } + PROCESS_SWITCH(femtoUniverseDebugTrack, processMC, "Enable Debug processing for Monte Carlo", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx new file mode 100644 index 00000000000..5752ab63177 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx @@ -0,0 +1,118 @@ +// 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 femtoUniverseDebugV0.cxx +/// \brief Tasks that reads the particle tables and fills QA histograms for V0s +/// \author Luca Barioglio, TU München, luca.barioglio@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include +#include +#include +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "DataFormatsParameters/GRPObject.h" + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct femtoUniverseDebugV0 { + SliceCache cache; + + Configurable ConfPDGCodeV0{"ConfPDGCodePartOne", 3122, "V0 - PDG code"}; + Configurable ConfPDGCodeChildPos{"ConfPDGCodeChildPos", 2212, "Positive Child - PDG code"}; + Configurable ConfPDGCodeChildNeg{"ConfPDGCodeChildNeg", 211, "Negative Child- PDG code"}; + Configurable ConfCutV0{"ConfCutV0", 338, "V0 - Selection bit from cutCulator"}; + ConfigurableAxis ConfV0TempFitVarBins{"ConfV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfV0TempFitVarpTBins{"ConfV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + + Configurable ConfCutChildPos{"ConfCutChildPos", 150, "Positive Child of V0 - Selection bit from cutCulator"}; + Configurable ConfCutChildNeg{"ConfCutChildNeg", 149, "Negative Child of V0 - Selection bit from cutCulator"}; + Configurable ConfChildPosPidnSigmaMax{"ConfChildPosPidnSigmaMax", 3.f, "Positive Child of V0 - Selection bit from cutCulator"}; + Configurable ConfChildNegPidnSigmaMax{"ConfChildNegPidnSigmaMax", 3.f, "Negative Child of V0 - Selection bit from cutCulator"}; + Configurable ConfChildPosIndex{"ConfChildPosIndex", 1, "Positive Child of V0 - Index from cutCulator"}; + Configurable ConfChildNegIndex{"ConfChildNegIndex", 0, "Negative Child of V0 - Index from cutCulator"}; + Configurable> ConfChildPIDnSigmaMax{"ConfChildPIDnSigmaMax", std::vector{4.f, 3.f}, "V0 child sel: Max. PID nSigma TPC"}; + Configurable ConfChildnSpecies{"ConfChildnSpecies", 2, "Number of particle spieces (for V0 children) with PID info"}; + 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"}; + + using FemtoFullParticles = soa::Join; + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && ((aod::femtouniverseparticle::cut & ConfCutV0) == ConfCutV0); + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// Histogramming + FemtoUniverseEventHisto eventHisto; + FemtoUniverseParticleHisto posChildHistos; + FemtoUniverseParticleHisto negChildHistos; + FemtoUniverseParticleHisto V0Histos; + + /// Histogram output + HistogramRegistry EventRegistry{"Event", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry V0Registry{"FullV0QA", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + eventHisto.init(&EventRegistry); + posChildHistos.init(&V0Registry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, ConfPDGCodeChildPos.value, true); + negChildHistos.init(&V0Registry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, ConfPDGCodeChildNeg, true); + V0Histos.init(&V0Registry, ConfV0TempFitVarpTBins, ConfV0TempFitVarBins, false, ConfPDGCodeV0.value, true); + } + + /// Porduce QA plots for V0 selection in FemtoUniverse framework + void process(o2::aod::FDCollision const& col, FemtoFullParticles const& parts) + { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + eventHisto.fillQA(col); + for (auto& part : groupPartsOne) { + if (!part.has_children()) { + continue; + } + const auto& posChild = parts.iteratorAt(part.index() - 2); + const auto& negChild = parts.iteratorAt(part.index() - 1); + if (posChild.globalIndex() != part.childrenIds()[0] || negChild.globalIndex() != part.childrenIds()[1]) { + LOG(warn) << "Indices of V0 children do not match"; + continue; + } + // check cuts on V0 children + if ((posChild.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kV0Child) && (posChild.cut() & ConfCutChildPos) == ConfCutChildPos) && + (negChild.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kV0Child) && (negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) && + isFullPIDSelected(posChild.pidcut(), posChild.p(), 999.f, ConfChildPosIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfChildPosPidnSigmaMax.value, 1.f) && + isFullPIDSelected(negChild.pidcut(), negChild.p(), 999.f, ConfChildNegIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfChildNegPidnSigmaMax.value, 1.f)) { + V0Histos.fillQA(part); + posChildHistos.fillQA(posChild); + negChildHistos.fillQA(negChild); + } + } + } +}; + +WorkflowSpec + defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseHashTask.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseHashTask.cxx new file mode 100644 index 00000000000..65811436844 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseHashTask.cxx @@ -0,0 +1,57 @@ +// 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 femtoUniverseReaderTask.cxx +/// \brief Tasks that reads the track tables used for the pairing +/// This task is common for all femto analyses +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "Common/Core/EventMixing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/ASoAHelpers.h" + +using namespace o2; +using namespace o2::framework; + +struct femtoUniversePairHashTask { + + Configurable> CfgVtxBins{"CfgVtxBins", std::vector{-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"}; + Configurable> CfgMultBins{"CfgMultBins", std::vector{0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + // Configurable> CfgMultBins{"CfgMultBins", std::vector{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"}; + + std::vector CastCfgVtxBins, CastCfgMultBins; + + Produces hashes; + + void init(InitContext&) + { + /// here the Configurables are passed to std::vectors + CastCfgVtxBins = (std::vector)CfgVtxBins; + CastCfgMultBins = (std::vector)CfgMultBins; + } + + void process(o2::aod::FDCollision const& col) + { + /// the hash of the collision is computed and written to table + hashes(eventmixing::getMixingBin(CastCfgVtxBins, CastCfgMultBins, col.posZ(), col.multV0M())); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc)}; + + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx new file mode 100644 index 00000000000..e9d8b0af0ae --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx @@ -0,0 +1,541 @@ +// 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 femtoUniversePairTaskTrackPhi.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "TDatabasePDG.h" +#include "ReconstructionDataFormats/PID.h" +#include "Common/DataModel/PIDResponse.h" + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int nPart = 2; +static constexpr int nCuts = 5; +static const std::vector partNames{"PhiCandidate", "Track"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[nPart][nCuts]{ + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}}; +} // namespace + +struct femtoUniversePairTaskTrackPhi { + + using FemtoFullParticles = soa::Join; + SliceCache cache; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// Table for both particles + struct : o2::framework::ConfigurableGroup { + Configurable ConfNsigmaCombinedProton{"ConfNsigmaCombinedProton", 3.0, "TPC and TOF Proton Sigma (combined) for momentum > 0.5"}; + Configurable ConfNsigmaTPCProton{"ConfNsigmaTPCProton", 3.0, "TPC Proton Sigma for momentum < 0.5"}; + Configurable ConfNsigmaCombinedPion{"ConfNsigmaCombinedPion", 3.0, "TPC and TOF Pion Sigma (combined) for momentum > 0.5"}; + Configurable ConfNsigmaTPCPion{"ConfNsigmaTPCPion", 3.0, "TPC Pion Sigma for momentum < 0.5"}; + + Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; + Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; + Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable ConfPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable ConfEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"}; + } ConfBothTracks; + + /// Particle 1 --- IDENTIFIED TRACK + struct : o2::framework::ConfigurableGroup { + Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; + Configurable ConfPDGCodeTrack{"ConfPDGCodeTrack", 2212, "Particle 2 - PDG code"}; + // Configurable ConfCutTrack{"ConfCutTrack", 5542474, "Particle 2 - Selection bit"}; + Configurable ConfPIDTrack{"ConfPIDTrack", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + Configurable ConfTrackSign{"ConfTrackSign", 1, "Track sign"}; + Configurable ConfIsTrackIdentified{"ConfIsTrackIdentified", true, "Enable PID for the track"}; + } ConfTrack; + + /// Particle 2 --- PHI + struct : o2::framework::ConfigurableGroup { + Configurable ConfPDGCodePhi{"ConfPDGCodePhi", 333, "Phi meson - PDG code"}; + // Configurable ConfCutPhi{"ConfCutPhi", 5542474, "Phi meson - Selection bit from cutCulator"}; + Configurable ConfPIDPhi{"ConfPIDPhi", 2, "Phi meson - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + // Configurable ConfPtLowPhi{"ConfPtLowPhi", 0.5, "Lower limit for Pt for the Phi meson"}; // change according to wrzesa cuts + // Configurable ConfPtHighPhi{"ConfPtHighPhi", 1.5, "Higher limit for Pt for the Phi meson"}; + } ConfPhi; + + /// Partitions for particle 1 + Partition partsTrack = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == int8_t(ConfTrack.ConfTrackSign)); + Partition> partsTrackMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)); + + /// Partitions for particle 2 + Partition partsPhi = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kPhi)); + Partition> partsPhiMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kPhi)); + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartTrack; + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartPhi; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + int vPIDPhiCandidate, vPIDTrack; + std::vector kNsigma; + + /// particle part + ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarInvMassBins{"ConfDTempFitVarInvMassBins", {6000, 0.9, 4.0}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + /// Correlation part + ConfigurableAxis 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 + // ConfigurableAxis ConfMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis ConfmultBins3D{"ConfmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + + FemtoUniverseFemtoContainer sameEventFemtoCont; + FemtoUniverseFemtoContainer mixedEventFemtoCont; + FemtoUniverseAngularContainer sameEventAngularCont; + FemtoUniverseAngularContainer mixedEventAngularCont; + FemtoUniversePairCleaner pairCleaner; + FemtoUniverseDetaDphiStar pairCloseRejection; + FemtoUniverseTrackSelection trackCuts; + + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // PID for protons + bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfNsigmaTPCProton -> TPC Kaon Sigma for momentum < 0.5 + // ConfNsigmaCombinedProton -> TPC and TOF Kaon Sigma (combined) for momentum > 0.5 + + if (mom < 0.5) { + if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaTPCProton) { + return true; + } else { + return false; + } + } else if (mom > 0.4) { + if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < ConfBothTracks.ConfNsigmaCombinedProton) { + // if (TMath::Abs(nsigmaTPCPr) < ConfBothTracks.ConfNsigmaCombinedProton) { + return true; + } else { + return false; + } + } + return false; + } + + bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + if (mom < 0.3) { // 0.0-0.3 + if (TMath::Abs(nsigmaTPCK) < 3.0) { + return true; + } else { + return false; + } + } else if (mom < 0.45) { // 0.30 - 0.45 + if (TMath::Abs(nsigmaTPCK) < 2.0) { + return true; + } else { + return false; + } + } else if (mom < 0.55) { // 0.45-0.55 + if (TMath::Abs(nsigmaTPCK) < 1.0) { + return true; + } else { + return false; + } + } else if (mom < 1.5) { // 0.55-1.5 (now we use TPC and TOF) + if ((TMath::Abs(nsigmaTOFK) < 3.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + { + return true; + } + } else { + return false; + } + } else if (mom > 1.5) { // 1.5 - + if ((TMath::Abs(nsigmaTOFK) < 2.0) && (TMath::Abs(nsigmaTPCK) < 3.0)) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + bool IsPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfNsigmaTPCPion -> TPC Kaon Sigma for momentum < 0.5 + // ConfNsigmaCombinedPion -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 + if (true) { + if (mom < 0.5) { + if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaTPCPion) { + return true; + } else { + return false; + } + } else if (mom > 0.5) { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < ConfBothTracks.ConfNsigmaCombinedPion) { + // if (TMath::Abs(nsigmaTPCPi) < ConfBothTracks.ConfNsigmaCombinedPion) { + return true; + } else { + return false; + } + } + } + return false; + } + + bool IsParticleNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + { + switch (ConfTrack.ConfPDGCodeTrack) { + case 2212: // Proton + case -2212: // anty Proton + return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion + case -211: // Pion- + return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + break; + case 321: // Kaon+ + case -321: // Kaon- + return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + } + + void init(InitContext&) + { + eventHisto.init(&qaRegistry); + trackHistoPartPhi.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarInvMassBins, ConfBothTracks.ConfIsMC, ConfPhi.ConfPDGCodePhi); + if (!ConfTrack.ConfIsSame) { + trackHistoPartTrack.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfBothTracks.ConfIsMC, ConfTrack.ConfPDGCodeTrack); + } + + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + sameEventFemtoCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); + mixedEventFemtoCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); + sameEventAngularCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfEtaBins, ConfBothTracks.ConfPhiBins, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); + mixedEventAngularCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfBothTracks.ConfEtaBins, ConfBothTracks.ConfPhiBins, ConfBothTracks.ConfIsMC, ConfBothTracks.ConfUse3D); + + sameEventFemtoCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); + mixedEventFemtoCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); + sameEventAngularCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); + mixedEventAngularCont.setPDGCodes(ConfPhi.ConfPDGCodePhi, ConfTrack.ConfPDGCodeTrack); + + pairCleaner.init(&qaRegistry); + if (ConfIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); + } + + vPIDPhiCandidate = ConfPhi.ConfPIDPhi.value; + vPIDTrack = ConfTrack.ConfPIDTrack.value; + kNsigma = ConfBothTracks.ConfTrkPIDnSigmaMax.value; + } + + template + void fillCollision(CollisionType col) + { + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsTrack partition for the first particle passed by the process function + /// @param groupPartsPhi partition for the second particle passed by the process function + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupPartsTrack, PartitionType groupPartsPhi, PartType parts, float magFieldTesla, int multCol) + { + + /// Histogramming same event + for (auto& phicandidate : groupPartsPhi) { + trackHistoPartPhi.fillQA(phicandidate); + } + + if (!ConfTrack.ConfIsSame) { + for (auto& track : groupPartsTrack) { + // if (track.p() > ConfBothTracks.ConfCutTable->get("Track", "MaxP") || track.pt() > ConfBothTracks.ConfCutTable->get("Track", "MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(track.pidcut(), + // track.p(), + // ConfBothTracks.ConfCutTable->get("Track", "PIDthr"), + // vPIDTrack, + // ConfBothTracks.ConfNspecies, + // kNsigma, + // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPC"), + // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPCTOF"))) { + // continue; + // } + if (ConfTrack.ConfIsTrackIdentified) { + if (!IsParticleNSigma(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { + continue; + } + } + trackHistoPartTrack.fillQA(track); + } + } + /// Now build the combinations + for (auto& [track, phicandidate] : combinations(CombinationsFullIndexPolicy(groupPartsTrack, groupPartsPhi))) { + // if (track.p() > ConfBothTracks.ConfCutTable->get("PhiCandidate", "MaxP") || track.pt() > ConfBothTracks.ConfCutTable->get("PhiCandidate", "MaxPt") || phicandidate.p() > ConfBothTracks.ConfCutTable->get("Track", "MaxP") || phicandidate.pt() > ConfBothTracks.ConfCutTable->get("Track", "MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(track.pidcut(), + // track.p(), + // ConfBothTracks.ConfCutTable->get("PhiCandidate", "PIDthr"), + // vPIDPhiCandidate, + // ConfBothTracks.ConfNspecies, + // kNsigma, + // ConfBothTracks.ConfCutTable->get("PhiCandidate", "nSigmaTPC"), + // ConfBothTracks.ConfCutTable->get("PhiCandidate", "nSigmaTPCTOF")) || + // !isFullPIDSelected(phicandidate.pidcut(), + // phicandidate.p(), + // ConfBothTracks.ConfCutTable->get("Track", "PIDthr"), + // vPIDTrack, + // ConfBothTracks.ConfNspecies, + // kNsigma, + // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPC"), + // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPCTOF"))) { + // continue; + // } + if (ConfTrack.ConfIsTrackIdentified) { + if (!IsParticleNSigma(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { + continue; + } + } + // // Close Pair Rejection + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(track, phicandidate, parts, magFieldTesla)) { + continue; + } + } + + // Track Cleaning + if (!pairCleaner.isCleanPair(track, phicandidate, parts)) { + continue; + } + sameEventFemtoCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D); + sameEventAngularCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D); + } + } + + /// process function for to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processSameEvent(o2::aod::FDCollision& col, + FemtoFullParticles& parts) + { + fillCollision(col); + + auto thegroupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsPhi = partsPhi->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsTrack, thegroupPartsPhi, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processSameEvent, "Enable processing same event", true); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processSameEventMC(o2::aod::FDCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + + auto thegroupPartsPhi = partsPhiMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTrack = partsTrackMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsTrack, thegroupPartsPhi, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processSameEventMC, "Enable processing same event for Monte Carlo", false); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsTrack partition for the identified passed by the process function + /// \param groupPartsPhi partition for Phi meson passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsTrack, PartitionType groupPartsPhi, PartType parts, float magFieldTesla, int multCol) + { + + for (auto& [track, phicandidate] : combinations(CombinationsFullIndexPolicy(groupPartsTrack, groupPartsPhi))) { + // if (track.p() > ConfBothTracks.ConfCutTable->get("PhiCandidate", "MaxP") || track.pt() > ConfBothTracks.ConfCutTable->get("PhiCandidate", "MaxPt") || phicandidate.p() > ConfBothTracks.ConfCutTable->get("Track", "MaxP") || phicandidate.pt() > ConfBothTracks.ConfCutTable->get("Track", "MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(track.pidcut(), + // track.p(), + // ConfBothTracks.ConfCutTable->get("PhiCandidate", "PIDthr"), + // vPIDPhiCandidate, + // ConfBothTracks.ConfNspecies, + // kNsigma, + // ConfBothTracks.ConfCutTable->get("PhiCandidate", "nSigmaTPC"), + // ConfBothTracks.ConfCutTable->get("PhiCandidate", "nSigmaTPCTOF")) || + // !isFullPIDSelected(phicandidate.pidcut(), + // phicandidate.p(), + // ConfBothTracks.ConfCutTable->get("Track", "PIDthr"), + // vPIDTrack, + // ConfBothTracks.ConfNspecies, + // kNsigma, + // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPC"), + // ConfBothTracks.ConfCutTable->get("Track", "nSigmaTPCTOF"))) { + // continue; + // } + if (ConfTrack.ConfIsTrackIdentified) { + if (!IsParticleNSigma(track.p(), trackCuts.getNsigmaTPC(track, o2::track::PID::Proton), trackCuts.getNsigmaTOF(track, o2::track::PID::Proton), trackCuts.getNsigmaTPC(track, o2::track::PID::Pion), trackCuts.getNsigmaTOF(track, o2::track::PID::Pion), trackCuts.getNsigmaTPC(track, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(track, o2::track::PID::Kaon))) { + continue; + } + } + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(track, phicandidate, parts, magFieldTesla)) { + continue; + } + } + + mixedEventFemtoCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D); + mixedEventAngularCont.setPair(track, phicandidate, multCol, ConfBothTracks.ConfUse3D); + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEvent(o2::aod::FDCollisions& cols, + FemtoFullParticles& parts) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsPhi = partsPhi->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsPhi.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTrack.size() == 0 ) continue; + + doMixedEvent(groupPartsTrack, groupPartsPhi, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processMixedEvent, "Enable processing mixed events", true); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMC(o2::aod::FDCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsTrack = partsTrackMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsPhi = partsPhiMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsPhi.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTrack.size() == 0 ) continue; + + doMixedEvent(groupPartsTrack, groupPartsPhi, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackPhi, processMixedEventMC, "Enable processing mixed events MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack.cxx new file mode 100644 index 00000000000..b2c899261f0 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrack.cxx @@ -0,0 +1,415 @@ +// 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 femtoUniversePairTaskTrackTrack.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "TDatabasePDG.h" + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int nPart = 2; +static constexpr int nCuts = 5; +static const std::vector partNames{"PartOne", "PartTwo"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[nPart][nCuts]{ + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}}; +} // namespace + +struct femtoUniversePairTaskTrackTrack { + SliceCache cache; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// Particle selection part + + /// Table for both particles + Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; + Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; + Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + + /// Particle 1 + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; + Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; + Configurable ConfPIDPartOne{"ConfPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && ((aod::femtouniverseparticle::cut & ConfCutPartOne) == ConfCutPartOne); + Partition> partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && ((aod::femtouniverseparticle::cut & ConfCutPartOne) == ConfCutPartOne); + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOne; + + /// Particle 2 + Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 2212, "Particle 2 - PDG code"}; + Configurable ConfCutPartTwo{"ConfCutPartTwo", 5542474, "Particle 2 - Selection bit"}; + Configurable ConfPIDPartTwo{"ConfPIDPartTwo", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && + // (aod::femtouniverseparticle::pt < cfgCutTable->get("PartTwo", "MaxPt")) && + ((aod::femtouniverseparticle::cut & ConfCutPartTwo) == ConfCutPartTwo); + Partition> partsTwoMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && + ((aod::femtouniverseparticle::cut & ConfCutPartTwo) == ConfCutPartTwo); + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwo; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + int vPIDPartOne, vPIDPartTwo; + std::vector kNsigma; + + /// particle part + ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + /// Correlation part + ConfigurableAxis 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 + // ConfigurableAxis ConfMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + + ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis ConfmultBins3D{"ConfmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable ConfPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable ConfEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"}; + + FemtoUniverseFemtoContainer sameEventFemtoCont; + FemtoUniverseFemtoContainer mixedEventFemtoCont; + FemtoUniverseAngularContainer sameEventAngularCont; + FemtoUniverseAngularContainer mixedEventAngularCont; + FemtoUniversePairCleaner pairCleaner; + FemtoUniverseDetaDphiStar pairCloseRejection; + + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfIsMC, ConfPDGCodePartOne, false); + if (!ConfIsSame) { + trackHistoPartTwo.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, ConfIsMC, ConfPDGCodePartTwo, false); + } + + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + sameEventFemtoCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D); + mixedEventFemtoCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfIsMC, ConfUse3D); + sameEventAngularCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, ConfIsMC, ConfUse3D); + mixedEventAngularCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, ConfIsMC, ConfUse3D); + + sameEventFemtoCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + mixedEventFemtoCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + sameEventAngularCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + mixedEventAngularCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + + pairCleaner.init(&qaRegistry); + if (ConfIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); + } + + vPIDPartOne = ConfPIDPartOne.value; + vPIDPartTwo = ConfPIDPartTwo.value; + kNsigma = ConfTrkPIDnSigmaMax.value; + } + + template + void fillCollision(CollisionType col) + { + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsOne partition for the first particle passed by the process function + /// @param groupPartsTwo partition for the second particle passed by the process function + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol) + { + + /// Histogramming same event + for (auto& part : groupPartsOne) { + if (part.p() > ConfCutTable->get("PartOne", "MaxP") || part.pt() > ConfCutTable->get("PartOne", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(part.pidcut(), + part.p(), + ConfCutTable->get("PartOne", "PIDthr"), + vPIDPartOne, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartOne", "nSigmaTPC"), + ConfCutTable->get("PartOne", "nSigmaTPCTOF"))) { + continue; + } + + trackHistoPartOne.fillQA(part); + } + + if (!ConfIsSame) { + for (auto& part : groupPartsTwo) { + if (part.p() > ConfCutTable->get("PartTwo", "MaxP") || part.pt() > ConfCutTable->get("PartTwo", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(part.pidcut(), + part.p(), + ConfCutTable->get("PartTwo", "PIDthr"), + vPIDPartTwo, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartTwo", "nSigmaTPC"), + ConfCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + continue; + } + trackHistoPartTwo.fillQA(part); + } + } + /// Now build the combinations + for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (p1.p() > ConfCutTable->get("PartOne", "MaxP") || p1.pt() > ConfCutTable->get("PartOne", "MaxPt") || p2.p() > ConfCutTable->get("PartTwo", "MaxP") || p2.pt() > ConfCutTable->get("PartTwo", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(p1.pidcut(), + p1.p(), + ConfCutTable->get("PartOne", "PIDthr"), + vPIDPartOne, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartOne", "nSigmaTPC"), + ConfCutTable->get("PartOne", "nSigmaTPCTOF")) || + !isFullPIDSelected(p2.pidcut(), + p2.p(), + ConfCutTable->get("PartTwo", "PIDthr"), + vPIDPartTwo, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartTwo", "nSigmaTPC"), + ConfCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + continue; + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + sameEventFemtoCont.setPair(p1, p2, multCol, ConfUse3D); + sameEventAngularCont.setPair(p1, p2, multCol, ConfUse3D); + } + } + + /// process function for to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processSameEvent(o2::aod::FDCollision& col, + o2::aod::FDParticles& parts) + { + fillCollision(col); + + auto thegroupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrack, processSameEvent, "Enable processing same event", true); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processSameEventMC(o2::aod::FDCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + + auto thegroupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrack, processSameEventMC, "Enable processing same event for Monte Carlo", false); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol) + { + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (p1.p() > ConfCutTable->get("PartOne", "MaxP") || p1.pt() > ConfCutTable->get("PartOne", "MaxPt") || p2.p() > ConfCutTable->get("PartTwo", "MaxP") || p2.pt() > ConfCutTable->get("PartTwo", "MaxPt")) { + continue; + } + if (!isFullPIDSelected(p1.pidcut(), + p1.p(), + ConfCutTable->get("PartOne", "PIDthr"), + vPIDPartOne, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartOne", "nSigmaTPC"), + ConfCutTable->get("PartOne", "nSigmaTPCTOF")) || + !isFullPIDSelected(p2.pidcut(), + p2.p(), + ConfCutTable->get("PartTwo", "PIDthr"), + vPIDPartTwo, + ConfNspecies, + kNsigma, + ConfCutTable->get("PartTwo", "nSigmaTPC"), + ConfCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + continue; + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + mixedEventFemtoCont.setPair(p1, p2, multCol, ConfUse3D); + mixedEventAngularCont.setPair(p1, p2, multCol, ConfUse3D); + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEvent(o2::aod::FDCollisions& cols, + o2::aod::FDParticles& parts) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrack, processMixedEvent, "Enable processing mixed events", true); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMC(o2::aod::FDCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrack, processMixedEventMC, "Enable processing mixed events MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx new file mode 100644 index 00000000000..6854b1097f0 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx @@ -0,0 +1,665 @@ +// 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 femtoUniversePairTaskTrackTrackExtended.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "TDatabasePDG.h" +#include "ReconstructionDataFormats/PID.h" +#include "Common/DataModel/PIDResponse.h" + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int nPart = 2; +static constexpr int nCuts = 5; +static const std::vector partNames{"PartOne", "PartTwo"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[nPart][nCuts]{ + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}}; +} // namespace + +struct femtoUniversePairTaskTrackTrackExtended { + + /// Particle selection part + + /// Table for both particles + struct : o2::framework::ConfigurableGroup { + Configurable ConfNsigmaCombined{"ConfNsigmaCombined", 3.0f, "TPC and TOF Pion Sigma (combined) for momentum > ConfTOFPtMin"}; + Configurable ConfNsigmaTPC{"ConfNsigmaTPC", 3.0f, "TPC Pion Sigma for momentum < ConfTOFPtMin"}; + Configurable ConfTOFPtMin{"ConfTOFPtMin", 0.5f, "Min. Pt for which TOF is required for PID."}; + Configurable ConfEtaMax{"ConfEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; + + Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; + Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; + Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + } twotracksconfigs; + + using FemtoFullParticles = soa::Join; + // Filters for selecting particles (both p1 and p2) + Filter trackCutFilter = requireGlobalTrackInFilter(); // Global track cuts + Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.ConfEtaMax); // example filtering on configurable + using FilteredFemtoFullParticles = soa::Filtered; + // using FilteredFemtoFullParticles = FemtoFullParticles; //if no filtering is applied uncomment this option + + SliceCache cache; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// Particle 1 + struct : o2::framework::ConfigurableGroup { + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; + Configurable ConfIsTrackOneIdentified{"ConfIsTrackOneIdentified", true, "Enable PID for the track one"}; + // Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; + Configurable ConfPIDPartOne{"ConfPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + Configurable ConfPtLowPart1{"ConfPtLowPart1", 0.5, "Lower limit for Pt for the first particle"}; + Configurable ConfPtHighPart1{"ConfPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; + Configurable ConfChargePart1{"ConfChargePart1", 1, "Particle 1 sign"}; + } trackonefilter; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == trackonefilter.ConfChargePart1 && aod::femtouniverseparticle::pt < trackonefilter.ConfPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.ConfPtLowPart1; + Partition> partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == trackonefilter.ConfChargePart1 && aod::femtouniverseparticle::pt < trackonefilter.ConfPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.ConfPtLowPart1; + // && ((aod::femtouniverseparticle::cut & ConfCutPartOne) == ConfCutPartOne); + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOne; + + /// Particle 2 + Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; + struct : o2::framework::ConfigurableGroup { + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 2212, "Particle 2 - PDG code"}; + Configurable ConfIsTrackTwoIdentified{"ConfIsTrackTwoIdentified", true, "Enable PID for the track two"}; + // Configurable ConfCutPartTwo{"ConfCutPartTwo", 5542474, "Particle 2 - Selection bit"}; + Configurable ConfPIDPartTwo{"ConfPIDPartTwo", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + Configurable ConfPtLowPart2{"ConfPtLowPart2", 0.5, "Lower limit for Pt for the second particle"}; + Configurable ConfPtHighPart2{"ConfPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; + Configurable ConfChargePart2{"ConfChargePart2", -1, "Particle 2 sign"}; + } tracktwofilter; + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == tracktwofilter.ConfChargePart2) && aod::femtouniverseparticle::pt < tracktwofilter.ConfPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.ConfPtLowPart2; + + Partition> partsTwoMC = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack) && (aod::femtouniverseparticle::sign == tracktwofilter.ConfChargePart2) && aod::femtouniverseparticle::pt < tracktwofilter.ConfPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.ConfPtLowPart2; + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwo; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + int vPIDPartOne, vPIDPartTwo; + std::vector kNsigma; + + /// particle part + ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + /// Correlation part + ConfigurableAxis 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 + // ConfigurableAxis ConfMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + + ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis ConfmultBins3D{"ConfmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable ConfPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable ConfEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"}; + + FemtoUniverseContainer sameEventCont; + FemtoUniverseContainer mixedEventCont; + FemtoUniversePairCleaner pairCleaner; + FemtoUniverseDetaDphiStar pairCloseRejection; + FemtoUniverseTrackSelection trackCuts; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + /// @brief Counter for particle swapping + int fNeventsProcessed = 0; + // PID for protons + bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // ConfNsigmaTPC -> TPC Sigma for momentum < ConfTOFPtMin + // ConfNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > ConfTOFPtMin + + if (mom < twotracksconfigs.ConfTOFPtMin) { + if (TMath::Abs(nsigmaTPCPr) < twotracksconfigs.ConfNsigmaTPC) { + return true; + } else { + return false; + } + } else { + if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < twotracksconfigs.ConfNsigmaCombined) { + return true; + } else { + return false; + } + } + return false; + } + + bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // ConfNsigmaTPC -> TPC Sigma for momentum < ConfTOFPtMin + // ConfNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > ConfTOFPtMin + if (true) { + if (mom < twotracksconfigs.ConfTOFPtMin) { + if (TMath::Abs(nsigmaTPCK) < twotracksconfigs.ConfNsigmaTPC) { + return true; + } else { + return false; + } + } else { + if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < twotracksconfigs.ConfNsigmaCombined) { + return true; + } else { + return false; + } + } + } + return false; + } + + bool IsPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // ConfNsigmaTPC -> TPC Sigma for momentum < ConfTOFPtMin + // ConfNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > ConfTOFPtMin + if (true) { + if (mom < twotracksconfigs.ConfTOFPtMin) { + if (TMath::Abs(nsigmaTPCPi) < twotracksconfigs.ConfNsigmaTPC) { + return true; + } else { + return false; + } + } else { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < twotracksconfigs.ConfNsigmaCombined) { + return true; + } else { + return false; + } + } + } + return false; + } + + bool IsParticleNSigma(int8_t particle_number, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + { + if (particle_number == 1) { + switch (trackonefilter.ConfPDGCodePartOne) { + case 2212: // Proton + case -2212: // anty Proton + return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion + case -211: // Pion- + case 111: // Pion 0 + return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + break; + case 321: // Kaon+ + case -321: // Kaon- + case 130: // Kaon 0 LONG + case 310: // Kaon 0 SHORT + return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } else if (particle_number == 2) { + switch (tracktwofilter.ConfPDGCodePartTwo) { + case 2212: // Proton + case -2212: // anty Proton + return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion + case -211: // Pion- + case 111: // Pion 0 + return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + break; + case 321: // Kaon+ + case -321: // Kaon- + case 130: // Kaon 0 LONG + case 310: // Kaon 0 SHORT + return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } else { + LOGF(fatal, "Wrong number of particle chosen! It should be 1 or 2. It is -> %d", particle_number); + } + return false; + } + + void init(InitContext&) + { + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, twotracksconfigs.ConfIsMC, trackonefilter.ConfPDGCodePartOne, true); // last true = isDebug + if (!ConfIsSame) { + trackHistoPartTwo.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, twotracksconfigs.ConfIsMC, tracktwofilter.ConfPDGCodePartTwo, true); // last true = isDebug + } + + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); + mixedEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); + sameEventCont.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + mixedEventCont.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + pairCleaner.init(&qaRegistry); + if (ConfIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); + } + + vPIDPartOne = trackonefilter.ConfPIDPartOne.value; + vPIDPartTwo = tracktwofilter.ConfPIDPartTwo.value; + kNsigma = twotracksconfigs.ConfTrkPIDnSigmaMax.value; + } + + template + void fillCollision(CollisionType col) + { + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsOne partition for the first particle passed by the process function + /// @param groupPartsTwo partition for the second particle passed by the process function + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol) + { + // variables for particle swapping + bool swpart = fNeventsProcessed % 2; + fNeventsProcessed++; + + /// Histogramming same event + for (auto& part : groupPartsOne) { + // if (part.p() > twotracksconfigs.ConfCutTable->get("PartOne", "MaxP") || part.pt() > twotracksconfigs.ConfCutTable->get("PartOne", "MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(part.pidcut(), + // part.p(), + // twotracksconfigs.ConfCutTable->get("PartOne", "PIDthr"), + // vPIDPartOne, + // twotracksconfigs.ConfNspecies, + // kNsigma, + // twotracksconfigs.ConfCutTable->get("PartOne", "nSigmaTPC"), + // twotracksconfigs.ConfCutTable->get("PartOne", "nSigmaTPCTOF"))) { + // continue; + // } + if (trackonefilter.ConfIsTrackOneIdentified) { + if (!IsParticleNSigma((int8_t)1, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + } + + trackHistoPartOne.fillQA(part); + } + + if (!ConfIsSame) { + for (auto& part : groupPartsTwo) { + // if (part.p() > twotracksconfigs.ConfCutTable->get("PartTwo", "MaxP") || part.pt() > twotracksconfigs.ConfCutTable->get("PartTwo", "MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(part.pidcut(), + // part.p(), + // twotracksconfigs.ConfCutTable->get("PartTwo", "PIDthr"), + // vPIDPartTwo, + // twotracksconfigs.ConfNspecies, + // kNsigma, + // twotracksconfigs.ConfCutTable->get("PartTwo", "nSigmaTPC"), + // twotracksconfigs.ConfCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + // continue; + // } + if (tracktwofilter.ConfIsTrackTwoIdentified) { + if (!IsParticleNSigma((int8_t)2, part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + } + trackHistoPartTwo.fillQA(part); + } + + /// Now build the combinations for non-identical particle pairs + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + // if (p1.p() > twotracksconfigs.ConfCutTable->get("PartOne", "MaxP") || p1.pt() > twotracksconfigs.ConfCutTable->get("PartOne", "MaxPt") || p2.p() > twotracksconfigs.ConfCutTable->get("PartTwo", "MaxP") || p2.pt() > twotracksconfigs.ConfCutTable->get("PartTwo", "MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(p1.pidcut(), + // p1.p(), + // twotracksconfigs.ConfCutTable->get("PartOne", "PIDthr"), + // vPIDPartOne, + // twotracksconfigs.ConfNspecies, + // kNsigma, + // twotracksconfigs.ConfCutTable->get("PartOne", "nSigmaTPC"), + // twotracksconfigs.ConfCutTable->get("PartOne", "nSigmaTPCTOF")) || + // !isFullPIDSelected(p2.pidcut(), + // p2.p(), + // twotracksconfigs.ConfCutTable->get("PartTwo", "PIDthr"), + // vPIDPartTwo, + // twotracksconfigs.ConfNspecies, + // kNsigma, + // twotracksconfigs.ConfCutTable->get("PartTwo", "nSigmaTPC"), + // twotracksconfigs.ConfCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + // continue; + // } + + if (trackonefilter.ConfIsTrackOneIdentified) { + if (!IsParticleNSigma((int8_t)1, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + continue; + } + } + + if (tracktwofilter.ConfIsTrackTwoIdentified) { + if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + continue; + } + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + if (swpart) + sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + else + sameEventCont.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D); + + swpart = !swpart; + } + } else { + + /// Now build the combinations for identical particle pairs (different combination policy than for non-identical!) + for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsTwo))) { + // if (p1.p() > twotracksconfigs.ConfCutTable->get("PartOne", "MaxP") || p1.pt() > twotracksconfigs.ConfCutTable->get("PartOne", "MaxPt") || p2.p() > twotracksconfigs.ConfCutTable->get("PartTwo", "MaxP") || p2.pt() > twotracksconfigs.ConfCutTable->get("PartTwo", "MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(p1.pidcut(), + // p1.p(), + // twotracksconfigs.ConfCutTable->get("PartOne", "PIDthr"), + // vPIDPartOne, + // twotracksconfigs.ConfNspecies, + // kNsigma, + // twotracksconfigs.ConfCutTable->get("PartOne", "nSigmaTPC"), + // twotracksconfigs.ConfCutTable->get("PartOne", "nSigmaTPCTOF")) || + // !isFullPIDSelected(p2.pidcut(), + // p2.p(), + // twotracksconfigs.ConfCutTable->get("PartTwo", "PIDthr"), + // vPIDPartTwo, + // twotracksconfigs.ConfNspecies, + // kNsigma, + // twotracksconfigs.ConfCutTable->get("PartTwo", "nSigmaTPC"), + // twotracksconfigs.ConfCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + // continue; + // } + + if (trackonefilter.ConfIsTrackOneIdentified) { + if (!IsParticleNSigma((int8_t)1, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + continue; + } + } + + if (tracktwofilter.ConfIsTrackTwoIdentified) { + if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + continue; + } + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + } + } + } + + /// process function for to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processSameEvent(o2::aod::FDCollision& col, + FilteredFemtoFullParticles& parts) + { + fillCollision(col); + + auto thegroupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackExtended, processSameEvent, "Enable processing same event", true); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processSameEventMC(o2::aod::FDCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + + auto thegroupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackExtended, processSameEventMC, "Enable processing same event for Monte Carlo", false); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol) + { + + // variables for particle swapping + bool swpart = fNeventsProcessed % 2; + fNeventsProcessed++; + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + // if (p1.p() > twotracksconfigs.ConfCutTable->get("PartOne", "MaxP") || p1.pt() > twotracksconfigs.ConfCutTable->get("PartOne", "MaxPt") || p2.p() > twotracksconfigs.ConfCutTable->get("PartTwo", "MaxP") || p2.pt() > twotracksconfigs.ConfCutTable->get("PartTwo", "MaxPt")) { + // continue; + // } + // if (!isFullPIDSelected(p1.pidcut(), + // p1.p(), + // twotracksconfigs.ConfCutTable->get("PartOne", "PIDthr"), + // vPIDPartOne, + // twotracksconfigs.ConfNspecies, + // kNsigma, + // twotracksconfigs.ConfCutTable->get("PartOne", "nSigmaTPC"), + // twotracksconfigs.ConfCutTable->get("PartOne", "nSigmaTPCTOF")) || + // !isFullPIDSelected(p2.pidcut(), + // p2.p(), + // twotracksconfigs.ConfCutTable->get("PartTwo", "PIDthr"), + // vPIDPartTwo, + // twotracksconfigs.ConfNspecies, + // kNsigma, + // twotracksconfigs.ConfCutTable->get("PartTwo", "nSigmaTPC"), + // twotracksconfigs.ConfCutTable->get("PartTwo", "nSigmaTPCTOF"))) { + // continue; + // } + if (trackonefilter.ConfIsTrackOneIdentified) { + if (!IsParticleNSigma((int8_t)1, p1.p(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + continue; + } + } + + if (tracktwofilter.ConfIsTrackTwoIdentified) { + if (!IsParticleNSigma((int8_t)2, p2.p(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + continue; + } + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + if (swpart) + mixedEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + else + mixedEventCont.setPair(p2, p1, multCol, twotracksconfigs.ConfUse3D); + + swpart = !swpart; + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEvent(o2::aod::FDCollisions& cols, + FilteredFemtoFullParticles& parts) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackExtended, processMixedEvent, "Enable processing mixed events", true); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMC(o2::aod::FDCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackExtended, processMixedEventMC, "Enable processing mixed events MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMcTruth.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMcTruth.cxx new file mode 100644 index 00000000000..a7dab8bc872 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMcTruth.cxx @@ -0,0 +1,251 @@ +// 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 femtoUniversePairTaskTrackTrackMcTruth.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Malgorzata Janik, WUT, majanik@cern.ch +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "TDatabasePDG.h" + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct femtoUniversePairTaskTrackTrackMcTruth { + SliceCache cache; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// Particle selection part + + /// Configurables for both particles + Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable ConfEtaMax{"ConfEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; + + /// Particle 1 + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; + Configurable ConfNoPDGPartOne{"ConfNoPDGPartOne", false, "0: selecting part by PDG, 1: no PID selection"}; + Configurable ConfPtLowPart1{"ConfPtLowPart1", 0.5, "Lower limit for Pt for the first particle"}; + Configurable ConfPtHighPart1{"ConfPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (ConfNoPDGPartOne || aod::femtouniverseparticle::pidcut == ConfPDGCodePartOne) && + aod::femtouniverseparticle::pt < ConfPtHighPart1 && aod::femtouniverseparticle::pt > ConfPtLowPart1&& nabs(aod::femtouniverseparticle::eta) < ConfEtaMax; + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOne; + + /// Particle 2 + Configurable ConfIsSame{"ConfIsSame", false, "Pairs of the same particle"}; + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 2212, "Particle 2 - PDG code"}; + Configurable ConfNoPDGPartTwo{"ConfNoPDGPartTwo", false, "0: selecting part by PDG, 1: no PID selection"}; + Configurable ConfPtLowPart2{"ConfPtLowPart2", 0.5, "Lower limit for Pt for the second particle"}; + Configurable ConfPtHighPart2{"ConfPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (ConfNoPDGPartTwo || aod::femtouniverseparticle::pidcut == ConfPDGCodePartTwo) && + aod::femtouniverseparticle::pt < ConfPtHighPart2 && aod::femtouniverseparticle::pt > ConfPtLowPart2&& nabs(aod::femtouniverseparticle::eta) < ConfEtaMax; + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwo; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + int vPIDPartOne, vPIDPartTwo; + std::vector kNsigma; + + /// particle part + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarPDGBins{"ConfDTempFitVarInvMassBins", {6000, -2300, 2300}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + + /// Correlation part + 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 + // ConfigurableAxis ConfMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + + ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis ConfmultBins3D{"ConfmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable ConfPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable ConfEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"}; + + FemtoUniverseContainer sameEventCont; + FemtoUniverseContainer mixedEventCont; + FemtoUniversePairCleaner pairCleaner; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarPDGBins, 0, ConfPDGCodePartOne, false); + if (!ConfIsSame) { + trackHistoPartTwo.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarPDGBins, 0, ConfPDGCodePartTwo, false); + } + + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, 0, ConfUse3D); + mixedEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, 0, ConfUse3D); + sameEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + mixedEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); + pairCleaner.init(&qaRegistry); + } + + template + void fillCollision(CollisionType col) + { + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsOne partition for the first particle passed by the process function + /// @param groupPartsTwo partition for the second particle passed by the process function + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol) + { + + /// Histogramming same event + for (auto& part : groupPartsOne) { + + trackHistoPartOne.fillQA(part); + } + + if (!ConfIsSame) { + for (auto& part : groupPartsTwo) { + + trackHistoPartTwo.fillQA(part); + } + } + /// Now build the combinations + for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsTwo))) { + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + sameEventCont.setPair(p1, p2, multCol, ConfUse3D); + } + } + + /// process function for to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processSameEvent(o2::aod::FDCollision& col, + o2::aod::FDParticles& parts) + { + fillCollision(col); + + auto thegroupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr()); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackMcTruth, processSameEvent, "Enable processing same event", true); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol) + { + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + mixedEventCont.setPair(p1, p2, multCol, ConfUse3D); + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEvent(o2::aod::FDCollisions& cols, + o2::aod::FDParticles& parts) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackMcTruth, processMixedEvent, "Enable processing mixed events", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKt.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKt.cxx new file mode 100644 index 00000000000..cc8dac5dc0b --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackMultKt.cxx @@ -0,0 +1,710 @@ +// 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 femtoUniversePairTaskTrackTrackMultKt.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Georgios Mantzaridis, TU München, georgios.mantzaridis@tum.de +/// \author Anton Riedel, TU München, anton.riedel@tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl +/// \author Alicja Płachta, WUT Warsaw, alicja.plachta.stud@pw.edu.pl + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "TDatabasePDG.h" +#include "ReconstructionDataFormats/PID.h" +#include "Common/DataModel/PIDResponse.h" + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairWithCentMultKt.h" + +using namespace o2; +using namespace o2::analysis::femtoUniverse; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +namespace +{ +static constexpr int nPart = 2; +static constexpr int nCuts = 5; +static const std::vector partNames{"PartOne", "PartTwo"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTable[nPart][nCuts]{ + {4.05f, 1.f, 3.f, 3.f, 100.f}, + {4.05f, 1.f, 3.f, 3.f, 100.f}}; +} // namespace + +struct femtoUniversePairTaskTrackTrackMultKt { + + Service pdg; + + /// Particle selection part + + /// Table for both particles + struct : o2::framework::ConfigurableGroup { + Configurable ConfNsigmaCombined{"ConfNsigmaCombined", 3.0f, "TPC and TOF Pion Sigma (combined) for momentum > ConfTOFPtMin"}; + Configurable ConfNsigmaTPC{"ConfNsigmaTPC", 3.0f, "TPC Pion Sigma for momentum < ConfTOFPtMin"}; + Configurable ConfTOFPtMin{"ConfTOFPtMin", 0.5f, "Min. Pt for which TOF is required for PID."}; + Configurable ConfEtaMax{"ConfEtaMax", 0.8f, "Higher limit for |Eta| (the same for both particles)"}; + + Configurable> ConfCutTable{"ConfCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; + Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; + Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + + } twotracksconfigs; + + using FemtoFullParticles = soa::Join; + // Filters for selecting particles (both p1 and p2) + Filter trackAdditionalfilter = (nabs(aod::femtouniverseparticle::eta) < twotracksconfigs.ConfEtaMax); // example filtering on configurable + using FilteredFemtoFullParticles = soa::Filtered; + // using FilteredFemtoFullParticles = FemtoFullParticles; //if no filtering is applied uncomment this option + + SliceCache cache; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// Particle 1 + struct : o2::framework::ConfigurableGroup { + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 211, "Particle 1 - PDG code"}; + // Configurable ConfCutPartOne{"ConfCutPartOne", 5542474, "Particle 1 - Selection bit from cutCulator"}; + Configurable ConfPIDPartOne{"ConfPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + Configurable ConfPtLowPart1{"ConfPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; + Configurable ConfPtHighPart1{"ConfPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; + Configurable ConfChargePart1{"ConfChargePart1", 1, "Particle 1 sign"}; + } trackonefilter; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == trackonefilter.ConfChargePart1 && aod::femtouniverseparticle::pt < trackonefilter.ConfPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.ConfPtLowPart1; + + Partition> partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && aod::femtouniverseparticle::sign == trackonefilter.ConfChargePart1 && aod::femtouniverseparticle::pt < trackonefilter.ConfPtHighPart1 && aod::femtouniverseparticle::pt > trackonefilter.ConfPtLowPart1; + // + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOne; + + /// Particle 2 + struct : o2::framework::ConfigurableGroup { + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 211, "Particle 2 - PDG code"}; + // Configurable ConfCutPartTwo{"ConfCutPartTwo", 5542474, "Particle 2 - Selection bit"}; + Configurable ConfPIDPartTwo{"ConfPIDPartTwo", 2, "Particle 2 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector> + + Configurable ConfPtLowPart2{"ConfPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; + Configurable ConfPtHighPart2{"ConfPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; + Configurable ConfChargePart2{"ConfChargePart2", -1, "Particle 2 sign"}; + } tracktwofilter; + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == tracktwofilter.ConfChargePart2) && aod::femtouniverseparticle::pt < tracktwofilter.ConfPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.ConfPtLowPart2; + + Partition> partsTwoMC = aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack) && (aod::femtouniverseparticle::sign == tracktwofilter.ConfChargePart2) && aod::femtouniverseparticle::pt < tracktwofilter.ConfPtHighPart2 && aod::femtouniverseparticle::pt > tracktwofilter.ConfPtLowPart2; + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwo; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + /// The configurables need to be passed to an std::vector + int vPIDPartOne, vPIDPartTwo; + std::vector kNsigma; + + /// Particle part + ConfigurableAxis ConfTempFitVarBins{"ConfDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTempFitVarpTBins{"ConfTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + /// Correlation part + ConfigurableAxis 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 + ConfigurableAxis ConfMultKstarBins{"ConfMultKstarBins", {VARIABLE_WIDTH, 0.0f, 13.0f, 20.0f, 30.0f, 40.0f, 50.0f, 100.0f, 99999.f}, "Bins for kstar analysis in multiplicity bins (10 is maximum)"}; + ConfigurableAxis ConfKtKstarBins{"ConfKtKstarBins", {VARIABLE_WIDTH, 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f, 2.0f, 99999.f}, "Bins for kstar analysis in kT bins (10 is maximum)"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + + ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis ConfmultBins3D{"ConfmultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + + Configurable cfgProcessPM{"cfgProcessPM", false, "Process particles of the opposite charge"}; + Configurable cfgProcessPP{"cfgProcessPP", true, "Process particles of the same, positice charge"}; + Configurable cfgProcessMM{"cfgProcessMM", true, "Process particles of the same, positice charge"}; + Configurable cfgProcessMultBins{"cfgProcessMultBins", true, "Process kstar histograms in multiplicity bins (in multiplicity bins)"}; + Configurable cfgProcessKtBins{"cfgProcessKtBins", true, "Process kstar histograms in kT bins (if cfgProcessMultBins is set false, this will not be processed regardless this Configurable state)"}; + + FemtoUniverseFemtoContainer sameEventCont; + FemtoUniverseFemtoContainer mixedEventCont; + + FemtoUniverseFemtoContainer sameEventContPP; + FemtoUniverseFemtoContainer mixedEventContPP; + + FemtoUniverseFemtoContainer sameEventContMM; + FemtoUniverseFemtoContainer mixedEventContMM; + + FemtoUniversePairCleaner pairCleaner; + FemtoUniverseDetaDphiStar pairCloseRejection; + FemtoUniverseTrackSelection trackCuts; + + PairWithCentMultKt sameEventMultCont; + PairWithCentMultKt mixedEventMultCont; + + PairWithCentMultKt sameEventMultContPP; + PairWithCentMultKt mixedEventMultContPP; + + PairWithCentMultKt sameEventMultContMM; + PairWithCentMultKt mixedEventMultContMM; + + float mass1 = -1; + float mass2 = -1; + + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryPM{"CorrelationsPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryPP{"CorrelationsPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry resultRegistryMM{"CorrelationsMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry MixQaRegistry{"MixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + HistogramRegistry SameMultRegistryPM{"SameMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry MixedMultRegistryPM{"MixedMultRegistryPM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + HistogramRegistry SameMultRegistryPP{"SameMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry MixedMultRegistryPP{"MixedMultRegistryPP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + HistogramRegistry SameMultRegistryMM{"SameMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry MixedMultRegistryMM{"MixedMultRegistryMM", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // PID for protons + bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // ConfNsigmaTPC -> TPC Sigma for momentum < 0.5 + // ConfNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > 0.5 + + if (mom < twotracksconfigs.ConfTOFPtMin) { + if (TMath::Abs(nsigmaTPCPr) < twotracksconfigs.ConfNsigmaTPC) { + return true; + } else { + return false; + } + } else { + if (TMath::Hypot(nsigmaTOFPr, nsigmaTPCPr) < twotracksconfigs.ConfNsigmaCombined) { + return true; + } else { + return false; + } + } + return false; + } + + bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // ConfNsigmaTPCTOFKaon -> are we doing TPC TOF PID for Kaons? (boolean) + // ConfNsigmaTPC -> TPC Kaon Sigma for momentum < 0.5 + // ConfNsigmaCombined -> TPC and TOF Sigma (combined) for momentum > 0.5 + if (true) { + if (mom < twotracksconfigs.ConfTOFPtMin) { + if (TMath::Abs(nsigmaTPCK) < twotracksconfigs.ConfNsigmaTPC) { + return true; + } else { + return false; + } + } else { + if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < twotracksconfigs.ConfNsigmaCombined) { + return true; + } else { + return false; + } + } + } + return false; + } + + bool IsPionNSigma(float mom, float nsigmaTPCPi, float nsigmaTOFPi) + { + //|nsigma_TPC| < 3 for p < 0.5 GeV/c + //|nsigma_combined| < 3 for p > 0.5 + + // using configurables: + // ConfTOFPtMin - momentum value when we start using TOF; set to 1000 if TOF not needed + // ConfNsigmaTPC -> TPC Sigma for momentum < 0.5 + // ConfNsigmaCombined -> TPC and TOF Pion Sigma (combined) for momentum > 0.5 + if (true) { + if (mom < twotracksconfigs.ConfTOFPtMin) { + if (TMath::Abs(nsigmaTPCPi) < twotracksconfigs.ConfNsigmaTPC) { + return true; + } else { + return false; + } + } else { + if (TMath::Hypot(nsigmaTOFPi, nsigmaTPCPi) < twotracksconfigs.ConfNsigmaCombined) { + return true; + } else { + return false; + } + } + } + return false; + } + + bool IsParticleNSigma(int8_t particle_number, float mom, float nsigmaTPCPr, float nsigmaTOFPr, float nsigmaTPCPi, float nsigmaTOFPi, float nsigmaTPCK, float nsigmaTOFK) + { + if (particle_number == 1) { + switch (trackonefilter.ConfPDGCodePartOne) { + case 2212: // Proton + case -2212: // Antiproton + return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion+ + case -211: // Pion- + return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + break; + case 321: // Kaon+ + case -321: // Kaon- + return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } else if (particle_number == 2) { + switch (tracktwofilter.ConfPDGCodePartTwo) { + case 2212: // Proton + case -2212: // Antiproton + return IsProtonNSigma(mom, nsigmaTPCPr, nsigmaTOFPr); + break; + case 211: // Pion+ + case -211: // Pion- + return IsPionNSigma(mom, nsigmaTPCPi, nsigmaTOFPi); + break; + case 321: // Kaon+ + case -321: // Kaon- + return IsKaonNSigma(mom, nsigmaTPCK, nsigmaTOFK); + break; + default: + return false; + } + return false; + } else { + LOGF(fatal, "Wrong number of particle chosen! It should be 1 or 2. It is -> %d", particle_number); + } + return false; + } + + void init(InitContext&) + { + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, twotracksconfigs.ConfIsMC, trackonefilter.ConfPDGCodePartOne, true); + + trackHistoPartTwo.init(&qaRegistry, ConfTempFitVarpTBins, ConfTempFitVarBins, twotracksconfigs.ConfIsMC, tracktwofilter.ConfPDGCodePartTwo, true); + + MixQaRegistry.add("MixingQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + MixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + mass1 = pdg->Mass(trackonefilter.ConfPDGCodePartOne); + mass2 = pdg->Mass(tracktwofilter.ConfPDGCodePartTwo); + + if (cfgProcessPM) { + sameEventCont.init(&resultRegistryPM, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); + mixedEventCont.init(&resultRegistryPM, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); + + sameEventCont.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + mixedEventCont.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + + if (cfgProcessMultBins) { + sameEventMultCont.init(&SameMultRegistryPM, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins); + mixedEventMultCont.init(&MixedMultRegistryPM, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins); + } + } + + if (cfgProcessPP) { + sameEventContPP.init(&resultRegistryPP, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); + mixedEventContPP.init(&resultRegistryPP, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); + sameEventContPP.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + mixedEventContPP.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + + if (cfgProcessMultBins) { + sameEventMultContPP.init(&SameMultRegistryPP, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins); + mixedEventMultContPP.init(&MixedMultRegistryPP, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins); + } + } + + if (cfgProcessMM) { + sameEventContMM.init(&resultRegistryMM, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); + mixedEventContMM.init(&resultRegistryMM, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, twotracksconfigs.ConfIsMC, twotracksconfigs.ConfUse3D); + sameEventContMM.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + mixedEventContMM.setPDGCodes(trackonefilter.ConfPDGCodePartOne, tracktwofilter.ConfPDGCodePartTwo); + + if (cfgProcessMultBins) { + sameEventMultContMM.init(&SameMultRegistryMM, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins); + mixedEventMultContMM.init(&MixedMultRegistryMM, ConfkstarBins, ConfMultKstarBins, ConfKtKstarBins, cfgProcessKtBins); + } + } + + pairCleaner.init(&qaRegistry); + if (ConfIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); + } + + vPIDPartOne = trackonefilter.ConfPIDPartOne.value; + vPIDPartTwo = tracktwofilter.ConfPIDPartTwo.value; + kNsigma = twotracksconfigs.ConfTrkPIDnSigmaMax.value; + } + + template + void fillCollision(CollisionType col) + { + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupPartsOne partition for the first particle passed by the process function + /// @param groupPartsTwo partition for the second particle passed by the process function + /// @param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, int ContType, bool fillQA) + { + + /// Histogramming same event + if ((ContType == 1 || ContType == 2) && fillQA) { + for (auto& part : groupPartsOne) { + if (!IsParticleNSigma((int8_t)1, part.pt(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + trackHistoPartOne.fillQA(part); + } + } + + if ((ContType == 1 || ContType == 3) && fillQA) { + for (auto& part : groupPartsTwo) { + if (!IsParticleNSigma((int8_t)2, part.pt(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { + continue; + } + trackHistoPartTwo.fillQA(part); + } + } + + if (ContType == 1) { + + /// Now build the combinations for non-identical particle pairs + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if (!IsParticleNSigma((int8_t)1, p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + continue; + } + + if (!IsParticleNSigma((int8_t)2, p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + continue; + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + + sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + sameEventMultCont.fill(kstar, multCol, kT); + } + } else { + /// Now build the combinations for identical particles pairs + for (auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsOne, groupPartsOne))) { + + if (!IsParticleNSigma((int8_t)2, p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + continue; + } + + if (!IsParticleNSigma((int8_t)2, p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + continue; + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + switch (ContType) { + case 2: { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass1); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass1); + + sameEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + sameEventMultContPP.fill(kstar, multCol, kT); + break; + } + + case 3: { + float kstar = FemtoUniverseMath::getkstar(p1, mass2, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass2, p2, mass2); + + sameEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + sameEventMultContMM.fill(kstar, multCol, kT); + break; + } + default: + break; + } + } + } + } + + /// process function for to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoUniverseParticleTable + void processSameEvent(o2::aod::FDCollision& col, + FilteredFemtoFullParticles& parts) + { + fillCollision(col); + + auto thegroupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + bool fillQA = true; + + if (cfgProcessPM) { + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 1, fillQA); + fillQA = false; + } + if (cfgProcessPP) + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), 2, fillQA); + if (cfgProcessMM) + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 3, fillQA); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackMultKt, processSameEvent, "Enable processing same event", true); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// \param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processSameEventMC(o2::aod::FDCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + + auto thegroupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + bool fillQA = true; + if (cfgProcessPM) { + doSameEvent(thegroupPartsOne, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 1, fillQA); + fillQA = false; + } + if (cfgProcessPP) + doSameEvent(thegroupPartsOne, thegroupPartsOne, parts, col.magField(), col.multNtr(), 2, fillQA); + if (cfgProcessMM) + doSameEvent(thegroupPartsTwo, thegroupPartsTwo, parts, col.magField(), col.multNtr(), 3, fillQA); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackMultKt, processSameEventMC, "Enable processing same event for Monte Carlo", false); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, int ContType) + { + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + + if (!IsParticleNSigma((int8_t)2, p1.pt(), trackCuts.getNsigmaTPC(p1, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p1, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p1, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p1, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p1, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p1, o2::track::PID::Kaon))) { + continue; + } + + if (!IsParticleNSigma((int8_t)2, p2.pt(), trackCuts.getNsigmaTPC(p2, o2::track::PID::Proton), trackCuts.getNsigmaTOF(p2, o2::track::PID::Proton), trackCuts.getNsigmaTPC(p2, o2::track::PID::Pion), trackCuts.getNsigmaTOF(p2, o2::track::PID::Pion), trackCuts.getNsigmaTPC(p2, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(p2, o2::track::PID::Kaon))) { + continue; + } + + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + + switch (ContType) { + case 1: { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass2); + mixedEventCont.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + mixedEventMultCont.fill(kstar, multCol, kT); + break; + } + case 2: { + float kstar = FemtoUniverseMath::getkstar(p1, mass1, p2, mass1); + float kT = FemtoUniverseMath::getkT(p1, mass1, p2, mass1); + mixedEventContPP.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + mixedEventMultContPP.fill(kstar, multCol, kT); + break; + } + + case 3: { + float kstar = FemtoUniverseMath::getkstar(p1, mass2, p2, mass2); + float kT = FemtoUniverseMath::getkT(p1, mass2, p2, mass2); + mixedEventContMM.setPair(p1, p2, multCol, twotracksconfigs.ConfUse3D); + if (cfgProcessMultBins) + mixedEventMultContMM.fill(kstar, multCol, kT); + break; + } + default: + break; + } + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoUniverseParticleTable + void processMixedEvent(o2::aod::FDCollisions& cols, + FilteredFemtoFullParticles& parts) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + if (cfgProcessPM) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol, 1); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol, 2); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol, 3); + } + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackMultKt, processMixedEvent, "Enable processing mixed events", true); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth + /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMC(o2::aod::FDCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + /// \todo before mixing we should check whether both collisions contain a pair of particles! + // if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; + + if (cfgProcessPM) { + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol, 1); + } + if (cfgProcessPP) { + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol, 2); + } + if (cfgProcessMM) { + auto groupPartsOne = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + doMixedEvent(groupPartsOne, groupPartsTwo, parts, magFieldTesla1, multiplicityCol, 3); + } + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackTrackMultKt, processMixedEventMC, "Enable processing mixed events MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0.cxx new file mode 100644 index 00000000000..7de3a9db2a8 --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0.cxx @@ -0,0 +1,270 @@ +// 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 femtoUniversePairTaskTrackTrack.cxx +/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw, zuzanna.chochulska.stud@pw.edu.pl + +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StepTHn.h" + +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUtils.h" + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::femtoUniverse; + +namespace +{ +static constexpr int nTrack = 1; +static constexpr int nV0Children = 2; +static constexpr int nCuts = 5; +static const std::vector TrackName{"Track"}; +static const std::vector V0ChildrenName{"PosChild", "NegChild"}; +static const std::vector cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF", "MaxP"}; +static const float cutsTableTrack[nTrack][nCuts]{{4.05f, 0.75f, 3.f, 3.f, 100.f}}; +static const float cutsTableV0Children[nV0Children][nCuts]{ + {90.f, 99.f, 5.f, 5.f, 100.f}, + {90.f, 99.f, 5.f, 5.f, 100.f}}; +} // namespace + +struct femtoUniversePairTaskTrackV0 { + SliceCache cache; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// Particle 1 (track) + Configurable> ConfTrkCutTable{"ConfTrkCutTable", {cutsTableTrack[0], nTrack, nCuts, TrackName, cutNames}, "Particle selections"}; + Configurable ConfTrkPDGCodePartOne{"ConfTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"}; + Configurable ConfTrkCutPartOne{"ConfTrkCutPartOne", 5542474, "Particle 1 (Track) - Selection bit from cutCulator"}; + Configurable ConfTrkPIDPartOne{"ConfTrkPIDPartOne", 2, "Particle 1 - Read from cutCulator"}; + Configurable ConfNspecies{"ConfNspecies", 2, "Number of particle spieces with PID info"}; + Configurable> ConfTrkPIDnSigmaMax{"ConfTrkPIDnSigmaMax", std::vector{4.f, 3.f, 2.f}, "This configurable needs to be the same as the one used in the producer task"}; + ConfigurableAxis ConfTrkTempFitVarBins{"ConfTrkDTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfTrkTempFitVarpTBins{"ConfTrkTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && ((aod::femtouniverseparticle::cut & ConfTrkCutPartOne) == ConfTrkCutPartOne); + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOne; + + /// Particle 2 (V0) + Configurable> ConfV0ChildrenCutTable{"ConfV0ChildrenCutTable", {cutsTableV0Children[0], nV0Children, nCuts, V0ChildrenName, cutNames}, "V0 Children selections"}; + Configurable ConfV0PDGCodePartTwo{"ConfV0PDGCodePartTwo", 3122, "Particle 2 (V0) - PDG code"}; + Configurable ConfV0CutPartTwo{"ConfV0CutPartTwo", 338, "Particle 2 (V0) - Selection bit"}; + ConfigurableAxis ConfV0TempFitVarBins{"ConfV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis ConfV0TempFitVarpTBins{"ConfV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + + Configurable ConfCutChildPos{"ConfCutChildPos", 150, "Positive Child of V0 - Selection bit from cutCulator"}; + Configurable ConfCutChildNeg{"ConfCutChildNeg", 149, "Negative Child of V0 - Selection bit from cutCulator"}; + Configurable ConfChildPosIndex{"ConfChildPosIndex", 1, "Positive Child of V0 - Index from cutCulator"}; + Configurable ConfChildNegIndex{"ConfChildNegIndex", 0, "Negative Child of V0 - Index from cutCulator"}; + Configurable> ConfChildPIDnSigmaMax{"ConfChildPIDnSigmaMax", std::vector{4.f, 3.f}, "V0 child sel: Max. PID nSigma TPC"}; + Configurable ConfChildnSpecies{"ConfChildnSpecies", 2, "Number of particle spieces (for V0 children) with PID info"}; + 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"}; + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && ((aod::femtouniverseparticle::cut & ConfV0CutPartTwo) == ConfV0CutPartTwo); + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwo; + FemtoUniverseParticleHisto posChildHistos; + FemtoUniverseParticleHisto negChildHistos; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + int vPIDPartOne; + std::vector kNsigma; + + /// Correlation part + Configurable ConfIsMC{"ConfIsMC", false, "Enable additional Histogramms in the case of a MonteCarlo Run"}; + Configurable ConfUse3D{"ConfUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + ConfigurableAxis ConfMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis ConfkstarBins{"ConfkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis ConfkTBins{"ConfkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis ConfmTBins{"ConfmTBins", {225, 0., 7.5}, "binning mT"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable ConfPhiBins{"ConfPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable ConfEtaBins{"ConfEtaBins", 29, "Number of eta bins in deta dphi"}; + + ConfigurableAxis ConfmTBins3D{"ConfmTBins3D", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + ConfigurableAxis ConfmultBins3D{"ConfMultBins3D", {VARIABLE_WIDTH, 0.0f, 20.0f, 30.0f, 40.0f, 99999.0f}, "multiplicity Binning for the 3Dimensional plot: k* vs multiplicity vs mT (set <> to true in order to use)"}; + + FemtoUniverseContainer sameEventCont; + FemtoUniverseContainer mixedEventCont; + FemtoUniversePairCleaner pairCleaner; + FemtoUniverseDetaDphiStar pairCloseRejection; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext&) + { + eventHisto.init(&qaRegistry); + trackHistoPartOne.init(&qaRegistry, ConfTrkTempFitVarpTBins, ConfTrkTempFitVarBins, ConfIsMC, ConfTrkPDGCodePartOne); + trackHistoPartTwo.init(&qaRegistry, ConfV0TempFitVarpTBins, ConfV0TempFitVarBins, ConfIsMC, ConfV0PDGCodePartTwo); + posChildHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, false); + negChildHistos.init(&qaRegistry, ConfChildTempFitVarpTBins, ConfChildTempFitVarBins, false, false); + + sameEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, ConfIsMC, ConfUse3D); + sameEventCont.setPDGCodes(ConfTrkPDGCodePartOne, ConfV0PDGCodePartTwo); + mixedEventCont.init(&resultRegistry, ConfkstarBins, ConfMultBins, ConfkTBins, ConfmTBins, ConfmultBins3D, ConfmTBins3D, ConfEtaBins, ConfPhiBins, ConfIsMC, ConfUse3D); + mixedEventCont.setPDGCodes(ConfTrkPDGCodePartOne, ConfV0PDGCodePartTwo); + pairCleaner.init(&qaRegistry); + if (ConfIsCPR.value) { + pairCloseRejection.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value); + } + vPIDPartOne = ConfTrkPIDPartOne.value; + kNsigma = ConfTrkPIDnSigmaMax.value; + } + + /// This function processes the same event and takes care of all the histogramming + /// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + void processSameEvent(o2::aod::FDCollision& col, o2::aod::FDParticles& parts) + { + const auto& magFieldTesla = col.magField(); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + const int multCol = col.multNtr(); + + eventHisto.fillQA(col); + + /// Histogramming same event + for (auto& part : groupPartsOne) { + if (part.p() > ConfTrkCutTable->get("Track", "MaxP") || part.pt() > ConfTrkCutTable->get("Track", "MaxPt") || + !isFullPIDSelected(part.pidcut(), part.p(), ConfTrkCutTable->get("Track", "PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfTrkCutTable->get("Track", "nSigmaTPC"), ConfTrkCutTable->get("Track", "nSigmaTPCTOF"))) { + continue; + } + trackHistoPartOne.fillQA(part); + } + + for (auto& part : groupPartsTwo) { + const auto& posChild = parts.iteratorAt(part.index() - 2); + const auto& negChild = parts.iteratorAt(part.index() - 1); + // check cuts on V0 children + if (!((posChild.cut() & ConfCutChildPos) == ConfCutChildPos) || !((negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) || + !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildPosIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || + !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildNegIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { + continue; + } + trackHistoPartTwo.fillQA(part); + posChildHistos.fillQA(posChild); + negChildHistos.fillQA(negChild); + } + + /// Now build the combinations + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (p1.p() > ConfTrkCutTable->get("Track", "MaxP") || p1.pt() > ConfTrkCutTable->get("Track", "MaxPt") || + !isFullPIDSelected(p1.pidcut(), p1.p(), ConfTrkCutTable->get("Track", "PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfTrkCutTable->get("Track", "nSigmaTPC"), ConfTrkCutTable->get("Track", "nSigmaTPCTOF"))) { + continue; + } + const auto& posChild = parts.iteratorAt(p2.index() - 2); + const auto& negChild = parts.iteratorAt(p2.index() - 1); + // check cuts on V0 children + if (!((posChild.cut() & ConfCutChildPos) == ConfCutChildPos) || !((negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) || + !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildPosIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || + !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildNegIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { + continue; + } + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + sameEventCont.setPair(p1, p2, multCol, ConfUse3D); + } + } + + PROCESS_SWITCH(femtoUniversePairTaskTrackV0, processSameEvent, "Enable processing same event", true); + + /// This function processes the mixed event + /// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ... + void processMixedEvent(o2::aod::FDCollisions& cols, o2::aod::FDParticles& parts) + { + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + + const int multCol = collision1.multNtr(); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (p1.p() > ConfTrkCutTable->get("Track", "MaxP") || p1.pt() > ConfTrkCutTable->get("Track", "MaxPt") || + !isFullPIDSelected(p1.pidcut(), p1.p(), ConfTrkCutTable->get("Track", "PIDthr"), vPIDPartOne, ConfNspecies, kNsigma, ConfTrkCutTable->get("Track", "nSigmaTPC"), ConfTrkCutTable->get("Track", "nSigmaTPCTOF"))) { + continue; + } + const auto& posChild = parts.iteratorAt(p2.index() - 2); + const auto& negChild = parts.iteratorAt(p2.index() - 1); + // check cuts on V0 children + if (!((posChild.cut() & ConfCutChildPos) == ConfCutChildPos) || !((negChild.cut() & ConfCutChildNeg) == ConfCutChildNeg) || + !isFullPIDSelected(posChild.pidcut(), posChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildPosIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("PosChild", "nSigmaTPCTOF")) || + !isFullPIDSelected(negChild.pidcut(), negChild.p(), ConfV0ChildrenCutTable->get("PosChild", "PIDthr"), ConfChildNegIndex.value, ConfChildnSpecies.value, ConfChildPIDnSigmaMax.value, ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPC"), ConfV0ChildrenCutTable->get("NegChild", "nSigmaTPCTOF"))) { + continue; + } + if (ConfIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1)) { + continue; + } + } + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + mixedEventCont.setPair(p1, p2, multCol, ConfUse3D); + } + } + } + + PROCESS_SWITCH(femtoUniversePairTaskTrackV0, processMixedEvent, "Enable processing mixed events", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldCollisionSelection.h b/PWGCF/FemtoWorld/Core/FemtoWorldCollisionSelection.h index bb58279001c..040a9a128cf 100644 --- a/PWGCF/FemtoWorld/Core/FemtoWorldCollisionSelection.h +++ b/PWGCF/FemtoWorld/Core/FemtoWorldCollisionSelection.h @@ -14,16 +14,16 @@ /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de /// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch -#ifndef FEMTOWORLDCOLLISIONSELECTION_H_ -#define FEMTOWORLDCOLLISIONSELECTION_H_ +#ifndef PWGCF_FEMTOWORLD_CORE_FEMTOWORLDCOLLISIONSELECTION_H_ +#define PWGCF_FEMTOWORLD_CORE_FEMTOWORLDCOLLISIONSELECTION_H_ + +#include +#include #include "Common/CCDB/TriggerAliases.h" #include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" -#include -#include - using namespace o2::framework; namespace o2::analysis::femtoWorld @@ -61,14 +61,22 @@ class FemtoWorldCollisionSelection } mHistogramRegistry = registry; mHistogramRegistry->add("Event/zvtxhist", "; vtx_{z} (cm); Entries", kTH1F, {{300, -12.5, 12.5}}); - mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{600, 0, 600}}); - mHistogramRegistry->add("Event/MultT0M", "; vMultT0M; Entries", kTH1F, {{600, 0, 600}}); + mHistogramRegistry->add("Event/MultV0M", "; vMultV0M; Entries", kTH1F, {{16384, 0, 32768}}); + mHistogramRegistry->add("Event/MultT0M", "; vMultT0M; Entries", kTH1F, {{4096, 0, 8192}}); + mHistogramRegistry->add("Event/MultNTracksPV", "; vMultNTracksPV; Entries", kTH1F, {{120, 0, 120}}); + mHistogramRegistry->add("Event/MultNTracklets", "; vMultNTrackslets; Entries", kTH1F, {{300, 0, 300}}); + mHistogramRegistry->add("Event/MultTPC", "; vMultTPC; Entries", kTH1I, {{600, 0, 600}}); } /// Print some debug information void printCuts() { - LOGF(info, "Debug information for FemtoWorldCollisionSelection \n Max. z-vertex: %f \n Check trigger: %B \n Trigger: %i \n Check offline: %B ", mZvtxMax, mCheckTrigger, mTrigger, mCheckOffline); + LOG(info) << "Debug information for FemtoDreamCollisionSelection"; + LOG(info) << "Max. z-vertex: " << mZvtxMax; + LOG(info) << "Check trigger: " << mCheckTrigger; + LOG(info) << "Trigger: " << mTrigger; + LOG(info) << " Check offline: " << mCheckOffline; + LOG(info) << " Check Run 3: " << mCheckIsRun3; } /// Check whether the collisions fulfills the specified selections @@ -104,8 +112,15 @@ class FemtoWorldCollisionSelection { if (mHistogramRegistry) { mHistogramRegistry->fill(HIST("Event/zvtxhist"), col.posZ()); - mHistogramRegistry->fill(HIST("Event/MultV0M"), col.multFV0M()); mHistogramRegistry->fill(HIST("Event/MultT0M"), col.multFT0M()); + mHistogramRegistry->fill(HIST("Event/MultNTracksPV"), col.multNTracksPV()); + mHistogramRegistry->fill(HIST("Event/MultNTracklets"), col.multTracklets()); + mHistogramRegistry->fill(HIST("Event/MultTPC"), col.multTPC()); + if (mCheckIsRun3) { + mHistogramRegistry->fill(HIST("Event/MultV0M"), col.multFV0M()); + } else { + mHistogramRegistry->fill(HIST("Event/MultV0M"), 0.5 * (col.multFV0M())); // in AliPhysics, the VOM was defined by (V0A + V0C)/2. + } } } @@ -135,4 +150,4 @@ class FemtoWorldCollisionSelection }; } // namespace o2::analysis::femtoWorld -#endif /* FEMTOWORLDCOLLISIONSELECTION_H_ */ +#endif // PWGCF_FEMTOWORLD_CORE_FEMTOWORLDCOLLISIONSELECTION_H_ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldContainer.h b/PWGCF/FemtoWorld/Core/FemtoWorldContainer.h index b85dd0b5fcd..a80af060d56 100644 --- a/PWGCF/FemtoWorld/Core/FemtoWorldContainer.h +++ b/PWGCF/FemtoWorld/Core/FemtoWorldContainer.h @@ -32,7 +32,6 @@ #include "TRandom.h" using namespace o2::framework; -using namespace o2::constants::math; namespace o2::analysis::femtoWorld { @@ -87,8 +86,8 @@ class FemtoWorldContainer framework::AxisSpec kTAxis = {kTBins, "#it{k}_{T} (GeV/#it{c})"}; framework::AxisSpec mTAxis = {mTBins, "#it{m}_{T} (GeV/#it{c}^{2})"}; - mPhiLow = (-static_cast(phiBins / 4) + 0.5) * 2. * PI / phiBins; - mPhiHigh = 2 * PI + (-static_cast(phiBins / 4) + 0.5) * 2. * PI / phiBins; + mPhiLow = (-static_cast(phiBins / 4) + 0.5) * 2. * o2::constants::math::PI / phiBins; + mPhiHigh = 2 * o2::constants::math::PI + (-static_cast(phiBins / 4) + 0.5) * 2. * o2::constants::math::PI / phiBins; framework::AxisSpec phiAxis = {phiBins, mPhiLow, mPhiHigh}; framework::AxisSpec etaAxis = {etaBins, -2.0, 2.0}; @@ -154,10 +153,10 @@ class FemtoWorldContainer double delta_phi = part1.phi() - part2.phi(); while (delta_phi < mPhiLow) { - delta_phi += TwoPI; + delta_phi += o2::constants::math::TwoPI; } while (delta_phi > mPhiHigh) { - delta_phi -= TwoPI; + delta_phi -= o2::constants::math::TwoPI; } TLorentzVector part1Vec; part1Vec.SetPtEtaPhiM(part1.pt(), part1.eta(), part1.phi(), mMassOne); diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h b/PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h index ce67573f411..f7262481a77 100644 --- a/PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h +++ b/PWGCF/FemtoWorld/Core/FemtoWorldDetaDphiStar.h @@ -14,13 +14,15 @@ /// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de /// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch -#ifndef FEMTOWORLDDETADPHISTAR_H_ -#define FEMTOWORLDDETADPHISTAR_H_ +#ifndef PWGCF_FEMTOWORLD_CORE_FEMTOWORLDDETADPHISTAR_H_ +#define PWGCF_FEMTOWORLD_CORE_FEMTOWORLDDETADPHISTAR_H_ -#include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" +#include +#include +#include +#include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" #include "Framework/HistogramRegistry.h" -#include namespace o2::analysis { @@ -70,6 +72,8 @@ class FemtoWorldDetaDphiStar } if constexpr (mPartOneType == o2::aod::femtoworldparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtoworldparticle::ParticleType::kPhi) { } + if constexpr (mPartOneType == o2::aod::femtoworldparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtoworldparticle::ParticleType::kD0D0bar) { + } } /// Check if pair is close or not template @@ -119,6 +123,9 @@ class FemtoWorldDetaDphiStar } else if constexpr (mPartOneType == o2::aod::femtoworldparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtoworldparticle::ParticleType::kPhi) { /// Track-Phi combination return true; + } else if constexpr (mPartOneType == o2::aod::femtoworldparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtoworldparticle::ParticleType::kD0D0bar) { + /// Track-D0 combination + return true; } else { LOG(fatal) << "FemtoWorldPairCleaner: Combination of objects not defined - quitting!"; return false; @@ -199,11 +206,11 @@ class FemtoWorldDetaDphiStar histdetadpiRadii[iHist][i]->Fill(part1.eta() - part2.eta(), dphi); } } - return (dPhiAvg / (float)num); + return (dPhiAvg / static_cast(num)); } }; } /* namespace femtoWorld */ } /* namespace o2::analysis */ -#endif /* FEMTOWORLDDETADPHISTAR_H_ */ +#endif // PWGCF_FEMTOWORLD_CORE_FEMTOWORLDDETADPHISTAR_H_ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h b/PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h index 85619a23185..5c20af3813e 100644 --- a/PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h +++ b/PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h @@ -14,8 +14,8 @@ /// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de, Laura Serksnyte , TU München /// \author Zuzanna Chochulska, WUT Warsaw, zchochul@cern.ch -#ifndef FEMTOWORLDPAIRCLEANER_H_ -#define FEMTOWORLDPAIRCLEANER_H_ +#ifndef PWGCF_FEMTOWORLD_CORE_FEMTOWORLDPAIRCLEANER_H_ +#define PWGCF_FEMTOWORLD_CORE_FEMTOWORLDPAIRCLEANER_H_ #include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" #include "Framework/HistogramRegistry.h" @@ -79,9 +79,9 @@ class FemtoWorldPairCleaner return false; } else if constexpr (mPartOneType == o2::aod::femtoworldparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtoworldparticle::ParticleType::kPhi) { return true; - } - - else { + } else if constexpr (mPartOneType == o2::aod::femtoworldparticle::ParticleType::kTrack && mPartTwoType == o2::aod::femtoworldparticle::ParticleType::kD0D0bar) { + return true; + } else { LOG(fatal) << "FemtoWorldPairCleaner: Combination of objects not defined - quitting!"; return false; } @@ -94,4 +94,4 @@ class FemtoWorldPairCleaner }; } // namespace o2::analysis::femtoWorld -#endif /* FEMTOWORLDPAIRCLEANER_H_ */ +#endif // PWGCF_FEMTOWORLD_CORE_FEMTOWORLDPAIRCLEANER_H_ diff --git a/PWGCF/FemtoWorld/Core/FemtoWorldPionContainer.h b/PWGCF/FemtoWorld/Core/FemtoWorldPionContainer.h index 4273c0cf3b9..9c68ac7c76e 100644 --- a/PWGCF/FemtoWorld/Core/FemtoWorldPionContainer.h +++ b/PWGCF/FemtoWorld/Core/FemtoWorldPionContainer.h @@ -32,7 +32,6 @@ #include "TRandom.h" using namespace o2::framework; -using namespace o2::constants::math; namespace o2::analysis::femtoWorld { @@ -91,8 +90,8 @@ class FemtoWorldPionContainer framework::AxisSpec kTAxis = {kTBins, "#it{k}_{T} (GeV/#it{c})"}; framework::AxisSpec mTAxis = {mTBins, "#it{m}_{T} (GeV/#it{c}^{2})"}; - mPhiLow = (-static_cast(phiBins / 4) + 0.5) * 2. * PI / phiBins; - mPhiHigh = 2 * PI + (-static_cast(phiBins / 4) + 0.5) * 2. * PI / phiBins; + mPhiLow = (-static_cast(phiBins / 4) + 0.5) * 2. * o2::constants::math::PI / phiBins; + mPhiHigh = 2 * o2::constants::math::PI + (-static_cast(phiBins / 4) + 0.5) * 2. * o2::constants::math::PI / phiBins; framework::AxisSpec phiAxis = {phiBins, mPhiLow, mPhiHigh}; framework::AxisSpec etaAxis = {etaBins, -2.0, 2.0}; @@ -141,10 +140,10 @@ class FemtoWorldPionContainer double delta_phi = part1.phi() - part2.phi(); while (delta_phi < mPhiLow) { - delta_phi += TwoPI; + delta_phi += o2::constants::math::TwoPI; } while (delta_phi > mPhiHigh) { - delta_phi -= TwoPI; + delta_phi -= o2::constants::math::TwoPI; } TLorentzVector part1Vec; part1Vec.SetPtEtaPhiM(part1.pt(), part1.eta(), part1.phi(), mMassOne); diff --git a/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h b/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h index df0db5a212c..d112f11c2ab 100644 --- a/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h +++ b/PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h @@ -31,6 +31,7 @@ namespace femtoworldcollision DECLARE_SOA_COLUMN(MultV0M, multV0M, float); //! V0M multiplicity DECLARE_SOA_COLUMN(Sphericity, sphericity, float); //! Sphericity of the event DECLARE_SOA_COLUMN(MagField, magField, float); //! Sphericity of the event +DECLARE_SOA_COLUMN(RunCentrality, runCent, float); //! Sphericity of the event } // namespace femtoworldcollision @@ -40,7 +41,7 @@ DECLARE_SOA_TABLE(FemtoWorldCollisions, "AOD", "FEMTOWORLDCOLS", femtoworldcollision::MultV0M, femtoworldcollision::Sphericity, femtoworldcollision::MagField, - o2::aod::cent::CentRun2V0M); + femtoworldcollision::RunCentrality); using FemtoWorldCollision = FemtoWorldCollisions::iterator; /// FemtoWorldTrack diff --git a/PWGCF/FemtoWorld/TableProducer/femtoWorldProducerTask.cxx b/PWGCF/FemtoWorld/TableProducer/femtoWorldProducerTask.cxx index 6b70d9dfb18..939c950410f 100644 --- a/PWGCF/FemtoWorld/TableProducer/femtoWorldProducerTask.cxx +++ b/PWGCF/FemtoWorld/TableProducer/femtoWorldProducerTask.cxx @@ -22,6 +22,7 @@ #include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" #include "PWGCF/FemtoWorld/Core/FemtoWorldPairCleaner.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -39,6 +40,7 @@ #include "ReconstructionDataFormats/Track.h" #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "Math/Vector4D.h" #include "TMath.h" @@ -47,16 +49,18 @@ using namespace o2; using namespace o2::analysis::femtoWorld; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; namespace o2::aod { -using FemtoFullCollision = soa::Join::iterator; +using FemtoFullCollisionRun2 = soa::Join::iterator; +using FemtoFullCollisionRun3 = soa::Join::iterator; using FemtoFullTracks = soa::Join outputCollision; Produces outputParts; - // Produces outputPhiCan; - // Produces outputDebugParts; // Configurables for D0/D0bar mesons Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; - Configurable selectionFlagHf{"selectionFlagHf", 1, "Selection Flag for HF flagged candidates"}; - Configurable selectionTopol{"selectionTopol", 1, "Selection Flag for topologically selected candidates"}; - Configurable selectionCand{"selectionCand", 1, "Selection Flag for conj. topol. selected candidates"}; - Configurable selectionPid{"selectionPid", 1, "Selection Flag for reco PID candidates"}; - Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; - - Configurable ConfDebugOutput{"ConfDebugOutput", true, "Debug output"}; // Choose if filtering or skimming version is run - Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; // Choose if running on converted data or pilot beam Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Pilot beam"}; + 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 FemtoWorldCollisionSelection colCuts; @@ -124,7 +119,6 @@ struct femtoWorldProducerTask { Configurable ConfStoreV0{"ConfStoreV0", true, "True: store V0 table"}; Configurable ConfStorePhi{"ConfStorePhi", true, "True: store Phi table"}; - Configurable ConfStoreD0D0bar{"ConfStoreD0D0bar", true, "True: store table with particles marked as D0 and D0bar"}; // just sanity check to make sure in case there are problems in conversion or MC production it does not affect results Configurable ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; @@ -215,34 +209,15 @@ struct femtoWorldProducerTask { // PHI Candidates FemtoWorldPhiSelection PhiCuts; - Configurable> ConfPhiSign{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kPhiSign, "ConfPhi"), std::vector{-1, 1}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kPhiSign, "Phi selection: ")}; - Configurable> ConfPhiPtMin{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kpTPhiMin, "ConfPhi"), std::vector{0.3f, 0.4f, 0.5f}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kpTPhiMin, "Phi selection: ")}; - // Configurable> ConfDCAPhiDaughMax{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kDCAPhiDaughMax, "ConfPhi"), std::vector{1.2f, 1.5f}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kDCAPhiDaughMax, "Phi selection: ")}; - // Configurable> ConfCPAPhiMin{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kCPAPhiMin, "ConfPhi"), std::vector{0.99f, 0.995f}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kCPAPhiMin, "Phi selection: ")}; - - // Configurable> PhiTranRadPhiMin{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kTranRadPhiMin, "ConfPhi"), std::vector{0.2f}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kTranRadPhiMin, "Phi selection: ")}; - // Configurable> PhiTranRadPhiMax{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kTranRadPhiMax, "ConfPhi"), std::vector{100.f}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kTranRadPhiMax, "Phi selection: ")}; - // Configurable> PhiDecVtxMax{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kDecVtxMax, "ConfPhi"), std::vector{100.f}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kDecVtxMax, "Phi selection: ")}; - - /*Configurable> ConfPhiDaughCharge{"ConfPhiDaughCharge", std::vector{-1, 1}, "Phi Daugh sel: Charge"}; - Configurable> ConfPhiDaughEta{"ConfPhiDaughEta", std::vector{0.8f}, "Phi Daugh sel: max eta"}; - Configurable> ConfPhiDaughTPCnclsMin{"ConfPhiDaughTPCnclsMin", std::vector{80.f, 70.f, 60.f}, "Phi Daugh sel: Min. nCls TPC"}; - Configurable> ConfPhiDaughDCAMin{"ConfPhiDaughDCAMin", std::vector{0.05f, 0.06f}, "Phi Daugh sel: Max. DCA Daugh to PV (cm)"}; - Configurable> ConfPhiDaughPIDnSigmaMax{"ConfPhiDaughPIDnSigmaMax", std::vector{5.f, 4.f}, "Phi Daugh sel: Max. PID nSigma TPC"}; - Configurable> ConfPhiDaughTPIDspecies{"ConfPhiDaughTPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Proton}, "Phi Daugh sel: Particles species for PID"};*/ - // Configurable> ConfPhiSign{FemtoWorldV0Selection::getSelectionName(femtoWorldV0Selection::kV0Sign, "ConfV0"), std::vector{-1, 1}, FemtoWorldV0Selection::getSelectionHelper(femtoWorldV0Selection::kV0Sign, "V0 selection: ")}; - - /// \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 + // Configurable> ConfPhiSign{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kPhiSign, "ConfPhi"), std::vector{-1, 1}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kPhiSign, "Phi selection: ")}; + // Configurable> ConfPhiPtMin{FemtoWorldPhiSelection::getSelectionName(femtoWorldPhiSelection::kpTPhiMin, "ConfPhi"), std::vector{0.3f, 0.4f, 0.5f}, FemtoWorldPhiSelection::getSelectionHelper(femtoWorldPhiSelection::kpTPhiMin, "Phi selection: ")}; HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; int mRunNumber; float mMagField; Service ccdb; /// Accessing the CCDB + HfHelper hfHelper; void init(InitContext&) { @@ -308,6 +283,7 @@ struct femtoWorldProducerTask { o2PhysicsTrackSelection->SetRequireHitsInITSLayers(1, {0, 1, 2, 3}); } } + mRunNumber = 0; mMagField = 0.0; /// Initializing CCDB @@ -321,58 +297,6 @@ struct femtoWorldProducerTask { } // PID - /* - bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) - { - bool fNsigmaTPCTOF = true; - double fNsigma = 3; - double fNsigma2 = 3; - if (fNsigmaTPCTOF) { - if (mom > 0.5) { - // if (TMath::Hypot( nsigmaTOFP, nsigmaTPCP )/TMath::Sqrt(2) < 3.0) - if (mom < 2.0) { - if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < fNsigma) { - return true; - } - } else if (TMath::Hypot(nsigmaTOFK, nsigmaTPCK) < fNsigma2) { - return true; - } - } else { - if (TMath::Abs(nsigmaTPCK) < fNsigma) { - return true; - } - } - } else { - if (mom < 0.4) { - if (nsigmaTOFK < -999.) { - if (TMath::Abs(nsigmaTPCK) < 2.0) { - return true; - } - } else if (TMath::Abs(nsigmaTOFK) < 3.0 && TMath::Abs(nsigmaTPCK) < 3.0) { - return true; - } - } else if ((mom >= 0.4 && mom <= 0.45) || (mom >= 0.5 && mom <= 0.6)) { - if (nsigmaTOFK < -999.) { - if (TMath::Abs(nsigmaTPCK) < 2.0) { - return true; - } - } else if (TMath::Abs(nsigmaTOFK) < 3.0 && TMath::Abs(nsigmaTPCK) < 3.0) { - return true; - } - } else if ((mom >= 0.45 && mom <= 0.5)) { - if (ConfKaonChangePID == true) { // reducing contamination - return false; - } else { - return true; - } - } else if (nsigmaTOFK < -999.) { - return false; - } else if (TMath::Abs(nsigmaTOFK) < 3.0 && TMath::Abs(nsigmaTPCK) < 3.0) { - return true; - } - } - return false; - }*/ bool IsKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) { //|nsigma_TPC| < 5 for p < 0.4 GeV/c @@ -399,32 +323,53 @@ struct femtoWorldProducerTask { } return false; } + /// Function to retrieve the nominal mgnetic field in kG (0.1T) and convert it directly to T - float getMagneticFieldTesla(uint64_t timestamp) + void getMagneticFieldTesla(aod::BCsWithTimestamps::iterator bc) { // TODO done only once (and not per run). Will be replaced by CCDBConfigurable - static o2::parameters::GRPObject* grpo = nullptr; - if (grpo == nullptr) { + // 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 0; + return; } LOGF(info, "Retrieved GRP for timestamp %llu with magnetic field of %d kG", timestamp, grpo->getNominalL3Field()); + output = 0.1 * (grpo->getNominalL3Field()); } - float output = 0.1 * (grpo->getNominalL3Field()); - return output; + mMagField = output; + mRunNumber = bc.runNumber(); } - - void processProd(aod::FemtoFullCollision const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks, - o2::aod::V0Datas const& fullV0s, soa::Join& candidates) /// \todo with FilteredFullV0s + void processProdTrackRun2(aod::FemtoFullCollisionRun2 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) { // get magnetic field for run - auto bc = col.bc_as(); + /*auto bc = col.bc_as(); if (mRunNumber != bc.runNumber()) { mMagField = getMagneticFieldTesla(bc.timestamp()); mRunNumber = bc.runNumber(); - } + }*/ + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); /// First thing to do is to check whether the basic event selection criteria are fulfilled // If the basic selection is NOT fulfilled: @@ -443,12 +388,7 @@ struct femtoWorldProducerTask { const auto centrality = col.centRun2V0M(); colCuts.fillQA(col); - // now the table is filled - if (ConfIsRun3) { - outputCollision(vtxZ, col.multFT0M(), spher, mMagField, -1); - } else { - outputCollision(vtxZ, mult, spher, mMagField, centrality); - } + outputCollision(vtxZ, mult, spher, mMagField, centrality); int childIDs[2] = {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 @@ -511,291 +451,1125 @@ struct femtoWorldProducerTask { -999.); tmpIDtrack.push_back(track.globalIndex()); } + } + PROCESS_SWITCH(femtoWorldProducerTask, processProdTrackRun2, "Produce Femto tables", true); - if (ConfStoreV0) { - for (auto& v0 : fullV0s) { - auto postrack = v0.posTrack_as(); - auto negtrack = v0.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); + void processProdTrackV0Run2(aod::FemtoFullCollisionRun2 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); - if ((cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0) > 0) && (cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts) > 0) && (cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegCuts) > 0)) { - 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(), - 0, // v0.p(), - 0, // mass - -999., // D0mass - -999., // D0bar mass - -999., // D0 flag - -999., // D0bar flag - aod::femtoworldparticle::ParticleType::kV0Child, - cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), - cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), - 0., - childIDs, - 0, - 0, - postrack.sign(), - postrack.beta(), - postrack.itsChi2NCl(), - postrack.tpcChi2NCl(), - postrack.tpcNSigmaKa(), - postrack.tofNSigmaKa(), - (uint8_t)postrack.tpcNClsFound(), - postrack.tpcNClsFindable(), - (uint8_t)postrack.tpcNClsCrossedRows(), - postrack.tpcNClsShared(), - postrack.tpcInnerParam(), - postrack.itsNCls(), - postrack.itsNClsInnerBarrel(), - postrack.dcaXY(), - postrack.dcaZ(), - postrack.tpcSignal(), - postrack.tpcNSigmaStoreEl(), - postrack.tpcNSigmaStorePi(), - postrack.tpcNSigmaStoreKa(), - postrack.tpcNSigmaStorePr(), - postrack.tpcNSigmaStoreDe(), - postrack.tofNSigmaStoreEl(), - postrack.tofNSigmaStorePi(), - postrack.tofNSigmaStoreKa(), - postrack.tofNSigmaStorePr(), - postrack.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999., - -999.); - const int rowOfPosTrack = outputParts.lastIndex(); - 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(), - 0, // momentum - 0, // mass - -999., // D0mass - -999., // D0bar mass - -999., // D0 flag - -999., // D0bar flag - aod::femtoworldparticle::ParticleType::kV0Child, - cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegCuts), - cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegPID), - 0., - childIDs, - 0, - 0, - negtrack.sign(), - negtrack.beta(), - negtrack.itsChi2NCl(), - negtrack.tpcChi2NCl(), - negtrack.tpcNSigmaKa(), - negtrack.tofNSigmaKa(), - (uint8_t)negtrack.tpcNClsFound(), - negtrack.tpcNClsFindable(), - (uint8_t)negtrack.tpcNClsCrossedRows(), - negtrack.tpcNClsShared(), - negtrack.tpcInnerParam(), - negtrack.itsNCls(), - negtrack.itsNClsInnerBarrel(), - negtrack.dcaXY(), - negtrack.dcaZ(), - negtrack.tpcSignal(), - negtrack.tpcNSigmaStoreEl(), - negtrack.tpcNSigmaStorePi(), - negtrack.tpcNSigmaStoreKa(), - negtrack.tpcNSigmaStorePr(), - negtrack.tpcNSigmaStoreDe(), - negtrack.tofNSigmaStoreEl(), - negtrack.tofNSigmaStorePi(), - negtrack.tofNSigmaStoreKa(), - negtrack.tofNSigmaStorePr(), - negtrack.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999., - -999.); - const int rowOfNegTrack = outputParts.lastIndex(); - int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; - outputParts(outputCollision.lastIndex(), - v0.pt(), - v0.eta(), - v0.phi(), - 0, // momentum - 0, // mass - -999., // D0mass - -999., // D0bar mass - -999., // D0 flag - -999., // D0bar flag - aod::femtoworldparticle::ParticleType::kV0, - cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), - 0, - v0.v0cosPA(col.posX(), col.posY(), col.posZ()), - indexChildID, - v0.mLambda(), - v0.mAntiLambda(), - postrack.sign(), - postrack.beta(), - postrack.itsChi2NCl(), - postrack.tpcChi2NCl(), - postrack.tpcNSigmaKa(), - postrack.tofNSigmaKa(), - (uint8_t)postrack.tpcNClsFound(), - postrack.tpcNClsFindable(), - (uint8_t)postrack.tpcNClsCrossedRows(), - postrack.tpcNClsShared(), - postrack.tpcInnerParam(), - postrack.itsNCls(), - postrack.itsNClsInnerBarrel(), - postrack.dcaXY(), - postrack.dcaZ(), - postrack.tpcSignal(), - postrack.tpcNSigmaStoreEl(), - postrack.tpcNSigmaStorePi(), - postrack.tpcNSigmaStoreKa(), - postrack.tpcNSigmaStorePr(), - postrack.tpcNSigmaStoreDe(), - postrack.tofNSigmaStoreEl(), - postrack.tofNSigmaStorePi(), - postrack.tofNSigmaStoreKa(), - postrack.tofNSigmaStorePr(), - postrack.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999., - -999.); - } + /// First thing to do is to check whether the basic event selection criteria are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(col.posZ(), col.multFV0M(), colCuts.computeSphericity(col, tracks), mMagField, col.centRun2V0M()); } + return; } - if (ConfStorePhi) { - for (auto& [p1, p2] : combinations(soa::CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { - if ((p1.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet) || (p2.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet)) { - continue; - } else if (p1.globalIndex() == p2.globalIndex()) { // checking not to correlate same particles - continue; - } else if ((p1.pt() < cfgPtLowPart1) || (p1.pt() > cfgPtHighPart1)) { // pT cuts for part1 - continue; - } else if ((p1.p() < cfgPLowPart1) || (p1.p() > cfgPHighPart1)) { // p cuts for part1 - continue; - } else if ((p1.eta() < cfgEtaLowPart1) || (p1.eta() > cfgEtaHighPart1)) { // eta cuts for part1 - continue; - } else if ((p2.pt() < cfgPtLowPart2) || (p2.pt() > cfgPtHighPart2)) { // pT cuts for part2 - continue; - } else if ((p2.p() < cfgPLowPart2) || (p2.p() > cfgPHighPart2)) { // p cuts for part2 - continue; - } else if ((p2.eta() < cfgEtaLowPart2) || (p2.eta() > cfgEtaHighPart2)) { // eta for part2 - continue; - } else if (!(IsKaonNSigma(p1.p(), p1.tpcNSigmaKa(), p1.tofNSigmaKa()))) { // PID for Kaons - continue; - } else if (!(IsKaonNSigma(p2.p(), p2.tpcNSigmaKa(), p2.tofNSigmaKa()))) { - continue; - } - - TLorentzVector part1Vec; - TLorentzVector part2Vec; - float mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartOne)->Mass(); - float mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartTwo)->Mass(); - part1Vec.SetPtEtaPhiM(p1.pt(), p1.eta(), p1.phi(), mMassOne); - part2Vec.SetPtEtaPhiM(p2.pt(), p2.eta(), p2.phi(), mMassTwo); + const auto vtxZ = col.posZ(); + const auto mult = col.multFV0M(); + const auto spher = colCuts.computeSphericity(col, tracks); + const auto centrality = col.centRun2V0M(); + colCuts.fillQA(col); - TLorentzVector sumVec(part1Vec); - sumVec += part2Vec; + outputCollision(vtxZ, mult, spher, mMagField, centrality); - float phiEta = sumVec.Eta(); - float phiPt = sumVec.Pt(); - float phiP = sumVec.P(); - float phiM = sumVec.M(); + int childIDs[2] = {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 - if (((phiM < ConfInvMassLowLimitPhi) || (phiM > ConfInvMassUpLimitPhi))) { - continue; + for (auto& track : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + track.p(), + 1, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kTrack, + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kCuts), + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), + childIDs, 0, 0, // początek nowej części + track.sign(), + track.beta(), + track.itsChi2NCl(), + track.tpcChi2NCl(), + track.tpcNSigmaKa(), + track.tofNSigmaKa(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaStoreEl(), + track.tpcNSigmaStorePi(), + track.tpcNSigmaStoreKa(), + track.tpcNSigmaStorePr(), + track.tpcNSigmaStoreDe(), + track.tofNSigmaStoreEl(), + track.tofNSigmaStorePi(), + track.tofNSigmaStoreKa(), + track.tofNSigmaStorePr(), + track.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + tmpIDtrack.push_back(track.globalIndex()); + } + + for (auto& v0 : fullV0s) { + auto postrack = v0.posTrack_as(); + auto negtrack = v0.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); + + if ((cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0) > 0) && (cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts) > 0) && (cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegCuts) > 0)) { + 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(), + 0, // v0.p(), + 0, // mass + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kV0Child, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0, + postrack.sign(), + postrack.beta(), + postrack.itsChi2NCl(), + postrack.tpcChi2NCl(), + postrack.tpcNSigmaKa(), + postrack.tofNSigmaKa(), + (uint8_t)postrack.tpcNClsFound(), + postrack.tpcNClsFindable(), + (uint8_t)postrack.tpcNClsCrossedRows(), + postrack.tpcNClsShared(), + postrack.tpcInnerParam(), + postrack.itsNCls(), + postrack.itsNClsInnerBarrel(), + postrack.dcaXY(), + postrack.dcaZ(), + postrack.tpcSignal(), + postrack.tpcNSigmaStoreEl(), + postrack.tpcNSigmaStorePi(), + postrack.tpcNSigmaStoreKa(), + postrack.tpcNSigmaStorePr(), + postrack.tpcNSigmaStoreDe(), + postrack.tofNSigmaStoreEl(), + postrack.tofNSigmaStorePi(), + postrack.tofNSigmaStoreKa(), + postrack.tofNSigmaStorePr(), + postrack.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + const int rowOfPosTrack = outputParts.lastIndex(); + 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(), + 0, // momentum + 0, // mass + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kV0Child, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegCuts), + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegPID), + 0., + childIDs, + 0, + 0, + negtrack.sign(), + negtrack.beta(), + negtrack.itsChi2NCl(), + negtrack.tpcChi2NCl(), + negtrack.tpcNSigmaKa(), + negtrack.tofNSigmaKa(), + (uint8_t)negtrack.tpcNClsFound(), + negtrack.tpcNClsFindable(), + (uint8_t)negtrack.tpcNClsCrossedRows(), + negtrack.tpcNClsShared(), + negtrack.tpcInnerParam(), + negtrack.itsNCls(), + negtrack.itsNClsInnerBarrel(), + negtrack.dcaXY(), + negtrack.dcaZ(), + negtrack.tpcSignal(), + negtrack.tpcNSigmaStoreEl(), + negtrack.tpcNSigmaStorePi(), + negtrack.tpcNSigmaStoreKa(), + negtrack.tpcNSigmaStorePr(), + negtrack.tpcNSigmaStoreDe(), + negtrack.tofNSigmaStoreEl(), + negtrack.tofNSigmaStorePi(), + negtrack.tofNSigmaStoreKa(), + negtrack.tofNSigmaStorePr(), + negtrack.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + const int rowOfNegTrack = outputParts.lastIndex(); + int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; + outputParts(outputCollision.lastIndex(), + v0.pt(), + v0.eta(), + v0.phi(), + 0, // momentum + 0, // mass + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kV0, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), + 0, + v0.v0cosPA(col.posX(), col.posY(), col.posZ()), + indexChildID, + v0.mLambda(), + v0.mAntiLambda(), + postrack.sign(), + postrack.beta(), + postrack.itsChi2NCl(), + postrack.tpcChi2NCl(), + postrack.tpcNSigmaKa(), + postrack.tofNSigmaKa(), + (uint8_t)postrack.tpcNClsFound(), + postrack.tpcNClsFindable(), + (uint8_t)postrack.tpcNClsCrossedRows(), + postrack.tpcNClsShared(), + postrack.tpcInnerParam(), + postrack.itsNCls(), + postrack.itsNClsInnerBarrel(), + postrack.dcaXY(), + postrack.dcaZ(), + postrack.tpcSignal(), + postrack.tpcNSigmaStoreEl(), + postrack.tpcNSigmaStorePi(), + postrack.tpcNSigmaStoreKa(), + postrack.tpcNSigmaStorePr(), + postrack.tpcNSigmaStoreDe(), + postrack.tofNSigmaStoreEl(), + postrack.tofNSigmaStorePi(), + postrack.tofNSigmaStoreKa(), + postrack.tofNSigmaStorePr(), + postrack.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + } + } + } + PROCESS_SWITCH(femtoWorldProducerTask, processProdTrackV0Run2, "Produce Femto tables", true); + + void processProdTrackPhiRun2(aod::FemtoFullCollisionRun2 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks, o2::aod::V0Datas const& fullV0s) + { + + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(col.posZ(), col.multFV0M(), colCuts.computeSphericity(col, tracks), mMagField, col.centRun2V0M()); + } + return; + } + + const auto vtxZ = col.posZ(); + const auto mult = col.multFV0M(); + const auto spher = colCuts.computeSphericity(col, tracks); + const auto centrality = col.centRun2V0M(); + colCuts.fillQA(col); + + outputCollision(vtxZ, mult, spher, mMagField, centrality); + + int childIDs[2] = {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 : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + track.p(), + 1, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kTrack, + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kCuts), + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), + childIDs, 0, 0, // początek nowej części + track.sign(), + track.beta(), + track.itsChi2NCl(), + track.tpcChi2NCl(), + track.tpcNSigmaKa(), + track.tofNSigmaKa(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaStoreEl(), + track.tpcNSigmaStorePi(), + track.tpcNSigmaStoreKa(), + track.tpcNSigmaStorePr(), + track.tpcNSigmaStoreDe(), + track.tofNSigmaStoreEl(), + track.tofNSigmaStorePi(), + track.tofNSigmaStoreKa(), + track.tofNSigmaStorePr(), + track.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + tmpIDtrack.push_back(track.globalIndex()); + } + + for (auto& [p1, p2] : combinations(soa::CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { + if ((p1.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet) || (p2.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet)) { + continue; + } else if (p1.globalIndex() == p2.globalIndex()) { // checking not to correlate same particles + continue; + } else if ((p1.pt() < cfgPtLowPart1) || (p1.pt() > cfgPtHighPart1)) { // pT cuts for part1 + continue; + } else if ((p1.p() < cfgPLowPart1) || (p1.p() > cfgPHighPart1)) { // p cuts for part1 + continue; + } else if ((p1.eta() < cfgEtaLowPart1) || (p1.eta() > cfgEtaHighPart1)) { // eta cuts for part1 + continue; + } else if ((p2.pt() < cfgPtLowPart2) || (p2.pt() > cfgPtHighPart2)) { // pT cuts for part2 + continue; + } else if ((p2.p() < cfgPLowPart2) || (p2.p() > cfgPHighPart2)) { // p cuts for part2 + continue; + } else if ((p2.eta() < cfgEtaLowPart2) || (p2.eta() > cfgEtaHighPart2)) { // eta for part2 + continue; + } else if (!(IsKaonNSigma(p1.p(), p1.tpcNSigmaKa(), p1.tofNSigmaKa()))) { // PID for Kaons + continue; + } else if (!(IsKaonNSigma(p2.p(), p2.tpcNSigmaKa(), p2.tofNSigmaKa()))) { + continue; + } + + TLorentzVector part1Vec; + TLorentzVector part2Vec; + float mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartOne)->Mass(); + float mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartTwo)->Mass(); + + part1Vec.SetPtEtaPhiM(p1.pt(), p1.eta(), p1.phi(), mMassOne); + part2Vec.SetPtEtaPhiM(p2.pt(), p2.eta(), p2.phi(), mMassTwo); + + TLorentzVector sumVec(part1Vec); + sumVec += part2Vec; + + float phiEta = sumVec.Eta(); + float phiPt = sumVec.Pt(); + float phiP = sumVec.P(); + float phiM = sumVec.M(); + + if (((phiM < ConfInvMassLowLimitPhi) || (phiM > ConfInvMassUpLimitPhi))) { + continue; + } + + PhiCuts.fillQA(col, p1, p1, p2); ///\todo fill QA also for daughters + auto cutContainerV0 = PhiCuts.getCutContainer(col, p1, p2); + if (true) { // temporary true value, we are doing simpler version first + int postrackID = p1.globalIndex(); + int rowInPrimaryTrackTablePos = -1; + rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); + childIDs[0] = rowInPrimaryTrackTablePos; + childIDs[1] = 0; + outputParts(outputCollision.lastIndex(), + p1.pt(), + p1.eta(), + p1.phi(), + p1.p(), + mMassOne, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kPhiChild, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0, + p1.sign(), + p1.beta(), + p1.itsChi2NCl(), + p1.tpcChi2NCl(), + p1.tpcNSigmaKa(), + p1.tofNSigmaKa(), + (uint8_t)p1.tpcNClsFound(), + p1.tpcNClsFindable(), + (uint8_t)p1.tpcNClsCrossedRows(), + p1.tpcNClsShared(), + p1.tpcInnerParam(), + p1.itsNCls(), + p1.itsNClsInnerBarrel(), + p1.dcaXY(), + p1.dcaZ(), + p1.tpcSignal(), + p1.tpcNSigmaStoreEl(), + p1.tpcNSigmaStorePi(), + p1.tpcNSigmaStoreKa(), + p1.tpcNSigmaStorePr(), + p1.tpcNSigmaStoreDe(), + p1.tofNSigmaStoreEl(), + p1.tofNSigmaStorePi(), + p1.tofNSigmaStoreKa(), + p1.tofNSigmaStorePr(), + p1.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + const int rowOfPosTrack = outputParts.lastIndex(); + int negtrackID = p2.globalIndex(); + int rowInPrimaryTrackTableNeg = -1; + rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); + childIDs[0] = 0; + childIDs[1] = rowInPrimaryTrackTableNeg; + outputParts(outputCollision.lastIndex(), + p2.pt(), + p2.eta(), + p2.phi(), + p2.p(), + mMassTwo, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kPhiChild, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegCuts), + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegPID), + 0., + childIDs, + 0, + 0, + p2.sign(), + p2.beta(), + p2.itsChi2NCl(), + p2.tpcChi2NCl(), + p2.tpcNSigmaKa(), + p2.tofNSigmaKa(), + (uint8_t)p2.tpcNClsFound(), + p2.tpcNClsFindable(), + (uint8_t)p2.tpcNClsCrossedRows(), + p2.tpcNClsShared(), + p2.tpcInnerParam(), + p2.itsNCls(), + p2.itsNClsInnerBarrel(), + p2.dcaXY(), + p2.dcaZ(), + p2.tpcSignal(), + p2.tpcNSigmaStoreEl(), + p2.tpcNSigmaStorePi(), + p2.tpcNSigmaStoreKa(), + p2.tpcNSigmaStorePr(), + p2.tpcNSigmaStoreDe(), + p2.tofNSigmaStoreEl(), + p2.tofNSigmaStorePi(), + p2.tofNSigmaStoreKa(), + p2.tofNSigmaStorePr(), + p2.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + + const int rowOfNegTrack = outputParts.lastIndex(); + int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; + float phiPhi = sumVec.Phi(); + if (sumVec.Phi() < 0) { + phiPhi = sumVec.Phi() + 2 * o2::constants::math::PI; + } else if (sumVec.Phi() >= 0) { + phiPhi = sumVec.Phi(); + } + outputParts(outputCollision.lastIndex(), + phiPt, + phiEta, + phiPhi, + phiP, + phiM, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kPhi, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), + 0, + 0, // p1.v0cosPA(col.posX(), col.posY(), col.posZ()), + indexChildID, + 0, // v0.mLambda(), + 0, // v0.mAntiLambda(), + p1.sign(), + p1.beta(), + p1.itsChi2NCl(), + p1.tpcChi2NCl(), + p1.tpcNSigmaKa(), + p1.tofNSigmaKa(), + (uint8_t)p1.tpcNClsFound(), + 0, // p1.tpcNClsFindable(), + 0, //(uint8_t)p1.tpcNClsCrossedRows(), + p1.tpcNClsShared(), + p1.tpcInnerParam(), + p1.itsNCls(), + p1.itsNClsInnerBarrel(), + 0, // p1.dcaXY(), + 0, // p1.dcaZ(), + p1.tpcSignal(), + p1.tpcNSigmaStoreEl(), + p1.tpcNSigmaStorePi(), + p1.tpcNSigmaStoreKa(), + p1.tpcNSigmaStorePr(), + p1.tpcNSigmaStoreDe(), + p1.tofNSigmaStoreEl(), + p1.tofNSigmaStorePi(), + p1.tofNSigmaStoreKa(), + p1.tofNSigmaStorePr(), + p1.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + } + } + } + PROCESS_SWITCH(femtoWorldProducerTask, processProdTrackPhiRun2, "Process data", false); + + void processProdTrackD0Run2(aod::FemtoFullCollisionRun2 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks, soa::Join const& candidates) + // void processCharmMesons(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(col.posZ(), col.multFV0M(), colCuts.computeSphericity(col, tracks), mMagField, col.centRun2V0M()); + } + return; + } + + const auto vtxZ = col.posZ(); + const auto mult = col.multFV0M(); + const auto spher = colCuts.computeSphericity(col, tracks); + const auto centrality = col.centRun2V0M(); + colCuts.fillQA(col); + + outputCollision(vtxZ, mult, spher, mMagField, centrality); + + int childIDs[2] = {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 + + /*int nTracks = 0; + if (col.numContrib() > 1) { + for (const auto& track : tracks) { + if (track.eta() < -4.0 || track.eta() > 4.0) { + continue; + } + if (std::abs(track.dcaXY()) > 0.0025 || std::abs(track.dcaZ()) > 0.0025) { + continue; + } + nTracks++; + } + }*/ + + for (const auto& track : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + track.p(), + 1, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kTrack, + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kCuts), + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), + childIDs, 0, 0, // początek nowej części + track.sign(), + track.beta(), + track.itsChi2NCl(), + track.tpcChi2NCl(), + track.tpcNSigmaKa(), + track.tofNSigmaKa(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaStoreEl(), + track.tpcNSigmaStorePi(), + track.tpcNSigmaStoreKa(), + track.tpcNSigmaStorePr(), + track.tpcNSigmaStoreDe(), + track.tofNSigmaStoreEl(), + track.tofNSigmaStorePi(), + track.tofNSigmaStoreKa(), + track.tofNSigmaStorePr(), + track.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + tmpIDtrack.push_back(track.globalIndex()); + } + + // loop over 2-prong candidates + for (auto& candidate : candidates) { // selectedD0Candidates + + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + continue; + } + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate)) > yCandMax) { + continue; + } + + // we retrieve also the event index from one of the daughters + auto posDauTrack = candidate.prong0_as(); // positive daughter + auto negDauTrack = candidate.prong1_as(); // negative daughter + + if ((candidate.isSelD0() >= selectionFlagD0) || (candidate.isSelD0bar() >= selectionFlagD0bar)) { // temporary true value, we are doing simpler version first + int postrackID = candidate.prong0Id(); + int rowInPrimaryTrackTablePos = -1; + rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); + childIDs[0] = rowInPrimaryTrackTablePos; + childIDs[1] = 0; + outputParts(outputCollision.lastIndex(), + candidate.ptProng0(), + -999., // eta + -999., // phi + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), // momentum + 0., // posDauTrack.m(), //general mass + -999., // D0mass + -999., // D0bar mass + candidate.isSelD0(), // D0 flag + candidate.isSelD0bar(), // D0bar flag + aod::femtoworldparticle::ParticleType::kD0D0barChild, + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0, + posDauTrack.sign(), + posDauTrack.beta(), + -999., // p1.itsChi2NCl(), + -999., // p1.tpcChi2NCl(), + -999., // p1.tpcNSigmaKa(), + -999., // p1.tofNSigmaKa(), + -999., //(uint8_t)p1.tpcNClsFound(), + -999., // p1.tpcNClsFindable(), + -999., //(uint8_t)p1.tpcNClsCrossedRows(), + -999., // p1.tpcNClsShared(), + -999., // p1.tpcInnerParam(), + -999., // p1.itsNCls(), + -999., // p1.itsNClsInnerBarrel(), + posDauTrack.dcaXY(), + posDauTrack.dcaZ(), + posDauTrack.tpcSignal(), + -999., // p1.tpcNSigmaStoreEl(), + -999., // candidate.prong0_as().tpcNSigmaPi(), //p1.tpcNSigmaStorePi(), + -999., // candidate.prong0_as().tpcNSigmaKa(), //p1.tpcNSigmaStoreKa(), + -999., // p1.tpcNSigmaStorePr(), + -999., // p1.tpcNSigmaStoreDe(), + -999., // p1.tofNSigmaStoreEl(), + -999., // candidate.prong0_as().tofNSigmaPi(), //p1.tofNSigmaStorePi(), + -999., // candidate.prong0_as().tofNSigmaKa(), //p1.tofNSigmaStoreKa(), + -999., // p1.tofNSigmaStorePr(), + -999., // p1.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + const int rowOfPosTrack = outputParts.lastIndex(); + int negtrackID = candidate.prong1Id(); + // int negtrackID = candidate.prong1().globalIndex(); + int rowInPrimaryTrackTableNeg = -1; + rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); + childIDs[0] = 0; + childIDs[1] = rowInPrimaryTrackTableNeg; + outputParts(outputCollision.lastIndex(), + candidate.ptProng1(), + 0., // negDauTrack.eta(), + 0., // negDauTrack.phi(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), // negDauTrack.p(), + 0., // negDauTrack.m(), + -999., // D0mass + -999., // D0bar mass + candidate.isSelD0(), // D0 flag + candidate.isSelD0bar(), // D0bar flag + aod::femtoworldparticle::ParticleType::kD0D0barChild, + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0, + negDauTrack.sign(), + negDauTrack.beta(), + -999., // negDauTrack.itsChi2NCl(), + -999., // negDauTrack.tpcChi2NCl(), + -999., // negDauTrack.tpcNSigmaKa(), + -999., // negDauTrack.tofNSigmaKa(), + -999., //(uint8_t)p1.tpcNClsFound(), + -999., // p1.tpcNClsFindable(), + -999., //(uint8_t)p1.tpcNClsCrossedRows(), + -999., // p1.tpcNClsShared(), + -999., // p1.tpcInnerParam(), + -999., // p1.itsNCls(), + -999., // p1.itsNClsInnerBarrel(), + negDauTrack.dcaXY(), + negDauTrack.dcaZ(), + negDauTrack.tpcSignal(), + -999., // p1.tpcNSigmaStoreEl(), + -999., // negDauTrack.tpcNSigmaStorePi(), + -999., // negDauTrack.tpcNSigmaStoreKa(), + -999., // p1.tpcNSigmaStorePr(), + -999., // p1.tpcNSigmaStoreDe(), + -999., // p1.tofNSigmaStoreEl(), + -999., // negDauTrack.tofNSigmaStorePi(), + -999., // negDauTrack.tofNSigmaStoreKa(), + -999., // p1.tofNSigmaStorePr(), + -999., // p1.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + + const int rowOfNegTrack = outputParts.lastIndex(); + int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; + outputParts(outputCollision.lastIndex(), + candidate.pt(), + candidate.eta(), + candidate.phi(), + candidate.p(), + 0., // general mass + hfHelper.invMassD0ToPiK(candidate), // D0mass + hfHelper.invMassD0barToKPi(candidate), // D0bar mass + candidate.isSelD0(), // D0 flag + candidate.isSelD0bar(), // D0bar flag + aod::femtoworldparticle::ParticleType::kD0D0bar, + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), + 0, + 0, // p1.v0cosPA(col.posX(), col.posY(), col.posZ()), + indexChildID, + -999, // v0.mLambda(), + -999, // v0.mAntiLambda(), + -999., // p1.sign(), + -999., // p1.beta(), + -999., // p1.itsChi2NCl(), + -999., // p1.tpcChi2NCl(), + -999., // p1.tpcNSigmaKa(), + -999., // p1.tofNSigmaKa(), + -999., //(uint8_t)p1.tpcNClsFound(), + -999., // p1.tpcNClsFindable(), + -999., //(uint8_t)p1.tpcNClsCrossedRows(), + -999., // p1.tpcNClsShared(), + -999., // p1.tpcInnerParam(), + -999., // p1.itsNCls(), + -999., // p1.itsNClsInnerBarrel(), + -999., // candidate.dcaXY(), + -999., // candidate.dcaZ(), + -999., // p1.tpcSignal(), + -999., // p1.tpcNSigmaStoreEl(), + -999., // p1.tpcNSigmaStorePi(), + -999., // p1.tpcNSigmaStoreKa(), + -999., // p1.tpcNSigmaStorePr(), + -999., // p1.tpcNSigmaStoreDe(), + -999., // p1.tofNSigmaStoreEl(), + -999., // p1.tofNSigmaStorePi(), + -999., // p1.tofNSigmaStoreKa(), + -999., // p1.tofNSigmaStorePr(), + -999., // p1.tofNSigmaStoreDe(), + -999., // daughDCA + candidate.decayLength(), + -999., + -999., + -999., + -999., + -999.); + } + } + } + PROCESS_SWITCH(femtoWorldProducerTask, processProdTrackD0Run2, "Process data", false); + + void processProdTrackRun3(aod::FemtoFullCollisionRun3 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(col.posZ(), col.multFV0M(), colCuts.computeSphericity(col, tracks), mMagField, col.centFT0M()); + } + return; + } + + const auto vtxZ = col.posZ(); + // const auto mult = col.multFV0M(); + const auto spher = colCuts.computeSphericity(col, tracks); + const auto centrality = col.centFT0M(); + colCuts.fillQA(col); + + outputCollision(vtxZ, col.multFT0M(), spher, mMagField, centrality); + + int childIDs[2] = {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 : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + track.p(), + 1, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kTrack, + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kCuts), + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), + childIDs, 0, 0, // początek nowej części + track.sign(), + track.beta(), + track.itsChi2NCl(), + track.tpcChi2NCl(), + track.tpcNSigmaKa(), + track.tofNSigmaKa(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaStoreEl(), + track.tpcNSigmaStorePi(), + track.tpcNSigmaStoreKa(), + track.tpcNSigmaStorePr(), + track.tpcNSigmaStoreDe(), + track.tofNSigmaStoreEl(), + track.tofNSigmaStorePi(), + track.tofNSigmaStoreKa(), + track.tofNSigmaStorePr(), + track.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + tmpIDtrack.push_back(track.globalIndex()); + } + } + PROCESS_SWITCH(femtoWorldProducerTask, processProdTrackRun3, "Produce Femto tables", true); + + void processProdTrackV0Run3(aod::FemtoFullCollisionRun3 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks, + o2::aod::V0Datas const& fullV0s) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(col.posZ(), col.multFV0M(), colCuts.computeSphericity(col, tracks), mMagField, col.centFT0M()); + } + return; + } + + const auto vtxZ = col.posZ(); + // const auto mult = col.multFV0M(); + const auto spher = colCuts.computeSphericity(col, tracks); + const auto centrality = col.centFT0M(); + colCuts.fillQA(col); + + outputCollision(vtxZ, col.multFT0M(), spher, mMagField, centrality); + + int childIDs[2] = {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 : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + track.p(), + 1, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kTrack, + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kCuts), + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), + childIDs, 0, 0, // początek nowej części + track.sign(), + track.beta(), + track.itsChi2NCl(), + track.tpcChi2NCl(), + track.tpcNSigmaKa(), + track.tofNSigmaKa(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaStoreEl(), + track.tpcNSigmaStorePi(), + track.tpcNSigmaStoreKa(), + track.tpcNSigmaStorePr(), + track.tpcNSigmaStoreDe(), + track.tofNSigmaStoreEl(), + track.tofNSigmaStorePi(), + track.tofNSigmaStoreKa(), + track.tofNSigmaStorePr(), + track.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + tmpIDtrack.push_back(track.globalIndex()); + } + + if (ConfStoreV0) { + for (auto& v0 : fullV0s) { + auto postrack = v0.posTrack_as(); + auto negtrack = v0.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; } - PhiCuts.fillQA(col, p1, p1, p2); ///\todo fill QA also for daughters - auto cutContainerV0 = PhiCuts.getCutContainer(col, p1, p2); - if (true) { // temporary true value, we are doing simpler version first - int postrackID = p1.globalIndex(); + 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); + + if ((cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0) > 0) && (cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts) > 0) && (cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegCuts) > 0)) { + int postrackID = v0.posTrackId(); int rowInPrimaryTrackTablePos = -1; rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); childIDs[0] = rowInPrimaryTrackTablePos; childIDs[1] = 0; outputParts(outputCollision.lastIndex(), - p1.pt(), - p1.eta(), - p1.phi(), - p1.p(), - mMassOne, + v0.positivept(), + v0.positiveeta(), + v0.positivephi(), + 0, // v0.p(), + 0, // mass -999., // D0mass -999., // D0bar mass -999., // D0 flag -999., // D0bar flag - aod::femtoworldparticle::ParticleType::kPhiChild, + aod::femtoworldparticle::ParticleType::kV0Child, cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), 0., childIDs, 0, 0, - p1.sign(), - p1.beta(), - p1.itsChi2NCl(), - p1.tpcChi2NCl(), - p1.tpcNSigmaKa(), - p1.tofNSigmaKa(), - (uint8_t)p1.tpcNClsFound(), - p1.tpcNClsFindable(), - (uint8_t)p1.tpcNClsCrossedRows(), - p1.tpcNClsShared(), - p1.tpcInnerParam(), - p1.itsNCls(), - p1.itsNClsInnerBarrel(), - p1.dcaXY(), - p1.dcaZ(), - p1.tpcSignal(), - p1.tpcNSigmaStoreEl(), - p1.tpcNSigmaStorePi(), - p1.tpcNSigmaStoreKa(), - p1.tpcNSigmaStorePr(), - p1.tpcNSigmaStoreDe(), - p1.tofNSigmaStoreEl(), - p1.tofNSigmaStorePi(), - p1.tofNSigmaStoreKa(), - p1.tofNSigmaStorePr(), - p1.tofNSigmaStoreDe(), + postrack.sign(), + postrack.beta(), + postrack.itsChi2NCl(), + postrack.tpcChi2NCl(), + postrack.tpcNSigmaKa(), + postrack.tofNSigmaKa(), + (uint8_t)postrack.tpcNClsFound(), + postrack.tpcNClsFindable(), + (uint8_t)postrack.tpcNClsCrossedRows(), + postrack.tpcNClsShared(), + postrack.tpcInnerParam(), + postrack.itsNCls(), + postrack.itsNClsInnerBarrel(), + postrack.dcaXY(), + postrack.dcaZ(), + postrack.tpcSignal(), + postrack.tpcNSigmaStoreEl(), + postrack.tpcNSigmaStorePi(), + postrack.tpcNSigmaStoreKa(), + postrack.tpcNSigmaStorePr(), + postrack.tpcNSigmaStoreDe(), + postrack.tofNSigmaStoreEl(), + postrack.tofNSigmaStorePi(), + postrack.tofNSigmaStoreKa(), + postrack.tofNSigmaStorePr(), + postrack.tofNSigmaStoreDe(), -999., -999., -999., @@ -804,250 +1578,54 @@ struct femtoWorldProducerTask { -999., -999.); const int rowOfPosTrack = outputParts.lastIndex(); - int negtrackID = p2.globalIndex(); + int negtrackID = v0.negTrackId(); int rowInPrimaryTrackTableNeg = -1; rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); childIDs[0] = 0; childIDs[1] = rowInPrimaryTrackTableNeg; outputParts(outputCollision.lastIndex(), - p2.pt(), - p2.eta(), - p2.phi(), - p2.p(), - mMassTwo, + v0.negativept(), + v0.negativeeta(), + v0.negativephi(), + 0, // momentum + 0, // mass -999., // D0mass -999., // D0bar mass -999., // D0 flag -999., // D0bar flag - aod::femtoworldparticle::ParticleType::kPhiChild, + aod::femtoworldparticle::ParticleType::kV0Child, cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegCuts), cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegPID), 0., childIDs, 0, 0, - p2.sign(), - p2.beta(), - p2.itsChi2NCl(), - p2.tpcChi2NCl(), - p2.tpcNSigmaKa(), - p2.tofNSigmaKa(), - (uint8_t)p2.tpcNClsFound(), - p2.tpcNClsFindable(), - (uint8_t)p2.tpcNClsCrossedRows(), - p2.tpcNClsShared(), - p2.tpcInnerParam(), - p2.itsNCls(), - p2.itsNClsInnerBarrel(), - p2.dcaXY(), - p2.dcaZ(), - p2.tpcSignal(), - p2.tpcNSigmaStoreEl(), - p2.tpcNSigmaStorePi(), - p2.tpcNSigmaStoreKa(), - p2.tpcNSigmaStorePr(), - p2.tpcNSigmaStoreDe(), - p2.tofNSigmaStoreEl(), - p2.tofNSigmaStorePi(), - p2.tofNSigmaStoreKa(), - p2.tofNSigmaStorePr(), - p2.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999., - -999.); - - const int rowOfNegTrack = outputParts.lastIndex(); - int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; - float phiPhi = sumVec.Phi(); - if (sumVec.Phi() < 0) { - phiPhi = sumVec.Phi() + 2 * o2::constants::math::PI; - } else if (sumVec.Phi() >= 0) { - phiPhi = sumVec.Phi(); - } - outputParts(outputCollision.lastIndex(), - phiPt, - phiEta, - phiPhi, - phiP, - phiM, - -999., // D0mass - -999., // D0bar mass - -999., // D0 flag - -999., // D0bar flag - aod::femtoworldparticle::ParticleType::kPhi, - cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), - 0, - 0, // p1.v0cosPA(col.posX(), col.posY(), col.posZ()), - indexChildID, - 0, // v0.mLambda(), - 0, // v0.mAntiLambda(), - p1.sign(), - p1.beta(), - p1.itsChi2NCl(), - p1.tpcChi2NCl(), - p1.tpcNSigmaKa(), - p1.tofNSigmaKa(), - (uint8_t)p1.tpcNClsFound(), - 0, // p1.tpcNClsFindable(), - 0, //(uint8_t)p1.tpcNClsCrossedRows(), - p1.tpcNClsShared(), - p1.tpcInnerParam(), - p1.itsNCls(), - p1.itsNClsInnerBarrel(), - 0, // p1.dcaXY(), - 0, // p1.dcaZ(), - p1.tpcSignal(), - p1.tpcNSigmaStoreEl(), - p1.tpcNSigmaStorePi(), - p1.tpcNSigmaStoreKa(), - p1.tpcNSigmaStorePr(), - p1.tpcNSigmaStoreDe(), - p1.tofNSigmaStoreEl(), - p1.tofNSigmaStorePi(), - p1.tofNSigmaStoreKa(), - p1.tofNSigmaStorePr(), - p1.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999., - -999.); - } - } - } - if (ConfStoreD0D0bar) { - - // loop over 2-prong candidates - for (auto& candidate : candidates) { // selectedD0Candidates - - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { - continue; - } - if (yCandMax >= 0. && std::abs(yD0(candidate)) > yCandMax) { - continue; - } - - auto invMassD0 = invMassD0ToPiK(candidate); - auto invMassD0bar = invMassD0barToKPi(candidate); - - // we retrieve also the event index from one of the daughters - auto posDauTrack = candidate.prong0_as(); // positive daughter - auto negDauTrack = candidate.prong1_as(); // negative daughter - // candidate.prong1_as().tofNSigmaPi() - // candidate.prong1_as().tofNSigmaKa() - - if ((candidate.isSelD0() == 1) || (candidate.isSelD0bar() == 1)) { // temporary true value, we are doing simpler version first - int postrackID = candidate.prong0Id(); - int rowInPrimaryTrackTablePos = -1; - rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); - childIDs[0] = rowInPrimaryTrackTablePos; - childIDs[1] = 0; - outputParts(outputCollision.lastIndex(), - candidate.ptProng0(), - -999., // eta - -999., // phi - RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), // momentum - 0., // posDauTrack.m(), //general mass - -999., // D0mass - -999., // D0bar mass - candidate.isSelD0(), // D0 flag - candidate.isSelD0bar(), // D0bar flag - aod::femtoworldparticle::ParticleType::kD0D0barChild, - 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), - 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), - 0., - childIDs, - 0, - 0, - posDauTrack.sign(), - posDauTrack.beta(), - -999., // p1.itsChi2NCl(), - -999., // p1.tpcChi2NCl(), - -999., // p1.tpcNSigmaKa(), - -999., // p1.tofNSigmaKa(), - -999., //(uint8_t)p1.tpcNClsFound(), - -999., // p1.tpcNClsFindable(), - -999., //(uint8_t)p1.tpcNClsCrossedRows(), - -999., // p1.tpcNClsShared(), - -999., // p1.tpcInnerParam(), - -999., // p1.itsNCls(), - -999., // p1.itsNClsInnerBarrel(), - posDauTrack.dcaXY(), - posDauTrack.dcaZ(), - posDauTrack.tpcSignal(), - -999., // p1.tpcNSigmaStoreEl(), - -999., // candidate.prong0_as().tpcNSigmaPi(), //p1.tpcNSigmaStorePi(), - -999., // candidate.prong0_as().tpcNSigmaKa(), //p1.tpcNSigmaStoreKa(), - -999., // p1.tpcNSigmaStorePr(), - -999., // p1.tpcNSigmaStoreDe(), - -999., // p1.tofNSigmaStoreEl(), - -999., // candidate.prong0_as().tofNSigmaPi(), //p1.tofNSigmaStorePi(), - -999., // candidate.prong0_as().tofNSigmaKa(), //p1.tofNSigmaStoreKa(), - -999., // p1.tofNSigmaStorePr(), - -999., // p1.tofNSigmaStoreDe(), - -999., - -999., - -999., - -999., - -999., - -999., - -999.); - const int rowOfPosTrack = outputParts.lastIndex(); - int negtrackID = candidate.prong1Id(); - // int negtrackID = candidate.prong1().globalIndex(); - int rowInPrimaryTrackTableNeg = -1; - rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); - childIDs[0] = 0; - childIDs[1] = rowInPrimaryTrackTableNeg; - outputParts(outputCollision.lastIndex(), - candidate.ptProng1(), - 0., // negDauTrack.eta(), - 0., // negDauTrack.phi(), - RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), // negDauTrack.p(), - 0., // negDauTrack.m(), - -999., // D0mass - -999., // D0bar mass - candidate.isSelD0(), // D0 flag - candidate.isSelD0bar(), // D0bar flag - aod::femtoworldparticle::ParticleType::kD0D0barChild, - 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), - 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), - 0., - childIDs, - 0, - 0, - negDauTrack.sign(), - negDauTrack.beta(), - -999., // negDauTrack.itsChi2NCl(), - -999., // negDauTrack.tpcChi2NCl(), - -999., // negDauTrack.tpcNSigmaKa(), - -999., // negDauTrack.tofNSigmaKa(), - -999., //(uint8_t)p1.tpcNClsFound(), - -999., // p1.tpcNClsFindable(), - -999., //(uint8_t)p1.tpcNClsCrossedRows(), - -999., // p1.tpcNClsShared(), - -999., // p1.tpcInnerParam(), - -999., // p1.itsNCls(), - -999., // p1.itsNClsInnerBarrel(), - negDauTrack.dcaXY(), - negDauTrack.dcaZ(), - negDauTrack.tpcSignal(), - -999., // p1.tpcNSigmaStoreEl(), - -999., // negDauTrack.tpcNSigmaStorePi(), - -999., // negDauTrack.tpcNSigmaStoreKa(), - -999., // p1.tpcNSigmaStorePr(), - -999., // p1.tpcNSigmaStoreDe(), - -999., // p1.tofNSigmaStoreEl(), - -999., // negDauTrack.tofNSigmaStorePi(), - -999., // negDauTrack.tofNSigmaStoreKa(), - -999., // p1.tofNSigmaStorePr(), - -999., // p1.tofNSigmaStoreDe(), + negtrack.sign(), + negtrack.beta(), + negtrack.itsChi2NCl(), + negtrack.tpcChi2NCl(), + negtrack.tpcNSigmaKa(), + negtrack.tofNSigmaKa(), + (uint8_t)negtrack.tpcNClsFound(), + negtrack.tpcNClsFindable(), + (uint8_t)negtrack.tpcNClsCrossedRows(), + negtrack.tpcNClsShared(), + negtrack.tpcInnerParam(), + negtrack.itsNCls(), + negtrack.itsNClsInnerBarrel(), + negtrack.dcaXY(), + negtrack.dcaZ(), + negtrack.tpcSignal(), + negtrack.tpcNSigmaStoreEl(), + negtrack.tpcNSigmaStorePi(), + negtrack.tpcNSigmaStoreKa(), + negtrack.tpcNSigmaStorePr(), + negtrack.tpcNSigmaStoreDe(), + negtrack.tofNSigmaStoreEl(), + negtrack.tofNSigmaStorePi(), + negtrack.tofNSigmaStoreKa(), + negtrack.tofNSigmaStorePr(), + negtrack.tofNSigmaStoreDe(), -999., -999., -999., @@ -1055,54 +1633,53 @@ struct femtoWorldProducerTask { -999., -999., -999.); - const int rowOfNegTrack = outputParts.lastIndex(); int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; outputParts(outputCollision.lastIndex(), - candidate.pt(), - candidate.eta(), - candidate.phi(), - candidate.p(), - 0., // general mass - invMassD0, // D0mass - invMassD0bar, // D0bar mass - candidate.isSelD0(), // D0 flag - candidate.isSelD0bar(), // D0bar flag - aod::femtoworldparticle::ParticleType::kD0D0bar, - 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), + v0.pt(), + v0.eta(), + v0.phi(), + 0, // momentum + 0, // mass + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kV0, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), 0, - 0, // p1.v0cosPA(col.posX(), col.posY(), col.posZ()), + v0.v0cosPA(col.posX(), col.posY(), col.posZ()), indexChildID, - -999, // v0.mLambda(), - -999, // v0.mAntiLambda(), - -999., // p1.sign(), - -999., // p1.beta(), - -999., // p1.itsChi2NCl(), - -999., // p1.tpcChi2NCl(), - -999., // p1.tpcNSigmaKa(), - -999., // p1.tofNSigmaKa(), - -999., //(uint8_t)p1.tpcNClsFound(), - -999., // p1.tpcNClsFindable(), - -999., //(uint8_t)p1.tpcNClsCrossedRows(), - -999., // p1.tpcNClsShared(), - -999., // p1.tpcInnerParam(), - -999., // p1.itsNCls(), - -999., // p1.itsNClsInnerBarrel(), - -999., // candidate.dcaXY(), - -999., // candidate.dcaZ(), - -999., // p1.tpcSignal(), - -999., // p1.tpcNSigmaStoreEl(), - -999., // p1.tpcNSigmaStorePi(), - -999., // p1.tpcNSigmaStoreKa(), - -999., // p1.tpcNSigmaStorePr(), - -999., // p1.tpcNSigmaStoreDe(), - -999., // p1.tofNSigmaStoreEl(), - -999., // p1.tofNSigmaStorePi(), - -999., // p1.tofNSigmaStoreKa(), - -999., // p1.tofNSigmaStorePr(), - -999., // p1.tofNSigmaStoreDe(), - -999., // daughDCA - candidate.decayLength(), + v0.mLambda(), + v0.mAntiLambda(), + postrack.sign(), + postrack.beta(), + postrack.itsChi2NCl(), + postrack.tpcChi2NCl(), + postrack.tpcNSigmaKa(), + postrack.tofNSigmaKa(), + (uint8_t)postrack.tpcNClsFound(), + postrack.tpcNClsFindable(), + (uint8_t)postrack.tpcNClsCrossedRows(), + postrack.tpcNClsShared(), + postrack.tpcInnerParam(), + postrack.itsNCls(), + postrack.itsNClsInnerBarrel(), + postrack.dcaXY(), + postrack.dcaZ(), + postrack.tpcSignal(), + postrack.tpcNSigmaStoreEl(), + postrack.tpcNSigmaStorePi(), + postrack.tpcNSigmaStoreKa(), + postrack.tpcNSigmaStorePr(), + postrack.tpcNSigmaStoreDe(), + postrack.tofNSigmaStoreEl(), + postrack.tofNSigmaStorePi(), + postrack.tofNSigmaStoreKa(), + postrack.tofNSigmaStorePr(), + postrack.tofNSigmaStoreDe(), + -999., + -999., -999., -999., -999., @@ -1112,7 +1689,589 @@ struct femtoWorldProducerTask { } } } - PROCESS_SWITCH(femtoWorldProducerTask, processProd, "Produce Femto tables", true); + PROCESS_SWITCH(femtoWorldProducerTask, processProdTrackV0Run3, "Produce Femto tables", true); + + void processProdTrackPhiRun3(aod::FemtoFullCollisionRun3 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks, o2::aod::V0Datas const& fullV0s) + { + + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(col.posZ(), col.multFV0M(), colCuts.computeSphericity(col, tracks), mMagField, col.centFT0M()); + } + return; + } + + const auto vtxZ = col.posZ(); + // const auto mult = col.multFV0M(); + const auto spher = colCuts.computeSphericity(col, tracks); + const auto centrality = col.centFT0M(); + colCuts.fillQA(col); + + outputCollision(vtxZ, col.multFT0M(), spher, mMagField, centrality); + + int childIDs[2] = {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 : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + track.p(), + 1, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kTrack, + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kCuts), + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), + childIDs, 0, 0, // początek nowej części + track.sign(), + track.beta(), + track.itsChi2NCl(), + track.tpcChi2NCl(), + track.tpcNSigmaKa(), + track.tofNSigmaKa(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaStoreEl(), + track.tpcNSigmaStorePi(), + track.tpcNSigmaStoreKa(), + track.tpcNSigmaStorePr(), + track.tpcNSigmaStoreDe(), + track.tofNSigmaStoreEl(), + track.tofNSigmaStorePi(), + track.tofNSigmaStoreKa(), + track.tofNSigmaStorePr(), + track.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + tmpIDtrack.push_back(track.globalIndex()); + } + + for (auto& [p1, p2] : combinations(soa::CombinationsStrictlyUpperIndexPolicy(tracks, tracks))) { + if ((p1.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet) || (p2.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet)) { + continue; + } else if (p1.globalIndex() == p2.globalIndex()) { // checking not to correlate same particles + continue; + } else if ((p1.pt() < cfgPtLowPart1) || (p1.pt() > cfgPtHighPart1)) { // pT cuts for part1 + continue; + } else if ((p1.p() < cfgPLowPart1) || (p1.p() > cfgPHighPart1)) { // p cuts for part1 + continue; + } else if ((p1.eta() < cfgEtaLowPart1) || (p1.eta() > cfgEtaHighPart1)) { // eta cuts for part1 + continue; + } else if ((p2.pt() < cfgPtLowPart2) || (p2.pt() > cfgPtHighPart2)) { // pT cuts for part2 + continue; + } else if ((p2.p() < cfgPLowPart2) || (p2.p() > cfgPHighPart2)) { // p cuts for part2 + continue; + } else if ((p2.eta() < cfgEtaLowPart2) || (p2.eta() > cfgEtaHighPart2)) { // eta for part2 + continue; + } else if (!(IsKaonNSigma(p1.p(), p1.tpcNSigmaKa(), p1.tofNSigmaKa()))) { // PID for Kaons + continue; + } else if (!(IsKaonNSigma(p2.p(), p2.tpcNSigmaKa(), p2.tofNSigmaKa()))) { + continue; + } + + TLorentzVector part1Vec; + TLorentzVector part2Vec; + float mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartOne)->Mass(); + float mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePartTwo)->Mass(); + + part1Vec.SetPtEtaPhiM(p1.pt(), p1.eta(), p1.phi(), mMassOne); + part2Vec.SetPtEtaPhiM(p2.pt(), p2.eta(), p2.phi(), mMassTwo); + + TLorentzVector sumVec(part1Vec); + sumVec += part2Vec; + + float phiEta = sumVec.Eta(); + float phiPt = sumVec.Pt(); + float phiP = sumVec.P(); + float phiM = sumVec.M(); + + if (((phiM < ConfInvMassLowLimitPhi) || (phiM > ConfInvMassUpLimitPhi))) { + continue; + } + + PhiCuts.fillQA(col, p1, p1, p2); ///\todo fill QA also for daughters + auto cutContainerV0 = PhiCuts.getCutContainer(col, p1, p2); + if (true) { // temporary true value, we are doing simpler version first + int postrackID = p1.globalIndex(); + int rowInPrimaryTrackTablePos = -1; + rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); + childIDs[0] = rowInPrimaryTrackTablePos; + childIDs[1] = 0; + outputParts(outputCollision.lastIndex(), + p1.pt(), + p1.eta(), + p1.phi(), + p1.p(), + mMassOne, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kPhiChild, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0, + p1.sign(), + p1.beta(), + p1.itsChi2NCl(), + p1.tpcChi2NCl(), + p1.tpcNSigmaKa(), + p1.tofNSigmaKa(), + (uint8_t)p1.tpcNClsFound(), + p1.tpcNClsFindable(), + (uint8_t)p1.tpcNClsCrossedRows(), + p1.tpcNClsShared(), + p1.tpcInnerParam(), + p1.itsNCls(), + p1.itsNClsInnerBarrel(), + p1.dcaXY(), + p1.dcaZ(), + p1.tpcSignal(), + p1.tpcNSigmaStoreEl(), + p1.tpcNSigmaStorePi(), + p1.tpcNSigmaStoreKa(), + p1.tpcNSigmaStorePr(), + p1.tpcNSigmaStoreDe(), + p1.tofNSigmaStoreEl(), + p1.tofNSigmaStorePi(), + p1.tofNSigmaStoreKa(), + p1.tofNSigmaStorePr(), + p1.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + const int rowOfPosTrack = outputParts.lastIndex(); + int negtrackID = p2.globalIndex(); + int rowInPrimaryTrackTableNeg = -1; + rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); + childIDs[0] = 0; + childIDs[1] = rowInPrimaryTrackTableNeg; + outputParts(outputCollision.lastIndex(), + p2.pt(), + p2.eta(), + p2.phi(), + p2.p(), + mMassTwo, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kPhiChild, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegCuts), + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kNegPID), + 0., + childIDs, + 0, + 0, + p2.sign(), + p2.beta(), + p2.itsChi2NCl(), + p2.tpcChi2NCl(), + p2.tpcNSigmaKa(), + p2.tofNSigmaKa(), + (uint8_t)p2.tpcNClsFound(), + p2.tpcNClsFindable(), + (uint8_t)p2.tpcNClsCrossedRows(), + p2.tpcNClsShared(), + p2.tpcInnerParam(), + p2.itsNCls(), + p2.itsNClsInnerBarrel(), + p2.dcaXY(), + p2.dcaZ(), + p2.tpcSignal(), + p2.tpcNSigmaStoreEl(), + p2.tpcNSigmaStorePi(), + p2.tpcNSigmaStoreKa(), + p2.tpcNSigmaStorePr(), + p2.tpcNSigmaStoreDe(), + p2.tofNSigmaStoreEl(), + p2.tofNSigmaStorePi(), + p2.tofNSigmaStoreKa(), + p2.tofNSigmaStorePr(), + p2.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + + const int rowOfNegTrack = outputParts.lastIndex(); + int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; + float phiPhi = sumVec.Phi(); + if (sumVec.Phi() < 0) { + phiPhi = sumVec.Phi() + 2 * o2::constants::math::PI; + } else if (sumVec.Phi() >= 0) { + phiPhi = sumVec.Phi(); + } + outputParts(outputCollision.lastIndex(), + phiPt, + phiEta, + phiPhi, + phiP, + phiM, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kPhi, + cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), + 0, + 0, // p1.v0cosPA(col.posX(), col.posY(), col.posZ()), + indexChildID, + 0, // v0.mLambda(), + 0, // v0.mAntiLambda(), + p1.sign(), + p1.beta(), + p1.itsChi2NCl(), + p1.tpcChi2NCl(), + p1.tpcNSigmaKa(), + p1.tofNSigmaKa(), + (uint8_t)p1.tpcNClsFound(), + 0, // p1.tpcNClsFindable(), + 0, //(uint8_t)p1.tpcNClsCrossedRows(), + p1.tpcNClsShared(), + p1.tpcInnerParam(), + p1.itsNCls(), + p1.itsNClsInnerBarrel(), + 0, // p1.dcaXY(), + 0, // p1.dcaZ(), + p1.tpcSignal(), + p1.tpcNSigmaStoreEl(), + p1.tpcNSigmaStorePi(), + p1.tpcNSigmaStoreKa(), + p1.tpcNSigmaStorePr(), + p1.tpcNSigmaStoreDe(), + p1.tofNSigmaStoreEl(), + p1.tofNSigmaStorePi(), + p1.tofNSigmaStoreKa(), + p1.tofNSigmaStorePr(), + p1.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + } + } + } + PROCESS_SWITCH(femtoWorldProducerTask, processProdTrackPhiRun3, "Process data", false); + + void processProdTrackD0Run3(aod::FemtoFullCollisionRun3 const& col, aod::BCsWithTimestamps const&, aod::FemtoFullTracks const& tracks, soa::Join const& candidates) + // void processCharmMesons(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates) + { + + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + /// First thing to do is to check whether the basic event selection criteria are fulfilled + // If the basic selection is NOT fulfilled: + // in case of skimming run - don't store such collisions + // in case of trigger run - store such collisions but don't store any particle candidates for such collisions + if (!colCuts.isSelected(col)) { + if (ConfIsTrigger) { + outputCollision(col.posZ(), col.multFT0M(), colCuts.computeSphericity(col, tracks), mMagField, col.centFT0M()); + } + return; + } + + const auto vtxZ = col.posZ(); + // const auto mult = collision.multFV0M(); + const auto spher = colCuts.computeSphericity(col, tracks); + const auto centrality = col.centFT0M(); + colCuts.fillQA(col); + + outputCollision(vtxZ, col.multFT0M(), spher, mMagField, centrality); + + int childIDs[2] = {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 (const auto& track : tracks) { + /// if the most open selection criteria are not fulfilled there is no point looking further at the track + if (!trackCuts.isSelectedMinimal(track)) { + continue; + } + trackCuts.fillQA(track); + // the bit-wise container of the systematic variations is obtained + // now the table is filled + outputParts(outputCollision.lastIndex(), + track.pt(), + track.eta(), + track.phi(), + track.p(), + 1, + -999., // D0mass + -999., // D0bar mass + -999., // D0 flag + -999., // D0bar flag + aod::femtoworldparticle::ParticleType::kTrack, + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kCuts), + 0, // cutContainer.at(femtoWorldTrackSelection::TrackContainerPosition::kPID), + track.dcaXY(), + childIDs, 0, 0, // początek nowej części + track.sign(), + track.beta(), + track.itsChi2NCl(), + track.tpcChi2NCl(), + track.tpcNSigmaKa(), + track.tofNSigmaKa(), + (uint8_t)track.tpcNClsFound(), + track.tpcNClsFindable(), + (uint8_t)track.tpcNClsCrossedRows(), + track.tpcNClsShared(), + track.tpcInnerParam(), + track.itsNCls(), + track.itsNClsInnerBarrel(), + track.dcaXY(), + track.dcaZ(), + track.tpcSignal(), + track.tpcNSigmaStoreEl(), + track.tpcNSigmaStorePi(), + track.tpcNSigmaStoreKa(), + track.tpcNSigmaStorePr(), + track.tpcNSigmaStoreDe(), + track.tofNSigmaStoreEl(), + track.tofNSigmaStorePi(), + track.tofNSigmaStoreKa(), + track.tofNSigmaStorePr(), + track.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + tmpIDtrack.push_back(track.globalIndex()); + } + + // loop over 2-prong candidates + for (const auto& candidate : candidates) { // selectedD0Candidates + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + continue; + } + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate)) > yCandMax) { + continue; + } + + // we retrieve also the event index from one of the daughters + auto posDauTrack = candidate.prong0_as(); // positive daughter + auto negDauTrack = candidate.prong1_as(); // negative daughter + // candidate.prong1_as().tofNSigmaPi() + // candidate.prong1_as().tofNSigmaKa() + + if ((candidate.isSelD0() == 1) || (candidate.isSelD0bar() == 1)) { // temporary true value, we are doing simpler version first + int postrackID = candidate.prong0Id(); + int rowInPrimaryTrackTablePos = -1; + rowInPrimaryTrackTablePos = getRowDaughters(postrackID, tmpIDtrack); + childIDs[0] = rowInPrimaryTrackTablePos; + childIDs[1] = 0; + outputParts(outputCollision.lastIndex(), + candidate.ptProng0(), + -999., // eta + -999., // phi + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), // momentum + 0., // posDauTrack.m(), //general mass + -999., // D0mass + -999., // D0bar mass + candidate.isSelD0(), // D0 flag + candidate.isSelD0bar(), // D0bar flag + aod::femtoworldparticle::ParticleType::kD0D0barChild, + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0, + posDauTrack.sign(), + posDauTrack.beta(), + -999., // p1.itsChi2NCl(), + -999., // p1.tpcChi2NCl(), + -999., // p1.tpcNSigmaKa(), + -999., // p1.tofNSigmaKa(), + -999., //(uint8_t)p1.tpcNClsFound(), + -999., // p1.tpcNClsFindable(), + -999., //(uint8_t)p1.tpcNClsCrossedRows(), + -999., // p1.tpcNClsShared(), + -999., // p1.tpcInnerParam(), + -999., // p1.itsNCls(), + -999., // p1.itsNClsInnerBarrel(), + posDauTrack.dcaXY(), + posDauTrack.dcaZ(), + posDauTrack.tpcSignal(), + -999., // p1.tpcNSigmaStoreEl(), + -999., // candidate.prong0_as().tpcNSigmaPi(), //p1.tpcNSigmaStorePi(), + -999., // candidate.prong0_as().tpcNSigmaKa(), //p1.tpcNSigmaStoreKa(), + -999., // p1.tpcNSigmaStorePr(), + -999., // p1.tpcNSigmaStoreDe(), + -999., // p1.tofNSigmaStoreEl(), + -999., // candidate.prong0_as().tofNSigmaPi(), //p1.tofNSigmaStorePi(), + -999., // candidate.prong0_as().tofNSigmaKa(), //p1.tofNSigmaStoreKa(), + -999., // p1.tofNSigmaStorePr(), + -999., // p1.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + const int rowOfPosTrack = outputParts.lastIndex(); + int negtrackID = candidate.prong1Id(); + // int negtrackID = candidate.prong1().globalIndex(); + int rowInPrimaryTrackTableNeg = -1; + rowInPrimaryTrackTableNeg = getRowDaughters(negtrackID, tmpIDtrack); + childIDs[0] = 0; + childIDs[1] = rowInPrimaryTrackTableNeg; + outputParts(outputCollision.lastIndex(), + candidate.ptProng1(), + 0., // negDauTrack.eta(), + 0., // negDauTrack.phi(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), // negDauTrack.p(), + 0., // negDauTrack.m(), + -999., // D0mass + -999., // D0bar mass + candidate.isSelD0(), // D0 flag + candidate.isSelD0bar(), // D0bar flag + aod::femtoworldparticle::ParticleType::kD0D0barChild, + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosCuts), + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kPosPID), + 0., + childIDs, + 0, + 0, + negDauTrack.sign(), + negDauTrack.beta(), + -999., // negDauTrack.itsChi2NCl(), + -999., // negDauTrack.tpcChi2NCl(), + -999., // negDauTrack.tpcNSigmaKa(), + -999., // negDauTrack.tofNSigmaKa(), + -999., //(uint8_t)p1.tpcNClsFound(), + -999., // p1.tpcNClsFindable(), + -999., //(uint8_t)p1.tpcNClsCrossedRows(), + -999., // p1.tpcNClsShared(), + -999., // p1.tpcInnerParam(), + -999., // p1.itsNCls(), + -999., // p1.itsNClsInnerBarrel(), + negDauTrack.dcaXY(), + negDauTrack.dcaZ(), + negDauTrack.tpcSignal(), + -999., // p1.tpcNSigmaStoreEl(), + -999., // negDauTrack.tpcNSigmaStorePi(), + -999., // negDauTrack.tpcNSigmaStoreKa(), + -999., // p1.tpcNSigmaStorePr(), + -999., // p1.tpcNSigmaStoreDe(), + -999., // p1.tofNSigmaStoreEl(), + -999., // negDauTrack.tofNSigmaStorePi(), + -999., // negDauTrack.tofNSigmaStoreKa(), + -999., // p1.tofNSigmaStorePr(), + -999., // p1.tofNSigmaStoreDe(), + -999., + -999., + -999., + -999., + -999., + -999., + -999.); + + const int rowOfNegTrack = outputParts.lastIndex(); + int indexChildID[2] = {rowOfPosTrack, rowOfNegTrack}; + outputParts(outputCollision.lastIndex(), + candidate.pt(), + candidate.eta(), + candidate.phi(), + candidate.p(), + 0., // general mass + hfHelper.invMassD0ToPiK(candidate), // D0mass + hfHelper.invMassD0barToKPi(candidate), // D0bar mass + candidate.isSelD0(), // D0 flag + candidate.isSelD0bar(), // D0bar flag + aod::femtoworldparticle::ParticleType::kD0D0bar, + 0., // cutContainerV0.at(femtoWorldV0Selection::V0ContainerPosition::kV0), + 0, + 0, // p1.v0cosPA(col.posX(), col.posY(), col.posZ()), + indexChildID, + -999, // v0.mLambda(), + -999, // v0.mAntiLambda(), + -999., // p1.sign(), + -999., // p1.beta(), + -999., // p1.itsChi2NCl(), + -999., // p1.tpcChi2NCl(), + -999., // p1.tpcNSigmaKa(), + -999., // p1.tofNSigmaKa(), + -999., //(uint8_t)p1.tpcNClsFound(), + -999., // p1.tpcNClsFindable(), + -999., //(uint8_t)p1.tpcNClsCrossedRows(), + -999., // p1.tpcNClsShared(), + -999., // p1.tpcInnerParam(), + -999., // p1.itsNCls(), + -999., // p1.itsNClsInnerBarrel(), + -999., // candidate.dcaXY(), + -999., // candidate.dcaZ(), + -999., // p1.tpcSignal(), + -999., // p1.tpcNSigmaStoreEl(), + -999., // p1.tpcNSigmaStorePi(), + -999., // p1.tpcNSigmaStoreKa(), + -999., // p1.tpcNSigmaStorePr(), + -999., // p1.tpcNSigmaStoreDe(), + -999., // p1.tofNSigmaStoreEl(), + -999., // p1.tofNSigmaStorePi(), + -999., // p1.tofNSigmaStoreKa(), + -999., // p1.tofNSigmaStorePr(), + -999., // p1.tofNSigmaStoreDe(), + -999., // daughDCA + candidate.decayLength(), + -999., + -999., + -999., + -999., + -999.); + } + } + } + PROCESS_SWITCH(femtoWorldProducerTask, processProdTrackD0Run3, "Process data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt index e20375296a3..7613d544a6c 100644 --- a/PWGCF/FemtoWorld/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoWorld/Tasks/CMakeLists.txt @@ -43,3 +43,8 @@ o2physics_add_dpl_workflow(femto-world-pair-proton-antiproton SOURCES femtoWorldPairTaskProtonAntiproton.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto-world-efficiency-task + SOURCES femtoWorldEfficiencyTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGCF/FemtoWorld/Tasks/femtoWorldEfficiencyTask.cxx b/PWGCF/FemtoWorld/Tasks/femtoWorldEfficiencyTask.cxx new file mode 100644 index 00000000000..935e7e21e24 --- /dev/null +++ b/PWGCF/FemtoWorld/Tasks/femtoWorldEfficiencyTask.cxx @@ -0,0 +1,520 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file femtoWorldEfficiencyTask.cxx +/// \author Lukasz Graczykowski, WUT Warsaw, lgraczyk@cern.ch +/// \author Malgorzata Janik, WUT Warsaw, majanik@cern.ch +/// \author Alicja Plachta, WUT Warsaw, alicja.plachta@cern.ch +/// \author Barbara Chytla, WUT Warsaw, barbara.chytla@cern.ch + +// O2 includes +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" +#include "PWGLF/DataModel/LFResonanceTables.h" +#include "PWGCF/FemtoWorld/Core/FemtoWorldCollisionSelection.h" +#include "PWGCF/FemtoWorld/DataModel/FemtoWorldDerived.h" +#include "Framework/O2DatabasePDGPlugin.h" + +#include "TPDGCode.h" + +using namespace o2; +using namespace o2::analysis::femtoWorld; +using namespace o2::track; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// using TracksPID = aod::FullTracks; // This is okay. +using TracksPID = soa::Join; // for helper task with "full" +// using TracksPID = soa::Join; // This is okay for "no full" + +using CollisionsEvSel = soa::Join; + +// Femto World Efficiency task +struct femtoWorldEficiencyTask { + + Service pdgDB; + + // histogram registries produced + HistogramRegistry registryQAevent{"QAHistosEvent", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryQAtrack{"QAHistosTrack", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryPID{"PIDHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryPDG{"PDGHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryPri{"PriHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryPriCuts{"PriHistosCuts", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; // for tracking efficiency = cuts only + HistogramRegistry registryGlobal{"GlobalTrackHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + HistogramRegistry registryMCtruth{"MCtruthHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + // configurables + Configurable pidnSigmaCut{"pidnSigmaCut", 3.0f, "TPC and TOF PID cut "}; + Configurable tofPtCut{"tofPtCut", 0.5f, "From what pT TOF is used"}; + Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run 3 data"}; // Choose if running on converted data or run 3 data + // track cuts + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable cfgPtLow{"cfgPtLow", 0.2, "Lower limit for Pt"}; + Configurable cfgPtHigh{"cfgPtHigh", 4., "Higher limit for Pt"}; + Configurable cfgDcaXY{"cfgDcaXY", 2.4, "Value of max. DCA_XY"}; + Configurable cfgDcaZ{"cfgDcaZ", 3.2, "Value of max. DCA_Z"}; + /// Event cuts + o2::analysis::femtoWorld::FemtoWorldCollisionSelection colCuts; + 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 ConfPIDnoTOF{"ConfPIDnoTOF", false, "Use only TPC in PID, no TOF"}; + + void init(InitContext&) + { + colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3); + colCuts.init(®istryQAevent); + + // event cuts - already done in FemtoWorldCollisionSelection.h + // registryQAevent.add("before/reco/zvtx", "vtx_{#it{z}}", kTH1F, {{300, -15.0, 15.0, "vtx_{#it{z}} (cm)"}}); + // registryQAevent.add("before/reco/multiplicity", "V0M multiplicity class", kTH1F, {{100, 0.0, 100.0, "V0M multiplicity (%)"}}); + + // track cuts + registryQAtrack.add("after/all/plus/pt", "Charged particles #it{p}_{T}", kTH1F, {{150, 0.0, 15.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryQAtrack.add("after/all/plus/eta", "Charged particles #eta", kTH1F, {{400, -1.0, 1.0, "#eta"}}); + registryQAtrack.add("after/all/plus/phi", "Charged particles #varphi", kTH1F, {{360, 0.0, constants::math::TwoPI, "#varphi"}}); + registryQAtrack.add("after/all/plus/etaphi", "#eta - #varphi;#eta;#varphi", {HistType::kTH2F, {{200, -1, 1}, {200, 0, 2 * TMath::Pi()}}}); + registryQAtrack.add("after/all/plus/DCAxy", "DCAyx; #it{p}_{T} (GeV/#it{c}); DCA_{xy} (cm)", kTH2F, {{1000, 0, 10}, {1000, -5, 5}}); + registryQAtrack.add("after/all/plus/DCAz", "DCAz; #it{p}_{T} (GeV/#it{c}); DCA_{z} (cm)", kTH2F, {{1000, 0, 10}, {1000, -5, 5}}); + registryQAtrack.addClone("after/all/plus/", "after/all/minus/"); + registryQAtrack.addClone("after/all/", "after/pion/"); + registryQAtrack.addClone("after/all/", "after/kaon/"); + registryQAtrack.addClone("after/all/", "after/proton/"); + + // global track histos + registryGlobal.add("crossedRows", "Number of crossed rows TPC", kTH1F, {{159, 0, 158, "N crossed rows"}}); + registryGlobal.add("RowsOverClustersTPC", "Ratio of crossed rows over findable TPC clusters", kTH1F, {{100, 0.5, 2., "N crossed rows"}}); + registryGlobal.add("chi2TPC", "Chi2 per TPC cluster", kTH1F, {{500, 0, 5, "Chi2 per TPC cluster"}}); + registryGlobal.add("chi2ITS", "Chi2 per ITS cluster", kTH1F, {{500, 0, 40, "Chi2 per ITS cluster"}}); + registryGlobal.add("dcaZ", "DCA to z vertex", kTH1F, {{500, 0, 4., "DCA to z vertex"}}); + registryGlobal.add("dcaXY", "DCA to xy vertex", kTH1F, {{500, 0, 4., "DCA to xy vertex"}}); + registryGlobal.add("clustersITS", "Number of ITS clusters", kTH1F, {{8, 0, 7, "N crossed rows"}}); // perhaps change to itsClusterMap + registryGlobal.add("pt", "#it{p}_{T}", kTH1F, {{150, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}}); + registryGlobal.add("eta", "#eta", kTH1F, {{400, -1.0, 1.0, "#eta"}}); + + // nsigmas + registryPID.add("pid/plus/TOF_TPC_Map", "TOF + TPC Combined PID for all;#sigma_{TOF}^{all};#sigma_{TPC}^{all}", {HistType::kTH2F, {{100, -5, 5}, {100, -5, 5}}}); + registryPID.addClone("pid/plus/", "pid/minus/"); + + registryPID.add("pid/kaon/plus/TOF_TPC_Map", "TOF + TPC Combined PID;#sigma_{TOF};#sigma_{TPC}", {HistType::kTH2F, {{100, -5, 5}, {100, -5, 5}}}); + registryPID.add("pid/kaon/plus/TOF_Nsigma", "TOF NSigma;#it{p}_{T} (GeV/#it{c});#sigma_{TOF};", {HistType::kTH2F, {{100, 0, 10}, {100, -5, 5}}}); + registryPID.add("pid/kaon/plus/TPC_Nsigma", "TPC NSigma;#it{p}_{T} (GeV/#it{c});#sigma_{TPC};", {HistType::kTH2F, {{100, 0, 10}, {100, -5, 5}}}); + registryPID.add("pid/kaon/plus/TPC_dEdx", "TPC dE/dx;#it{p}_{T} (GeV/#it{c});#it{dE/dx};", {HistType::kTH2F, {{100, 0, 10}, {100, -50, 200}}}); + registryPID.add("pid/kaon/plus/TOF_Beta", "TOF Signal;#it{p}_{T} (GeV/#it{c});#TOF Beta;", {HistType::kTH2F, {{100, 0, 10}, {100, 0, 5}}}); + registryPID.addClone("pid/kaon/plus/", "pid/kaon/minus/"); + + registryPID.addClone("pid/kaon/", "pid/pion/"); + registryPID.addClone("pid/kaon/", "pid/proton/"); + + // PDG + registryPDG.add("plus/PDGPi", "PDGPi;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {8001, -4000.5, 4000.5}}}); + registryPDG.add("plus/PDGKa", "PDGKa;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {8001, -4000.5, 4000.5}}}); + registryPDG.add("plus/PDGPr", "PDGPr;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {8001, -4000.5, 4000.5}}}); + + registryPDG.add("minus/PDGPi", "PDGPi;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {8001, -4000.5, 4000.5}}}); + registryPDG.add("minus/PDGKa", "PDGKa;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {8001, -4000.5, 4000.5}}}); + registryPDG.add("minus/PDGPr", "PDGPr;#it{p}_{T} (GeV/c); PDG", {HistType::kTH2F, {{500, 0, 5}, {8001, -4000.5, 4000.5}}}); + + // Pri + registryPri.add("plus/PiPri", "PiPri;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryPri.add("plus/KaPri", "KaPri;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryPri.add("plus/PrPri", "PrPri;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryPri.add("plus/AllPri", "AllPri;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryPri.add("minus/PiPri", "PiPri;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryPri.add("minus/KaPri", "KaPri;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryPri.add("minus/PrPri", "PrPri;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryPri.add("minus/AllPri", "AllPri;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryPri.add("plus/PiPriPt", "PiPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPri.add("plus/KaPriPt", "KaPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPri.add("plus/PrPriPt", "PrPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPri.add("plus/AllPriPt", "AllPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + registryPri.add("minus/PiPriPt", "PiPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPri.add("minus/KaPriPt", "KaPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPri.add("minus/PrPriPt", "PrPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPri.add("minus/AllPriPt", "AllPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + registryPri.add("plus/TOFmatchingAll", ";#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPri.add("minus/TOFmatchingAll", ";#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + // Pri our tracking cuts only + registryPriCuts.add("plus/PiPriPt", "PiPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPriCuts.add("plus/KaPriPt", "KaPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPriCuts.add("plus/PrPriPt", "PrPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + registryPriCuts.add("minus/PiPriPt", "PiPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPriCuts.add("minus/KaPriPt", "KaPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryPriCuts.add("minus/PrPriPt", "PrPri;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + // MC truth + registryMCtruth.add("plus/MCtruthPi", "MC truth pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("plus/MCtruthKa", "MC truth kaons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("plus/MCtruthPr", "MC truth protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCtruth.add("minus/MCtruthPi", "MC truth pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("minus/MCtruthKa", "MC truth kaons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("minus/MCtruthPr", "MC truth protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCtruth.add("plus/MCtruthPiPt", "MC truth pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("plus/MCtruthKaPt", "MC truth kaons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("plus/MCtruthPrPt", "MC truth protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("plus/MCtruthAllPt", "MC truth all;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + registryMCtruth.add("minus/MCtruthPiPt", "MC truth pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthKaPt", "MC truth kaons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthPrPt", "MC truth protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthAllPt", "MC truth all;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + } + + bool IsNSigmaAccept(float nsigmaTPC, float nsigmaTOF, float mom) + { + if (ConfPIDnoTOF) { + if (TMath::Abs(nsigmaTPC) < pidnSigmaCut) { + return true; + } else { + return false; + } + } else { + if (mom > tofPtCut) { + if (TMath::Hypot(nsigmaTOF, nsigmaTPC) < pidnSigmaCut) + return true; + } else { + if (TMath::Abs(nsigmaTPC) < pidnSigmaCut) + return true; + } + return false; + } + } + + Filter trackFilter = nabs(aod::track::eta) < cfgCutEta && requireGlobalTrackInFilter() && aod::track::pt > cfgPtLow&& aod::track::pt < cfgPtHigh; + + void processReco(const CollisionsEvSel::iterator& collision, + soa::Filtered> const& tracks /*, aod::BCsWithTimestamps const&*/) + { + if (ConfIsRun3) { + if (!collision.sel8()) + return; + } + + // auto bc = collision.bc_as(); /// adding timestamp to access magnetic field later + // Default event selection + // colCuts.printCuts(); + if (!colCuts.isSelected(collision)) + return; + colCuts.fillQA(collision); + + // Loop over tracks + for (auto& track : tracks) { + // Tracks are already filtered by the pre-filters + + // track.hasTOF() - to check if TOF info available + + // cuts on tracks: + if (!ConfPIDnoTOF) { + if (track.pt() > tofPtCut && !track.hasTOF()) + continue; // if no TOF information above tofPtCut reject such track + } + + registryGlobal.fill(HIST("crossedRows"), track.tpcNClsCrossedRows()); + registryGlobal.fill(HIST("RowsOverClustersTPC"), track.tpcCrossedRowsOverFindableCls()); + registryGlobal.fill(HIST("chi2TPC"), track.tpcChi2NCl()); + registryGlobal.fill(HIST("chi2ITS"), track.itsChi2NCl()); + registryGlobal.fill(HIST("dcaZ"), track.dcaZ()); + registryGlobal.fill(HIST("dcaXY"), track.dcaXY()); + registryGlobal.fill(HIST("clustersITS"), track.itsNCls()); + registryGlobal.fill(HIST("pt"), track.pt()); + registryGlobal.fill(HIST("eta"), track.eta()); + + // no PID histograms + if (track.sign() > 0) { + registryQAtrack.fill(HIST("after/all/plus/etaphi"), track.eta(), track.phi()); + registryQAtrack.fill(HIST("after/all/plus/pt"), track.pt()); + registryQAtrack.fill(HIST("after/all/plus/eta"), track.eta()); + registryQAtrack.fill(HIST("after/all/plus/phi"), track.phi()); + registryQAtrack.fill(HIST("after/all/plus/DCAxy"), track.pt(), track.dcaXY()); + registryQAtrack.fill(HIST("after/all/plus/DCAz"), track.pt(), track.dcaZ()); + } + if (track.sign() < 0) { + registryQAtrack.fill(HIST("after/all/minus/etaphi"), track.eta(), track.phi()); + registryQAtrack.fill(HIST("after/all/minus/pt"), track.pt()); + registryQAtrack.fill(HIST("after/all/minus/eta"), track.eta()); + registryQAtrack.fill(HIST("after/all/minus/phi"), track.phi()); + registryQAtrack.fill(HIST("after/all/minus/DCAxy"), track.pt(), track.dcaXY()); + registryQAtrack.fill(HIST("after/all/minus/DCAz"), track.pt(), track.dcaZ()); + } + + // Add PID selection criteria here + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.pt())) { + if (track.sign() > 0) { + registryPID.fill(HIST("pid/pion/plus/TOF_TPC_Map"), track.tofNSigmaPi(), track.tpcNSigmaPi()); + registryPID.fill(HIST("pid/pion/plus/TOF_Nsigma"), track.pt(), track.tofNSigmaPi()); + registryPID.fill(HIST("pid/pion/plus/TPC_Nsigma"), track.pt(), track.tpcNSigmaPi()); + registryPID.fill(HIST("pid/pion/plus/TPC_dEdx"), track.pt(), track.tpcSignal()); + registryPID.fill(HIST("pid/pion/plus/TOF_Beta"), track.pt(), track.beta()); + + registryQAtrack.fill(HIST("after/pion/plus/etaphi"), track.eta(), track.phi()); + registryQAtrack.fill(HIST("after/pion/plus/pt"), track.pt()); + registryQAtrack.fill(HIST("after/pion/plus/eta"), track.eta()); + registryQAtrack.fill(HIST("after/pion/plus/phi"), track.phi()); + registryQAtrack.fill(HIST("after/pion/plus/DCAxy"), track.pt(), track.dcaXY()); + registryQAtrack.fill(HIST("after/pion/plus/DCAz"), track.pt(), track.dcaZ()); + } + if (track.sign() < 0) { + registryPID.fill(HIST("pid/pion/minus/TOF_TPC_Map"), track.tofNSigmaPi(), track.tpcNSigmaPi()); + registryPID.fill(HIST("pid/pion/minus/TOF_Nsigma"), track.pt(), track.tofNSigmaPi()); + registryPID.fill(HIST("pid/pion/minus/TPC_Nsigma"), track.pt(), track.tpcNSigmaPi()); + registryPID.fill(HIST("pid/pion/minus/TPC_dEdx"), track.pt(), track.tpcSignal()); + registryPID.fill(HIST("pid/pion/minus/TOF_Beta"), track.pt(), track.beta()); + + registryQAtrack.fill(HIST("after/pion/minus/etaphi"), track.eta(), track.phi()); + registryQAtrack.fill(HIST("after/pion/minus/pt"), track.pt()); + registryQAtrack.fill(HIST("after/pion/minus/eta"), track.eta()); + registryQAtrack.fill(HIST("after/pion/minus/phi"), track.phi()); + registryQAtrack.fill(HIST("after/pion/minus/DCAxy"), track.pt(), track.dcaXY()); + registryQAtrack.fill(HIST("after/pion/minus/DCAz"), track.pt(), track.dcaZ()); + } + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.pt())) { + if (track.sign() > 0) { + registryPID.fill(HIST("pid/kaon/plus/TOF_TPC_Map"), track.tofNSigmaKa(), track.tpcNSigmaKa()); + registryPID.fill(HIST("pid/kaon/plus/TOF_Nsigma"), track.pt(), track.tofNSigmaKa()); + registryPID.fill(HIST("pid/kaon/plus/TPC_Nsigma"), track.pt(), track.tpcNSigmaKa()); + registryPID.fill(HIST("pid/kaon/plus/TPC_dEdx"), track.pt(), track.tpcSignal()); + registryPID.fill(HIST("pid/kaon/plus/TOF_Beta"), track.pt(), track.beta()); + + registryQAtrack.fill(HIST("after/kaon/plus/etaphi"), track.eta(), track.phi()); + registryQAtrack.fill(HIST("after/kaon/plus/pt"), track.pt()); + registryQAtrack.fill(HIST("after/kaon/plus/eta"), track.eta()); + registryQAtrack.fill(HIST("after/kaon/plus/phi"), track.phi()); + registryQAtrack.fill(HIST("after/kaon/plus/DCAxy"), track.pt(), track.dcaXY()); + registryQAtrack.fill(HIST("after/kaon/plus/DCAz"), track.pt(), track.dcaZ()); + } + if (track.sign() < 0) { + registryPID.fill(HIST("pid/kaon/minus/TOF_TPC_Map"), track.tofNSigmaKa(), track.tpcNSigmaKa()); + registryPID.fill(HIST("pid/kaon/minus/TOF_Nsigma"), track.pt(), track.tofNSigmaKa()); + registryPID.fill(HIST("pid/kaon/minus/TPC_Nsigma"), track.pt(), track.tpcNSigmaKa()); + registryPID.fill(HIST("pid/kaon/minus/TPC_dEdx"), track.pt(), track.tpcSignal()); + registryPID.fill(HIST("pid/kaon/minus/TOF_Beta"), track.pt(), track.beta()); + + registryQAtrack.fill(HIST("after/kaon/minus/etaphi"), track.eta(), track.phi()); + registryQAtrack.fill(HIST("after/kaon/minus/pt"), track.pt()); + registryQAtrack.fill(HIST("after/kaon/minus/eta"), track.eta()); + registryQAtrack.fill(HIST("after/kaon/minus/phi"), track.phi()); + registryQAtrack.fill(HIST("after/kaon/minus/DCAxy"), track.pt(), track.dcaXY()); + registryQAtrack.fill(HIST("after/kaon/minus/DCAz"), track.pt(), track.dcaZ()); + } + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.pt())) { + if (track.sign() > 0) { + registryPID.fill(HIST("pid/proton/plus/TOF_TPC_Map"), track.tofNSigmaPr(), track.tpcNSigmaPr()); + registryPID.fill(HIST("pid/proton/plus/TOF_Nsigma"), track.pt(), track.tofNSigmaPr()); + registryPID.fill(HIST("pid/proton/plus/TPC_Nsigma"), track.pt(), track.tpcNSigmaPr()); + registryPID.fill(HIST("pid/proton/plus/TPC_dEdx"), track.pt(), track.tpcSignal()); + registryPID.fill(HIST("pid/proton/plus/TOF_Beta"), track.pt(), track.beta()); + + registryQAtrack.fill(HIST("after/proton/plus/etaphi"), track.eta(), track.phi()); + registryQAtrack.fill(HIST("after/proton/plus/pt"), track.pt()); + registryQAtrack.fill(HIST("after/proton/plus/eta"), track.eta()); + registryQAtrack.fill(HIST("after/proton/plus/phi"), track.phi()); + registryQAtrack.fill(HIST("after/proton/plus/DCAxy"), track.pt(), track.dcaXY()); + registryQAtrack.fill(HIST("after/proton/plus/DCAz"), track.pt(), track.dcaZ()); + } + if (track.sign() < 0) { + registryPID.fill(HIST("pid/proton/minus/TOF_TPC_Map"), track.tofNSigmaPr(), track.tpcNSigmaPr()); + registryPID.fill(HIST("pid/proton/minus/TOF_Nsigma"), track.pt(), track.tofNSigmaPr()); + registryPID.fill(HIST("pid/proton/minus/TPC_Nsigma"), track.pt(), track.tpcNSigmaPr()); + registryPID.fill(HIST("pid/proton/minus/TPC_dEdx"), track.pt(), track.tpcSignal()); + registryPID.fill(HIST("pid/proton/minus/TOF_Beta"), track.pt(), track.beta()); + + registryQAtrack.fill(HIST("after/proton/minus/etaphi"), track.eta(), track.phi()); + registryQAtrack.fill(HIST("after/proton/minus/pt"), track.pt()); + registryQAtrack.fill(HIST("after/proton/minus/eta"), track.eta()); + registryQAtrack.fill(HIST("after/proton/minus/phi"), track.phi()); + registryQAtrack.fill(HIST("after/proton/minus/DCAxy"), track.pt(), track.dcaXY()); + registryQAtrack.fill(HIST("after/proton/minus/DCAz"), track.pt(), track.dcaZ()); + } + } + } + } + PROCESS_SWITCH(femtoWorldEficiencyTask, processReco, "Process reconstructed data", true); + + using BigTracksMC = soa::Join; + Preslice perCollisionID = aod::track::collisionId; + void processMCTruth(aod::McCollision const& collision, soa::SmallGroups> const& collisions, aod::McParticles const& mcparticles, soa::Filtered const& tracks) + { + // Loop over reconstructed collisions corresponding to MC collision + for (auto& collision : collisions) { + + // Group tracks belonging to collision + auto groupedTracks = tracks.sliceBy(perCollisionID, collision.globalIndex()); + + // Loop over tracks + for (auto& track : groupedTracks) { + if (!track.has_mcParticle()) { + continue; + } + const auto mcParticle = track.mcParticle(); + + if (track.sign() > 0) { + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.pt())) { + registryPDG.fill(HIST("plus/PDGPi"), track.pt(), mcParticle.pdgCode()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.pt())) { + registryPDG.fill(HIST("plus/PDGKa"), track.pt(), mcParticle.pdgCode()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.pt())) { + registryPDG.fill(HIST("plus/PDGPr"), track.pt(), mcParticle.pdgCode()); + } + } + if (track.sign() < 0) { + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.pt())) { + registryPDG.fill(HIST("minus/PDGPi"), track.pt(), mcParticle.pdgCode()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.pt())) { + registryPDG.fill(HIST("minus/PDGKa"), track.pt(), mcParticle.pdgCode()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.pt())) { + registryPDG.fill(HIST("minus/PDGPr"), track.pt(), mcParticle.pdgCode()); + } + } + + if (mcParticle.isPhysicalPrimary()) { + if (track.sign() > 0) { + // PID only + registryPri.fill(HIST("plus/AllPri"), track.pt(), track.eta()); + registryPri.fill(HIST("plus/AllPriPt"), mcParticle.pt()); + // histogram pt TOF matching + if (track.hasTOF()) { + registryPri.fill(HIST("plus/TOFmatchingAll"), mcParticle.pt()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.pt()) && mcParticle.pdgCode() == 211) { + registryPri.fill(HIST("plus/PiPri"), track.pt(), track.eta()); + registryPri.fill(HIST("plus/PiPriPt"), mcParticle.pt()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.pt()) && mcParticle.pdgCode() == 321) { + registryPri.fill(HIST("plus/KaPri"), track.pt(), track.eta()); + registryPri.fill(HIST("plus/KaPriPt"), mcParticle.pt()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.pt()) && mcParticle.pdgCode() == 2212) { + registryPri.fill(HIST("plus/PrPri"), track.pt(), track.eta()); + registryPri.fill(HIST("plus/PrPriPt"), mcParticle.pt()); + } + // tracking efficiency only + if (mcParticle.pdgCode() == 211) { + registryPriCuts.fill(HIST("plus/PiPriPt"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == 321) { + registryPriCuts.fill(HIST("plus/KaPriPt"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == 2212) { + registryPriCuts.fill(HIST("plus/PrPriPt"), mcParticle.pt()); + } + } + if (track.sign() < 0) { + // PID only + registryPri.fill(HIST("minus/AllPri"), track.pt(), track.eta()); + registryPri.fill(HIST("minus/AllPriPt"), mcParticle.pt()); + // histogram pt TOF matching + if (track.hasTOF()) { + registryPri.fill(HIST("minus/TOFmatchingAll"), mcParticle.pt()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.pt()) && mcParticle.pdgCode() == -211) { + registryPri.fill(HIST("minus/PiPri"), track.pt(), track.eta()); + registryPri.fill(HIST("minus/PiPriPt"), mcParticle.pt()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.pt()) && mcParticle.pdgCode() == -321) { + registryPri.fill(HIST("minus/KaPri"), track.pt(), track.eta()); + registryPri.fill(HIST("minus/KaPriPt"), mcParticle.pt()); + } + if (IsNSigmaAccept(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.pt()) && mcParticle.pdgCode() == -2212) { + registryPri.fill(HIST("minus/PrPri"), track.pt(), track.eta()); + registryPri.fill(HIST("minus/PrPriPt"), mcParticle.pt()); + } + // tracking efficiency only + if (mcParticle.pdgCode() == -211) { + registryPriCuts.fill(HIST("minus/PiPriPt"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == -321) { + registryPriCuts.fill(HIST("minus/KaPriPt"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == -2212) { + registryPriCuts.fill(HIST("minus/PrPriPt"), mcParticle.pt()); + } + } + } + } + } + // loop over MC particles + for (auto& mcparticle : mcparticles) { + if (!mcparticle.isPhysicalPrimary() || TMath::Abs(mcparticle.eta()) > cfgCutEta || mcparticle.pt() < cfgPtLow || mcparticle.pt() > cfgPtHigh) + continue; + + const auto& pdgParticle = pdgDB->GetParticle(mcparticle.pdgCode()); + if (!pdgParticle) { + continue; + } + + if (pdgParticle->Charge() > 0) { + registryMCtruth.fill(HIST("plus/MCtruthAllPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == 211) { + registryMCtruth.fill(HIST("plus/MCtruthPi"), mcparticle.pt(), mcparticle.eta()); + registryMCtruth.fill(HIST("plus/MCtruthPiPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == 321) { + registryMCtruth.fill(HIST("plus/MCtruthKa"), mcparticle.pt(), mcparticle.eta()); + registryMCtruth.fill(HIST("plus/MCtruthKaPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == 2212) { + registryMCtruth.fill(HIST("plus/MCtruthPr"), mcparticle.pt(), mcparticle.eta()); + registryMCtruth.fill(HIST("plus/MCtruthPrPt"), mcparticle.pt()); + } + + if (pdgParticle->Charge() < 0) { + registryMCtruth.fill(HIST("minus/MCtruthAllPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == -211) { + registryMCtruth.fill(HIST("minus/MCtruthPi"), mcparticle.pt(), mcparticle.eta()); + registryMCtruth.fill(HIST("minus/MCtruthPiPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == -321) { + registryMCtruth.fill(HIST("minus/MCtruthKa"), mcparticle.pt(), mcparticle.eta()); + registryMCtruth.fill(HIST("minus/MCtruthKaPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == -2212) { + registryMCtruth.fill(HIST("minus/MCtruthPr"), mcparticle.pt(), mcparticle.eta()); + registryMCtruth.fill(HIST("minus/MCtruthPrPt"), mcparticle.pt()); + } + } + } + PROCESS_SWITCH(femtoWorldEficiencyTask, processMCTruth, "Process MC truth data", true); + +}; // end of spectra task +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"femtoWorldEficiencyTask"}), + }; +} diff --git a/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskPionPion.cxx b/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskPionPion.cxx index b0d737f1519..a2d061ed1f4 100644 --- a/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskPionPion.cxx +++ b/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskPionPion.cxx @@ -255,25 +255,46 @@ struct femtoWorldPairTaskPionPion { // Function to build combinations template - void CombineParticles(T1 groupPartsOne, T1 groupPartsTwo, T2 cont, T3 parts, T4 magFieldTesla, int multCol) + void CombineParticles(T1 groupPartsOne, T1 groupPartsTwo, T2 cont, T3 parts, T4 magFieldTesla, int multCol, int sameOrMixed) { - for (auto& [p1, p2] : combinations(groupPartsOne, groupPartsTwo)) { - if (!(IsPionNSigma(p1.p(), p1.tpcNSigmaPi(), p1.tofNSigmaPi()))) { - continue; - } - if (!(IsPionNSigma(p2.p(), p2.tpcNSigmaPi(), p2.tofNSigmaPi()))) { - continue; - } - if (ConfIsCPR) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + if (sameOrMixed == 1) { + for (auto& [p1, p2] : combinations(groupPartsOne, groupPartsTwo)) { + if (!(IsPionNSigma(p1.p(), p1.tpcNSigmaPi(), p1.tofNSigmaPi()))) { + continue; + } + if (!(IsPionNSigma(p2.p(), p2.tpcNSigmaPi(), p2.tofNSigmaPi()))) { continue; } + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + cont.setPair(p1, p2, multCol); } - // track cleaning - if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; + } else if (sameOrMixed == 2) { + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (!(IsPionNSigma(p1.p(), p1.tpcNSigmaPi(), p1.tofNSigmaPi()))) { + continue; + } + if (!(IsPionNSigma(p2.p(), p2.tpcNSigmaPi(), p2.tofNSigmaPi()))) { + continue; + } + if (ConfIsCPR) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { + continue; + } + } + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + cont.setPair(p1, p2, multCol); } - cont.setPair(p1, p2, multCol); } } @@ -315,11 +336,11 @@ struct femtoWorldPairTaskPionPion { } /// Build the combinations if (ConfPlusMinus) - CombineParticles(groupPartsOne, groupPartsTwo, sameEventPlusMinCont, parts, magFieldTesla, multCol); + CombineParticles(groupPartsOne, groupPartsTwo, sameEventPlusMinCont, parts, magFieldTesla, multCol, 1); if (ConfPlusPlus) - CombineParticles(groupPartsOne, groupPartsOne, sameEventPlusPlusCont, parts, magFieldTesla, multCol); + CombineParticles(groupPartsOne, groupPartsOne, sameEventPlusPlusCont, parts, magFieldTesla, multCol, 1); if (ConfMinusMinus) - CombineParticles(groupPartsTwo, groupPartsTwo, sameEventMinMinCont, parts, magFieldTesla, multCol); + CombineParticles(groupPartsTwo, groupPartsTwo, sameEventMinMinCont, parts, magFieldTesla, multCol, 1); } PROCESS_SWITCH(femtoWorldPairTaskPionPion, processSameEvent, "Enable processing same event", true); @@ -333,9 +354,6 @@ struct femtoWorldPairTaskPionPion { MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), collision1.multV0M()})); - auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex(), cache); - const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -348,12 +366,21 @@ struct femtoWorldPairTaskPionPion { /// \todo before mixing we should check whether both collisions contain a pair of particles! // if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue; - if (ConfPlusMinus) - CombineParticles(groupPartsOne, groupPartsTwo, mixedEventPlusMinCont, parts, magFieldTesla1, multCol1); - if (ConfPlusPlus) - CombineParticles(groupPartsOne, groupPartsOne, mixedEventPlusPlusCont, parts, magFieldTesla1, multCol1); - if (ConfMinusMinus) - CombineParticles(groupPartsTwo, groupPartsTwo, mixedEventMinMinCont, parts, magFieldTesla1, multCol1); + if (ConfPlusMinus) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex(), cache); + CombineParticles(groupPartsOne, groupPartsTwo, mixedEventPlusMinCont, parts, magFieldTesla1, multCol1, 2); + } + if (ConfPlusPlus) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex(), cache); + CombineParticles(groupPartsOne, groupPartsTwo, mixedEventPlusPlusCont, parts, magFieldTesla1, multCol1, 2); + } + if (ConfMinusMinus) { + auto groupPartsOne = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex(), cache); + CombineParticles(groupPartsOne, groupPartsTwo, mixedEventMinMinCont, parts, magFieldTesla1, multCol1, 2); + } } } diff --git a/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskProtonAntiproton.cxx b/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskProtonAntiproton.cxx index 0e07a09c63b..066307a91d4 100644 --- a/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskProtonAntiproton.cxx +++ b/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskProtonAntiproton.cxx @@ -51,8 +51,8 @@ struct femtoWorldPairTaskProtonAntiproton { // Configurables for cuts // First particle - Configurable cfgPtLowPart1{"cfgPtLowPart1", 0.14, "Lower limit for Pt for the first particle"}; - Configurable cfgPtHighPart1{"cfgPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; + Configurable cfgPtLowPart1{"cfgPtLowPart1", 0.5, "Lower limit for Pt for the first particle"}; + Configurable cfgPtHighPart1{"cfgPtHighPart1", 2.5, "Higher limit for Pt for the first particle"}; Configurable cfgEtaLowPart1{"cfgEtaLowPart1", -0.8, "Lower limit for Eta for the first particle"}; Configurable cfgEtaHighPart1{"cfgEtaHighPart1", 0.8, "Higher limit for Eta for the first particle"}; Configurable cfgDcaXYPart1{"cfgDcaXYPart1", 2.4, "Value for DCA_XY for the first particle"}; @@ -62,8 +62,8 @@ struct femtoWorldPairTaskProtonAntiproton { Configurable cfgChi2TpcPart1{"cfgChi2TpcPart1", 4.0, "Chi2 / cluster for the TPC track segment for the first particle"}; Configurable cfgChi2ItsPart1{"cfgChi2ItsPart1", 36.0, "Chi2 / cluster for the ITS track segment for the first particle"}; // Second particle - Configurable cfgPtLowPart2{"cfgPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; - Configurable cfgPtHighPart2{"cfgPtHighPart2", 1.5, "Higher limit for Pt for the second particle"}; + Configurable cfgPtLowPart2{"cfgPtLowPart2", 0.5, "Lower limit for Pt for the second particle"}; + Configurable cfgPtHighPart2{"cfgPtHighPart2", 2.5, "Higher limit for Pt for the second particle"}; Configurable cfgEtaLowPart2{"cfgEtaLowPart2", -0.8, "Lower limit for Eta for the second particle"}; Configurable cfgEtaHighPart2{"cfgEtaHighPart2", 0.8, "Higher limit for Eta for the second particle"}; Configurable cfgDcaXYPart2{"cfgDcaXYPart2", 2.4, "Value for DCA_XY for the second particle"}; diff --git a/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskTrackD0.cxx b/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskTrackD0.cxx index 576d10acdec..f38f6aa84db 100644 --- a/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskTrackD0.cxx +++ b/PWGCF/FemtoWorld/Tasks/femtoWorldPairTaskTrackD0.cxx @@ -38,12 +38,6 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_correlation_d_dbar; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; -using namespace o2::constants::math; - namespace { static constexpr int nPart = 2; // number of particle types (for us it will be proton and phi) @@ -71,12 +65,12 @@ struct femtoWorldPairTaskTrackD0 { Configurable ConfNsigmaTPCPion{"ConfNsigmaTPCPion", 3.0, "TPC Pion Sigma for momentum < 0.5"}; /// Table for both particles Configurable> cfgCutTable{"cfgCutTable", {cutsTable[0], nPart, nCuts, partNames, cutNames}, "Particle selections"}; - Configurable cfgNspecies{"ccfgNspecies", 4, "Number of particle spieces with PID info"}; + // Configurable cfgNspecies{"ccfgNspecies", 4, "Number of particle spieces with PID info"}; /// Particle 1 (track) - Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"}; // proton (2212) - Configurable> ConfPIDPartOne{"ConfPIDPartOne", std::vector{2}, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> - Configurable cfgPtLowPart1{"cfgPtLowPart1", 0.5, "Lower limit for Pt for the first particle"}; // change according to wrzesa cuts + Configurable ConfPDGCodePartOne{"ConfPDGCodePartOne", 211, "Particle 1 - PDG code"}; // pion+ (211), proton (2212) + // Configurable> ConfPIDPartOne{"ConfPIDPartOne", std::vector{2}, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector>int>> + Configurable cfgPtLowPart1{"cfgPtLowPart1", 0.5, "Lower limit for Pt for the first particle"}; // change according to wrzesa cuts Configurable cfgPtHighPart1{"cfgPtHighPart1", 1.5, "Higher limit for Pt for the first particle"}; Configurable cfgEtaLowPart1{"cfgEtaLowPart1", -0.8, "Lower limit for Eta for the first particle"}; Configurable cfgEtaHighPart1{"cfgEtaHighPart1", 0.8, "Higher limit for Eta for the first particle"}; @@ -99,37 +93,24 @@ struct femtoWorldPairTaskTrackD0 { /// Histogramming for particle 1 FemtoWorldParticleHisto trackHistoPartOne; - /// Particle 2 (Phi) - Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 333, "Particle 1 - PDG code"}; // phi meson (333) - Configurable ConfCutPartTwo{"ConfCutPartTwo", 338, "Particle 2 - Selection bit"}; + /// Particle 2 (D0/D0bar) + Configurable ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 421, "Particle 1 - PDG code"}; // phi meson (333) + Configurable ConfCutPartTwo{"ConfCutPartTwo", 421, "Particle 2 - Selection bit"}; Configurable cfgPtLowPart2{"cfgPtLowPart2", 0.14, "Lower limit for Pt for the second particle"}; Configurable cfgPtHighPart2{"cfgPtHighPart2", 5.0, "Higher limit for Pt for the second particle"}; Configurable cfgEtaLowPart2{"cfgEtaLowPart2", -0.8, "Lower limit for Eta for the second particle"}; Configurable cfgEtaHighPart2{"cfgEtaHighPart2", 0.8, "Higher limit for Eta for the second particle"}; - /// Partition for particle 2 - Partition partsTwo = (aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kPhi)) && (aod::femtoworldparticle::pt < cfgPtHighPart2) && (aod::femtoworldparticle::pt > cfgPtLowPart2) // pT cuts - && (aod::femtoworldparticle::eta < cfgEtaHighPart2) && (aod::femtoworldparticle::eta > cfgEtaLowPart2); // Eta cuts - - /// Histogramming for particle 2 - FemtoWorldParticleHisto trackHistoPartTwo; - - // Partition for particle 3 (Phi daughters (K+ K-)) - Partition partsThree = (aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kPhiChild)); - - /// Histogramming for particle 3 - FemtoWorldParticleHisto trackHistoPartThree; - // Partition for D0/D0bar mesons Partition partsD0D0barMesons = (aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kD0D0bar)); Partition partsD0D0barDaughters = (aod::femtoworldparticle::partType == uint8_t(aod::femtoworldparticle::ParticleType::kD0D0barChild)); + // HIstogramin for particle 2 + // FemtoWorldParticleHisto trackHistoPartThree; + /// Histogramming for Event FemtoWorldEventHisto eventHisto; - /// The configurables need to be passed to an std::vector - std::vector vPIDPartOne; - /// Correlation part ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 150.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; @@ -145,8 +126,8 @@ struct femtoWorldPairTaskTrackD0 { FemtoWorldContainer sameEventCont; FemtoWorldContainer mixedEventCont; - FemtoWorldPairCleaner pairCleaner; - FemtoWorldDetaDphiStar pairCloseRejection; + FemtoWorldPairCleaner pairCleaner; + FemtoWorldDetaDphiStar pairCloseRejection; /// Histogram output HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -171,11 +152,7 @@ struct femtoWorldPairTaskTrackD0 { {"hbetaDaughters", "; p (GeV/#it{c}); TOF #beta", {HistType::kTH2F, {{300, 0., 15.}, {200, 0., 2.}}}}, {"hdEdxDaughters", "; p (GeV/#it{c}); TPC dE/dx (KeV/cm)", {HistType::kTH2F, {{300, 0., 15.}, {500, 0., 500.}}}}, {"hDCAxyDaughters", "; #it{DCA}_{xy} (cm); counts", {HistType::kTH1F, {{140, 0., 0.14}}}}, - {"hDCAzDaughters", "; #it{DCA}_{z} (cm); counts", {HistType::kTH1F, {{140, 0., 0.14}}}}, - {"hMassD0check", ";#it{M}(K#pi) (GeV/#it{c}^{2});counts", {HistType::kTH1F, {{300, 1.75, 2.05}}}}, - {"hPtD0check", ";#it{p}_{T} (GeV/#it{c});counts", {HistType::kTH1F, {{300, 0., 15.}}}}, - {"hMassD0barcheck", ";#it{M}(K#pi) (GeV/#it{c}^{2});counts", {HistType::kTH1F, {{300, 1.75, 2.05}}}}, - {"hPtD0barcheck", ";#it{p}_{T} (GeV/#it{c});counts", {HistType::kTH1F, {{300, 0., 15.}}}}}}; + {"hDCAzDaughters", "; #it{DCA}_{z} (cm); counts", {HistType::kTH1F, {{140, 0., 0.14}}}}}}; // PID for protons bool IsProtonNSigma(float mom, float nsigmaTPCPr, float nsigmaTOFPr) // previous version from: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/AliFemtoUser/AliFemtoMJTrackCut.cxx @@ -278,8 +255,7 @@ struct femtoWorldPairTaskTrackD0 { { eventHisto.init(&qaRegistry); trackHistoPartOne.init(&qaRegistry); - trackHistoPartTwo.init(&qaRegistry); - trackHistoPartThree.init(&qaRegistry); + // trackHistoPartThree.init(&qaRegistry); sameEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins, ConfPhiBins, ConfEtaBins, ConfMInvBins); sameEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo); @@ -289,8 +265,6 @@ struct femtoWorldPairTaskTrackD0 { if (ConfIsCPR) { pairCloseRejection.init(&resultRegistry, &qaRegistry, 0.01, 0.01, ConfCPRPlotPerRadii); /// \todo add config for Δη and ΔΦ cut values } - - vPIDPartOne = ConfPIDPartOne; } void processD0mesons(o2::aod::FemtoWorldCollision& col, o2::aod::FemtoWorldParticles& parts) @@ -300,7 +274,7 @@ struct femtoWorldPairTaskTrackD0 { for (auto& d0d0bar : groupPartsD0D0bar) { if (d0d0bar.flagD0() == 1) { - registry.fill(HIST("hInvMassD0"), d0d0bar.mass()); + registry.fill(HIST("hInvMassD0"), d0d0bar.massD0()); registry.fill(HIST("hMomentumD0"), d0d0bar.p()); registry.fill(HIST("hPtD0"), d0d0bar.pt()); registry.fill(HIST("hPhiD0"), d0d0bar.phi()); @@ -308,7 +282,7 @@ struct femtoWorldPairTaskTrackD0 { registry.fill(HIST("hDecayLengthD0"), d0d0bar.decayLength()); } if (d0d0bar.flagD0bar() == 1) { - registry.fill(HIST("hInvMassD0bar"), d0d0bar.mass()); + registry.fill(HIST("hInvMassD0bar"), d0d0bar.massD0bar()); registry.fill(HIST("hMomentumD0bar"), d0d0bar.p()); registry.fill(HIST("hPtD0bar"), d0d0bar.pt()); registry.fill(HIST("hPhiD0bar"), d0d0bar.phi()); @@ -347,8 +321,7 @@ struct femtoWorldPairTaskTrackD0 { { // const auto& magFieldTesla = col.magField(); auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex(), cache); - auto groupPartsThree = partsThree->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex(), cache); + auto groupPartsD0D0bar = partsD0D0barMesons->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, col.globalIndex(), cache); const int multCol = col.multV0M(); eventHisto.fillQA(col); @@ -360,31 +333,15 @@ struct femtoWorldPairTaskTrackD0 { } trackHistoPartOne.fillQA(part); } - for (auto& part : groupPartsTwo) { - trackHistoPartTwo.fillQAMult(part, multCol); - } - for (auto& part : groupPartsThree) { + /*for (auto& part : groupPartsD0D0bar) { trackHistoPartThree.fillQA(part); - } + }*/ /// Now build the combinations - for (auto& [p1, p2] : combinations(groupPartsOne, groupPartsTwo)) { + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsD0D0bar))) { if (!(IsParticleNSigma(p1.p(), p1.tpcNSigmaPr(), p1.tofNSigmaPr(), p1.tpcNSigmaPi(), p1.tofNSigmaPi(), p1.tpcNSigmaKa(), p1.tofNSigmaKa()))) { continue; } - // TODO: Include pairCloseRejection and pairCleaner - /* - if (ConfIsCPR) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla)) { - continue; - } - } - */ - // track cleaning - /*if (!pairCleaner.isCleanPair(p1, p2, parts)) { - continue; - }*/ - sameEventCont.setPair(p1, p2, multCol); } } @@ -401,8 +358,7 @@ struct femtoWorldPairTaskTrackD0 { for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, cols, cols)) { auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwo->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex(), cache); - auto groupPartsThree = partsThree->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex(), cache); + auto groupPartsD0D0bar = partsD0D0barMesons->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex(), cache); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -410,18 +366,10 @@ struct femtoWorldPairTaskTrackD0 { if (magFieldTesla1 != magFieldTesla2) { continue; } - - for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsD0D0bar))) { if (!(IsParticleNSigma(p1.p(), p1.tpcNSigmaPr(), p1.tofNSigmaPr(), p1.tpcNSigmaPi(), p1.tofNSigmaPi(), p1.tpcNSigmaKa(), p1.tofNSigmaKa()))) { continue; } - // TODO: Include pairCloseRejection and pairCleaner - /* - if (ConfIsCPR) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1)) { - continue; - } - }*/ mixedEventCont.setPair(p1, p2, collision1.multV0M()); } } diff --git a/PWGCF/FemtoWorld/Tasks/femtoWorldPionAllPairTask.cxx b/PWGCF/FemtoWorld/Tasks/femtoWorldPionAllPairTask.cxx index 7b3bbe8f4c4..44278d89471 100644 --- a/PWGCF/FemtoWorld/Tasks/femtoWorldPionAllPairTask.cxx +++ b/PWGCF/FemtoWorld/Tasks/femtoWorldPionAllPairTask.cxx @@ -102,7 +102,7 @@ struct FemtoWorldIdenticalPionPair { // Configurable> CfgCentBins{"CfgCentBins",{5.0f,10.0f,20.0f,30.0f,40.0f,50.0f},"Centrality Bins"}; ColumnBinningPolicy colBinning{{CfgVtxBins, CfgMultBins}, true}; - ColumnBinningPolicy colBinning2{{CfgVtxBins, CfgCentBinsMixing}, true}; + ColumnBinningPolicy colBinning2{{CfgVtxBins, CfgCentBinsMixing}, true}; ConfigurableAxis CfgkstarBins{"CfgkstarBins", {1500, 0., 6.}, "binning kstar"}; ConfigurableAxis CfgkTBins{"CfgkTBins", {150, 0., 9.}, "binning kT"}; @@ -174,7 +174,7 @@ struct FemtoWorldIdenticalPionPair { const auto& magFieldTesla = col.magField(); const int multCol = col.multV0M(); eventHisto.fillQA(col); - MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning2.getBin({col.posZ(), col.centRun2V0M()})); + MixQaRegistry.fill(HIST("MixingQA/hSECollisionBins"), colBinning2.getBin({col.posZ(), col.runCent()})); /// Histogramming same event for (auto& part : groupPartsOne) { @@ -244,7 +244,7 @@ struct FemtoWorldIdenticalPionPair { float kstar = FemtoWorldMath::getkstar(p1, mMassOne, p2, mMassTwo); // float kT=FemtoWorldMath::getkT(p1, mMassOne, p2, mMassTwo) - float v0mCent = col.centRun2V0M(); + float v0mCent = col.runCent(); SameEvCorrWithCent.fill(kstar, v0mCent); } } @@ -256,7 +256,7 @@ struct FemtoWorldIdenticalPionPair { { for (auto& [collision1, collision2] : soa::selfCombinations(colBinning2, 5, -1, cols, cols)) { - MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning2.getBin({collision1.posZ(), collision1.centRun2V0M()})); + MixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning2.getBin({collision1.posZ(), collision1.runCent()})); auto groupPartsOne = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision1.globalIndex(), cache); auto groupPartsTwo = partsOne->sliceByCached(aod::femtoworldparticle::femtoWorldCollisionId, collision2.globalIndex(), cache); @@ -308,7 +308,7 @@ struct FemtoWorldIdenticalPionPair { mixedEventCont.setPair(p1, p2, collision1.multV0M()); float kstar = FemtoWorldMath::getkstar(p1, mMassOne, p2, mMassTwo); - float v0mCent = collision1.centRun2V0M(); + float v0mCent = collision1.runCent(); // float kT=FemtoWorldMath::getkT(p1, mMassOne, p2, mMassTwo) MixedEvCorrWithCent.fill(kstar, v0mCent); } diff --git a/PWGCF/GenericFramework/FlowContainer.h b/PWGCF/GenericFramework/FlowContainer.h index 9c1315129e3..abafb105e26 100644 --- a/PWGCF/GenericFramework/FlowContainer.h +++ b/PWGCF/GenericFramework/FlowContainer.h @@ -9,8 +9,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef FLOWCONTAINER__H -#define FLOWCONTAINER__H +#ifndef PWGCF_GENERICFRAMEWORK_FLOWCONTAINER_H_ +#define PWGCF_GENERICFRAMEWORK_FLOWCONTAINER_H_ #include "TH3F.h" #include "TProfile2D.h" #include "TProfile.h" @@ -32,7 +32,7 @@ class FlowContainer : public TNamed { public: FlowContainer(); - FlowContainer(const char* name); + explicit FlowContainer(const char* name); ~FlowContainer(); enum StatisticsType { kSingleSample, kJackKnife, @@ -47,10 +47,10 @@ class FlowContainer : public TNamed if (fProf) fProf->RebinX(rN); }; - int GetNMultiBins() { return fProf->GetNbinsX(); }; - double GetMultiAtBin(int bin) { return fProf->GetXaxis()->GetBinCenter(bin); }; + int GetNMultiBins() { return fProf->GetNbinsX(); } + double GetMultiAtBin(int bin) { return fProf->GetXaxis()->GetBinCenter(bin); } int FillProfile(const char* hname, double multi, double y, double w, double rn); - TProfile2D* GetProfile() { return fProf; }; + TProfile2D* GetProfile() { return fProf; } void OverrideProfileErrors(TProfile2D* inpf); void ReadAndMerge(const char* infile); void PickAndMerge(TFile* tfi); @@ -58,32 +58,32 @@ class FlowContainer : public TNamed bool OverrideMainWithSub(int subind, bool ExcludeChosen); bool RandomizeProfile(int nSubsets = 0); bool CreateStatisticsProfile(StatisticsType StatType, int arg); - TObjArray* GetSubProfiles() { return fProfRand; }; + TObjArray* GetSubProfiles() { return fProfRand; } Long64_t Merge(TCollection* collist); void SetIDName(TString newname); //! do not store - void SetPtRebin(int newval) { fPtRebin = newval; }; + void SetPtRebin(int newval) { fPtRebin = newval; } void SetPtRebin(int nbins, double* binedges); void SetMultiRebin(int nbins, double* binedges); double* GetMultiRebin(int& nBins); - void SetPropagateErrors(bool newval) { fPropagateErrors = newval; }; + void SetPropagateErrors(bool newval) { fPropagateErrors = newval; } TProfile* GetCorrXXVsMulti(const char* order, int l_pti = 0); // pti = 0 for pt-integrated TProfile* GetCorrXXVsPt(const char* order, double lminmulti = -1, double lmaxmulti = -1); // 0 for multi. integrated TH1D* GetHistCorrXXVsMulti(const char* order, int l_pti = 0); // pti = 0 for pt-integrated TH1D* GetHistCorrXXVsPt(const char* order, double lminmulti = -1, double lmaxmulti = -1); // 0 for multi. integrated - TH1D* GetVN2VsMulti(int n = 2, int l_pta = 0) { return GetVN2VsX(n, kFALSE, l_pta); }; - TH1D* GetVN2VsPt(int n = 2, double min = -1, double max = -1) { return GetVN2VsX(n, kTRUE, min, max); }; - TH1D* GetCN4VsMulti(int n = 2, int pti = 0) { return GetCN4VsX(n, kFALSE, pti); }; - TH1D* GetCN4VsPt(int n = 2, double min = -1, double max = -1) { return GetCN4VsX(n, kTRUE, min, max); }; + TH1D* GetVN2VsMulti(int n = 2, int l_pta = 0) { return GetVN2VsX(n, kFALSE, l_pta); } + TH1D* GetVN2VsPt(int n = 2, double min = -1, double max = -1) { return GetVN2VsX(n, kTRUE, min, max); } + TH1D* GetCN4VsMulti(int n = 2, int pti = 0) { return GetCN4VsX(n, kFALSE, pti); } + TH1D* GetCN4VsPt(int n = 2, double min = -1, double max = -1) { return GetCN4VsX(n, kTRUE, min, max); } - TH1D* GetVN4VsMulti(int n = 2, int pti = 0) { return GetVN4VsX(n, kFALSE, pti); }; - TH1D* GetVN4VsPt(int n = 2, double min = -1, double max = -1) { return GetVN4VsX(n, kTRUE, min, max); }; + TH1D* GetVN4VsMulti(int n = 2, int pti = 0) { return GetVN4VsX(n, kFALSE, pti); } + TH1D* GetVN4VsPt(int n = 2, double min = -1, double max = -1) { return GetVN4VsX(n, kTRUE, min, max); } - TH1D* GetVN6VsMulti(int n = 2, int pti = 0) { return GetVN6VsX(n, kFALSE, pti); }; - TH1D* GetVN6VsPt(int n = 2, double min = -1, double max = -1) { return GetVN6VsX(n, kTRUE, min, max); }; + TH1D* GetVN6VsMulti(int n = 2, int pti = 0) { return GetVN6VsX(n, kFALSE, pti); } + TH1D* GetVN6VsPt(int n = 2, double min = -1, double max = -1) { return GetVN6VsX(n, kTRUE, min, max); } - TH1D* GetVN8VsMulti(int n = 2, int pti = 0) { return GetVN8VsX(n, kFALSE, pti); }; - TH1D* GetVN8VsPt(int n = 2, double min = -1, double max = -1) { return GetVN8VsX(n, kTRUE, min, max); }; + TH1D* GetVN8VsMulti(int n = 2, int pti = 0) { return GetVN8VsX(n, kFALSE, pti); } + TH1D* GetVN8VsPt(int n = 2, double min = -1, double max = -1) { return GetVN8VsX(n, kTRUE, min, max); } TH1D* GetCNN(int n = 2, int c = 2, bool onPt = kTRUE, double arg1 = -1, double arg2 = -1); TH1D* GetVNN(int n = 2, int c = 2, bool onPt = kTRUE, double arg1 = -1, double arg2 = -1); @@ -165,4 +165,4 @@ class FlowContainer : public TNamed ClassDef(FlowContainer, 2); }; -#endif \ No newline at end of file +#endif // PWGCF_GENERICFRAMEWORK_FLOWCONTAINER_H_ diff --git a/PWGCF/GenericFramework/GFW.cxx b/PWGCF/GenericFramework/GFW.cxx index 221b4324438..1541aaf8993 100644 --- a/PWGCF/GenericFramework/GFW.cxx +++ b/PWGCF/GenericFramework/GFW.cxx @@ -18,6 +18,12 @@ If used, modified, or distributed, please aknowledge the author of this code. */ #include "GFW.h" + +using std::complex; +using std::pair; +using std::string; +using std::vector; + GFW::GFW() : fInitialized(false) {} GFW::~GFW() diff --git a/PWGCF/GenericFramework/GFW.h b/PWGCF/GenericFramework/GFW.h index a9d575caea7..2b20ff7f2ad 100644 --- a/PWGCF/GenericFramework/GFW.h +++ b/PWGCF/GenericFramework/GFW.h @@ -18,6 +18,7 @@ If used, modified, or distributed, please aknowledge the author of this code. */ #ifndef PWGCF_GENERICFRAMEWORK_GFW_H_ #define PWGCF_GENERICFRAMEWORK_GFW_H_ + #include "GFWCumulant.h" #include "GFWPowerArray.h" #include @@ -25,19 +26,17 @@ If used, modified, or distributed, please aknowledge the author of this code. #include #include #include -using std::complex; -using std::string; -using std::vector; + class GFW { public: struct Region { int Nhar, NpT; - vector NparVec{}; + std::vector NparVec{}; double EtaMin = -999; double EtaMax = -999; int BitMask = 1; - string rName = ""; + std::string rName = ""; bool powsDefined = false; bool operator<(const Region& a) const { @@ -46,47 +45,47 @@ class GFW void PrintStructure() { printf("%s: eta [%f.. %f].", rName.c_str(), EtaMin, EtaMax); } }; struct CorrConfig { - vector> Regs{}; - vector> Hars{}; - vector Overlap; - vector ptInd; + std::vector> Regs{}; + std::vector> Hars{}; + std::vector Overlap; + std::vector ptInd; bool pTDif = false; - string Head = ""; + std::string Head = ""; }; GFW(); ~GFW(); - vector fRegions; - vector fCumulants; - void AddRegion(string refName, double lEtaMin, double lEtaMax, int lNpT, int BitMask); - void AddRegion(string refName, vector lNparVec, double lEtaMin, double lEtaMax, int lNpT, int BitMask); // Legacy - void AddRegion(string refName, int lNhar, int lNpar, double lEtaMin, double lEtaMax, int lNpT, int BitMask); // Legacy support, all powers are the same - void AddRegion(string refName, int lNhar, int* lNparVec, double lEtaMin, double lEtaMax, int lNpT, int BitMask); // Legacy support, array instead of a vector + std::vector fRegions; + std::vector fCumulants; + void AddRegion(std::string refName, double lEtaMin, double lEtaMax, int lNpT, int BitMask); + void AddRegion(std::string refName, std::vector lNparVec, double lEtaMin, double lEtaMax, int lNpT, int BitMask); // Legacy + void AddRegion(std::string refName, int lNhar, int lNpar, double lEtaMin, double lEtaMax, int lNpT, int BitMask); // Legacy support, all powers are the same + void AddRegion(std::string refName, int lNhar, int* lNparVec, double lEtaMin, double lEtaMax, int lNpT, int BitMask); // Legacy support, array instead of a vector int CreateRegions(); void Fill(double eta, int ptin, double phi, double weight, int mask, double secondWeight = -1); void Clear(); GFWCumulant GetCumulant(int index) { return fCumulants.at(index); } - CorrConfig GetCorrelatorConfig(string config, string head = "", bool ptdif = false); - complex Calculate(CorrConfig corconf, int ptbin, bool SetHarmsToZero); + CorrConfig GetCorrelatorConfig(std::string config, std::string head = "", bool ptdif = false); + std::complex Calculate(CorrConfig corconf, int ptbin, bool SetHarmsToZero); void InitializePowerArrays(); protected: bool fInitialized; - vector fListOfCFGs; - complex TwoRec(int n1, int n2, int p1, int p2, int ptbin, GFWCumulant*, GFWCumulant*, GFWCumulant*); - complex RecursiveCorr(GFWCumulant* qpoi, GFWCumulant* qref, GFWCumulant* qol, int ptbin, vector& hars, vector& pows); // POI, Ref. flow, overlapping region - complex RecursiveCorr(GFWCumulant* qpoi, GFWCumulant* qref, GFWCumulant* qol, int ptbin, vector& hars); // POI, Ref. flow, overlapping region + std::vector fListOfCFGs; + std::complex TwoRec(int n1, int n2, int p1, int p2, int ptbin, GFWCumulant*, GFWCumulant*, GFWCumulant*); + std::complex RecursiveCorr(GFWCumulant* qpoi, GFWCumulant* qref, GFWCumulant* qol, int ptbin, std::vector& hars, std::vector& pows); // POI, Ref. flow, overlapping region + std::complex RecursiveCorr(GFWCumulant* qpoi, GFWCumulant* qref, GFWCumulant* qol, int ptbin, std::vector& hars); // POI, Ref. flow, overlapping region void AddRegion(Region inreg) { fRegions.push_back(inreg); } Region GetRegion(int index) { return fRegions.at(index); } - int FindRegionByName(string refName); - vector>> GetHarmonicsSingleConfig(const CorrConfig&); + int FindRegionByName(std::string refName); + std::vector>> GetHarmonicsSingleConfig(const CorrConfig&); // Calculating functions: - complex Calculate(int poi, int ref, vector hars, int ptbin = 0); // For differential, need POI and reference - complex Calculate(int poi, vector hars); // For integrated case + std::complex Calculate(int poi, int ref, std::vector hars, int ptbin = 0); // For differential, need POI and reference + std::complex Calculate(int poi, std::vector hars); // For integrated case // Operations on strings. Equivalent to TString operations, but one to rid of root dependence - int s_index(string& instr, const string& pattern, const int& spos = 0); - bool s_contains(string& instr, const string& pattern); - void s_replace(string& instr, const string& pattern1, const string& pattern2, const int& spos = 0); - void s_replace_all(string& instr, const string& pattern1, const string& pattern2); - bool s_tokenize(string& instr, string& substr, int& spos, const string& delim); + int s_index(std::string& instr, const std::string& pattern, const int& spos = 0); + bool s_contains(std::string& instr, const std::string& pattern); + void s_replace(std::string& instr, const std::string& pattern1, const std::string& pattern2, const int& spos = 0); + void s_replace_all(std::string& instr, const std::string& pattern1, const std::string& pattern2); + bool s_tokenize(std::string& instr, std::string& substr, int& spos, const std::string& delim); }; #endif // PWGCF_GENERICFRAMEWORK_GFW_H_ diff --git a/PWGCF/GenericFramework/GFWCumulant.cxx b/PWGCF/GenericFramework/GFWCumulant.cxx index 6ced53f6334..a82e3bcd08b 100644 --- a/PWGCF/GenericFramework/GFWCumulant.cxx +++ b/PWGCF/GenericFramework/GFWCumulant.cxx @@ -16,7 +16,12 @@ A part of A container to store Q vectors for one subevent with an extra layer to recursively calculate particle correlations. If used, modified, or distributed, please aknowledge the author of this code. */ + #include "GFWCumulant.h" + +using std::complex; +using std::vector; + GFWCumulant::GFWCumulant() : fQvector(0), fUsed(kBlank), fNEntries(-1), diff --git a/PWGCF/GenericFramework/GFWCumulant.h b/PWGCF/GenericFramework/GFWCumulant.h index 7aff3c4acf9..70341e8e625 100644 --- a/PWGCF/GenericFramework/GFWCumulant.h +++ b/PWGCF/GenericFramework/GFWCumulant.h @@ -18,11 +18,11 @@ If used, modified, or distributed, please aknowledge the author of this code. */ #ifndef PWGCF_GENERICFRAMEWORK_GFWCUMULANT_H_ #define PWGCF_GENERICFRAMEWORK_GFWCUMULANT_H_ + #include #include #include -using std::complex; -using std::vector; + class GFWCumulant { public: @@ -42,22 +42,22 @@ class GFWCumulant int GetN() { return fNEntries; } bool IsPtBinFilled(int ptb); void CreateComplexVectorArray(int N = 1, int P = 1, int Pt = 1); - void CreateComplexVectorArrayVarPower(int N = 1, vector Pvec = {1}, int Pt = 1); + void CreateComplexVectorArrayVarPower(int N = 1, std::vector Pvec = {1}, int Pt = 1); int PW(int ind) { return fPowVec.at(ind); }; // No checks to speed up, be carefull!!! void DestroyComplexVectorArray(); - complex Vec(int, int, int ptbin = 0); // envelope class to summarize pt-dif. Q-vec getter + std::complex Vec(int, int, int ptbin = 0); // envelope class to summarize pt-dif. Q-vec getter protected: - complex*** fQvector; + std::complex*** fQvector; uint fUsed; int fNEntries; // Q-vectors. Could be done recursively, but maybe defining each one of them explicitly is easier to read int fN; //! Harmonics int fPow; //! Power - vector fPowVec; //! Powers array + std::vector fPowVec; //! Powers array int fPt; //! fPt bins bool* fFilledPts; bool fInitialized; // Arrays are initialized - complex fNullQ = 0; + std::complex fNullQ = 0; }; #endif // PWGCF_GENERICFRAMEWORK_GFWCUMULANT_H_ diff --git a/PWGCF/GenericFramework/GFWPowerArray.cxx b/PWGCF/GenericFramework/GFWPowerArray.cxx index 197e836ed05..82291e507a2 100644 --- a/PWGCF/GenericFramework/GFWPowerArray.cxx +++ b/PWGCF/GenericFramework/GFWPowerArray.cxx @@ -10,6 +10,10 @@ // or submit itself to any jurisdiction. #include "GFWPowerArray.h" + +using std::string; +using std::vector; + int GFWPowerArray::getHighestHarmonic(const HarSet& inhar) { // Highest possible harmonic: sum of same-sign harmonics diff --git a/PWGCF/GenericFramework/GFWPowerArray.h b/PWGCF/GenericFramework/GFWPowerArray.h index 9562d601e5c..12d7361fbc2 100644 --- a/PWGCF/GenericFramework/GFWPowerArray.h +++ b/PWGCF/GenericFramework/GFWPowerArray.h @@ -11,17 +11,16 @@ #ifndef PWGCF_GENERICFRAMEWORK_GFWPOWERARRAY_H_ #define PWGCF_GENERICFRAMEWORK_GFWPOWERARRAY_H_ + #include #include #include -using namespace std; -using std::string; -using std::vector; -typedef vector HarSet; + +typedef std::vector HarSet; class GFWPowerArray { public: - static HarSet GetPowerArray(vector inHarmonics); + static HarSet GetPowerArray(std::vector inHarmonics); static void PowerArrayTest(); private: diff --git a/PWGCF/GenericFramework/GFWWeights.cxx b/PWGCF/GenericFramework/GFWWeights.cxx index e1d4333fc88..d40cb26d3b8 100644 --- a/PWGCF/GenericFramework/GFWWeights.cxx +++ b/PWGCF/GenericFramework/GFWWeights.cxx @@ -11,7 +11,8 @@ #include "GFWWeights.h" #include "TMath.h" -GFWWeights::GFWWeights() : fDataFilled(kFALSE), +GFWWeights::GFWWeights() : TNamed("", ""), + fDataFilled(kFALSE), fMCFilled(kFALSE), fW_data(0), fW_mcrec(0), @@ -20,7 +21,18 @@ GFWWeights::GFWWeights() : fDataFilled(kFALSE), fIntEff(0), fAccInt(0), fNbinsPt(0), - fbinsPt(0){}; + fbinsPt(0) {} +GFWWeights::GFWWeights(const char* name) : TNamed(name, name), + fDataFilled(kFALSE), + fMCFilled(kFALSE), + fW_data(0), + fW_mcrec(0), + fW_mcgen(0), + fEffInt(0), + fIntEff(0), + fAccInt(0), + fNbinsPt(0), + fbinsPt(0) {} GFWWeights::~GFWWeights() { delete fW_data; @@ -48,7 +60,7 @@ void GFWWeights::Init(bool AddData, bool AddMC) fbinsPt = new double[2]; fbinsPt[0] = -1; fbinsPt[1] = 1e6; - }; + } if (AddData) { fW_data = new TObjArray(); fW_data->SetName("GFWWeights_Data"); @@ -56,7 +68,7 @@ void GFWWeights::Init(bool AddData, bool AddMC) const char* tnd = GetBinName(0, 0, Form("data_%s", this->GetName())); fW_data->Add(new TH3D(tnd, ";#varphi;#eta;v_{z}", 60, 0, TMath::TwoPi(), 64, -1.6, 1.6, 40, -10, 10)); fDataFilled = kTRUE; - }; + } if (AddMC) { fW_mcrec = new TObjArray(); fW_mcrec->SetName("GFWWeights_MCRec"); @@ -68,10 +80,10 @@ void GFWWeights::Init(bool AddData, bool AddMC) const char* tng = GetBinName(0, 0, "mcgen"); // all integrated over cent. anyway fW_mcrec->Add(new TH3D(tnr, ";#it{p}_{T};#eta;v_{z}", fNbinsPt, 0, 20, 64, -1.6, 1.6, 40, -10, 10)); fW_mcgen->Add(new TH3D(tng, ";#it{p}_{T};#eta;v_{z}", fNbinsPt, 0, 20, 64, -1.6, 1.6, 40, -10, 10)); - ((TH3D*)fW_mcrec->At(fW_mcrec->GetEntries() - 1))->GetXaxis()->Set(fNbinsPt, fbinsPt); - ((TH3D*)fW_mcgen->At(fW_mcgen->GetEntries() - 1))->GetXaxis()->Set(fNbinsPt, fbinsPt); + reinterpret_cast(fW_mcrec->At(fW_mcrec->GetEntries() - 1))->GetXaxis()->Set(fNbinsPt, fbinsPt); + reinterpret_cast(fW_mcgen->At(fW_mcgen->GetEntries() - 1))->GetXaxis()->Set(fNbinsPt, fbinsPt); fMCFilled = kTRUE; - }; + } }; void GFWWeights::Fill(double phi, double eta, double vz, double pt, double cent, int htype, double weight) @@ -81,23 +93,23 @@ void GFWWeights::Fill(double phi, double eta, double vz, double pt, double cent, if (htype == 0) { tar = fW_data; pf = Form("data_%s", this->GetName()); - }; + } if (htype == 1) { tar = fW_mcrec; pf = "mcrec"; - }; + } if (htype == 2) { tar = fW_mcgen; pf = "mcgen"; - }; + } if (!tar) return; - TH3D* th3 = (TH3D*)tar->FindObject(GetBinName(0, 0, pf)); // pT bin 0, V0M bin 0, since all integrated + TH3D* th3 = reinterpret_cast(tar->FindObject(GetBinName(0, 0, pf))); // pT bin 0, V0M bin 0, since all integrated if (!th3) { if (!htype) tar->Add(new TH3D(GetBinName(0, 0, pf), ";#varphi;#eta;v_{z}", 60, 0, TMath::TwoPi(), 64, -1.6, 1.6, 40, -10, 10)); // 0,0 since all integrated - th3 = (TH3D*)tar->At(tar->GetEntries() - 1); - }; + th3 = reinterpret_cast(tar->At(tar->GetEntries() - 1)); + } th3->Fill(htype ? pt : phi, eta, vz, weight); }; double GFWWeights::GetWeight(double phi, double eta, double vz, double pt, double cent, int htype) @@ -107,18 +119,18 @@ double GFWWeights::GetWeight(double phi, double eta, double vz, double pt, doubl if (htype == 0) { tar = fW_data; pf = "data"; - }; + } if (htype == 1) { tar = fW_mcrec; pf = "mcrec"; - }; + } if (htype == 2) { tar = fW_mcgen; pf = "mcgen"; - }; + } if (!tar) return 1; - TH3D* th3 = (TH3D*)tar->FindObject(GetBinName(0, 0, pf)); + TH3D* th3 = reinterpret_cast(tar->FindObject(GetBinName(0, 0, pf))); if (!th3) return 1; //-1; int xind = th3->GetXaxis()->FindBin(htype ? pt : phi); @@ -164,7 +176,7 @@ double GFWWeights::FindMax(TH3D* inh, int& ix, int& iy, int& iz) iy = j; iz = k; maxv = inh->GetBinContent(i, j, k); - }; + } return maxv; }; void GFWWeights::MCToEfficiency() @@ -172,14 +184,14 @@ void GFWWeights::MCToEfficiency() if (fW_mcgen->GetEntries() < 1) { printf("MC gen. array empty. This is probably because effs. have been calculated and the generated particle histograms have been cleared out!\n"); return; - }; + } for (int i = 0; i < fW_mcrec->GetEntries(); i++) { - TH3D* hr = (TH3D*)fW_mcrec->At(i); - TH3D* hg = (TH3D*)fW_mcgen->At(i); + TH3D* hr = reinterpret_cast(fW_mcrec->At(i)); + TH3D* hg = reinterpret_cast(fW_mcgen->At(i)); hr->Sumw2(); hg->Sumw2(); hr->Divide(hg); - }; + } fW_mcgen->Clear(); }; void GFWWeights::RebinNUA(int nX, int nY, int nZ) @@ -187,24 +199,24 @@ void GFWWeights::RebinNUA(int nX, int nY, int nZ) if (fW_data->GetEntries() < 1) return; for (int i = 0; i < fW_data->GetEntries(); i++) { - ((TH3D*)fW_data->At(i))->RebinX(nX); - ((TH3D*)fW_data->At(i))->RebinY(nY); - ((TH3D*)fW_data->At(i))->RebinZ(nZ); - }; + reinterpret_cast(fW_data->At(i))->RebinX(nX); + reinterpret_cast(fW_data->At(i))->RebinY(nY); + reinterpret_cast(fW_data->At(i))->RebinZ(nZ); + } }; void GFWWeights::CreateNUA(bool IntegrateOverCentAndPt) { if (!IntegrateOverCentAndPt) { printf("Method is outdated! NUA is integrated over centrality and pT. Quit now, or the behaviour will be bad\n"); return; - }; + } TH1D* h1; if (fW_data->GetEntries() < 1) return; if (IntegrateOverCentAndPt) { if (fAccInt) delete fAccInt; - fAccInt = (TH3D*)fW_data->At(0)->Clone("IntegratedAcceptance"); + fAccInt = reinterpret_cast(fW_data->At(0)->Clone("IntegratedAcceptance")); fAccInt->Sumw2(); for (int etai = 1; etai <= fAccInt->GetNbinsY(); etai++) { fAccInt->GetYaxis()->SetRange(etai, etai); @@ -214,24 +226,24 @@ void GFWWeights::CreateNUA(bool IntegrateOverCentAndPt) fAccInt->GetZaxis()->SetRange(vzi, vzi); if (fAccInt->Integral() < 1) continue; - h1 = (TH1D*)fAccInt->Project3D("x"); + h1 = reinterpret_cast(fAccInt->Project3D("x")); double maxv = h1->GetMaximum(); for (int phii = 1; phii <= h1->GetNbinsX(); phii++) { fAccInt->SetBinContent(phii, etai, vzi, fAccInt->GetBinContent(phii, etai, vzi) / maxv); fAccInt->SetBinError(phii, etai, vzi, fAccInt->GetBinError(phii, etai, vzi) / maxv); - }; + } delete h1; - }; + } fAccInt->GetZaxis()->SetRange(1, fAccInt->GetNbinsZ()); - }; + } fAccInt->GetYaxis()->SetRange(1, fAccInt->GetNbinsY()); return; - }; + } }; TH1D* GFWWeights::GetdNdPhi() { - TH3D* temph = (TH3D*)fW_data->At(0)->Clone("tempH3"); - TH1D* reth = (TH1D*)temph->Project3D("x"); + TH3D* temph = reinterpret_cast(fW_data->At(0)->Clone("tempH3")); + TH1D* reth = reinterpret_cast(temph->Project3D("x")); reth->SetName("RetHist"); delete temph; double max = reth->GetMaximum(); @@ -250,24 +262,24 @@ void GFWWeights::CreateNUE(bool IntegrateOverCentrality) if (!IntegrateOverCentrality) { printf("Method is outdated! NUE is integrated over centrality. Quit now, or the behaviour will be bad\n"); return; - }; + } TH3D* num = 0; TH3D* den = 0; if (fW_mcrec->GetEntries() < 1 || fW_mcgen->GetEntries() < 1) return; if (IntegrateOverCentrality) { - num = (TH3D*)fW_mcrec->At(0); - den = (TH3D*)fW_mcgen->At(0); + num = reinterpret_cast(fW_mcrec->At(0)); + den = reinterpret_cast(fW_mcgen->At(0)); num->Sumw2(); den->Sumw2(); num->RebinY(2); den->RebinY(2); num->RebinZ(5); den->RebinZ(5); - fEffInt = (TH3D*)num->Clone("Efficiency_Integrated"); + fEffInt = reinterpret_cast(num->Clone("Efficiency_Integrated")); fEffInt->Divide(den); return; - }; + } }; void GFWWeights::ReadAndMerge(TString filelinks, TString listName, bool addData, bool addRec, bool addGen) { @@ -280,22 +292,22 @@ void GFWWeights::ReadAndMerge(TString filelinks, TString listName, bool addData, if (nFiles == 0) { printf("No files to read!\n"); return; - }; + } if (!fW_data && addData) { fW_data = new TObjArray(); fW_data->SetName("Weights_Data"); fW_data->SetOwner(kTRUE); - }; + } if (!fW_mcrec && addRec) { fW_mcrec = new TObjArray(); fW_mcrec->SetName("Weights_MCRec"); fW_mcrec->SetOwner(kTRUE); - }; + } if (!fW_mcgen && addGen) { fW_mcgen = new TObjArray(); fW_mcgen->SetName("Weights_MCGen"); fW_mcgen->SetOwner(kTRUE); - }; + } TFile* tf = 0; for (int i = 0; i < nFiles; i++) { auto retVal = fscanf(flist, "%s\n", str); @@ -305,14 +317,14 @@ void GFWWeights::ReadAndMerge(TString filelinks, TString listName, bool addData, printf("Could not open file %s!\n", str); tf->Close(); continue; - }; - TList* tl = (TList*)tf->Get(listName.Data()); - GFWWeights* tw = (GFWWeights*)tl->FindObject(this->GetName()); + } + TList* tl = reinterpret_cast(tf->Get(listName.Data())); + GFWWeights* tw = reinterpret_cast(tl->FindObject(this->GetName())); if (!tw) { printf("Could not fetch weights object from %s\n", str); tf->Close(); continue; - }; + } if (addData) AddArray(fW_data, tw->GetDataArray()); if (addRec) @@ -321,33 +333,34 @@ void GFWWeights::ReadAndMerge(TString filelinks, TString listName, bool addData, AddArray(fW_mcgen, tw->GetGenArray()); tf->Close(); delete tw; - }; + } }; void GFWWeights::AddArray(TObjArray* targ, TObjArray* sour) { if (!sour) { printf("Source array does not exist!\n"); return; - }; + } for (int i = 0; i < sour->GetEntries(); i++) { - TH3D* sourh = (TH3D*)sour->At(i); - TH3D* targh = (TH3D*)targ->FindObject(sourh->GetName()); + TH3D* sourh = reinterpret_cast(sour->At(i)); + TH3D* targh = reinterpret_cast(targ->FindObject(sourh->GetName())); if (!targh) { - targh = (TH3D*)sourh->Clone(sourh->GetName()); + targh = reinterpret_cast(sourh->Clone(sourh->GetName())); targh->SetDirectory(0); targ->Add(targh); - } else + } else { targh->Add(sourh); - }; + } + } }; void GFWWeights::OverwriteNUA() { if (!fAccInt) CreateNUA(); TString ts(fW_data->At(0)->GetName()); - TH3D* trash = (TH3D*)fW_data->RemoveAt(0); + TH3D* trash = reinterpret_cast(fW_data->RemoveAt(0)); delete trash; - fW_data->Add((TH3D*)fAccInt->Clone(ts.Data())); + fW_data->Add(reinterpret_cast(fAccInt->Clone(ts.Data()))); delete fAccInt; } Long64_t GFWWeights::Merge(TCollection* collist) @@ -357,25 +370,25 @@ Long64_t GFWWeights::Merge(TCollection* collist) fW_data = new TObjArray(); fW_data->SetName("Weights_Data"); fW_data->SetOwner(kTRUE); - }; + } if (!fW_mcrec) { fW_mcrec = new TObjArray(); fW_mcrec->SetName("Weights_MCRec"); fW_mcrec->SetOwner(kTRUE); - }; + } if (!fW_mcgen) { fW_mcgen = new TObjArray(); fW_mcgen->SetName("Weights_MCGen"); fW_mcgen->SetOwner(kTRUE); - }; + } GFWWeights* l_w = 0; TIter all_w(collist); - while ((l_w = ((GFWWeights*)all_w()))) { + while ((l_w = (reinterpret_cast(all_w())))) { AddArray(fW_data, l_w->GetDataArray()); AddArray(fW_mcrec, l_w->GetRecArray()); AddArray(fW_mcgen, l_w->GetGenArray()); nmerged++; - }; + } return nmerged; }; TH1D* GFWWeights::GetIntegratedEfficiencyHist() @@ -383,29 +396,29 @@ TH1D* GFWWeights::GetIntegratedEfficiencyHist() if (!fW_mcgen) { printf("MCGen array does not exist!\n"); return 0; - }; + } if (!fW_mcrec) { printf("MCRec array does not exist!\n"); return 0; - }; + } if (!fW_mcgen->GetEntries()) { printf("MCGen array is empty!\n"); return 0; - }; + } if (!fW_mcrec->GetEntries()) { printf("MCRec array is empty!\n"); return 0; - }; - TH3D* num = (TH3D*)fW_mcrec->At(0)->Clone("Numerator"); + } + TH3D* num = reinterpret_cast(fW_mcrec->At(0)->Clone("Numerator")); for (int i = 1; i < fW_mcrec->GetEntries(); i++) - num->Add((TH3D*)fW_mcrec->At(i)); - TH3D* den = (TH3D*)fW_mcgen->At(0)->Clone("Denominator"); + num->Add(reinterpret_cast(fW_mcrec->At(i))); + TH3D* den = reinterpret_cast(fW_mcgen->At(0)->Clone("Denominator")); for (int i = 1; i < fW_mcgen->GetEntries(); i++) - den->Add((TH3D*)fW_mcgen->At(i)); - TH1D* num1d = (TH1D*)num->Project3D("x"); + den->Add(reinterpret_cast(fW_mcgen->At(i))); + TH1D* num1d = reinterpret_cast(num->Project3D("x")); num1d->SetName("retHist"); num1d->Sumw2(); - TH1D* den1d = (TH1D*)den->Project3D("x"); + TH1D* den1d = reinterpret_cast(den->Project3D("x")); den1d->Sumw2(); num1d->Divide(den1d); delete num; @@ -420,7 +433,7 @@ bool GFWWeights::CalculateIntegratedEff() fIntEff = GetIntegratedEfficiencyHist(); if (!fIntEff) { return kFALSE; - }; + } fIntEff->SetName("IntegratedEfficiency"); return kTRUE; } @@ -433,12 +446,12 @@ double GFWWeights::GetIntegratedEfficiency(double pt) } TH1D* GFWWeights::GetEfficiency(double etamin, double etamax, double vzmin, double vzmax) { - TH3D* num = (TH3D*)fW_mcrec->At(0)->Clone("Numerator"); + TH3D* num = reinterpret_cast(fW_mcrec->At(0)->Clone("Numerator")); for (int i = 1; i < fW_mcrec->GetEntries(); i++) - num->Add((TH3D*)fW_mcrec->At(i)); - TH3D* den = (TH3D*)fW_mcgen->At(0)->Clone("Denominator"); + num->Add(reinterpret_cast(fW_mcrec->At(i))); + TH3D* den = reinterpret_cast(fW_mcgen->At(0)->Clone("Denominator")); for (int i = 1; i < fW_mcgen->GetEntries(); i++) - den->Add((TH3D*)fW_mcgen->At(i)); + den->Add(reinterpret_cast(fW_mcgen->At(i))); int eb1 = num->GetYaxis()->FindBin(etamin + 1e-6); int eb2 = num->GetYaxis()->FindBin(etamax - 1e-6); int vz1 = num->GetZaxis()->FindBin(vzmin + 1e-6); @@ -447,8 +460,8 @@ TH1D* GFWWeights::GetEfficiency(double etamin, double etamax, double vzmin, doub num->GetZaxis()->SetRange(vz1, vz2); den->GetYaxis()->SetRange(eb1, eb2); den->GetZaxis()->SetRange(vz1, vz2); - TH1D* num1d = (TH1D*)num->Project3D("x"); - TH1D* den1d = (TH1D*)den->Project3D("x"); + TH1D* num1d = reinterpret_cast(num->Project3D("x")); + TH1D* den1d = reinterpret_cast(den->Project3D("x")); delete num; delete den; num1d->Sumw2(); @@ -456,4 +469,4 @@ TH1D* GFWWeights::GetEfficiency(double etamin, double etamax, double vzmin, doub num1d->Divide(den1d); delete den1d; return num1d; -} \ No newline at end of file +} diff --git a/PWGCF/GenericFramework/GFWWeights.h b/PWGCF/GenericFramework/GFWWeights.h index c863a4b4895..67fb3d8f116 100644 --- a/PWGCF/GenericFramework/GFWWeights.h +++ b/PWGCF/GenericFramework/GFWWeights.h @@ -9,8 +9,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef GFWWeights__H -#define GFWWeights__H +#ifndef PWGCF_GENERICFRAMEWORK_GFWWEIGHTS_H_ +#define PWGCF_GENERICFRAMEWORK_GFWWEIGHTS_H_ #include "TObjArray.h" #include "TNamed.h" #include "TH3D.h" @@ -24,26 +24,27 @@ class GFWWeights : public TNamed { public: GFWWeights(); + explicit GFWWeights(const char* name); ~GFWWeights(); void Init(bool AddData = kTRUE, bool AddM = kTRUE); void Fill(double phi, double eta, double vz, double pt, double cent, int htype, double weight = 1); // htype: 0 for data, 1 for mc rec, 2 for mc gen double GetWeight(double phi, double eta, double vz, double pt, double cent, int htype); // htype: 0 for data, 1 for mc rec, 2 for mc gen double GetNUA(double phi, double eta, double vz); // This just fetches correction from integrated NUA, should speed up double GetNUE(double pt, double eta, double vz); // fetches weight from fEffInt - bool IsDataFilled() { return fDataFilled; }; - bool IsMCFilled() { return fMCFilled; }; + bool IsDataFilled() { return fDataFilled; } + bool IsMCFilled() { return fMCFilled; } double FindMax(TH3D* inh, int& ix, int& iy, int& iz); void MCToEfficiency(); - TObjArray* GetRecArray() { return fW_mcrec; }; - TObjArray* GetGenArray() { return fW_mcgen; }; - TObjArray* GetDataArray() { return fW_data; }; + TObjArray* GetRecArray() { return fW_mcrec; } + TObjArray* GetGenArray() { return fW_mcgen; } + TObjArray* GetDataArray() { return fW_data; } void CreateNUA(bool IntegrateOverCentAndPt = kTRUE); void CreateNUE(bool IntegrateOverCentrality = kTRUE); TH1D* GetIntegratedEfficiencyHist(); bool CalculateIntegratedEff(); double GetIntegratedEfficiency(double pt); - void SetDataFilled(bool newval) { fDataFilled = newval; }; - void SetMCFilled(bool newval) { fMCFilled = newval; }; + void SetDataFilled(bool newval) { fDataFilled = newval; } + void SetMCFilled(bool newval) { fMCFilled = newval; } void ReadAndMerge(TString filelinks, TString listName = "OutputList", bool addData = kTRUE, bool addRec = kTRUE, bool addGen = kTRUE); void SetPtBins(int Nbins, double* bins); Long64_t Merge(TCollection* collist); @@ -74,4 +75,4 @@ class GFWWeights : public TNamed ClassDef(GFWWeights, 1); }; -#endif \ No newline at end of file +#endif // PWGCF_GENERICFRAMEWORK_GFWWEIGHTS_H_ diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h index 09bf8ce6a60..c99bf50c2e8 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h @@ -8,22 +8,87 @@ // 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_MULTIPARTICLECORRELATIONS_CORE_MUPA_CONFIGURABLES_H_ #define PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_CONFIGURABLES_H_ #include // Task configuration: -Configurable cfTaskName{"cfTaskName", "Default task name", "set task name - use eventually to determine weights for this task"}; -Configurable cfVerbose{"cfVerbose", true, "run or not in verbose mode"}; +Configurable cfTaskName{ + "cfTaskName", "Default task name", + "set task name - use eventually to determine weights for this task"}; +Configurable cfVerbose{ + "cfVerbose", false, + "run or not in verbose mode (but not for function calls per particle)"}; +Configurable cfVerboseForEachParticle{ + "cfVerboseForEachParticle", false, + "run or not in verbose mode (also for function calls per particle)"}; +Configurable cfDoAdditionalInsanityChecks{ + "cfDoAdditionalInsanityChecks", false, + "do additional insanity checks at run time (this leads to small loss of performance)"}; +Configurable cfUseCCDB{ + "cfUseCCDB", true, + "access personal files from CCDB or from home dir in AliEn"}; +Configurable cfWhatToProcess{ + "cfWhatToProcess", "Rec", + "Rec = process only reconstructed, Sim = process only simulated, RecSim = process both reconstructed and simulated"}; // Test0: -Configurable cfCalculateTest0{"cfCalculateTest0", false, "calculate or not Test0"}; -Configurable cfLabels{"cfLabels", "/home/abilandz/DatasetsO2/labels.root", "TBI description"}; +Configurable cfCalculateTest0{"cfCalculateTest0", false, + "calculate or not Test0"}; +Configurable cfFileWithLabels{"cfFileWithLabels", + "/home/abilandz/DatasetsO2/labels.root", "path to external ROOT file which specifies all labels"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" + +// Particle weights: +Configurable cfUsePhiWeights{"cfUsePhiWeights", false, + "use or not phi weights"}; +Configurable cfUsePtWeights{"cfUsePtWeights", false, + "use or not pt weights"}; +Configurable cfUseEtaWeights{"cfUseEtaWeights", false, + "use or not eta weights"}; +Configurable cfFileWithWeights{"cfFileWithWeights", + "/home/abilandz/DatasetsO2/weights.root", "path to external ROOT file which holds all particle weights in O2 format"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" // Event cuts: -Configurable Vz_min{"Vz_min", -10.0, "minimum vertex z range [cm]"}; -Configurable Vz_max{"Vz_max", 10.0, "maximum vertex z range [cm]"}; +Configurable cNumberOfEvents_min{ + "cNumberOfEvents_min", -1, + "minimum number of events to process (set to -1 to ignore)"}; +Configurable cNumberOfEvents_max{"cNumberOfEvents_max", 1000000000, + "maximum number of events to process"}; +Configurable cTotalMultiplicity_min{ + "cTotalMultiplicity_min", -1, + "minimum total multiplicity of an event to be processed (set to -1 to " + "ignore)"}; +Configurable cTotalMultiplicity_max{ + "cTotalMultiplicity_max", 1000000000, + "maximum total multiplicity of an event to be processed"}; +Configurable cSelectedTracks_min{ + "cSelectedTracks_min", -1, + "minimum number of selected tracks (set to -1 to ignore)"}; +Configurable cSelectedTracks_max{"cSelectedTracks_max", 1000000000, + "maximum number of selected tracks"}; +Configurable cCentrality_min{"cCentrality_min", 0., + "minimum centrality"}; +Configurable cCentrality_max{"cCentrality_max", 100., + "maximum centrality"}; +Configurable cVertex_x_min{"cVertex_x_min", -10.0, + "minimum vertex x range [cm]"}; +Configurable cVertex_x_max{"cVertex_x_max", 10.0, + "maximum vertex x range [cm]"}; +Configurable cVertex_y_min{"cVertex_y_min", -10.0, + "minimum vertex y range [cm]"}; +Configurable cVertex_y_max{"cVertex_y_max", 10.0, + "maximum vertex y range [cm]"}; +Configurable cVertex_z_min{"cVertex_z_min", -10.0, + "minimum vertex z range [cm]"}; +Configurable cVertex_z_max{"cVertex_z_max", 10.0, + "maximum vertex z range [cm]"}; +Configurable cNContributors_min{ + "cNContributors_min", -1, + "minimum number of vertex contributors (set to -1 to ignore)"}; +Configurable cNContributors_max{"cNContributors_max", 1000000000, + "maximum number of vertex contributors"}; // Particle cuts: Configurable pt_min{"pt_min", 0.2, "minimum track pt value [GeV/c]"}; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h index a7c521718e1..017b04d5d2f 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h @@ -8,12 +8,15 @@ // 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_MULTIPARTICLECORRELATIONS_CORE_MUPA_DATAMEMBERS_H_ #define PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_DATAMEMBERS_H_ // Remarks: -// 0. Starting with C++11, it's possible to initialize data members at declaration, so I do it here -// 1. Use //! fBaseList{"Default list name", OutputObjHandlingPolicy::AnalysisObject, OutputObjSourceType::OutputObjSource}; +OutputObj fBaseList{"Default list name", + OutputObjHandlingPolicy::AnalysisObject, + OutputObjSourceType::OutputObjSource}; TProfile* fBasePro = NULL; //! void Preprocess(T const& collision) +// Bool_t MaxNumberOfEvents(const Int_t rs); +// void GetParticleWeights(); +// template void DetermineAndPropagateRunNumber(T const& collision) +// template void CheckCurrentRunNumber(T const& collision); +// template void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) +// template Bool_t EventCuts(T1 const& collision, T2 const& tracks) +// void MainLoopOverParticlesRec(TracksRec const& tracks) +// void MainLoopOverParticlesRecSim(TracksRecSim const& tracks) +// void MainLoopOverParticlesSim(TracksSim const& tracks) +// template void FillParticleHistograms(T const& track, eBeforeAfter ba) +// template void ParticleCuts(T const& track, eRecSim rs) +// void ResetEventByEventQuantities(); + +// Double_t Weight(const Double_t &value, const char *variable) +// void CalculateEverything(); +// void CalculateCorrelations(); +// void CalculateNestedLoops(); // calculate all standard isotropic correlations with nested loops +// Double_t CalculateCustomNestedLoop(TArrayI *harmonics); // calculate nested loop for the specified harmonics // *) Called after all events are processed (former "Terminate()"): // void ComparisonNestedLoopsVsCorrelations(); @@ -59,20 +76,14 @@ // *) Particle weights: // void SetWeightsHist(TH1D* const hist, const char *variable) // TH1D* GetWeightsHist(const char *variable) -// TH1D* GetHistogramWithWeights(const char *filePath, const char *variable) +// TH1D* GetHistogramWithWeights(const char* filePath, const char* runNumber, +// const char* variable) // *) Test0: // TObjArray* GetObjArrayWithLabels(const char *filePath) // *) Utility: -// void Red(const char* text); -// void Green(const char* text); -// void Yellow(const char* text); -// void Blue(const char* text); -// TObject* GetObjectFromList(TList *list, Char_t *objectName); // 20220803 NOT_PORTED_YET -// Int_t NumberOfNonEmptyLines(const char *externalFile); // 20220803 NOT_PORTED_YET -// void Exit(const char* functionName, const Int_t lineNumber, const char* message); // 20220803 NOT_PORTED_YET -// void Warning(const char* functionName, const Int_t lineNumber, const char* message); // 20220803 NOT_PORTED_YET +// TObject* GetObjectFromList(TList *list, Char_t *objectName); //============================================================ @@ -80,20 +91,34 @@ void BookBaseList() { // ... + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + TList* temp = new TList(); temp->SetOwner(kTRUE); fBaseList.setObject(temp); // fBaseList.object->SetName("4444"); - fBasePro = new TProfile("fBasePro", "flags for the whole analysis", eConfiguration_N, 0., eConfiguration_N); + fBasePro = new TProfile("fBasePro", "flags for the whole analysis", + eConfiguration_N, 0., eConfiguration_N); fBasePro->SetStats(kFALSE); fBasePro->SetLineColor(eColor); fBasePro->SetFillColor(eFillColor); - // Remark: If I want to change the ordering of bin lables, simply change the ordering in enum eConfiguration { ... }, nothing needs to be changed here. - fBasePro->GetXaxis()->SetBinLabel(eTaskName, Form("fTaskName = %s", fTaskName.Data())); + // Remark: If I want to change the ordering of bin lables, simply change the + // ordering in enum eConfiguration { ... }, nothing needs to be changed here. + fBasePro->GetXaxis()->SetBinLabel(eTaskName, + Form("fTaskName = %s", fTaskName.Data())); + fBasePro->GetXaxis()->SetBinLabel(eRunNumber, + Form("fRunNumber = %s", fRunNumber.Data())); fBasePro->GetXaxis()->SetBinLabel(eVerbose, "fVerbose"); fBasePro->Fill(eVerbose - 0.5, (Int_t)fVerbose); + fBasePro->GetXaxis()->SetBinLabel(eVerboseForEachParticle, + "fVerboseForEachParticle"); + fBasePro->Fill(eVerboseForEachParticle - 0.5, (Int_t)fVerboseForEachParticle); + fBasePro->GetXaxis()->SetBinLabel(eUseCCDB, "fUseCCDB"); + fBasePro->Fill(eUseCCDB - 0.5, (Int_t)fUseCCDB); fBaseList->Add(fBasePro); @@ -101,13 +126,60 @@ void BookBaseList() //============================================================ +void WhatToProcess() +{ + // Set here what to process: only rec, both rec and sim, only sim. + // Use in combination with configurable cfWhatToProcess. + // TBI 20231017 I call this function, but it still has no desired effect, until I can call PROCESS_SWITCH( ) by passing a variable, instead only literals 'true' or 'false', as it is now + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + if (fWhatToProcess.EqualTo("Rec")) { + gProcessRec = true; + } else if (fWhatToProcess.EqualTo("RecSim")) { + gProcessRecSim = true; + } else if (fWhatToProcess.EqualTo("Sim")) { + gProcessSim = true; + } else { + LOGF(info, "\033[1;32m This option is not supported! fWhatToProcess = %s \033[0m", fWhatToProcess.Data()); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", __PRETTY_FUNCTION__, __LINE__); + } + + // Make sure that only one of these flags is set to kTRUE. + // This is needed, becase these flags are used in PROCESS_SWITCH, + // and if 2 or more are kTRUE, then corresponding process function + // is executed over ALL data, then another process(...) function, etc. + if ((Int_t)gProcessRec + (Int_t)gProcessRecSim + (Int_t)gProcessSim > 1) { + LOGF(info, "\033[1;32m Only one flag can be kTRUE: gProcessRec = %d, gProcessRecSim = %d, gProcessSim = %d \033[0m", (Int_t)gProcessRec, (Int_t)gProcessRecSim, (Int_t)gProcessSim); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", __PRETTY_FUNCTION__, __LINE__); + } + +} // WhatToProcess() + +//============================================================ + void DefaultConfiguration() { // Default task configuration. - // a) Default values are hardcoded as Configurables in the file MuPa-Configurables.h - // b) If corresponding fields are available in an external json file at run time, the default values hardcoded here are overwritten with values set in json file. - // Remember #1: To take into account configuration from external json file, use additional flag for executable, e.g.: --configuration json://my-config.json - // Remember #2: If names of Configurables in the json file are not identical to the internal definitions in MuPa-Configurables.h, the settings in json file are silently ignored. + // a) Default values are hardcoded as Configurables in the file + // MuPa-Configurables.h b) If corresponding fields are available in an + // external json file at run time, the default values hardcoded here are + // overwritten with values set in json file. + // Remember #1: To take into account configuration from external json file, + // use additional flag for executable, e.g.: --configuration + // json://my-config.json + // And yes, --configuration json://my-config.json has to be + // supplied to all executables in the pipe chain (workflow), + // not only to mine! + // Remember #2: If names of Configurables in the json file are not + // identical to the internal definitions in MuPa-Configurables.h, the + // settings in json file are silently ignored. + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } // Configurable cfTaskName{ ... } fTaskName = TString(cfTaskName); @@ -115,13 +187,40 @@ void DefaultConfiguration() // Configurable cfVerbose{ ... } fVerbose = cfVerbose; + // Configurable cfVerboseForEachParticle{ ... } + fVerboseForEachParticle = cfVerboseForEachParticle; + + // Configurable cfDoAdditionalInsanityChecks{ ... } + fDoAdditionalInsanityChecks = cfDoAdditionalInsanityChecks; + + // Configurable cfUseCCDB{ ... } + fUseCCDB = cfUseCCDB; + + // Configurable cfWhatToProcess{ ... ) + fWhatToProcess = TString(cfWhatToProcess); + // ... // Configurable cfCalculateTest0{ ... }; fCalculateTest0 = cfCalculateTest0; - // Configurable cfLabels{ ... } - fFileWithLabels = TString(cfLabels); + // Configurable cfFileWithLabels{ ... } + fFileWithLabels = TString(cfFileWithLabels); + + // Configurable cfUsePhiWeights{"cfUsePhiWeights", false, "use or not + // phi weights"}; + pw_a.fUseWeights[wPHI] = cfUsePhiWeights; + + // Configurable cfUsePtWeights{"cfUsePtWeights", false, "use or not pt + // weights"}; + pw_a.fUseWeights[wPT] = cfUsePtWeights; + + // Configurable cfUseEtaWeights{"cfUseEtaWeights", false, "use or not + // eta weights"}; + pw_a.fUseWeights[wETA] = cfUseEtaWeights; + + // Configurable cfFileWithWeights{ ... } + fFileWithWeights = TString(cfFileWithWeights); // ... @@ -134,7 +233,8 @@ void DefaultConfiguration() // task->SetCalculateNestedLoops(kFALSE); fCalculateNestedLoops = kFALSE; - // task->SetCalculateCustomNestedLoop(kFALSE); // independent e-b-e cross-check with custom nested loop + // task->SetCalculateCustomNestedLoop(kFALSE); // independent e-b-e + // cross-check with custom nested loop fCalculateCustomNestedLoop = kFALSE; } // void DefaultConfiguration() @@ -150,24 +250,30 @@ void DefaultBooking() // c) QA; if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Event histograms: - // Each default setting can be overuled e.g. with: task->SetBookEventHistograms("NumberOfEvents",kFALSE); + // Each default setting can be overuled e.g. with: + // task->SetBookEventHistograms("NumberOfEvents",kFALSE); ceh_a.fBookEventHistograms[eNumberOfEvents] = kTRUE; ceh_a.fBookEventHistograms[eTotalMultiplicity] = kTRUE; - ceh_a.fBookEventHistograms[eSelectedParticles] = kTRUE; + ceh_a.fBookEventHistograms[eSelectedTracks] = kTRUE; ceh_a.fBookEventHistograms[eCentrality] = kTRUE; ceh_a.fBookEventHistograms[eVertex_x] = kTRUE; ceh_a.fBookEventHistograms[eVertex_y] = kTRUE; ceh_a.fBookEventHistograms[eVertex_z] = kTRUE; + ceh_a.fBookEventHistograms[eNContributors] = kTRUE; // b) Particle histograms: - // Each default setting can be overuled e.g. with: task->SetBookParticleHistograms("Phi",kFALSE); + // Each default setting can be overuled e.g. with: + // task->SetBookParticleHistograms("Phi",kFALSE); cph_a.fBookParticleHistograms[ePhi] = kTRUE; cph_a.fBookParticleHistograms[ePt] = kTRUE; cph_a.fBookParticleHistograms[eEta] = kTRUE; + cph_a.fBookParticleHistograms[etpcNClsCrossedRows] = kTRUE; + cph_a.fBookParticleHistograms[eDCA_xy] = kTRUE; + cph_a.fBookParticleHistograms[eDCA_z] = kTRUE; // c) QA: // ... @@ -184,7 +290,7 @@ void DefaultBinning() // b) Default binning for particle histograms; if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Default binning for event histograms: @@ -193,13 +299,13 @@ void DefaultBinning() ceh_a.fEventHistogramsBins[eNumberOfEvents][1] = 0.; ceh_a.fEventHistogramsBins[eNumberOfEvents][2] = 1.; // task->SetEventHistogramsBins("TotalMultiplicity",1000,0.,1000.); - ceh_a.fEventHistogramsBins[eTotalMultiplicity][0] = 1000; + ceh_a.fEventHistogramsBins[eTotalMultiplicity][0] = 10000; ceh_a.fEventHistogramsBins[eTotalMultiplicity][1] = 0.; ceh_a.fEventHistogramsBins[eTotalMultiplicity][2] = 10000.; - // task->SetEventHistogramsBins("SelectedParticles",1000,0.,1000.); - ceh_a.fEventHistogramsBins[eSelectedParticles][0] = 1000; - ceh_a.fEventHistogramsBins[eSelectedParticles][1] = 0.; - ceh_a.fEventHistogramsBins[eSelectedParticles][2] = 10000.; + // task->SetEventHistogramsBins("SelectedTracks",1000,0.,1000.); + ceh_a.fEventHistogramsBins[eSelectedTracks][0] = 10000; + ceh_a.fEventHistogramsBins[eSelectedTracks][1] = 0.; + ceh_a.fEventHistogramsBins[eSelectedTracks][2] = 10000.; // task->SetEventHistogramsBins("Centrality",100,0.,100.); ceh_a.fEventHistogramsBins[eCentrality][0] = 100; ceh_a.fEventHistogramsBins[eCentrality][1] = 0.; @@ -216,6 +322,10 @@ void DefaultBinning() ceh_a.fEventHistogramsBins[eVertex_z][0] = 1000; ceh_a.fEventHistogramsBins[eVertex_z][1] = -20.; ceh_a.fEventHistogramsBins[eVertex_z][2] = 20.; + // task->SetEventHistogramsBins("NContributors",1000,0.,1000.); + ceh_a.fEventHistogramsBins[eNContributors][0] = 1000; + ceh_a.fEventHistogramsBins[eNContributors][1] = 0.; + ceh_a.fEventHistogramsBins[eNContributors][2] = 1000.; // b) Default binning for particle histograms: // task->SetParticleHistogramsBins("Phi",360,0.,TMath::TwoPi()); @@ -231,18 +341,90 @@ void DefaultBinning() cph_a.fParticleHistogramsBins[eEta][1] = -1.; cph_a.fParticleHistogramsBins[eEta][2] = 1.; + cph_a.fParticleHistogramsBins[etpcNClsCrossedRows][0] = 200; + cph_a.fParticleHistogramsBins[etpcNClsCrossedRows][1] = 0.; + cph_a.fParticleHistogramsBins[etpcNClsCrossedRows][2] = 200.; + + cph_a.fParticleHistogramsBins[eDCA_xy][0] = 2000; + cph_a.fParticleHistogramsBins[eDCA_xy][1] = -10.; + cph_a.fParticleHistogramsBins[eDCA_xy][2] = 10.; + + cph_a.fParticleHistogramsBins[eDCA_z][0] = 2000; + cph_a.fParticleHistogramsBins[eDCA_z][1] = -10.; + cph_a.fParticleHistogramsBins[eDCA_z][2] = 10.; + + // ... + } // void DefaultBinning() //============================================================ void DefaultCuts() { - // ... + // Define default cuts. Default cuts are hardwired in MuPa-Configurables.h. + + // a) Default event cuts; + // b) Default particle cuts. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } + // a) Default event cuts: + ceh_a.fEventCuts[eNumberOfEvents][eMin] = + cNumberOfEvents_min; // Configurable + // cNumberOfEvents_min{"cNumberOfEvents_min", ... + ceh_a.fEventCuts[eNumberOfEvents][eMax] = + cNumberOfEvents_max; // Configurable + // cNumberOfEvents_max{"cNumberOfEvents_max", ... + + ceh_a.fEventCuts[eTotalMultiplicity][eMin] = cTotalMultiplicity_min; // Configurable + // cTotalMultiplicity_min{"cTotalMultiplicity_min", + // ... + ceh_a.fEventCuts[eTotalMultiplicity][eMax] = cTotalMultiplicity_max; // Configurable + // cTotalMultiplicity_max{"cTotalMultiplicity_max", + // ... + + ceh_a.fEventCuts[eSelectedTracks][eMin] = + cSelectedTracks_min; // Configurable + // cSelectedTracks_min{"cSelectedTracks_min", ... + ceh_a.fEventCuts[eSelectedTracks][eMax] = + cSelectedTracks_max; // Configurable + // cSelectedTracks_max{"cSelectedTracks_max", ... + + ceh_a.fEventCuts[eCentrality][eMin] = + cCentrality_min; // Configurable cCentrality_min{"cCentrality_min", + // ... + ceh_a.fEventCuts[eCentrality][eMax] = + cCentrality_max; // Configurable cCentrality_max{"cCentrality_max", + // ... + + ceh_a.fEventCuts[eVertex_x][eMin] = + cVertex_x_min; // Configurable cVertex_x_min{"cVertex_x_min", ... + ceh_a.fEventCuts[eVertex_x][eMax] = + cVertex_x_max; // Configurable cVertex_x_max{"cVertex_x_max", ... + + ceh_a.fEventCuts[eVertex_y][eMin] = + cVertex_y_min; // Configurable cVertex_y_min{"cVertex_y_min", ... + ceh_a.fEventCuts[eVertex_y][eMax] = + cVertex_y_max; // Configurable cVertex_y_max{"cVertex_y_max", ... + + ceh_a.fEventCuts[eVertex_z][eMin] = + cVertex_z_min; // Configurable cVertex_z_min{"cVertex_z_min", ... + ceh_a.fEventCuts[eVertex_z][eMax] = + cVertex_z_max; // Configurable cVertex_z_max{"cVertex_z_max", ... + + ceh_a.fEventCuts[eNContributors][eMin] = + cNContributors_min; // Configurable + // cNContributors_min{"cNContributors_min", ... + ceh_a.fEventCuts[eNContributors][eMax] = + cNContributors_max; // Configurable + // cNContributors_max{"cNContributors_max", ... + + // ... + + // b) Default particle cuts: + } // void DefaultCuts() //============================================================ @@ -260,7 +442,7 @@ void BookAndNestAllLists() // *) Results. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // *) QA: @@ -329,40 +511,58 @@ void BookEventHistograms() // b) Book specific event histograms. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Book the profile holding flags: - fEventHistogramsPro = new TProfile("fEventHistogramsPro", "flags for event histograms", 25, 0., 25.); + fEventHistogramsPro = new TProfile("fEventHistogramsPro", + "flags for event histograms", 25, 0., 25.); fEventHistogramsPro->SetStats(kFALSE); fEventHistogramsPro->SetLineColor(eColor); fEventHistogramsPro->SetFillColor(eFillColor); // ... fEventHistogramsList->Add(fEventHistogramsPro); - Int_t fBeforeAfterColor[2] = {kRed, kGreen}; //! [0 = kRed,1 = kGreen] TBI 20220713 only temporarily here + Int_t fBeforeAfterColor[2] = { + kRed, + kGreen}; //! [0 = kRed,1 = kGreen] TBI 20220713 only temporarily here // b) Book specific control event histograms: - TString stype[eEventHistograms_N] = {"NumberOfEvents", "TotalMultiplicity", "SelectedParticles", "Centrality", "Vertex_x", "Vertex_y", "Vertex_z"}; // keep in sync. with enum eEventHistograms + TString stype[eEventHistograms_N] = { + "NumberOfEvents", "TotalMultiplicity", "SelectedTracks", + "Centrality", "Vertex_x", "Vertex_y", + "Vertex_z", "NContributors"}; // keep in sync. with enum + // eEventHistograms TString srs[2] = {"rec", "sim"}; TString sba[2] = {"before", "after"}; - for (Int_t t = 0; t < eEventHistograms_N; t++) // type, see enum eEventHistograms + for (Int_t t = 0; t < eEventHistograms_N; + t++) // type, see enum eEventHistograms { if (!ceh_a.fBookEventHistograms[t]) { continue; } for (Int_t rs = 0; rs < 2; rs++) // reco/sim { + if ((gProcessRec && rs == eSim) || (gProcessSim && rs == eRec)) { + continue; // if I am analyzing only reconstructed data, do not book histos for simulated, and vice versa. + } for (Int_t ba = 0; ba < 2; ba++) // before/after cuts { - ceh_a.fEventHistograms[t][rs][ba] = new TH1D(Form("fEventHistograms[%s][%s][%s]", stype[t].Data(), srs[rs].Data(), sba[ba].Data()), Form("%s, %s, %s", stype[t].Data(), srs[rs].Data(), sba[ba].Data()), (Int_t)ceh_a.fEventHistogramsBins[t][0], ceh_a.fEventHistogramsBins[t][1], ceh_a.fEventHistogramsBins[t][2]); + ceh_a.fEventHistograms[t][rs][ba] = new TH1D( + Form("fEventHistograms[%s][%s][%s]", stype[t].Data(), + srs[rs].Data(), sba[ba].Data()), + Form("%s, %s, %s", stype[t].Data(), srs[rs].Data(), sba[ba].Data()), + (Int_t)ceh_a.fEventHistogramsBins[t][0], + ceh_a.fEventHistogramsBins[t][1], ceh_a.fEventHistogramsBins[t][2]); ceh_a.fEventHistograms[t][rs][ba]->SetLineColor(fBeforeAfterColor[ba]); - ceh_a.fEventHistograms[t][rs][ba]->SetFillColor(fBeforeAfterColor[ba] - 10); + ceh_a.fEventHistograms[t][rs][ba]->SetFillColor(fBeforeAfterColor[ba] - + 10); fEventHistogramsList->Add(ceh_a.fEventHistograms[t][rs][ba]); } // for(Int_t ba=0;ba<2;ba++) } // for(Int_t rs=0;rs<2;rs++) // reco/sim - } // for(Int_t t=0;tSetStats(kFALSE); fParticleHistogramsPro->SetLineColor(eColor); fParticleHistogramsPro->SetFillColor(eFillColor); // ... fParticleHistogramsList->Add(fParticleHistogramsPro); - Int_t fBeforeAfterColor[2] = {kRed, kGreen}; //! [0 = kRed,1 = kGreen] TBI 20220713 only temporarily here + Int_t fBeforeAfterColor[2] = { + kRed, + kGreen}; //! [0 = kRed,1 = kGreen] TBI 20220713 only temporarily here // b) Book specific control particle histograms: - TString stype[eParticleHistograms_N] = {"Phi", "Pt", "Eta"}; // keep in sync. with enum eParticleHistograms + TString stype[eParticleHistograms_N] = { + "Phi", "Pt", "Eta", "tpcNClsCrossedRows", + "DCA_xy", "DCA_z"}; // keep in sync. with enum eParticleHistograms TString srs[2] = {"rec", "sim"}; TString sba[2] = {"before", "after"}; - for (Int_t t = 0; t < eParticleHistograms_N; t++) // type, see enum eParticleHistograms + for (Int_t t = 0; t < eParticleHistograms_N; + t++) // type, see enum eParticleHistograms { if (!cph_a.fBookParticleHistograms[t]) { continue; } for (Int_t rs = 0; rs < 2; rs++) // reco/sim { + if ((gProcessRec && rs == eSim) || (gProcessSim && rs == eRec)) { + continue; // if I am analyzing only reconstructed data, do not book histos for simulated, and vice versa. + } for (Int_t ba = 0; ba < 2; ba++) // before/after cuts { - cph_a.fParticleHistograms[t][rs][ba] = new TH1D(Form("fParticleHistograms[%s][%s][%s]", stype[t].Data(), srs[rs].Data(), sba[ba].Data()), Form("%s, %s, %s", stype[t].Data(), srs[rs].Data(), sba[ba].Data()), (Int_t)cph_a.fParticleHistogramsBins[t][0], cph_a.fParticleHistogramsBins[t][1], cph_a.fParticleHistogramsBins[t][2]); - cph_a.fParticleHistograms[t][rs][ba]->SetLineColor(fBeforeAfterColor[ba]); - cph_a.fParticleHistograms[t][rs][ba]->SetFillColor(fBeforeAfterColor[ba] - 10); + cph_a.fParticleHistograms[t][rs][ba] = new TH1D( + Form("fParticleHistograms[%s][%s][%s]", stype[t].Data(), + srs[rs].Data(), sba[ba].Data()), + Form("%s, %s, %s", stype[t].Data(), srs[rs].Data(), sba[ba].Data()), + (Int_t)cph_a.fParticleHistogramsBins[t][0], + cph_a.fParticleHistogramsBins[t][1], + cph_a.fParticleHistogramsBins[t][2]); + cph_a.fParticleHistograms[t][rs][ba]->SetLineColor( + fBeforeAfterColor[ba]); + cph_a.fParticleHistograms[t][rs][ba]->SetFillColor( + fBeforeAfterColor[ba] - 10); fParticleHistogramsList->Add(cph_a.fParticleHistograms[t][rs][ba]); } // for(Int_t ba=0;ba<2;ba++) } // for(Int_t rs=0;rs<2;rs++) // reco/sim - } // for(Int_t t=0;tSetStats(kFALSE); fQvectorFlagsPro->SetLineColor(eColor); fQvectorFlagsPro->SetFillColor(eFillColor); @@ -455,11 +674,12 @@ void BookCorrelationsHistograms() // c) Histograms. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Book the profile holding flags: - fCorrelationsFlagsPro = new TProfile("fCorrelationsFlagsPro", "flags for correlations", 3, 0., 3.); + fCorrelationsFlagsPro = new TProfile("fCorrelationsFlagsPro", + "flags for correlations", 3, 0., 3.); fCorrelationsFlagsPro->SetStats(kFALSE); fCorrelationsFlagsPro->SetLineColor(eColor); fCorrelationsFlagsPro->SetFillColor(eFillColor); @@ -474,9 +694,12 @@ void BookCorrelationsHistograms() } // b) Common local labels: - TString oVariable[4] = {"#varphi_{1}-#varphi_{2}", "#varphi_{1}+#varphi_{2}-#varphi_{3}-#varphi_{4}", - "#varphi_{1}+#varphi_{2}+#varphi_{3}-#varphi_{4}-#varphi_{5}-#varphi_{6}", - "#varphi_{1}+#varphi_{2}+#varphi_{3}+#varphi_{4}-#varphi_{5}-#varphi_{6}-#varphi_{7}-#varphi_{8}"}; + TString oVariable[4] = { + "#varphi_{1}-#varphi_{2}", + "#varphi_{1}+#varphi_{2}-#varphi_{3}-#varphi_{4}", + "#varphi_{1}+#varphi_{2}+#varphi_{3}-#varphi_{4}-#varphi_{5}-#varphi_{6}", + "#varphi_{1}+#varphi_{2}+#varphi_{3}+#varphi_{4}-#varphi_{5}-#varphi_{6}-" + "#varphi_{7}-#varphi_{8}"}; TString vvVariable[3] = {"int", "mult", "cent"}; @@ -485,16 +708,23 @@ void BookCorrelationsHistograms() { for (Int_t n = 0; n < 6; n++) // harmonic [n=1,n=2,...,n=6] { - for (Int_t v = 0; v < 3; v++) // variable [0=integrated,1=vs. multiplicity,2=vs. centrality] + for (Int_t v = 0; v < 3; + v++) // variable [0=integrated,1=vs. multiplicity,2=vs. centrality] { // ... TBI 20220809 ... port the rest - // c_a.fCorrelationsPro[k][n][v] = new TProfile(Form("c_a.fCorrelationsPro[%d][%d][%s]",k,n,vvVariable[v].Data()),harmonicArray.Data(),vvvariableNBins[v],vvvariableMinMax[v][0],vvvariableMinMax[v][1]); - c_a.fCorrelationsPro[k][n][v] = new TProfile(Form("fCorrelationsPro[%d][%d][%s]", k, n, vvVariable[v].Data()), "some title", 2000, 0., 2000.); + // c_a.fCorrelationsPro[k][n][v] = new + // TProfile(Form("c_a.fCorrelationsPro[%d][%d][%s]",k,n,vvVariable[v].Data()),harmonicArray.Data(),vvvariableNBins[v],vvvariableMinMax[v][0],vvvariableMinMax[v][1]); + c_a.fCorrelationsPro[k][n][v] = new TProfile( + Form("fCorrelationsPro[%d][%d][%s]", k, n, vvVariable[v].Data()), + "some title", 2000, 0., 2000.); c_a.fCorrelationsPro[k][n][v]->SetStats(kFALSE); c_a.fCorrelationsPro[k][n][v]->Sumw2(); - c_a.fCorrelationsPro[k][n][v]->GetXaxis()->SetTitle(vvVariable[v].Data()); - c_a.fCorrelationsPro[k][n][v]->GetYaxis()->SetTitle(Form("#LT#LTcos[%s(%s)]#GT#GT", 1 == n + 1 ? "" : Form("%d", n + 1), oVariable[k].Data())); + c_a.fCorrelationsPro[k][n][v]->GetXaxis()->SetTitle( + vvVariable[v].Data()); + c_a.fCorrelationsPro[k][n][v]->GetYaxis()->SetTitle( + Form("#LT#LTcos[%s(%s)]#GT#GT", 1 == n + 1 ? "" : Form("%d", n + 1), + oVariable[k].Data())); fCorrelationsList->Add(c_a.fCorrelationsPro[k][n][v]); } } @@ -513,11 +743,12 @@ void BookWeightsHistograms() // c) Histograms. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Book the profile holding flags: - fWeightsFlagsPro = new TProfile("fWeightsFlagsPro", "flags for particle weights", 3, 0., 3.); + fWeightsFlagsPro = + new TProfile("fWeightsFlagsPro", "flags for particle weights", 3, 0., 3.); fWeightsFlagsPro->SetStats(kFALSE); fWeightsFlagsPro->SetLineColor(eColor); fWeightsFlagsPro->SetFillColor(eFillColor); @@ -525,12 +756,11 @@ void BookWeightsHistograms() fWeightsFlagsPro->GetXaxis()->SetBinLabel(1, "w_{#varphi}"); fWeightsFlagsPro->GetXaxis()->SetBinLabel(2, "w_{p_{t}}"); fWeightsFlagsPro->GetXaxis()->SetBinLabel(3, "w_{#eta}"); - /* - for(Int_t w=0;wFill(w+0.5,1.); - } - */ + for (Int_t w = 0; w < eWeights_N; w++) // use weights [phi,pt,eta] + { + if (pw_a.fUseWeights[w]) + fWeightsFlagsPro->Fill(w + 0.5, 1.); + } fWeightsList->Add(fWeightsFlagsPro); // b) Common local labels: TBI 20220713 book before @@ -540,12 +770,20 @@ void BookWeightsHistograms() // c) Histograms: for (Int_t w = 0; w < eWeights_N; w++) // use weights [phi,pt,eta] { - // if(!fUseWeights[w]){continue;} - if (!pw_a.fWeightsHist[w]) // yes, because these histos are cloned from the external ones, see SetWeightsHist(TH1D* const hist, const char *variable) - { - // pw_a.fWeightsHist[w] = new TH1D(Form("fWeightsHist[%d]",w),"",(Int_t)fKinematicsBins[w][0],fKinematicsBins[w][1],fKinematicsBins[w][2]); - pw_a.fWeightsHist[w] = new TH1D(Form("fWeightsHist[%d]", w), "", 200, -100., 100.); - pw_a.fWeightsHist[w]->SetTitle(Form("Particle weights for %s", sWeights[w].Data())); + if (!pw_a.fUseWeights[w]) { + continue; + } + if (!pw_a.fWeightsHist[w]) { + // yes, because these histos are cloned from the + // external ones, see SetWeightsHist(TH1D* const + // hist, const char *variable) + + // pw_a.fWeightsHist[w] = new + // TH1D(Form("fWeightsHist[%d]",w),"",(Int_t)fKinematicsBins[w][0],fKinematicsBins[w][1],fKinematicsBins[w][2]); + pw_a.fWeightsHist[w] = + new TH1D(Form("fWeightsHist[%d]", w), "", 200, -100., 100.); + pw_a.fWeightsHist[w]->SetTitle( + Form("Particle weights for %s", sWeights[w].Data())); pw_a.fWeightsHist[w]->SetStats(kFALSE); pw_a.fWeightsHist[w]->GetXaxis()->SetTitle(sVariable[w].Data()); pw_a.fWeightsHist[w]->SetFillColor(eFillColor); @@ -566,11 +804,12 @@ void BookNestedLoopsHistograms() // *) ... if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Book the profile holding flags: - fNestedLoopsFlagsPro = new TProfile("fNestedLoopsFlagsPro", "flags for nested loops", 2, 0., 2.); + fNestedLoopsFlagsPro = + new TProfile("fNestedLoopsFlagsPro", "flags for nested loops", 2, 0., 2.); fNestedLoopsFlagsPro->SetStats(kFALSE); fNestedLoopsFlagsPro->GetXaxis()->SetLabelSize(0.05); fNestedLoopsFlagsPro->GetXaxis()->SetBinLabel(1, "fCalculateNestedLoops"); @@ -583,27 +822,36 @@ void BookNestedLoopsHistograms() } const Int_t iMaxSize = 2e4; - nl_a.ftaNestedLoops[0] = new TArrayD(iMaxSize); // ebe container for azimuthal angles - nl_a.ftaNestedLoops[1] = new TArrayD(iMaxSize); // ebe container for particle weights (product of all) + nl_a.ftaNestedLoops[0] = + new TArrayD(iMaxSize); // ebe container for azimuthal angles + nl_a.ftaNestedLoops[1] = new TArrayD( + iMaxSize); // ebe container for particle weights (product of all) - // TBI 20220823 port here if(fCalculatePtCorrelations) { ... } and if(fCalculateEtaCorrelations) { ... } + // TBI 20220823 port here if(fCalculatePtCorrelations) { ... } and + // if(fCalculateEtaCorrelations) { ... } if (!fCalculateNestedLoops) { return; } // b) Common local labels (keep 'em in sync with BookCorrelationsHistograms()) - TString oVariable[4] = {"#varphi_{1}-#varphi_{2}", "#varphi_{1}+#varphi_{2}-#varphi_{3}-#varphi_{4}", - "#varphi_{1}+#varphi_{2}+#varphi_{3}-#varphi_{4}-#varphi_{5}-#varphi_{6}", - "#varphi_{1}+#varphi_{2}+#varphi_{3}+#varphi_{4}-#varphi_{5}-#varphi_{6}-#varphi_{7}-#varphi_{8}"}; + TString oVariable[4] = { + "#varphi_{1}-#varphi_{2}", + "#varphi_{1}+#varphi_{2}-#varphi_{3}-#varphi_{4}", + "#varphi_{1}+#varphi_{2}+#varphi_{3}-#varphi_{4}-#varphi_{5}-#varphi_{6}", + "#varphi_{1}+#varphi_{2}+#varphi_{3}+#varphi_{4}-#varphi_{5}-#varphi_{6}-" + "#varphi_{7}-#varphi_{8}"}; /* - Int_t vvvariableNBins[5] = {1,(Int_t)fMultiplicityBins[0],(Int_t)fCentralityBins[0], - fUseCustomKineDependenceBins[PTq] ? fKineDependenceBins[PTq]->GetSize()-1 : (Int_t)fKinematicsBins[PT][0], - fUseCustomKineDependenceBins[ETAq] ? fKineDependenceBins[ETAq]->GetSize()-1 : (Int_t)fKinematicsBins[ETA][0]}; + Int_t vvvariableNBins[5] = + {1,(Int_t)fMultiplicityBins[0],(Int_t)fCentralityBins[0], + fUseCustomKineDependenceBins[PTq] ? + fKineDependenceBins[PTq]->GetSize()-1 : (Int_t)fKinematicsBins[PT][0], + fUseCustomKineDependenceBins[ETAq] ? + fKineDependenceBins[ETAq]->GetSize()-1 : (Int_t)fKinematicsBins[ETA][0]}; Double_t vvvariableMinMax[5][2] = { {0.,1.}, // integrated - {fMultiplicityBins[1],fMultiplicityBins[2]}, // multiplicity - {fCentralityBins[1],fCentralityBins[2]}, // centrality + {fMultiplicityBins[1],fMultiplicityBins[2]}, + // multiplicity {fCentralityBins[1],fCentralityBins[2]}, // centrality {fKinematicsBins[PT][1],fKinematicsBins[PT][2]}, {fKinematicsBins[ETA][1],fKinematicsBins[ETA][2]} }; @@ -615,7 +863,8 @@ void BookNestedLoopsHistograms() { for (Int_t n = 0; n < 6; n++) // harmonic [n=1,n=2,...,n=6] { - for (Int_t v = 0; v < 3; v++) // variable [0=integrated,1=vs. multiplicity,2=vs. centrality] + for (Int_t v = 0; v < 3; + v++) // variable [0=integrated,1=vs. multiplicity,2=vs. centrality] { // if(PTKINE == v && !fCalculatePtCorrelations){continue;} @@ -625,33 +874,45 @@ void BookNestedLoopsHistograms() // per demand, custom meeting for kine dependence: if(PTKINE == v && fUseCustomKineDependenceBins[PTq]) { - fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%d]",k,n,v),Form("#LT#LTcos[%s(%s)]#GT#GT",1==n+1?"":Form("%d",n+1),oVariable[k].Data()),fKineDependenceBins[PTq]->GetSize()-1,fKineDependenceBins[PTq]->GetArray()); + fNestedLoopsPro[k][n][v] = new + TProfile(Form("fNestedLoopsPro[%d][%d][%d]",k,n,v),Form("#LT#LTcos[%s(%s)]#GT#GT",1==n+1?"":Form("%d",n+1),oVariable[k].Data()),fKineDependenceBins[PTq]->GetSize()-1,fKineDependenceBins[PTq]->GetArray()); } else if(ETAKINE == v && fUseCustomKineDependenceBins[ETAq]) { - fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%d]",k,n,v),Form("#LT#LTcos[%s(%s)]#GT#GT",1==n+1?"":Form("%d",n+1),oVariable[k].Data()),fKineDependenceBins[ETAq]->GetSize()-1,fKineDependenceBins[ETAq]->GetArray()); + fNestedLoopsPro[k][n][v] = new + TProfile(Form("fNestedLoopsPro[%d][%d][%d]",k,n,v),Form("#LT#LTcos[%s(%s)]#GT#GT",1==n+1?"":Form("%d",n+1),oVariable[k].Data()),fKineDependenceBins[ETAq]->GetSize()-1,fKineDependenceBins[ETAq]->GetArray()); } else { */ // the default binning: - // fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%d]",k,n,v),Form("#LT#LTcos[%s(%s)]#GT#GT",1==n+1?"":Form("%d",n+1),oVariable[k].Data()),vvvariableNBins[v],vvvariableMinMax[v][0],vvvariableMinMax[v][1]); - nl_a.fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%d]", k, n, v), Form("#LT#LTcos[%s(%s)]#GT#GT", 1 == n + 1 ? "" : Form("%d", n + 1), oVariable[k].Data()), 2000, 0., 2000.); + // fNestedLoopsPro[k][n][v] = new + // TProfile(Form("fNestedLoopsPro[%d][%d][%d]",k,n,v),Form("#LT#LTcos[%s(%s)]#GT#GT",1==n+1?"":Form("%d",n+1),oVariable[k].Data()),vvvariableNBins[v],vvvariableMinMax[v][0],vvvariableMinMax[v][1]); + nl_a.fNestedLoopsPro[k][n][v] = new TProfile( + Form("fNestedLoopsPro[%d][%d][%d]", k, n, v), + Form("#LT#LTcos[%s(%s)]#GT#GT", 1 == n + 1 ? "" : Form("%d", n + 1), + oVariable[k].Data()), + 2000, 0., 2000.); // } // else nl_a.fNestedLoopsPro[k][n][v]->SetStats(kFALSE); nl_a.fNestedLoopsPro[k][n][v]->Sumw2(); - nl_a.fNestedLoopsPro[k][n][v]->GetXaxis()->SetTitle(vvVariable[v].Data()); + nl_a.fNestedLoopsPro[k][n][v]->GetXaxis()->SetTitle( + vvVariable[v].Data()); // fNestedLoopsPro[k][n][v]->SetFillColor(colorsW[v]-10); // fNestedLoopsPro[k][n][v]->SetLineColor(colorsW[v]); /* - if(fUseFixedNumberOfRandomlySelectedParticles && 1==v) // just a warning for the meaning of multiplicity in this special case + if(fUseFixedNumberOfRandomlySelectedTracks && 1==v) // just a warning + for the meaning of multiplicity in this special case { - nl_a.fNestedLoopsPro[k][n][1]->GetXaxis()->SetTitle("WARNING: for each multiplicity, fFixedNumberOfRandomlySelectedParticles is selected randomly in Q-vector"); + nl_a.fNestedLoopsPro[k][n][1]->GetXaxis()->SetTitle("WARNING: for each + multiplicity, fFixedNumberOfRandomlySelectedTracks is selected randomly + in Q-vector"); } */ fNestedLoopsList->Add(nl_a.fNestedLoopsPro[k][n][v]); - } // for(Int_t v=0;v<5;v++) // variable [0=integrated,1=vs. multiplicity,2=vs. centrality] + } // for(Int_t v=0;v<5;v++) // variable [0=integrated,1=vs. + // multiplicity,2=vs. centrality] } // for(Int_t n=0;n<6;n++) // harmonic [n=1,n=2,...,n=6] } // for(Int_t n=0;n<6;n++) // harmonics [n=1,n=2,...,n=6] @@ -669,7 +930,7 @@ void BookTest0Histograms() // d) Book what needs to be booked. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Book the profile holding flags: @@ -685,19 +946,17 @@ void BookTest0Histograms() } // b) Book placeholder and make sure all labels are stored in the placeholder: - StoreLabelsInPlaceholder(); + this->StoreLabelsInPlaceholder(); if (fTest0LabelsPlaceholder) { fTest0List->Add(fTest0LabelsPlaceholder); } // c) Retreive labels from placeholder: if (!(this->RetrieveCorrelationsLabels())) { - cout << __LINE__ << endl; - exit(1); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } - // TBC 20230530 - } // void BookTest0Histograms() //============================================================ @@ -710,11 +969,12 @@ void BookResultsHistograms() // *) ... if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Book the profile holding flags: - fResultsFlagsPro = new TProfile("fResultsFlagsPro", "flags for results histograms", 1, 0., 1.); + fResultsFlagsPro = new TProfile("fResultsFlagsPro", + "flags for results histograms", 1, 0., 1.); fResultsFlagsPro->SetStats(kFALSE); fResultsFlagsPro->SetLineColor(eColor); fResultsFlagsPro->SetFillColor(eFillColor); @@ -729,6 +989,87 @@ void BookResultsHistograms() //============================================================ +template +void Preprocess(T const& collision) +{ + // Do all thingies before starting to process data (e.g. count number of events, fetch the run number, etc.). + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + // *) If I reached max number of events, ignore the remaining collisions: + if (MaxNumberOfEvents()) { + fProcessRemainingEvents = kFALSE; + } + + // *) Determine and propagate run number info to already booked objects: + if (!fRunNumberIsDetermined) { + DetermineAndPropagateRunNumber(collision); + } + if (fDoAdditionalInsanityChecks && fRunNumberIsDetermined) { + CheckCurrentRunNumber(collision); + } + + // *) Fetch the weights for this particular run number. Do it only once. + // TBI 20231012 If eventualy I can access programatically run number in init(...) at run time, this shall go there. + if (!fParticleWeightsAreFetched) { + if (pw_a.fUseWeights[wPHI] || pw_a.fUseWeights[wPT] || pw_a.fUseWeights[wETA]) { + GetParticleWeights(); + fParticleWeightsAreFetched = kTRUE; + } + } + +} // template void Preprocess(T const& collision) + +//============================================================ + +template +void DetermineAndPropagateRunNumber(T const& collision) +{ + // Determine and propagate run number info to already booked objects, wherever it's relevant. + // Make sure in process(...) that this function is called only once. + + // TBI 20231018 At the moment I can access run number info only in process(...) via collision.bc().runNumber(), but not in init(...) + // Once I can access run number info in init(...), this function shall be called in init(...), not in process(...) + + // a) Determine run number; + // b) Propagate run number to all booked objects, wherever that info is relevant. + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + // a) Determine run number: + fRunNumber = Form("%d", collision.bc().runNumber()); + if (fRunNumber.EqualTo("")) { + LOGF(error, "\033[1;33m%s fRunNumber is empty, collision.bc().runNumber() failed...\033[0m", __PRETTY_FUNCTION__); + LOGF(fatal, "collision.bc().runNumber() = %d", collision.bc().runNumber()); + } + fRunNumberIsDetermined = kTRUE; + + // b) Propagate run number to all booked objects, wherever that info is relevant: + fBasePro->GetXaxis()->SetBinLabel(eRunNumber, Form("fRunNumber = %s", fRunNumber.Data())); + // ... + +} // template void DetermineAndPropagateRunNumber(T const& collision) + +//============================================================ + +template +void CheckCurrentRunNumber(T const& collision) +{ + // Insanity check for the current run number. + + if (!fRunNumber.EqualTo(Form("%d", collision.bc().runNumber()))) { + LOGF(error, "\033[1;33m%s Run number changed within process(). This most likely indicates that a given masterjob is processing 2 or more different runs in one go.\033[0m", __PRETTY_FUNCTION__); + LOGF(fatal, "fRunNumber = %s, collision.bc().runNumber() = %d", fRunNumber.Data(), collision.bc().runNumber()); + } + +} // template void CheckCurrentRunNumber(aod::Collision const& collision) + +//============================================================ + void ResetEventByEventQuantities() { // Reset all global event-by-event quantities here: @@ -739,7 +1080,7 @@ void ResetEventByEventQuantities() // d) Fisher-Yates algorithm. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Event-by-event quantities: @@ -766,7 +1107,8 @@ void ResetEventByEventQuantities() nl_a.ftaNestedLoops[1]->Reset(); } - // TBI 20220803 port still if(fCalculatePtCorrelations){...} and if(fCalculateEtaCorrelations){...} + // TBI 20220803 port still if(fCalculatePtCorrelations){...} and + // if(fCalculateEtaCorrelations){...} } // if(fCalculateNestedLoops||fCalculateCustomNestedLoop) @@ -776,51 +1118,122 @@ void ResetEventByEventQuantities() //============================================================ -Bool_t EventCuts(aod::Collision const& collision) +template +Bool_t EventCuts(T1 const& collision, T2 const& tracks) { - // ... + + // Event cuts on reconstructed and simulated data. + + // TBI 20231019 Do I need an additional argument "eRecSim rs" if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } - if ((collision.posZ() < Vz_min) || (collision.posZ() > Vz_max)) { + // NumberOfEvents: => cut directly in void process( ... ) + + // TotalMultiplicity: + if ((tracks.size() < ceh_a.fEventCuts[eTotalMultiplicity][eMin]) || + (tracks.size() > ceh_a.fEventCuts[eTotalMultiplicity][eMax])) { + return kFALSE; + } + + // SelectedTracks: => cut directly in void process( ... ) + + // Centrality: TBI + // if (( TBI < ceh_a.fEventCuts[eCentrality][eMin]) || ( TBI > + // ceh_a.fEventCuts[eCentrality][eMax])) { + // return kFALSE; + // } + + // Vertex_x: + if ((collision.posX() < ceh_a.fEventCuts[eVertex_x][eMin]) || + (collision.posX() > ceh_a.fEventCuts[eVertex_x][eMax])) { + return kFALSE; + } + + // Vertex_y: + if ((collision.posY() < ceh_a.fEventCuts[eVertex_y][eMin]) || + (collision.posY() > ceh_a.fEventCuts[eVertex_y][eMax])) { + return kFALSE; + } + + // Vertex_z: + if ((collision.posZ() < ceh_a.fEventCuts[eVertex_z][eMin]) || + (collision.posZ() > ceh_a.fEventCuts[eVertex_z][eMax])) { + return kFALSE; + } + + // NContributors: + if ((collision.numContrib() < ceh_a.fEventCuts[eNContributors][eMin]) || + (collision.numContrib() > ceh_a.fEventCuts[eNContributors][eMax])) { return kFALSE; } - // ... return kTRUE; -} // void EventCuts(aod::Collision const& collision) +} // template Bool_t EventCuts(aod::Collision const& collision, T const& tracks) //============================================================ -void FillEventHistograms(aod::Collision const& collision, aod::Tracks const& tracks, const Int_t rs, const Int_t ba) // reco or sim, before or after event cuts +template +void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) { - // Fill all event histograms. + // Fill all event histograms for reconstructed or simulated data. + + // a) Common to both reconstructed and simulated; + // b) Only reconstructed; + // c) Only simulated. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } + // a) Common to both reconstructed and simulated; ceh_a.fEventHistograms[eNumberOfEvents][rs][ba]->Fill(0.5); - ceh_a.fEventHistograms[eTotalMultiplicity][rs][ba]->Fill(tracks.size()); - ceh_a.fEventHistograms[eVertex_x][rs][ba]->Fill(collision.posX()); - ceh_a.fEventHistograms[eVertex_y][rs][ba]->Fill(collision.posY()); - ceh_a.fEventHistograms[eVertex_z][rs][ba]->Fill(collision.posZ()); - - // TBI 20220808 ctd. with centrality, selected tracks -} // void FillEventHistograms(aod::Collision const& collision, aod::Tracks const& tracks, const Int_t rs, const Int_t ba); // reco or sim, before or after event cuts + // b) Only reconstructed: + if constexpr (rs == eRec) { + ceh_a.fEventHistograms[eTotalMultiplicity][eRec][ba]->Fill(tracks.size()); + // SelectedTracks => filled directly in void process( ... ) + // ceh_a.fEventHistograms[eCentrality][eRec][ba]->Fill( TBI ); => TBI + // 20231007 not ready yet + ceh_a.fEventHistograms[eVertex_x][eRec][ba]->Fill(collision.posX()); + ceh_a.fEventHistograms[eVertex_y][eRec][ba]->Fill(collision.posY()); + ceh_a.fEventHistograms[eVertex_z][eRec][ba]->Fill(collision.posZ()); + ceh_a.fEventHistograms[eNContributors][eRec][ba]->Fill(collision.numContrib()); + } // if constexpr (rs == eRec) { + + // c) Only simulated: + if constexpr (rs == eSim) { + + // TBI 20231021 here I need to access info from CollisionSim = aod::McCollision; + + // ceh_a.fEventHistograms[eTotalMultiplicity][eSim][ba]->Fill(tracks.size()); + // SelectedTracks => filled directly in void process( ... ) + // ceh_a.fEventHistograms[eCentrality][eSim][ba]->Fill( TBI ); => TBI + // 20231007 not ready yet + /* + ceh_a.fEventHistograms[eVertex_x][eSim][ba]->Fill(collision.posX()); + ceh_a.fEventHistograms[eVertex_y][eSim][ba]->Fill(collision.posY()); + ceh_a.fEventHistograms[eVertex_z][eSim][ba]->Fill(collision.posZ()); + ceh_a.fEventHistograms[eNContributors][eSim][ba]->Fill(collision.numContrib()); + */ + } // if constexpr (rs == eSim) { + +} // template void FillEventHistograms(...) //============================================================ -Bool_t ParticleCuts(aod::Track const& track) +template +Bool_t ParticleCuts(T const& track) { - // ... + // Particles cuts. - if (fVerbose) { - Green(__PRETTY_FUNCTION__); + // TBI 20231021 implement remaining cuts + + if (fVerboseForEachParticle) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } if ((track.pt() < pt_min) || (track.pt() > pt_max)) { @@ -829,40 +1242,57 @@ Bool_t ParticleCuts(aod::Track const& track) return kTRUE; -} // void ParticleCuts(aod::Track const& tracks) +} // template Bool_t ParticleCuts(T const& track) //============================================================ -void FillParticleHistograms(aod::Track const& track, const Int_t rs, const Int_t ba) // reco or sim, before or after particle cuts +template +void FillParticleHistograms(T const& track, eBeforeAfter ba) { - // Fill all particle histograms. + // Fill all particle histograms for reconstructed and simulated data. - if (fVerbose) { - Green(__PRETTY_FUNCTION__); + if (fVerboseForEachParticle) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + if constexpr (rs == eRec) { + cph_a.fParticleHistograms[ePhi][eRec][ba]->Fill(track.phi()); + cph_a.fParticleHistograms[ePt][eRec][ba]->Fill(track.pt()); + cph_a.fParticleHistograms[eEta][eRec][ba]->Fill(track.eta()); } - cph_a.fParticleHistograms[ePhi][rs][ba]->Fill(track.phi()); - cph_a.fParticleHistograms[ePt][rs][ba]->Fill(track.pt()); - cph_a.fParticleHistograms[eEta][rs][ba]->Fill(track.eta()); + if constexpr (rs == eSim) { + cph_a.fParticleHistograms[ePhi][eSim][ba]->Fill(track.phi()); + cph_a.fParticleHistograms[ePt][eSim][ba]->Fill(track.pt()); + cph_a.fParticleHistograms[eEta][eSim][ba]->Fill(track.eta()); + } - // TBI 20220808 ctd. with other particle histograms, DCA, etc. + /* TBI 20231019 use also these + check further + // From aod::TracksExtra + cph_a.fParticleHistograms[etpcNClsCrossedRows][rs][ba]->Fill(track.tpcNClsCrossedRows()); -} // void FillParticleHistograms(aod::Track const& track, const Int_t rs, const Int_t ba); // reco or sim, before or after particle cuts + // From aod::TracksDCA + cph_a.fParticleHistograms[eDCA_xy][rs][ba]->Fill(track.dcaXY()); + cph_a.fParticleHistograms[eDCA_z][rs][ba]->Fill(track.dcaZ()); + */ + +} // template void FillParticleHistograms(...) //============================================================ void CalculateCorrelations() { // Calculate analytically multiparticle correlations from Q-vectors - // In this method, only isotropic correlations for which all harmonics are the same are evaluated. - // For the calculus of generic multiparticle correlations, see method CalculateGenericCorrelations() + // In this method, only isotropic correlations for which all harmonics are the + // same are evaluated. For the calculus of generic multiparticle correlations, + // see method CalculateGenericCorrelations() // a) Flush 'n' fill the generic Q-vectors; // b) Calculate correlations; // c) Flush the generic Q-vectors. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Flush 'n' fill the generic Q-vectors: @@ -878,18 +1308,22 @@ void CalculateCorrelations() for (Int_t h = 1; h <= gMaxHarmonic; h++) // harmonic { // 2p: - // if(fSelectedParticles<2){return;} - // if(fVerbose){cout< CalculateCorrelations(void), 2p, h = %d .... ",h)< CalculateCorrelations(void), 2p, h = %d + // .... ",h)< 0.0) { twoC /= wTwo; } else { return; } // ... TBI 20220809 ... use the line below eventually - // else { Exit(__PRETTY_FUNCTION__,__LINE__,Form("wTwo = %f is not positive. fSelectedParticles = %d",wTwo,fSelectedParticles)); return; } + // else { Exit(__PRETTY_FUNCTION__,__LINE__,Form("wTwo = %f is not positive. + // fSelectedTracks = %d",wTwo,fSelectedTracks)); return; } /* ... TBI 20220809 ... enable eventually if(fCalculateCustomNestedLoop) @@ -899,22 +1333,27 @@ void CalculateCorrelations() harmonics->SetAt(h,0); harmonics->SetAt(-h,1); Double_t nestedLoopValue = this->CalculateCustomNestedLoop(harmonics); - if(TMath::Abs(nestedLoopValue) > 0. && TMath::Abs(twoC - nestedLoopValue)>1.e-5) + if(TMath::Abs(nestedLoopValue) > 0. && TMath::Abs(twoC - + nestedLoopValue)>1.e-5) { - Exit(__PRETTY_FUNCTION__,__LINE__,Form("nestedLoopValue = %f is not the same as twoC = %f",nestedLoopValue,twoC)); exit(1); + Exit(__PRETTY_FUNCTION__,__LINE__,Form("nestedLoopValue = %f is not the same + as twoC = %f",nestedLoopValue,twoC)); exit(1); } else { - cout< e-b-e check with CustomNestedLoop is OK for isotropic 2-p, harmonic %d",h)< e-b-e check with CustomNestedLoop is OK for isotropic 2-p, + harmonic %d",h)<GetAt(h-1))>0.){twoC/=pow(fOnTheFlyFlowAmplitudes->GetAt(h-1),2.);} - else if(fUseInternalValidation && fInternalValidationAmplitudes && fRescaleWithTheoreticalInput && + else if(fUseInternalValidation && fInternalValidationAmplitudes && + fRescaleWithTheoreticalInput && TMath::Abs(fInternalValidationAmplitudes->GetAt(h-1))>0.){twoC/=pow(fInternalValidationAmplitudes->GetAt(h-1),2.);} */ @@ -924,7 +1363,7 @@ void CalculateCorrelations() c_a.fCorrelationsPro[0][h - 1][0]->Fill(0.5, twoC, wTwo); } // vs. multiplicity: - // if(c_a.fCorrelationsPro[0][h-1][1]){c_a.fCorrelationsPro[0][h-1][1]->Fill(fSelectedParticles+0.5,twoC,wTwo);} + // if(c_a.fCorrelationsPro[0][h-1][1]){c_a.fCorrelationsPro[0][h-1][1]->Fill(fSelectedTracks+0.5,twoC,wTwo);} // vs. centrality: // if(c_a.fCorrelationsPro[0][h-1][2]){c_a.fCorrelationsPro[0][h-1][2]->Fill(fCentrality,twoC,wTwo);} @@ -944,19 +1383,20 @@ void CalculateNestedLoops() // Calculate correlations with nested loops. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } - cout << "fSelectedTracks = " << fSelectedTracks << endl; + LOGF(info, "\033[1;32m fSelectedTracks = %d\033[0m", fSelectedTracks); Int_t nParticles = fSelectedTracks; /* TBI 20220823 enable the lines below eventually - if(fUseFixedNumberOfRandomlySelectedParticles) + if(fUseFixedNumberOfRandomlySelectedTracks) { nParticles = 0; for(Int_t i=0;iGetSize();i++) { - if(TMath::Abs(ftaNestedLoops[0]->GetAt(i)) > 0. && TMath::Abs(ftaNestedLoops[1]->GetAt(i)) > 0.){nParticles++;} + if(TMath::Abs(ftaNestedLoops[0]->GetAt(i)) > 0. && + TMath::Abs(ftaNestedLoops[1]->GetAt(i)) > 0.){nParticles++;} } } cout<<"nParticles = "<GetAt(i1); Double_t dW1 = nl_a.ftaNestedLoops[1]->GetAt(i1); @@ -980,15 +1420,19 @@ void CalculateNestedLoops() { // fill cos, 2p, integreated: if (nl_a.fNestedLoopsPro[0][h][0]) { - nl_a.fNestedLoopsPro[0][h][0]->Fill(0.5, TMath::Cos((h + 1.) * (dPhi1 - dPhi2)), dW1 * dW2); + nl_a.fNestedLoopsPro[0][h][0]->Fill( + 0.5, TMath::Cos((h + 1.) * (dPhi1 - dPhi2)), dW1 * dW2); } // fill cos, 2p, vs. M: if (nl_a.fNestedLoopsPro[0][h][1]) { - nl_a.fNestedLoopsPro[0][h][1]->Fill(fSelectedTracks + 0.5, TMath::Cos((h + 1.) * (dPhi1 - dPhi2)), dW1 * dW2); + nl_a.fNestedLoopsPro[0][h][1]->Fill( + fSelectedTracks + 0.5, TMath::Cos((h + 1.) * (dPhi1 - dPhi2)), + dW1 * dW2); } // fill cos, 2p, vs. centrality: if (nl_a.fNestedLoopsPro[0][h][2]) { - nl_a.fNestedLoopsPro[0][h][2]->Fill(fCentrality, TMath::Cos((h + 1.) * (dPhi1 - dPhi2)), dW1 * dW2); + nl_a.fNestedLoopsPro[0][h][2]->Fill( + fCentrality, TMath::Cos((h + 1.) * (dPhi1 - dPhi2)), dW1 * dW2); } } // for(int h=1; h<=6; h++) } // for(int i2=0; i2GetNbinsX(); nBinsNL = nl_a.fNestedLoopsPro[0][0][0]->GetNbinsX(); if (nBinsQV != nBinsNL) { - cout << __LINE__ << endl; - exit(1); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } cout << endl; cout << " [0] : integrated" << endl; for (Int_t o = 0; o < 4; o++) { - cout << Form(" ==== <<%d>>-particle correlations ====", 2 * (o + 1)) << endl; + cout << Form(" ==== <<%d>>-particle correlations ====", 2 * (o + 1)) + << endl; for (Int_t h = 0; h < 6; h++) { for (Int_t b = 1; b <= nBinsQV; b++) { if (c_a.fCorrelationsPro[o][h][0]) { @@ -1040,9 +1486,9 @@ void ComparisonNestedLoopsVsCorrelations() cout << Form(" h=%d, Q-vectors: ", h + 1) << valueQV << endl; cout << Form(" h=%d, Nested loops: ", h + 1) << valueNL << endl; if (TMath::Abs(valueQV - valueNL) > 1.e-5) { - cout << Form("[%d][%d][%d]", o, h, 0) << endl; - cout << __LINE__ << endl; - exit(1); + LOGF(info, "\n\033[1;33m[%d][%d][%d] \033[0m\n", o, h, 0); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } } // if(TMath::Abs(valueQV)>0. && TMath::Abs(valueNL)>0.) } // for(Int_t b=1;b<=nBinsQV;b++) @@ -1097,7 +1543,9 @@ TComplex Three(Int_t n1, Int_t n2, Int_t n3) { // Generic three-particle correlation . - TComplex three = Q(n1, 1) * Q(n2, 1) * Q(n3, 1) - Q(n1 + n2, 2) * Q(n3, 1) - Q(n2, 1) * Q(n1 + n3, 2) - Q(n1, 1) * Q(n2 + n3, 2) + 2. * Q(n1 + n2 + n3, 3); + TComplex three = Q(n1, 1) * Q(n2, 1) * Q(n3, 1) - Q(n1 + n2, 2) * Q(n3, 1) - + Q(n2, 1) * Q(n1 + n3, 2) - Q(n1, 1) * Q(n2 + n3, 2) + + 2. * Q(n1 + n2 + n3, 3); return three; @@ -1107,9 +1555,19 @@ TComplex Three(Int_t n1, Int_t n2, Int_t n3) TComplex Four(Int_t n1, Int_t n2, Int_t n3, Int_t n4) { - // Generic four-particle correlation . - - TComplex four = Q(n1, 1) * Q(n2, 1) * Q(n3, 1) * Q(n4, 1) - Q(n1 + n2, 2) * Q(n3, 1) * Q(n4, 1) - Q(n2, 1) * Q(n1 + n3, 2) * Q(n4, 1) - Q(n1, 1) * Q(n2 + n3, 2) * Q(n4, 1) + 2. * Q(n1 + n2 + n3, 3) * Q(n4, 1) - Q(n2, 1) * Q(n3, 1) * Q(n1 + n4, 2) + Q(n2 + n3, 2) * Q(n1 + n4, 2) - Q(n1, 1) * Q(n3, 1) * Q(n2 + n4, 2) + Q(n1 + n3, 2) * Q(n2 + n4, 2) + 2. * Q(n3, 1) * Q(n1 + n2 + n4, 3) - Q(n1, 1) * Q(n2, 1) * Q(n3 + n4, 2) + Q(n1 + n2, 2) * Q(n3 + n4, 2) + 2. * Q(n2, 1) * Q(n1 + n3 + n4, 3) + 2. * Q(n1, 1) * Q(n2 + n3 + n4, 3) - 6. * Q(n1 + n2 + n3 + n4, 4); + // Generic four-particle correlation + // . + + TComplex four = + Q(n1, 1) * Q(n2, 1) * Q(n3, 1) * Q(n4, 1) - + Q(n1 + n2, 2) * Q(n3, 1) * Q(n4, 1) - + Q(n2, 1) * Q(n1 + n3, 2) * Q(n4, 1) - + Q(n1, 1) * Q(n2 + n3, 2) * Q(n4, 1) + 2. * Q(n1 + n2 + n3, 3) * Q(n4, 1) - + Q(n2, 1) * Q(n3, 1) * Q(n1 + n4, 2) + Q(n2 + n3, 2) * Q(n1 + n4, 2) - + Q(n1, 1) * Q(n3, 1) * Q(n2 + n4, 2) + Q(n1 + n3, 2) * Q(n2 + n4, 2) + + 2. * Q(n3, 1) * Q(n1 + n2 + n4, 3) - Q(n1, 1) * Q(n2, 1) * Q(n3 + n4, 2) + + Q(n1 + n2, 2) * Q(n3 + n4, 2) + 2. * Q(n2, 1) * Q(n1 + n3 + n4, 3) + + 2. * Q(n1, 1) * Q(n2 + n3 + n4, 3) - 6. * Q(n1 + n2 + n3 + n4, 4); return four; @@ -1119,10 +1577,11 @@ TComplex Four(Int_t n1, Int_t n2, Int_t n3, Int_t n4) void ResetQ() { - // Reset the components of generic Q-vectors. Use it whenever you call the standard functions for correlations, for some custom Q-vectors. + // Reset the components of generic Q-vectors. Use it whenever you call the + // standard functions for correlations, for some custom Q-vectors. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } for (Int_t h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { @@ -1138,17 +1597,18 @@ void ResetQ() void SetWeightsHist(TH1D* const hist, const char* variable) { - - // Copy histogram holding weights from an external file to the corresponding data member. + // Copy histogram holding weights from an external file to the corresponding + // data member. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // Basic protection: - if (!(TString(variable).EqualTo("phi") || TString(variable).EqualTo("pt") || TString(variable).EqualTo("eta"))) { - cout << __LINE__ << endl; - exit(1); + if (!(TString(variable).EqualTo("phi") || TString(variable).EqualTo("pt") || + TString(variable).EqualTo("eta"))) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } Int_t ppe = -1; @@ -1164,15 +1624,14 @@ void SetWeightsHist(TH1D* const hist, const char* variable) // Finally: hist->SetDirectory(0); - pw_a.fWeightsHist[ppe] = reinterpret_cast(hist->Clone()); // use eventually this line - // fWeightsHist = reinterpret_cast(hist->Clone()); + pw_a.fWeightsHist[ppe] = reinterpret_cast(hist->Clone()); if (!pw_a.fWeightsHist[ppe]) { - cout << __LINE__ << endl; - exit(1); - } // use eventually this line + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } // Flag: - // fUseWeights[ppe] = kTRUE; // use eventually this line + pw_a.fUseWeights[ppe] = kTRUE; } // void SetWeightsHist(TH1D* const hist, const char *variable) @@ -1183,13 +1642,14 @@ TH1D* GetWeightsHist(const char* variable) // The standard getter. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // Basic protection: - if (!(TString(variable).EqualTo("phi") || TString(variable).EqualTo("pt") || TString(variable).EqualTo("eta"))) { - cout << __LINE__ << endl; - exit(1); + if (!(TString(variable).EqualTo("phi") || TString(variable).EqualTo("pt") || + TString(variable).EqualTo("eta"))) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } Int_t ppe = -1; @@ -1204,156 +1664,313 @@ TH1D* GetWeightsHist(const char* variable) } // Finally: - return pw_a.fWeightsHist[ppe]; // use eventually this line - // return fWeightsHist; + return pw_a.fWeightsHist[ppe]; } // TH1D* GetWeightsHist(const char *variable) //============================================================ -TH1D* GetHistogramWithWeights(const char* filePath, const char* variable) +TH1D* GetHistogramWithWeights(const char* filePath, const char* runNumber, + const char* variable) { // ... // a) Return value; // b) Basic protection for arguments; - // c) Determine from filePath if the file in on a local machine, or in AliEn; - // d) Handle the AliEn case; - // e) Handle the local case; - // f) Access the external ROOT file and fetch the desired histogram with weights; - - // e) Close the external ROOT file. + // c) Determine from filePath if the file in on a local machine, or in AliEn, + // or in CCDB; d) Handle the AliEn case; e) Handle the CCDB case; f) Handle + // the local case; g) The final touch on histogram with weights. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + LOGF(info, "\033[1;33m filePath = %s\033[0m", filePath); + LOGF(info, "\033[1;33m runNumber = %s\033[0m", runNumber); + LOGF(info, "\033[1;33m variable = %s\033[0m", variable); + LOGF(info, "\033[1;33m fTaskName = %s\033[0m", fTaskName.Data()); } // a) Return value: TH1D* hist = NULL; // b) Basic protection for arguments: - if (!(TString(variable).EqualTo("phi") || TString(variable).EqualTo("pt") || TString(variable).EqualTo("eta"))) { - cout << __LINE__ << endl; - exit(1); + if (!(TString(variable).EqualTo("phi") || TString(variable).EqualTo("pt") || + TString(variable).EqualTo("eta"))) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } - // c) Determine from filePath if the file in on a local machine, or in AliEn: - // Algorithm: If filePath begins with "/alice/cern.ch/" then it's in AliEn. - // Therefore, files on AliEn must be specified with abs path, for local files both abs and relative paths are fine. + // c) Determine from filePath if the file in on a local machine, or in home + // dir AliEn, or in CCDB: + // Algorithm: If filePath begins with "/alice/cern.ch/" then it's in home + // dir AliEn. If filePath begins with "/alice-ccdb.cern.ch/" then it's in + // CCDB. Therefore, files in AliEn and CCDB must be specified with abs path, + // for local files both abs and relative paths are just fine. Bool_t bFileIsInAliEn = kFALSE; + Bool_t bFileIsInCCDB = kFALSE; if (TString(filePath).BeginsWith("/alice/cern.ch/")) { bFileIsInAliEn = kTRUE; - } + } else { + if (TString(filePath).BeginsWith("/alice-ccdb.cern.ch/")) { + bFileIsInCCDB = kTRUE; + } // else { + } // if (TString(filePath).BeginsWith("/alice/cern.ch/")) { - // d) Handle the AliEn case: - TFile* weightsFile = NULL; if (bFileIsInAliEn) { + // d) Handle the AliEn case: TGrid* alien = TGrid::Connect("alien", gSystem->Getenv("USER"), "", ""); if (!alien) { - cout << __LINE__ << endl; - exit(1); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + TFile* weightsFile = TFile::Open(Form("alien://%s", filePath), "READ"); + if (!weightsFile) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + + TList* baseList = NULL; + weightsFile->GetObject( + "ccdb_object", baseList); // TBI 20231008 for simplicity, harwired name + // of base TList is "ccdb_object" also for + // AliEn case, see if I need to change this + if (!baseList) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + + TList* listWithRuns = + reinterpret_cast(GetObjectFromList(baseList, runNumber)); + if (!listWithRuns) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + + hist = reinterpret_cast(GetObjectFromList( + listWithRuns, Form("%s_%s", variable, fTaskName.Data()))); + if (!hist) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + + } else if (bFileIsInCCDB) { + + // e) Handle the CCDB case: Remember that here I do not access the file, + // instead directly object in that file. + // My home dir in CCDB: https://alice-ccdb.cern.ch/browse/Users/a/abilandz/ + // Inspired by: + // 1. Discussion at: + // https://alice-talk.web.cern.ch/t/access-to-lhc-filling-scheme/1073/17 + // 2. See also: + // https://github.com/AliceO2Group/O2Physics/blob/master/Tutorials/src/efficiencyGlobal.cxx + // https://github.com/AliceO2Group/O2Physics/blob/master/Tutorials/src/efficiencyPerRun.cxx + // 3. O2 Analysis Tutorial 2.0: + // https://indico.cern.ch/event/1267433/timetable/#20230417.detailed + + ccdb->setURL("http://alice-ccdb.cern.ch"); + if (fVerbose) { + LOGF(info, "\033[1;32mAccessing in CCDB %s\033[0m", + TString(filePath).ReplaceAll("/alice-ccdb.cern.ch/", "").Data()); } - weightsFile = TFile::Open(Form("alien://%s", filePath), "READ"); + + TList* baseList = + reinterpret_cast(ccdb->get(TString(filePath) + .ReplaceAll("/alice-ccdb.cern.ch/", "") + .Data())); + + if (!baseList) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + + TList* listWithRuns = + reinterpret_cast(GetObjectFromList(baseList, runNumber)); + if (!listWithRuns) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + + hist = reinterpret_cast(GetObjectFromList( + listWithRuns, Form("%s_%s", variable, fTaskName.Data()))); + + if (!hist) { + LOGF(info, "\033[1;33m%s_%s \033[0m", variable, fTaskName.Data()); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + } else { - // e) Handle the local case: + + // f) Handle the local case: + // TBI 20231008 In principle, also for the local case in O2, I could + // maintain the same local structure of weights as it was in AliPhysics. + // But for simplicity, in O2 I organize local weights in the + // same way as in AliEn or CCDB. // Check if the external ROOT file exists at specified path: if (gSystem->AccessPathName(filePath, kFileExists)) { - Red(Form("if(gSystem->AccessPathName(filePath,kFileExists)), filePath = %s", filePath)); - cout << __LINE__ << endl; - exit(1); + LOGF(info, + "\033[1;33m if(gSystem->AccessPathName(filePath,kFileExists)), " + "filePath = %s \033[0m", + filePath); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } - weightsFile = TFile::Open(filePath, "READ"); - } // if(bFileIsInAliEn) - // f) Access the external ROOT file and fetch the desired histogram with weights: - if (!weightsFile) { - cout << __LINE__ << endl; - exit(1); - } - - /* + TFile* weightsFile = TFile::Open(filePath, "READ"); + if (!weightsFile) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } - hist = reinterpret_cast(weightsFile->Get("phi_Task=>0.0-5.0_clone_96")); + TList* baseList = NULL; + weightsFile->GetObject( + "ccdb_object", baseList); // TBI 20231008 for simplicity, harwired name + // of base TList is "ccdb_object" also for + // local case, see if I need to change this + if (!baseList) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } - // hist = reinterpret_cast(weightsFile->Get(Form("%s_%s",variable,fTaskName->Data()))); // 20220712 this was the original line, instead of thew one above, which is there temporarily + TList* listWithRuns = + reinterpret_cast(GetObjectFromList(baseList, runNumber)); + if (!listWithRuns) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } - if (!hist) { - hist = reinterpret_cast(weightsFile->Get(Form("%s", variable))); - } // yes, for some simple tests I can have only histogram named e.g. 'phi' - // if(!hist){Red(Form("%s_%s",variable,fTaskName->Data())); cout<<__LINE__<SetDirectory(0); - hist->SetTitle(filePath); + hist = reinterpret_cast(GetObjectFromList( + listWithRuns, Form("%s_%s", variable, fTaskName.Data()))); + if (!hist) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } - // e) Close the external ROOT file: - weightsFile->Close(); - delete weightsFile; - weightsFile = NULL; + } // else { - */ + // g) The final touch on histogram with weights: + hist->SetDirectory(0); + hist->SetTitle(Form("%s, %s", filePath, runNumber)); return hist; -} // TH1D* GetHistogramWithWeights(const char *filePath, const char *variable) +} // TH1D* GetHistogramWithWeights(const char* filePath, const char* runNumber, +// const char* variable) //============================================================ TObjArray* GetObjArrayWithLabels(const char* filePath) { - // This function extracts from an external file TObjArray named "labels", and returns it. - // File can be both local or in AliEn => AliEn file must beging with "/alice/cern.ch/" + // This function extracts from an external file TObjArray named "labels", and + // returns it. External file can be: 1) on a local computer; 2) in home + // directory AliEn => configurable "cfFileWithLabels" must begin with + // "/alice/cern.ch/" 3) in CCDB => configurable "cfFileWithLabels" must begin + // with "/alice-ccdb.cern.ch/" For all CCDB wisdom, see toggle "CCDB" in page + // "O2" // a) Return value; // b) Determine from filePath if the file in on a local machine, or in AliEn; // c) Handle the AliEn case; - // d) Handle the local case; - // e) Access the external ROOT file and fetch the desired histogram with weights; + // d) Handle the CCDB case; + // e) Handle the local case. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Return value: TObjArray* oa; - // b) Determine from filePath if the file in on a local machine, or in AliEn: - // Algorithm: If filePath begins with "/alice/cern.ch/" then it's in AliEn. - // Therefore, files on AliEn must be specified with abs path, for local files both abs and relative paths are fine. + // b) Determine from filePath if the file in on a local machine, or in home + // dir AliEn, or in CCDB: + // Algorithm: If filePath begins with "/alice/cern.ch/" then it's in home + // dir AliEn. + // If filePath begins with "/alice-ccdb.cern.ch/" then it's in + // CCDB. Therefore, files in AliEn and CCDB must be specified + // with abs path, for local files both abs and relative paths + // are just fine. Bool_t bFileIsInAliEn = kFALSE; + Bool_t bFileIsInCCDB = kFALSE; if (TString(filePath).BeginsWith("/alice/cern.ch/")) { bFileIsInAliEn = kTRUE; - } + } else { + if (TString(filePath).BeginsWith("/alice-ccdb.cern.ch/")) { + bFileIsInCCDB = kTRUE; + } // else { + } // if (TString(filePath).BeginsWith("/alice/cern.ch/")) { - // c) Handle the AliEn case: TFile* oaFile = NULL; // file holding TObjArray with all labels if (bFileIsInAliEn) { + // c) Handle the AliEn case: TGrid* alien = TGrid::Connect("alien", gSystem->Getenv("USER"), "", ""); if (!alien) { - cout << __LINE__ << endl; - exit(1); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } oaFile = TFile::Open(Form("alien://%s", filePath), "READ"); + if (!oaFile) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + oaFile->GetObject( + "labels", oa); // TBI 20230530 hardcoded name of TObjArray is "labels", + // perhaps I can do this also via Configurables? Keep in + // sync with O2::TranslateASCIIintoObjArray + if (!oa) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + } else if (bFileIsInCCDB) { + + // d) Handle the CCDB case: Remember that here I do not access the file, + // instead directly object in that file. + // My home dir in CCDB: https://alice-ccdb.cern.ch/browse/Users/a/abilandz/ + // Inspired by: + // 1. Discussion at: + // https://alice-talk.web.cern.ch/t/access-to-lhc-filling-scheme/1073/17 + // 2. See also: + // https://github.com/AliceO2Group/O2Physics/blob/master/Tutorials/src/efficiencyGlobal.cxx + // https://github.com/AliceO2Group/O2Physics/blob/master/Tutorials/src/efficiencyPerRun.cxx + // 3. O2 Analysis Tutorial 2.0: + // https://indico.cern.ch/event/1267433/timetable/#20230417.detailed + + ccdb->setURL("http://alice-ccdb.cern.ch"); + oa = reinterpret_cast(ccdb->get( + TString(filePath) + .ReplaceAll("/alice-ccdb.cern.ch/", "") + .Data())); + + if (!oa) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } } else { - // d) Handle the local case: + + // e) Handle the local case: // Check if the external ROOT file exists at specified path: if (gSystem->AccessPathName(filePath, kFileExists)) { - Red(Form("if(gSystem->AccessPathName(filePath,kFileExists)), filePath = %s", filePath)); - cout << __LINE__ << endl; - exit(1); + LOGF(info, + "\033[1;33m if(gSystem->AccessPathName(filePath,kFileExists)), " + "filePath = %s \033[0m", + filePath); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } oaFile = TFile::Open(filePath, "READ"); - } // if(bFileIsInAliEn) + if (!oaFile) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + oaFile->GetObject( + "labels", oa); // TBI 20230530 hardcoded name of TObjArray is "labels", + // perhaps I can do this also via Configurables? Keep in + // sync with O2::TranslateASCIIintoObjArray + if (!oa) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } - // e) Access the external ROOT file and fetch the desired TObjArray with labels: - if (!oaFile) { - cout << __LINE__ << endl; - exit(1); - } - oaFile->GetObject("labels", oa); // TBI 20230530 hardcoded name of TObjArray is "labels", perhaps I can do this also via Configurables? - if (!oa) { - cout << __LINE__ << endl; - exit(1); - } + } // else { return oa; @@ -1371,7 +1988,7 @@ void StoreLabelsInPlaceholder() // d) Finally, store the labels from external source into placeholder. if (fVerbose) { - Green(__PRETTY_FUNCTION__); + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); } // a) Initialize all counters; @@ -1383,14 +2000,18 @@ void StoreLabelsInPlaceholder() // b) Fetch TObjArray with labels from an external file: TObjArray* oa = GetObjArrayWithLabels(fFileWithLabels.Data()); if (!oa) { - cout << __LINE__ << endl; - cout << Form(" fFileWithLabels = %s", fFileWithLabels.Data()) << endl; - exit(1); + LOGF(info, "\033[1;33m fFileWithLabels = %s \033[0m", + fFileWithLabels.Data()); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } // c) Book the placeholder fTest0LabelsPlaceholder for all labels: Int_t nLabels = oa->GetEntries(); - fTest0LabelsPlaceholder = new TH1I("fTest0LabelsPlaceholder", Form("placeholder for all labels, %d in total", nLabels), nLabels, 0, nLabels); + fTest0LabelsPlaceholder = + new TH1I("fTest0LabelsPlaceholder", + Form("placeholder for all labels, %d in total", nLabels), + nLabels, 0, nLabels); fTest0LabelsPlaceholder->SetStats(kFALSE); // d) Finally, store the labels from external source into placeholder: @@ -1399,8 +2020,8 @@ void StoreLabelsInPlaceholder() for (Int_t e = 0; e < nLabels; e++) { TObjArray* temp = TString(oa->At(e)->GetName()).Tokenize(" "); if (!temp) { - cout << __LINE__ << endl; - exit(1); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } order = temp->GetEntries(); delete temp; // yes, otherwise it's a memory leak @@ -1408,9 +2029,12 @@ void StoreLabelsInPlaceholder() continue; } // empty lines, or the label format which is not supported // 1-p => 0, 2-p => 1, etc.: - t0_a.fTest0Labels[order - 1][counter[order - 1]] = new TString(oa->At(e)->GetName()); // okay... - fTest0LabelsPlaceholder->GetXaxis()->SetBinLabel(bin++, t0_a.fTest0Labels[order - 1][counter[order - 1]]->Data()); - // cout<<__LINE__<<": "<Data()<At(e)->GetName()); // okay... + fTest0LabelsPlaceholder->GetXaxis()->SetBinLabel( + bin++, t0_a.fTest0Labels[order - 1][counter[order - 1]]->Data()); + // cout<<__LINE__<<": + // "<Data()<GetEntries()<GetXaxis()->GetBinLabel(b)).Tokenize(" "); + TObjArray* oa = TString(fTest0LabelsPlaceholder->GetXaxis()->GetBinLabel(b)) + .Tokenize(" "); if (!oa) { - cout << __LINE__ << endl; - exit(1); + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); } order = oa->GetEntries(); delete oa; // yes, otherwise it's a memory leak @@ -1444,8 +2074,10 @@ Bool_t RetrieveCorrelationsLabels() continue; } // empty lines, or the label format which is not supported // 1-p => 0, 2-p => 1, etc.: - t0_a.fTest0Labels[order - 1][counter[order - 1]] = new TString(fTest0LabelsPlaceholder->GetXaxis()->GetBinLabel(b)); // okay... - // cout<<__LINE__<<": "<Data()<GetXaxis()->GetBinLabel(b)); // okay... + // cout<<__LINE__<<": + // "<Data()<Get("hist-name"). + + // Usage: TH1D *hist = (TH1D*) + // GetObjectFromList("some-valid-TList-pointer","some-object-name"); + + // Example 1: + // GetObjectFromList("some-valid-TList-pointer","some-object-name")->Draw(); + // // yes, for histograms and profiles this is just fine, at least in + // interpreted code + + // To do: + // a) Check if I can make it working in compiled mode. + // b) If I have objects with same name, nested in different TLists, what then? + + // Insanity checks: + if (!list) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + if (!objectName) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + if (0 == list->GetEntries()) { + return NULL; + } + + // The object is in the current base list: + TObject* objectFinal = + list->FindObject(objectName); // final object I am after + if (objectFinal) + return objectFinal; + + // Search for object recursively in the nested lists: + TObject* objectIter; // iterator object in the loop below + TIter next(list); + while ( + (objectIter = next())) // double round braces are to silent the warnings + { + if (TString(objectIter->ClassName()).EqualTo("TList")) { + objectFinal = GetObjectFromList(reinterpret_cast(objectIter), objectName); + if (objectFinal) + return objectFinal; + } + } // while(objectIter = next()) + + return NULL; + +} // TObject* GetObjectFromList(TList *list, Char_t *objectName) //============================================================ -void Green(const char* text) +Double_t Weight(const Double_t& value, + const char* variable) // value, [phi,pt,eta] { - cout << "\n\033[1;32m" << text << "\033[0m\n" - << endl; -} + // Determine particle weight. + + // Basic protection: + if (!(TString(variable).EqualTo("phi") || TString(variable).EqualTo("pt") || + TString(variable).EqualTo("eta"))) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + + Int_t ppe = 0; // [phi,pt,eta] + if (TString(variable).EqualTo("pt")) { + ppe = 1; + } + if (TString(variable).EqualTo("eta")) { + ppe = 2; + } + + if (!pw_a.fWeightsHist[ppe]) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", + __PRETTY_FUNCTION__, __LINE__); + } + + Int_t bin = pw_a.fWeightsHist[ppe]->FindBin(value); + Double_t weight = 0.; + if (bin > pw_a.fWeightsHist[ppe]->GetNbinsX()) { + weight = 0.; // we are in the overflow, ignore this particle TBI_20210524 is + // this really the correct procedure? + } else { + weight = pw_a.fWeightsHist[ppe]->GetBinContent(bin); + } + + return weight; + +} // Weight(const Double_t &value, const char *variable) // value, [phi,pt,eta] //============================================================ -void Yellow(const char* text) +void GetParticleWeights() { - cout << "\n\033[1;33m" << text << "\033[0m\n" - << endl; -} + // Get the particle weights. Call this function only once. + + // TBI 20231012 Here the current working assumption is that: + // a) Corrections do not change within a given run; + // b) Hyperloop proceeses the dataset one masterjob per run number. + // If any of these 2 assumptions are violated, this code will have to be modified. + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + if (pw_a.fUseWeights[wPHI]) { + TH1D* phiWeights = GetHistogramWithWeights(fFileWithWeights.Data(), fRunNumber.Data(), "phi"); + if (!phiWeights) { + LOGF(fatal, "in function \033[1;31m%s at line %d, phiWeights is NULL. Check the external file %s with particle weights\033[0m", __PRETTY_FUNCTION__, __LINE__, fFileWithWeights.Data()); + } + SetWeightsHist(phiWeights, "phi"); + } + + if (pw_a.fUseWeights[wPT]) { + TH1D* ptWeights = GetHistogramWithWeights(fFileWithWeights.Data(), fRunNumber.Data(), "pt"); + if (!ptWeights) { + LOGF(fatal, "in function \033[1;31m%s at line %d, ptWeights is NULL. Check the external file %s with particle weights\033[0m", __PRETTY_FUNCTION__, __LINE__, fFileWithWeights.Data()); + } + SetWeightsHist(ptWeights, "pt"); + } + + if (pw_a.fUseWeights[wETA]) { + TH1D* etaWeights = GetHistogramWithWeights(fFileWithWeights.Data(), fRunNumber.Data(), "eta"); + if (!etaWeights) { + LOGF(fatal, "in function \033[1;31m%s at line %d, etaWeights is NULL. Check the external file %s with particle weights\033[0m", __PRETTY_FUNCTION__, __LINE__, fFileWithWeights.Data()); + } + SetWeightsHist(etaWeights, "eta"); + } + +} // void GetParticleWeights() //============================================================ -void Blue(const char* text) +Bool_t MaxNumberOfEvents() { - cout << "\n\033[1;34m" << text << "\033[0m\n" - << endl; -} + // Check if max number of events was reached. See also configurable cNumberOfEvents_max. + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + // *) Return value: + Bool_t reachedMaxNumberOfEvents = kFALSE; + + // *) Determine from which histogram the relevant info will be taken: + Int_t rs = -44; // reconstructed or simulated + if (gProcessRec || gProcessRecSim) { + rs = eRec; + } else if (gProcessSim) { + rs = eSim; + } else { + LOGF(fatal, "in function \033[1;31m%s at line %d, not a single flag gProcess* is true \033[0m", __PRETTY_FUNCTION__, __LINE__); + } + + // *) Okay, do the thing: + if (ceh_a.fEventHistograms[eNumberOfEvents][rs][eAfter]->GetBinContent(1) >= ceh_a.fEventCuts[eNumberOfEvents][eMax]) { + reachedMaxNumberOfEvents = kTRUE; + } + + // *) Hasta la vista: + return reachedMaxNumberOfEvents; + +} // void MaxNumberOfEvents() //============================================================ +void MainLoopOverParticlesRec(TracksRec const& tracks) +{ + // This is the main loop over particles, in which Q-vectors and particle histograms are filled, particle cuts applied, etc. + // Only 'rec' info is processed in this loop, set gProcessRec = true via configurable "cfWhatToProcess" + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + Double_t dPhi = 0., wPhi = 1.; // azimuthal angle and corresponding phi weight + Double_t dPt = 0., wPt = 1.; // transverse momentum and corresponding pT weight + Double_t dEta = 0., wEta = 1.; // pseudorapidity and corresponding eta weight + Double_t wToPowerP = 1.; // weight raised to power p + fSelectedTracks = 0; // reset number of selected tracks + for (auto& track : tracks) { + + // *) Fill particle histograms for reconstructed particle before particle cuts: + FillParticleHistograms(track, eBefore); + + // *) Particle cuts: + if (!ParticleCuts(track)) { + continue; + } + + // *) Fill particle histograms for reconstructed data after particle cuts: + FillParticleHistograms(track, eAfter); + + // *) Fill Q-vectors: + // Take kinematics from reconstructed particles: + dPhi = track.phi(); + dPt = track.pt(); + dEta = track.eta(); + + // Particle weights: + if (pw_a.fUseWeights[wPHI]) { + wPhi = Weight(dPhi, "phi"); // corresponding phi weight + if (!(wPhi > 0.)) { + LOGF(error, "\033[1;33m%s wPhi is not positive, skipping this particle for the time being...\033[0m", __PRETTY_FUNCTION__); + LOGF(error, "dPhi = %f\nwPhi = %f", dPhi, wPhi); + continue; + } + } // if(pw_a.fUseWeights[wPHI]) + if (pw_a.fUseWeights[wPT]) { + wPt = Weight(dPt, "pt"); // corresponding pt weight + if (!(wPt > 0.)) { + LOGF(error, "\033[1;33m%s wPt is not positive, skipping this particle for the time being...\033[0m", __PRETTY_FUNCTION__); + LOGF(error, "dPt = %f\nwPt = %f", dPt, wPt); + continue; + } + } // if(pw_a.fUseWeights[wPT]) + if (pw_a.fUseWeights[wETA]) { + wEta = Weight(dEta, "eta"); // corresponding eta weight + if (!(wEta > 0.)) { + LOGF(error, "\033[1;33m%s wEta is not positive, skipping this particle for the time being...\033[0m", __PRETTY_FUNCTION__); + LOGF(error, "dEta = %f\nwEta = %f", dEta, wEta); + continue; + } + } // if(pw_a.fUseWeights[wETA]) + + for (Int_t h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (Int_t wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw_a.fUseWeights[wPHI] || pw_a.fUseWeights[wPT] || pw_a.fUseWeights[wETA]) { + wToPowerP = pow(wPhi * wPt * wEta, wp); + } + qv_a.fQvector[h][wp] += TComplex(wToPowerP * TMath::Cos(h * dPhi), wToPowerP * TMath::Sin(h * dPhi)); + } // for(Int_t wp=0;wpAddAt(dPhi, fSelectedTracks); + } // remember that the 2nd argument here must start from 0 + if (nl_a.ftaNestedLoops[1]) { + nl_a.ftaNestedLoops[1]->AddAt(wPhi * wPt * wEta, fSelectedTracks); + } // remember that the 2nd argument here must start from 0 + } // if(fCalculateNestedLoops||fCalculateCustomNestedLoop) + + // *) Counter of selected tracks in the current event: + fSelectedTracks++; + if (fSelectedTracks >= cSelectedTracks_max) { + break; + } + + } // for (auto& track : tracks) + +} // void MainLoopOverParticlesRec(TracksRec const& tracks) + +//============================================================ + +void MainLoopOverParticlesRecSim(TracksRecSim const& tracks) +{ + // This is the main loop over particles, in which Q-vectors and particle histograms are filled, particle cuts applied, etc. + // Both 'rec' and 'sim' info are processed in this loop, set gProcessRecSim = true via configurable "cfWhatToProcess" + // It sufficcess to pass only rec info, because here I access sim info via labels. + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + Double_t dPhi = 0., wPhi = 1.; // azimuthal angle and corresponding phi weight + Double_t dPt = 0., wPt = 1.; // transverse momentum and corresponding pT weight + Double_t dEta = 0., wEta = 1.; // pseudorapidity and corresponding eta weight + Double_t wToPowerP = 1.; // weight raised to power p + fSelectedTracks = 0; // reset number of selected tracks + for (auto& track : tracks) { + + // *) Fill particle histograms for reconstructed particle before particle cuts: + FillParticleHistograms(track, eBefore); + + // *) Fill particle histograms for corresponding simulated particle before particle cuts: + if (track.has_mcParticle()) { + auto mcParticle = track.mcParticle(); + FillParticleHistograms(mcParticle, eBefore); // great, this works straight like this, thanks O2 people! + } else { + LOGF(debug, "in function \033[1;31m%s at line %d, track.has_mcParticle() is false. \033[0m", __PRETTY_FUNCTION__, __LINE__); + } + + // *) Particle cuts: + if (!ParticleCuts(track)) { + continue; + } + + // *) Fill particle histograms for reconstructed data after particle cuts: + FillParticleHistograms(track, eAfter); + + // *) Fill particle histograms for corresponding simulated particle after particle cuts: + // TBI 20231020 there is a duplication of code here, see above. I should get 'mcParticle' only once for this 'track' in this loop + if (track.has_mcParticle()) { + auto mcParticle = track.mcParticle(); + FillParticleHistograms(mcParticle, eAfter); // great, this works straight like this, thanks O2 people! + } else { + LOGF(debug, "in function \033[1;31m%s at line %d, track.has_mcParticle() is false. \033[0m", __PRETTY_FUNCTION__, __LINE__); + } + + // *) Fill Q-vectors: + // Take kinematics from reconstructed particles: + dPhi = track.phi(); + dPt = track.pt(); + dEta = track.eta(); + + // Particle weights: + if (pw_a.fUseWeights[wPHI]) { + wPhi = Weight(dPhi, "phi"); // corresponding phi weight + if (!(wPhi > 0.)) { + LOGF(error, "\033[1;33m%s wPhi is not positive, skipping this particle for the time being...\033[0m", __PRETTY_FUNCTION__); + LOGF(error, "dPhi = %f\nwPhi = %f", dPhi, wPhi); + continue; + } + } // if(pw_a.fUseWeights[wPHI]) + if (pw_a.fUseWeights[wPT]) { + wPt = Weight(dPt, "pt"); // corresponding pt weight + if (!(wPt > 0.)) { + LOGF(error, "\033[1;33m%s wPt is not positive, skipping this particle for the time being...\033[0m", __PRETTY_FUNCTION__); + LOGF(error, "dPt = %f\nwPt = %f", dPt, wPt); + continue; + } + } // if(pw_a.fUseWeights[wPT]) + if (pw_a.fUseWeights[wETA]) { + wEta = Weight(dEta, "eta"); // corresponding eta weight + if (!(wEta > 0.)) { + LOGF(error, "\033[1;33m%s wEta is not positive, skipping this particle for the time being...\033[0m", __PRETTY_FUNCTION__); + LOGF(error, "dEta = %f\nwEta = %f", dEta, wEta); + continue; + } + } // if(pw_a.fUseWeights[wETA]) + + for (Int_t h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (Int_t wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw_a.fUseWeights[wPHI] || pw_a.fUseWeights[wPT] || pw_a.fUseWeights[wETA]) { + wToPowerP = pow(wPhi * wPt * wEta, wp); + } + qv_a.fQvector[h][wp] += TComplex(wToPowerP * TMath::Cos(h * dPhi), wToPowerP * TMath::Sin(h * dPhi)); + } // for(Int_t wp=0;wpAddAt(dPhi, fSelectedTracks); + } // remember that the 2nd argument here must start from 0 + if (nl_a.ftaNestedLoops[1]) { + nl_a.ftaNestedLoops[1]->AddAt(wPhi * wPt * wEta, fSelectedTracks); + } // remember that the 2nd argument here must start from 0 + } // if(fCalculateNestedLoops||fCalculateCustomNestedLoop) + + // *) Counter of selected tracks in the current event: + fSelectedTracks++; + if (fSelectedTracks >= cSelectedTracks_max) { + break; + } + + } // for (auto& track : tracks) + +} // void MainLoopOverParticlesRecSim(TracksRecSim const& tracks) + +//============================================================ + +void MainLoopOverParticlesSim(TracksSim const& tracks) +{ + // This is the main loop over particles, in which Q-vectors and particle histograms are filled, particle cuts applied, etc. + // Only 'sim' info is processed in this loop, set gProcessSim = true via configurable "cfWhatToProcess" + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + // TBI 20231021 tbc... + +} // void MainLoopOverParticlesSim(TracksSim const& tracks) + +//============================================================ + +void CalculateEverything() +{ + // Calculate everything for selected events and particles. + // Remark: Data members for Q-vectors, containers for nested loops, etc., must all be filled when this function is called. + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + // *) Calculate multiparticle correlations (standard, isotropic, same harmonic): + if (fCalculateCorrelations) { + CalculateCorrelations(); + } + + // *) Calculate nested loops: + if (fCalculateNestedLoops) { + CalculateNestedLoops(); + + // TBI 20220823 this shall be called after all events are processed, only temporarily here called for each event: + ComparisonNestedLoopsVsCorrelations(); + } + +} // void CalculateEverything() + +//============================================================ + +void SteerRec(CollisionRec const& collision, TracksRec const& tracks) +{ + // This is the only function to be called in processRec(...), processRecSim(...), and processSim(...). + // All analysis workflow is defined step-by-step here, via dedicated function calls. + // Order of function calls obviously does matter. + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + // *) Do all thingies before starting to process data from this collision (e.g. count number of events, fetch the run number, etc.): + Preprocess(collision); // see enum eRecSim for possible values of 'rsb' + + // *) Fill event histograms for reconstructed data before event cuts: + FillEventHistograms(collision, tracks, eBefore); + + // *) Event cuts: + if (!EventCuts(collision, tracks)) { + return; + } + + // *) Fill event histograms for reconstructed data after event cuts: + FillEventHistograms(collision, tracks, eAfter); + + // *) Main loop over particles: + MainLoopOverParticlesRec(tracks); + + // *) Fill remaining event histograms for reconstructed data after event AND after particle cuts: + ceh_a.fEventHistograms[eSelectedTracks][eRec][eAfter]->Fill(fSelectedTracks); + + // *) Remaining event cuts which can be applied only after the loop over particles is performed: + if ((fSelectedTracks < ceh_a.fEventCuts[eSelectedTracks][eMin]) || (fSelectedTracks > ceh_a.fEventCuts[eSelectedTracks][eMax])) { + return; + } + + // *) Calculate everything for selected events and particles: + CalculateEverything(); + + // *) Reset event-by-event quantities: + ResetEventByEventQuantities(); + +} // void SteerRec(CollisionRec const& collision, TracksRec const& tracks) + +//============================================================ + +void SteerRecSim(CollisionRec const& collision, TracksRecSim const& tracks) +{ + // This is the only function to be called in processRec(...), processRecSim(...), and processSim(...). + // All analysis workflow is defined step-by-step here, via dedicated function calls. + // Order of function calls obviously does matter. + + if (fVerbose) { + LOGF(info, "\033[1;32m%s\033[0m", __PRETTY_FUNCTION__); + } + + // *) Do all thingies before starting to process data from this collision (e.g. count number of events, fetch the run number, etc.): + Preprocess(collision); // see enum eRecSim for possible values of 'rsb' + + // *) Fill event histograms for reconstructed data before event cuts: + FillEventHistograms(collision, tracks, eBefore); + FillEventHistograms(collision, tracks, eBefore); + + // *) Event cuts: + if (!EventCuts(collision, tracks)) { + return; + } + + // *) Fill event histograms for reconstructed data after event cuts: + FillEventHistograms(collision, tracks, eAfter); + FillEventHistograms(collision, tracks, eAfter); + + // *) Main loop over particles: + MainLoopOverParticlesRecSim(tracks); + + // *) Fill remaining event histograms for reconstructed data after event AND after particle cuts: + ceh_a.fEventHistograms[eSelectedTracks][eRec][eAfter]->Fill(fSelectedTracks); + // ceh_a.fEventHistograms[eSelectedTracks][eSim][eAfter]->Fill(fSelectedTracks); // TBI 20231020 do I really need this one? + + // *) Remaining event cuts which can be applied only after the loop over particles is performed: + if ((fSelectedTracks < ceh_a.fEventCuts[eSelectedTracks][eMin]) || (fSelectedTracks > ceh_a.fEventCuts[eSelectedTracks][eMax])) { + return; + } + + // *) Calculate everything for selected events and particles: + CalculateEverything(); + + // *) Reset event-by-event quantities: + ResetEventByEventQuantities(); + +} // void SteerRecSim(CollisionRec const& collision, TracksRecSim const& tracks) + +//============================================================ + +void SteerSim(CollisionSim const& collision, TracksSim const& tracks) +{ + + // TBI 20231021 tbc... + +} // void SteerSim(CollisionSim const& collision, TracksSim const& tracks) + #endif // PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_MEMBERFUNCTIONS_H_ diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx index 7443f5a6f44..27c5a683c10 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx @@ -10,11 +10,26 @@ // or submit itself to any jurisdiction. // O2: +#include #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/TrackSelectionTables.h" // needed for aod::TracksDCA table using namespace o2; using namespace o2::framework; +using CollisionRec = aod::Collision; +using CollisionSim = aod::McCollision; + +using TracksRec = soa::Join; +using TrackRec = soa::Join::iterator; + +using TracksRecSim = soa::Join; +using TrackRecSim = soa::Join::iterator; + +using TracksSim = aod::McParticles; +using TrackSim = aod::McParticles::iterator; + // ROOT: #include "TList.h" #include "TSystem.h" @@ -32,10 +47,20 @@ using namespace std; // *) Global constants: #include "PWGCF/MultiparticleCorrelations/Core/MuPa-GlobalConstants.h" +// *) These are indended flags for PROCESS_SWITCH, have to be global, at least for the time being... +// TBI 20231017 check this further, it doesn't work yet this way. It seems I have to pass to PROCESS_SWITCH( ) only literals 'true' or 'false' +// TBI 20231020 I could as well re-define them as data members... +bool gProcessRec = false; +bool gProcessRecSim = false; +bool gProcessSim = false; + // *) Main task: struct MultiparticleCorrelationsAB // this name is used in lower-case format to name the TDirectoryFile in AnalysisResults.root { + // *) CCDB: + Service ccdb; + // *) Configurables (cuts): #include "PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h" @@ -62,24 +87,22 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to Bool_t oldHistAddStatus = TH1::AddDirectoryStatus(); TH1::AddDirectory(kFALSE); - // *) Book base list: - BookBaseList(); - // *) Default configuration, booking, binning and cuts: DefaultConfiguration(); DefaultBooking(); DefaultBinning(); DefaultCuts(); // Remark: has to be called after DefaultBinning(), since some default cuts are defined through default binning, to ease bookeeping - // *) Configure the task with setters and getters: - // TH1D *phiWeights = task->GetHistogramWithWeights(Form("%s/%s/weights.root",directoryWeights.Data(),runNumber.Data()),"phi"); // original line - // TH1D* phiWeights = GetHistogramWithWeights("/alice/cern.ch/user/a/abilandz/weights.root", "phi"); // both relative and abs path shell be fine - // SetWeightsHist(phiWeights, "phi"); + // *) Set what to process - only rec, both rec and sim, only sim: + WhatToProcess(); // yes, this can be called here, after calling all Default* member functions above, because this has an effect only on Book* members functions // *) Book random generator: delete gRandom; gRandom = new TRandom3(fRandomSeed); // if uiSeed is 0, the seed is determined uniquely in space and time via TUUID + // *) Book base list: + BookBaseList(); + // *) Book all remaining objects; BookAndNestAllLists(); BookEventHistograms(); @@ -98,89 +121,86 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to // ------------------------------------------- - // *) Process the data: - void process(aod::Collision const& collision, aod::Tracks const& tracks) // called once per collision found in the time frame + // Since I am subscribing to different tables in each case, there are 3 separate implementations of process(...) + // A) Process only reconstructed data; + // B) Process both reconstructed and simulated data; + // C) Process only simulated data. + + // ------------------------------------------- + + // A) Process only reconstructed data: + void processRec(CollisionRec const& collision, aod::BCs const&, TracksRec const& tracks) { - // *) Fill event histograms for reconstructed data before event cuts: - FillEventHistograms(collision, tracks, eRec, eBefore); + // ... - // *) Event cuts: - if (!EventCuts(collision)) { - return; + // *) TBI 20231020 Temporary here (use configurable 'cfWhatToProcess' to set this flag corerectly): + if (!gProcessRec) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", __PRETTY_FUNCTION__, __LINE__); } - // *) Fill event histograms for reconstructed data after event cuts: - FillEventHistograms(collision, tracks, eRec, eAfter); - - // *) Main loop over particles: - Double_t dPhi = 0.; //, dPt = 0., dEta = 0.; - Double_t wPhi = 1.; //, wPt = 1., wEta = 1.; - Double_t wToPowerP = 1.; // final particle weight raised to power p - fSelectedTracks = 0; // reset number of selected tracks - for (auto& track : tracks) { - - // *) Fill particle histograms for reconstructed data before particle cuts: - FillParticleHistograms(track, eRec, eBefore); - - // *) Particle cuts: - if (!ParticleCuts(track)) { - continue; - } - - // *) Fill particle histograms for reconstructed data after particle cuts: - FillParticleHistograms(track, eRec, eAfter); - - // *) Fill Q-vectors: - dPhi = track.phi(); - // dPt = track.pt(); - // dEta = track.eta(); - for (Int_t h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (Int_t wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - // if (fUseWeights[0]||fUseWeights[1]||fUseWeights[2]) { - // wToPowerP = pow(wPhi*wPt*wEta,wp); - // } - qv_a.fQvector[h][wp] += TComplex(wToPowerP * TMath::Cos(h * dPhi), wToPowerP * TMath::Sin(h * dPhi)); - } // for(Int_t wp=0;wpAddAt(dPhi, fSelectedTracks); - } // remember that the 2nd argument here must start from 0 - if (nl_a.ftaNestedLoops[1]) { - nl_a.ftaNestedLoops[1]->AddAt(wPhi, fSelectedTracks); - } // remember that the 2nd argument here must start from 0 - } // if(fCalculateNestedLoops||fCalculateCustomNestedLoop) - - // *) Counter of selected tracks in the current event: - fSelectedTracks++; - if (fSelectedTracks > 100) { - break; - } // TBI 20220803 hardcoded 100 - - // *) tmp: - fResultsHist->Fill(pw_a.fWeightsHist[wPHI]->GetBinContent(pw_a.fWeightsHist[wPHI]->FindBin(track.phi()))); // TBI 20220713 meaningless, only temporarily here to check if this is feasible - - } // for (auto& track : tracks) - - // *) Calculate multiparticle correlations (standard, isotropic, same harmonic): - if (fCalculateCorrelations) { - CalculateCorrelations(); + // *) If I reached max number of events, ignore the remaining collisions: + if (!fProcessRemainingEvents) { + return; // TBI 20231008 Temporarily implemented this way. But what I really need here is a graceful exit + // from subsequent processing (which will also dump the output file, etc.). When that's possible, + // move this to a member function Steer*(...) } - // *) Calculate nested loops: - if (fCalculateNestedLoops) { - CalculateNestedLoops(); + // *) Steer all analysis steps: + SteerRec(collision, tracks); + // TBI 20231021 If I want to do some postprocessing after Steer(...), re-define Steer from void to bool, so that event cuts have effect, etc, + + } // void processRec(...) + PROCESS_SWITCH(MultiparticleCorrelationsAB, processRec, "process only reconstructed information", false); + + // ------------------------------------------- + + // B) Process both reconstructed and simulated data: + void processRecSim(CollisionRec const& collision, aod::BCs const&, TracksRecSim const& tracks, aod::McParticles const&) + { + // ... + + // *) TBI 20231020 Temporary here (use configurable 'cfWhatToProcess' to set this flag corerectly): + if (!gProcessRecSim) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", __PRETTY_FUNCTION__, __LINE__); + } + + // *) If I reached max number of events, ignore the remaining collisions: + if (!fProcessRemainingEvents) { + return; // TBI 20231008 Temporarily implemented this way. But what I really need here is a graceful exit + // from subsequent processing (which will also dump the output file, etc.). When that's possible, + // move this to a member function Steer(...) + } + + // *) Steer all analysis steps: + SteerRecSim(collision, tracks); + // TBI 20231021 If I want to do some postprocessing after Steer(...), re-define Steer from void to bool, so that event cuts have effect, etc, + + } // void processRecSim(...) + PROCESS_SWITCH(MultiparticleCorrelationsAB, processRecSim, "process both reconstructed and simulated information", true); + + // ------------------------------------------- + + // C) Process only simulated data: + void processSim(CollisionSim const& collision, aod::BCs const&, TracksSim const& tracks) + { + // ... + + // *) If I reached max number of events, ignore the remaining collisions: + if (!fProcessRemainingEvents) { + return; // TBI 20231008 Temporarily implemented this way. But what I really need here is a graceful exit from subsequent processing (which will also dump the output file, etc.) + } - // TBI 20220823 this shall be called after all events are processed, only temporarily here called for each event: - ComparisonNestedLoopsVsCorrelations(); + // *) TBI 20231020 Temporary here (use configurable 'cfWhatToProcess' to set this flag corerectly): + if (!gProcessSim) { + LOGF(fatal, "in function \033[1;31m%s at line %d\033[0m", __PRETTY_FUNCTION__, __LINE__); } - // *) Reset event-by-event objects: - ResetEventByEventQuantities(); + // *) Steer all analysis steps: + SteerSim(collision, tracks); + // TBI 20231021 If I want to do some postprocessing after Steer(...), re-define Steer from void to bool, so that event cuts have effect, etc, - } // void process(...) + } // void processSim(...) + PROCESS_SWITCH(MultiparticleCorrelationsAB, processSim, "process only simulated information", false); }; // struct MultiparticleCorrelationsAB diff --git a/PWGCF/TableProducer/CMakeLists.txt b/PWGCF/TableProducer/CMakeLists.txt index 89e55e89743..483570b3798 100644 --- a/PWGCF/TableProducer/CMakeLists.txt +++ b/PWGCF/TableProducer/CMakeLists.txt @@ -18,3 +18,8 @@ o2physics_add_dpl_workflow(dptdpt-filter SOURCES dptdptfilter.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(single-track-selector + SOURCES singletrackselector.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/TableProducer/dptdptfilter.cxx b/PWGCF/TableProducer/dptdptfilter.cxx index 460eac4aa0c..2b617bf26d8 100644 --- a/PWGCF/TableProducer/dptdptfilter.cxx +++ b/PWGCF/TableProducer/dptdptfilter.cxx @@ -47,10 +47,10 @@ using namespace o2::analysis; namespace o2::analysis::dptdptfilter { -using DptDptFullTracksPID = soa::Join; -using DptDptFullTracksPIDDetLevel = soa::Join; -using DptDptFullTracks = soa::Join; -using DptDptFullTracksDetLevel = soa::Join; +using DptDptFullTracksPID = soa::Join; +using DptDptFullTracksPIDDetLevel = soa::Join; +using DptDptFullTracks = soa::Join; +using DptDptFullTracksDetLevel = soa::Join; bool fullDerivedData = false; /* produce full derived data for its external storage */ @@ -145,7 +145,7 @@ using namespace dptdptfilter; struct DptDptFilter { Configurable cfgFullDerivedData{"fullderiveddata", false, "Produce the full derived data for external storage. Default false"}; - Configurable cfgCentMultEstimator{"centmultestimator", "V0M", "Centrality/multiplicity estimator detector: V0M,CL0,CL1,FV0A,FT0M,FT0A,FT0C,NOCM: none. Default V0M"}; + Configurable cfgCentMultEstimator{"centmultestimator", "V0M", "Centrality/multiplicity estimator detector: V0M,CL0,CL1,FV0A,FT0M,FT0A,FT0C,NTPV,NOCM: none. Default V0M"}; Configurable cfgSystem{"syst", "PbPb", "System: pp, PbPb, Pbp, pPb, XeXe, ppRun3, PbPbRun3. Default PbPb"}; Configurable cfgDataType{"datatype", "data", "Data type: data, datanoevsel, MC, FastMC, OnTheFlyMC. Default data"}; Configurable cfgTriggSel{"triggsel", "MB", "Trigger selection: MB, None. Default MB"}; @@ -199,17 +199,18 @@ struct DptDptFilter { if ((fDataType == kData) || (fDataType == kDataNoEvtSel) || (fDataType == kMC)) { /* create the reconstructed data histograms */ /* TODO: proper axes and axes titles according to the system; still incomplete */ + std::string multestimator = getCentMultEstimatorName(fCentMultEstimator); if (fSystem > kPbp) { fhCentMultB = new TH1F("CentralityB", "Centrality before cut; centrality (%)", 100, 0, 100); fhCentMultA = new TH1F("CentralityA", "Centrality; centrality (%)", 100, 0, 100); - fhMultB = new TH1F("V0MB", "V0 Multiplicity before cut;V0 Multiplicity;Collisions", 4001, -0.5, 4000.5); - fhMultA = new TH1F("V0MA", "V0 Multiplicity;V0 Multiplicity;Collisions", 4001, -0.5, 4000.5); + fhMultB = new TH1F("MultB", TString::Format("%s Multiplicity before cut;%s Multiplicity;Collisions", multestimator.c_str(), multestimator.c_str()), 4001, -0.5, 4000.5); + fhMultA = new TH1F("MultA", TString::Format("%s Multiplicity;%s Multiplicity;Collisions", multestimator.c_str(), multestimator.c_str()), 4001, -0.5, 4000.5); } else { /* for pp, pPb and Pbp systems use multiplicity instead */ fhCentMultB = new TH1F("MultiplicityB", "Multiplicity before cut; multiplicity (%)", 100, 0, 100); fhCentMultA = new TH1F("MultiplicityA", "Multiplicity; multiplicity (%)", 100, 0, 100); - fhMultB = new TH1F("V0MB", "V0 Multiplicity before cut;V0 Multiplicity;Collisions", 601, -0.5, 600.5); - fhMultA = new TH1F("V0MA", "V0 Multiplicity;V0 Multiplicity;Collisions", 601, -0.5, 600.5); + fhMultB = new TH1F("MultB", TString::Format("%s Multiplicity before cut;%s Multiplicity;Collisions", multestimator.c_str(), multestimator.c_str()), 601, -0.5, 600.5); + fhMultA = new TH1F("MultA", TString::Format("%s Multiplicity;%s Multiplicity;Collisions", multestimator.c_str(), multestimator.c_str()), 601, -0.5, 600.5); } fhVertexZB = new TH1F("VertexZB", "Vertex Z; z_{vtx}", 60, -15, 15); @@ -327,7 +328,7 @@ void DptDptFilter::processReconstructed(CollisionObject const& collision, Tracks LOGF(DPTDPTFILTERLOGCOLLISIONS, "DptDptFilterTask::processReconstructed(). New collision with %d tracks", ftracks.size()); - float mult = extractMultiplicity(collision); + float mult = extractMultiplicity(collision, fCentMultEstimator); fhCentMultB->Fill(tentativecentmult); fhMultB->Fill(mult); @@ -354,12 +355,12 @@ void DptDptFilter::processReconstructed(CollisionObject const& collision, Tracks void DptDptFilter::processWithCent(aod::CollisionEvSelCent const& collision, DptDptFullTracks const& ftracks) { - processReconstructed(collision, ftracks, collision.centFT0M()); + processReconstructed(collision, ftracks, getCentMultPercentile(collision)); } void DptDptFilter::processWithRun2Cent(aod::CollisionEvSelRun2Cent const& collision, DptDptFullTracks const& ftracks) { - processReconstructed(collision, ftracks, collision.centRun2V0M()); + processReconstructed(collision, ftracks, getCentMultPercentile(collision)); } void DptDptFilter::processWithoutCent(aod::CollisionEvSel const& collision, DptDptFullTracks const& ftracks) @@ -369,12 +370,12 @@ void DptDptFilter::processWithoutCent(aod::CollisionEvSel const& collision, DptD void DptDptFilter::processWithCentPID(aod::CollisionEvSelCent const& collision, DptDptFullTracksPID const& ftracks) { - processReconstructed(collision, ftracks, collision.centFT0M()); + processReconstructed(collision, ftracks, getCentMultPercentile(collision)); } void DptDptFilter::processWithRun2CentPID(aod::CollisionEvSelRun2Cent const& collision, DptDptFullTracksPID const& ftracks) { - processReconstructed(collision, ftracks, collision.centRun2V0M()); + processReconstructed(collision, ftracks, getCentMultPercentile(collision)); } void DptDptFilter::processWithoutCentPID(aod::CollisionEvSel const& collision, DptDptFullTracksPID const& ftracks) @@ -384,12 +385,12 @@ void DptDptFilter::processWithoutCentPID(aod::CollisionEvSel const& collision, D void DptDptFilter::processWithCentDetectorLevel(aod::CollisionEvSelCent const& collision, DptDptFullTracksDetLevel const& ftracks, aod::McParticles const&) { - processReconstructed(collision, ftracks, collision.centFT0M()); + processReconstructed(collision, ftracks, getCentMultPercentile(collision)); } void DptDptFilter::processWithRun2CentDetectorLevel(aod::CollisionEvSelRun2Cent const& collision, DptDptFullTracksDetLevel const& ftracks, aod::McParticles const&) { - processReconstructed(collision, ftracks, collision.centRun2V0M()); + processReconstructed(collision, ftracks, getCentMultPercentile(collision)); } void DptDptFilter::processWithoutCentDetectorLevel(aod::CollisionEvSel const& collision, DptDptFullTracksDetLevel const& ftracks, aod::McParticles const&) @@ -399,12 +400,12 @@ void DptDptFilter::processWithoutCentDetectorLevel(aod::CollisionEvSel const& co void DptDptFilter::processWithCentPIDDetectorLevel(aod::CollisionEvSelCent const& collision, DptDptFullTracksPIDDetLevel const& ftracks, aod::McParticles const&) { - processReconstructed(collision, ftracks, collision.centFT0M()); + processReconstructed(collision, ftracks, getCentMultPercentile(collision)); } void DptDptFilter::processWithRun2CentPIDDetectorLevel(aod::CollisionEvSelRun2Cent const& collision, DptDptFullTracksPIDDetLevel const& ftracks, aod::McParticles const&) { - processReconstructed(collision, ftracks, collision.centRun2V0M()); + processReconstructed(collision, ftracks, getCentMultPercentile(collision)); } void DptDptFilter::processWithoutCentPIDDetectorLevel(aod::CollisionEvSel const& collision, DptDptFullTracksPIDDetLevel const& ftracks, aod::McParticles const&) @@ -419,12 +420,12 @@ void DptDptFilter::processGenerated(CollisionObject const& mccollision, Particle uint8_t acceptedevent = uint8_t(false); if (IsEvtSelected(mccollision, centormult)) { - acceptedevent = true; - if (fullDerivedData) { - acceptedtrueevents(mccollision.bcId(), mccollision.posZ(), acceptedevent, centormult); - } else { - gencollisionsinfo(acceptedevent, centormult); - } + acceptedevent = uint8_t(true); + } + if (fullDerivedData) { + acceptedtrueevents(mccollision.bcId(), mccollision.posZ(), acceptedevent, centormult); + } else { + gencollisionsinfo(acceptedevent, centormult); } } @@ -443,6 +444,7 @@ void DptDptFilter::processGeneratorLevel(aod::McCollision const& mccollision, LOGF(DPTDPTFILTERLOGCOLLISIONS, "DptDptFilterTask::processGeneratorLevel(). Generated collision with more than one reconstructed collisions. Processing only the first accepted for centrality/multiplicity classes extraction"); } + bool processed = false; for (auto& tmpcollision : collisions) { if (tmpcollision.has_mcCollision()) { if (tmpcollision.mcCollisionId() == mccollision.globalIndex()) { @@ -450,11 +452,15 @@ void DptDptFilter::processGeneratorLevel(aod::McCollision const& mccollision, if (IsEvtSelected(collision, defaultcent)) { fhTrueVertexZAA->Fill((mccollision.posZ())); processGenerated(mccollision, mcparticles, defaultcent); + processed = true; break; /* TODO: only processing the first reconstructed accepted collision */ } } } } + if (!processed && !fullDerivedData) { + gencollisionsinfo(uint8_t(false), 105.0); + } } void DptDptFilter::processWithCentGeneratorLevel(aod::McCollision const& mccollision, @@ -544,14 +550,9 @@ struct DptDptFilterTracks { particleMaxDCAZ = cfgTrackSelection->mDCAz; } ownTrackSelection.ResetITSRequirements(); - ownTrackSelection.SetRequireITSRefit(false); - ownTrackSelection.SetRequireTPCRefit(false); - ownTrackSelection.SetRequireGoldenChi2(false); ownTrackSelection.SetMinNClustersTPC(cfgTrackSelection->mTPCclusters); ownTrackSelection.SetMinNCrossedRowsTPC(cfgTrackSelection->mTPCxRows); - ownTrackSelection.SetMinNCrossedRowsOverFindableClustersTPC(0); - ownTrackSelection.SetMaxChi2PerClusterITS(1e6f); - ownTrackSelection.SetMaxDcaXYPtDep(std::function{}); + ownTrackSelection.SetMaxDcaXYPtDep([&](float) { return cfgTrackSelection->mDCAxy; }); ownTrackSelection.SetMaxDcaXY(cfgTrackSelection->mDCAxy); ownTrackSelection.SetMaxDcaZ(cfgTrackSelection->mDCAz); o2::aod::track::TrackTypeEnum ttype; @@ -741,6 +742,8 @@ struct DptDptFilterTracks { float charge, MatchRecoGenSpecies sp); + /* TODO: as it is now when the derived data is stored (fullDerivedData = true) */ + /* the collision index stored with the track is wrong. This has to be fixed */ template void filterTracks(soa::Join const& collisions, passedtracks const& tracks) @@ -779,7 +782,7 @@ struct DptDptFilterTracks { } } } - LOGF(info, + LOGF(DPTDPTFILTERLOGCOLLISIONS, "Processed %d accepted collisions out of a total of %d with %d accepted tracks out of a " "total of %d", ncollaccepted, @@ -788,12 +791,23 @@ struct DptDptFilterTracks { tracks.size()); } - template - void filterParticles(ParticleListObject const& particles, MCCollisionObject const& mccollision, CollisionIndex colix) + /* TODO: for the time being the full derived data is still not supported */ + /* for doing that we need to get the index of the associated mc collision */ + void filterParticles(soa::Join const& gencollisions, aod::McParticles const& particles) { using namespace dptdptfilter; int acceptedparticles = 0; + int acceptedcollisions = 0; + if (!fullDerivedData) { + gentracksinfo.reserve(particles.size()); + } + + for (auto gencoll : gencollisions) { + if (gencoll.collisionaccepted()) { + acceptedcollisions++; + } + } for (auto& particle : particles) { float charge = 0.0; @@ -805,73 +819,81 @@ struct DptDptFilterTracks { int8_t pid = -1; if (charge != 0) { - /* before particle selection */ - fillParticleHistosBeforeSelection(particle, mccollision, charge); - - /* track selection */ - pid = AcceptParticle(particle, mccollision); - if (!(pid < 0)) { - /* the particle has been accepted */ - /* let's identify the particle */ - /* TODO: probably this needs to go to AcceptParticle */ - MatchRecoGenSpecies sp = IdentifyParticle(particle); - if (sp != kWrongSpecies) { - if (sp != kDptDptCharged) { - /* fill the charged particle histograms */ - fillParticleHistosAfterSelection(particle, mccollision, charge, kDptDptCharged); - /* update charged multiplicities */ + if (particle.has_mcCollision() && (particle.template mcCollision_as>()).collisionaccepted()) { + auto mccollision = particle.template mcCollision_as>(); + /* before particle selection */ + fillParticleHistosBeforeSelection(particle, mccollision, charge); + + /* track selection */ + /* TODO: at some point the pid has to be substituted by the identified species */ + pid = AcceptParticle(particle, mccollision); + if (!(pid < 0)) { + /* the particle has been accepted */ + /* let's identify the particle */ + /* TODO: probably this needs to go to AcceptParticle */ + MatchRecoGenSpecies sp = IdentifyParticle(particle); + if (sp != kWrongSpecies) { + if (sp != kDptDptCharged) { + /* fill the charged particle histograms */ + fillParticleHistosAfterSelection(particle, mccollision, charge, kDptDptCharged); + /* update charged multiplicities */ + if (pid % 2 == 0) { + partMultPos[kDptDptCharged]++; + } + if (pid % 2 == 1) { + partMultNeg[kDptDptCharged]++; + } + } + /* fill the species histograms */ + fillParticleHistosAfterSelection(particle, mccollision, charge, sp); + /* update species multiplicities */ if (pid % 2 == 0) { - partMultPos[kDptDptCharged]++; + partMultPos[sp]++; } if (pid % 2 == 1) { - partMultNeg[kDptDptCharged]++; + partMultNeg[sp]++; } + acceptedparticles++; + } else { + pid = -1; } - /* fill the species histograms */ - fillParticleHistosAfterSelection(particle, mccollision, charge, sp); - /* update species multiplicities */ - if (pid % 2 == 0) { - partMultPos[sp]++; - } - if (pid % 2 == 1) { - partMultNeg[sp]++; - } - if (fullDerivedData) { - scannedtruetracks(colix, pid, particle.pt(), particle.eta(), particle.phi()); - } - acceptedparticles++; - } else { - pid = -1; } } } else { if ((particle.mcCollisionId() == 0) && traceCollId0) { - LOGF(info, "Particle %d with fractional charge or equal to zero", particle.globalIndex()); + LOGF(DPTDPTFILTERLOGTRACKS, "Particle %d with fractional charge or equal to zero", particle.globalIndex()); } } + if (!fullDerivedData) { + gentracksinfo(pid); + } } - LOGF(DPTDPTFILTERLOGCOLLISIONS, "Accepted %d generated particles", acceptedparticles); + LOGF(DPTDPTFILTERLOGCOLLISIONS, + "Processed %d accepted generated collisions out of a total of %d with %d accepted particles out of a " + "total of %d", + acceptedcollisions, + gencollisions.size(), + acceptedparticles, + particles.size()); } - void filterRecoWithPID(soa::Join& collisions, - DptDptFullTracksPID const& tracks) + void filterRecoWithPID(soa::Join& collisions, DptDptFullTracksPID const& tracks) { filterTracks(collisions, tracks); } - PROCESS_SWITCH(DptDptFilterTracks, - filterRecoWithPID, - "Not stored derived data track filtering", - false) + PROCESS_SWITCH(DptDptFilterTracks, filterRecoWithPID, "Not stored derived data track filtering", false) - void filterRecoWithoutPID(soa::Join const& collisions, - DptDptFullTracks const& tracks) + void filterRecoWithoutPID(soa::Join const& collisions, DptDptFullTracks const& tracks) { filterTracks(collisions, tracks); } - PROCESS_SWITCH(DptDptFilterTracks, - filterRecoWithoutPID, - "Track filtering without PID information", - true) + PROCESS_SWITCH(DptDptFilterTracks, filterRecoWithoutPID, "Track filtering without PID information", true) + + void filterGenerated(soa::Join const& gencollisions, aod::McParticles const& particles) + { + filterParticles(gencollisions, particles); + } + PROCESS_SWITCH(DptDptFilterTracks, filterGenerated, "Generated particles filering", true) }; template diff --git a/PWGCF/TableProducer/dptdptfilter.h b/PWGCF/TableProducer/dptdptfilter.h index f8284891f2e..5b455095e42 100644 --- a/PWGCF/TableProducer/dptdptfilter.h +++ b/PWGCF/TableProducer/dptdptfilter.h @@ -29,8 +29,8 @@ namespace o2 { namespace aod { -using CollisionsEvSelCent = soa::Join; -using CollisionEvSelCent = soa::Join::iterator; +using CollisionsEvSelCent = soa::Join; +using CollisionEvSelCent = soa::Join::iterator; using CollisionsEvSelRun2Cent = soa::Join; using CollisionEvSelRun2Cent = soa::Join::iterator; using CollisionsEvSel = soa::Join; @@ -77,6 +77,7 @@ enum CentMultEstimatorType { kFT0M, ///< FT0M centrality/multiplicity estimator Run 3 kFT0A, ///< FT0A centrality/multiplicity estimator Run 3 kFT0C, ///< FT0C centrality/multiplicity estimator Run 3 + kNTPV, ///< NTPV centrality/multiplicity estimator Run 3 knCentMultEstimators ///< number of centrality/mutiplicity estimator }; @@ -256,6 +257,8 @@ inline CentMultEstimatorType getCentMultEstimator(std::string const& datastr) return kFT0A; } else if (datastr == "FT0C") { return kFT0C; + } else if (datastr == "NTPV") { + return kNTPV; } else if (datastr == "NOCM") { return kNOCM; } else { @@ -264,6 +267,43 @@ inline CentMultEstimatorType getCentMultEstimator(std::string const& datastr) return kNOCM; } +inline std::string getCentMultEstimatorName(CentMultEstimatorType est) +{ + switch (est) { + case kV0M: + return "V0M"; + break; + case kCL0: + return "CL0"; + break; + case kCL1: + return "CL1"; + break; + case kFV0A: + return "FV0A"; + break; + case kFT0M: + return "FT0M"; + break; + case kFT0A: + return "FT0A"; + break; + case kFT0C: + return "FT0C"; + break; + case kNTPV: + return "NTPV"; + break; + case kNOCM: + return "NOCM"; + break; + default: + LOGF(fatal, "Centrality/Multiplicity estimator %d not supported yet", est); + return "WRONG"; + break; + } +} + ////////////////////////////////////////////////////////////////////////////////// /// Trigger selection ////////////////////////////////////////////////////////////////////////////////// @@ -390,84 +430,107 @@ inline bool triggerSelection(aod::McCollision const&) /// \brief Extract the collision multiplicity from the event selection information template -inline float extractMultiplicity(CollisionObject const& collision) +inline float extractMultiplicity(CollisionObject const& collision, CentMultEstimatorType est) { - float mult = 0.0; - switch (fSystem) { - case kpp: - case kpPb: - case kPbp: - case kPbPb: - case kXeXe: - /* for the time being let's extract V0M */ - mult = collision.multFV0M(); + switch (est) { + case kV0M: + return collision.multFV0M(); break; - case kppRun3: - case kPbPbRun3: - /* for the time being let's extract T0M */ - mult = collision.multFT0M(); + case kCL0: + return collision.multTracklets(); + break; + case kCL1: + return collision.multTracklets(); + break; + case kFV0A: + return collision.multFV0A(); + break; + case kFT0M: + return collision.multFT0M(); + break; + case kFT0A: + return collision.multFT0A(); + break; + case kFT0C: + return collision.multFT0M(); + break; + case kNTPV: + return collision.multNTracksPV(); + break; + case kNOCM: + return collision.multFT0M(); break; default: + LOGF(fatal, "Centrality/Multiplicity estimator %d not supported yet", est); + return collision.multFT0M(); break; } - return mult; } ////////////////////////////////////////////////////////////////////////////////// /// Centrality selection ////////////////////////////////////////////////////////////////////////////////// -/// \brief Centrality selection when there is centrality/multiplicity information +/// \brief Centrality/multiplicity percentile template -inline bool centralitySelectionMult(CollisionObject collision, float& centmult) +float getCentMultPercentile(CollisionObject collision) { - auto getPercentile = [¢mult](auto mult) { - if (mult < 100 && 0 < mult) { - centmult = mult; - return true; - } - return false; - }; - bool centmultsel = false; if constexpr (framework::has_type_v || framework::has_type_v || framework::has_type_v) { switch (fCentMultEstimator) { case kV0M: - centmultsel = getPercentile(collision.centRun2V0M()); + return collision.centRun2V0M(); break; case kCL0: - centmultsel = getPercentile(collision.centRun2CL0()); + return collision.centRun2CL0(); break; case kCL1: - centmultsel = getPercentile(collision.centRun2CL1()); + return collision.centRun2CL1(); break; default: + return 105.0; break; } } if constexpr (framework::has_type_v || framework::has_type_v || framework::has_type_v || - framework::has_type_v) { + framework::has_type_v || + framework::has_type_v) { switch (fCentMultEstimator) { case kFV0A: - centmultsel = getPercentile(collision.centFV0A()); + return collision.centFV0A(); break; case kFT0M: - centmultsel = getPercentile(collision.centFT0M()); + return collision.centFT0M(); break; case kFT0A: - centmultsel = getPercentile(collision.centFT0A()); + return collision.centFT0A(); break; case kFT0C: - centmultsel = getPercentile(collision.centFT0C()); + return collision.centFT0C(); + break; + case kNTPV: + return collision.centNTPV(); break; default: + return 105.0; break; } } - return centmultsel; +} + +/// \brief Centrality selection when there is centrality/multiplicity information +template +inline bool centralitySelectionMult(CollisionObject collision, float& centmult) +{ + float mult = getCentMultPercentile(collision); + if (mult < 100 && 0 < mult) { + centmult = mult; + return true; + } + return false; } /// \brief Centrality selection when there is not centrality/multiplicity information diff --git a/PWGCF/TableProducer/filterCorrelations.cxx b/PWGCF/TableProducer/filterCorrelations.cxx index 8a9ac5766cc..24c398289e4 100644 --- a/PWGCF/TableProducer/filterCorrelations.cxx +++ b/PWGCF/TableProducer/filterCorrelations.cxx @@ -44,7 +44,7 @@ using CFMultiplicity = CFMultiplicities::iterator; } // namespace o2::aod struct FilterCF { - Service pdg; + Service pdg; // Configuration O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 7.0f, "Accepted z-vertex range") @@ -72,6 +72,9 @@ struct FilterCF { Produces outputCollisions; Produces outputTracks; + Produces outputMcCollisionLabels; + Produces outputTrackLabels; + Produces outputMcCollisions; Produces outputMcParticles; @@ -99,7 +102,7 @@ struct FilterCF { } auto bc = collision.bc_as(); - outputCollisions(-1, bc.runNumber(), collision.posZ(), collision.multiplicity(), bc.timestamp()); + outputCollisions(bc.runNumber(), collision.posZ(), collision.multiplicity(), bc.timestamp()); for (auto& track : tracks) { uint8_t trackType = 0; @@ -109,7 +112,7 @@ struct FilterCF { trackType = 2; } - outputTracks(outputCollisions.lastIndex(), -1, track.pt(), track.eta(), track.phi(), track.sign(), trackType); + outputTracks(outputCollisions.lastIndex(), track.pt(), track.eta(), track.phi(), track.sign(), trackType); yields->Fill(collision.multiplicity(), track.pt(), track.eta()); etaphi->Fill(collision.multiplicity(), track.eta(), track.phi()); @@ -117,90 +120,9 @@ struct FilterCF { } PROCESS_SWITCH(FilterCF, processData, "Process data", true); - void processMC1(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks) - { - if (cfgVerbosity > 0) { - LOGF(info, "processMC1: Tracks for collision: %d | Vertex: %.1f (%d) | INT7: %d", tracks.size(), collision.posZ(), collision.flags(), collision.sel7()); - } - - if (!keepCollision(collision)) { - return; - } - - auto bc = collision.bc_as(); - // NOTE only works if we save all MC collisions... - outputCollisions(collision.mcCollisionId(), bc.runNumber(), collision.posZ(), collision.multiplicity(), bc.timestamp()); - - for (auto& track : tracks) { - uint8_t trackType = 0; - if (track.isGlobalTrack()) { - trackType = 1; - } else if (track.isGlobalTrackSDD()) { - trackType = 2; - } - - // NOTE only works if we save all MC tracks... - outputTracks(outputCollisions.lastIndex(), track.mcParticleId(), truncateFloatFraction(track.pt()), truncateFloatFraction(track.eta()), truncateFloatFraction(track.phi()), track.sign(), trackType); - - yields->Fill(collision.multiplicity(), track.pt(), track.eta()); - etaphi->Fill(collision.multiplicity(), track.eta(), track.phi()); - } - } - PROCESS_SWITCH(FilterCF, processMC1, "Process MC: data part", false); - - Preslice perCollision = aod::track::collisionId; - void processMC2(aod::McCollision const& mcCollision, aod::McParticles const& particles, soa::SmallGroups> const& collisions, soa::Filtered> const& tracks) - { - if (cfgVerbosity > 0) { - LOGF(info, "processMC2: Particles for MC collision: %d | Vertex: %.1f", particles.size(), mcCollision.posZ()); - } - - bool* reconstructed = new bool[particles.size()]; - for (int i = 0; i < particles.size(); i++) { - reconstructed[i] = false; - } - for (auto& collision : collisions) { - auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); - if (cfgVerbosity > 0) { - LOGF(info, " Reconstructed collision at vtx-z = %f which has %d tracks", collision.posZ(), groupedTracks.size()); - } - - for (auto& track : groupedTracks) { - if (track.has_mcParticle()) { - reconstructed[track.mcParticleId() - particles.begin().globalIndex()] = true; - } - } - } - - int multiplicity = 0; - for (auto& particle : particles) { - int8_t sign = 0; - TParticlePDG* pdgparticle = pdg->GetParticle(particle.pdgCode()); - if (pdgparticle != nullptr) { - sign = (pdgparticle->Charge() > 0) ? 1.0 : ((pdgparticle->Charge() < 0) ? -1.0 : 0.0); - } - if (particle.isPhysicalPrimary() && sign != 0 && std::abs(particle.eta()) < cfgCutMCEta && particle.pt() > cfgCutMCPt) { - multiplicity++; - } - // use highest bit to flag if it is reconstructed - uint8_t flags = particle.flags() & ~aod::cfmcparticle::kReconstructed; // clear bit in case of clashes in the future - if (reconstructed[particle.index()]) { - flags |= aod::cfmcparticle::kReconstructed; - } - - // NOTE using "outputMcCollisions.lastIndex()+1" here to allow filling of outputMcCollisions *after* the loop - outputMcParticles(outputMcCollisions.lastIndex() + 1, truncateFloatFraction(particle.pt(), FLOAT_PRECISION), truncateFloatFraction(particle.eta(), FLOAT_PRECISION), - truncateFloatFraction(particle.phi(), FLOAT_PRECISION), sign, particle.pdgCode(), flags); - } - - outputMcCollisions(mcCollision.posZ(), multiplicity); - - delete[] reconstructed; - } - PROCESS_SWITCH(FilterCF, processMC2, "Process MC: MC part", false); - // NOTE not filtering collisions here because in that case there can be tracks referring to MC particles which are not part of the selected MC collisions Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice perCollision = aod::track::collisionId; void processMC(aod::McCollisions const& mcCollisions, aod::McParticles const& allParticles, soa::Join const& allCollisions, soa::Filtered> const& tracks, @@ -283,7 +205,8 @@ struct FilterCF { auto bc = collision.bc_as(); // NOTE works only when we store all MC collisions (as we do here) - outputCollisions(collision.mcCollisionId(), bc.runNumber(), collision.posZ(), collision.multiplicity(), bc.timestamp()); + outputCollisions(bc.runNumber(), collision.posZ(), collision.multiplicity(), bc.timestamp()); + outputMcCollisionLabels(collision.mcCollisionId()); for (auto& track : groupedTracks) { uint8_t trackType = 0; @@ -300,8 +223,9 @@ struct FilterCF { LOGP(fatal, "processMC: Track {} is referring to a MC particle which we do not store {} {} (reco flag {})", track.index(), track.mcParticleId(), mcParticleId, reconstructed[track.mcParticleId()]); } } - outputTracks(outputCollisions.lastIndex(), mcParticleId, + outputTracks(outputCollisions.lastIndex(), truncateFloatFraction(track.pt()), truncateFloatFraction(track.eta()), truncateFloatFraction(track.phi()), track.sign(), trackType); + outputTrackLabels(mcParticleId); yields->Fill(collision.multiplicity(), track.pt(), track.eta()); etaphi->Fill(collision.multiplicity(), track.eta(), track.phi()); diff --git a/PWGCF/TableProducer/singletrackselector.cxx b/PWGCF/TableProducer/singletrackselector.cxx new file mode 100644 index 00000000000..c47efdbdd8b --- /dev/null +++ b/PWGCF/TableProducer/singletrackselector.cxx @@ -0,0 +1,108 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \brief create a table applying some basic cuts on the ITS and DCA. +/// \author Sofia Tomassini +/// \since 31 May 2023 + +#include +#include +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" + +#include "PWGCF/DataModel/singletrackselector.h" + +#include "TDatabasePDG.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::track; +using namespace o2::aod; + +struct singleTrackSelector { + + Configurable applyEvSel{"applyEvSel", 2, "Flag to apply rapidity cut: 0 -> no event selection, 1 -> Run 2 event selection, 2 -> Run 3 event selection"}; + Configurable cutDcaXy{"cutDcaXy", 0.12, ""}; + Configurable cutPtMin{"cutPtMin", 0.4, "Minimum cut in pT"}; + Configurable cutTPCNSigmaPr{"cutTPCNSigmaPr", 5.f, "Cut on the TPC nsigma for protons"}; + Configurable cutTPCNSigmaDe{"cutTPCNSigmaDe", 5.f, "Cut on the TPC nsigma for deuteron"}; + + using Trks = soa::Join; + using Coll = soa::Join; + + Produces tableRow; + Produces tableRowColl; + + Filter eventFilter = (applyEvSel.node() == 0) || + ((applyEvSel.node() == 1) && (aod::evsel::sel7 == true)) || + ((applyEvSel.node() == 2) && (aod::evsel::sel8 == true)); + Filter vertexFilter = ((o2::aod::collision::posZ < 15.f) && (o2::aod::collision::posZ > -15.f)); + Filter trackFilter = ((o2::aod::track::itsChi2NCl <= 36.f) && (o2::aod::track::itsChi2NCl >= 0.f) && (o2::aod::track::tpcChi2NCl >= 0.f) && (o2::aod::track::tpcChi2NCl <= 4.f)); + + void process(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) + { + tableRow.reserve(tracks.size()); + tableRowColl(collision.globalIndex(), + collision.multTPC(), + collision.posZ()); + + for (auto& track : tracks) { + if (track.pt() < cutPtMin) { + continue; + } + if (abs(track.dcaXY()) > cutDcaXy) { + continue; + } + if (abs(track.tpcNSigmaPr()) < cutTPCNSigmaPr || abs(track.tpcNSigmaDe()) < cutTPCNSigmaDe) { + + tableRow(tableRowColl.lastIndex(), + track.hasITS(), + track.hasTOF(), + track.px(), + track.py(), + track.pz(), + track.tpcInnerParam(), + track.tpcSignal(), + track.beta(), + track.dcaXY(), + track.dcaZ(), + track.tpcNClsFound(), + track.tpcFoundOverFindableCls(), + track.tpcChi2NCl(), + track.itsNCls(), + track.itsChi2NCl(), + track.sign(), + track.eta(), + track.phi(), + singletrackselector::packInTableOffset(track.tpcNClsCrossedRows()), + singletrackselector::packInTable(track.tofNSigmaPr()), + singletrackselector::packInTable(track.tpcNSigmaPr()), + singletrackselector::packInTable(track.tofNSigmaDe()), + singletrackselector::packInTable(track.tpcNSigmaDe())); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index 26c7eefd645..6986c0bf4fc 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -566,8 +566,8 @@ struct CorrelationTask { } // NOTE SmallGroups includes soa::Filtered always - Preslice perCollision = aod::cftrack::cfCollisionId; - void processMCEfficiency(soa::Filtered::iterator const& mcCollision, aod::CFMcParticles const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracks const& tracks) + Preslice perCollision = aod::cftrack::cfCollisionId; + void processMCEfficiency(soa::Filtered::iterator const& mcCollision, aod::CFMcParticles const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracksWithLabel const& tracks) { if (cfgVerbosity > 0) { LOGF(info, "MC collision at vtx-z = %f with %d mc particles and %d reconstructed collisions", mcCollision.posZ(), mcParticles.size(), collisions.size()); @@ -606,7 +606,7 @@ struct CorrelationTask { PROCESS_SWITCH(CorrelationTask, processMCEfficiency, "MC: Extract efficiencies", false); // NOTE SmallGroups includes soa::Filtered always - void processMCSameDerived(soa::Filtered::iterator const& mcCollision, soa::Filtered const& mcParticles, soa::SmallGroups const& collisions) + void processMCSameDerived(soa::Filtered::iterator const& mcCollision, soa::Filtered const& mcParticles, soa::SmallGroups const& collisions) { if (cfgVerbosity > 0) { LOGF(info, "processMCSameDerived. MC collision: %d, particles: %d, collisions: %d", mcCollision.globalIndex(), mcParticles.size(), collisions.size()); @@ -634,8 +634,8 @@ struct CorrelationTask { PROCESS_SWITCH(CorrelationTask, processMCSameDerived, "Process MC same event on derived data", false); using BinningTypeMCDerived = ColumnBinningPolicy; - Preslice collisionPerMCCollision = aod::cfcollision::cfMcCollisionId; - void processMCMixedDerived(soa::Filtered& mcCollisions, soa::Filtered const& mcParticles, soa::Filtered const& collisions) + PresliceUnsorted collisionPerMCCollision = aod::cfcollision::cfMcCollisionId; + void processMCMixedDerived(soa::Filtered& mcCollisions, soa::Filtered const& mcParticles, soa::Filtered const& collisions) { // Strictly upper categorised collisions, for cfgNoMixedEvents combinations per bin, skipping those in entry -1 BinningTypeMCDerived configurableBinning{{axisVertex, axisMultiplicity}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. diff --git a/PWGCF/Tasks/dptdptcorrelations.cxx b/PWGCF/Tasks/dptdptcorrelations.cxx index 279dfca034f..b2a162c2261 100644 --- a/PWGCF/Tasks/dptdptcorrelations.cxx +++ b/PWGCF/Tasks/dptdptcorrelations.cxx @@ -67,12 +67,15 @@ bool ptorder = false; PairCuts fPairCuts; // pair suppression engine bool fUseConversionCuts = false; // suppress resonances and conversions bool fUseTwoTrackCut = false; // suppress too close tracks + +std::vector tname = {"O", "T"}; ///< the track names } // namespace correlationstask // Task for building correlations struct DptDptCorrelationsTask { /* the data collecting engine */ + template struct DataCollectingEngine { int nspecies = 1; /* for the time being just hadrons */ size_t nch = nspecies * 2; @@ -108,17 +111,6 @@ struct DptDptCorrelationsTask { std::vector> fhSum2PtPtnw_vsC{nch, {nch, nullptr}}; //!> fhSum2DptDptnw_vsC{nch, {nch, nullptr}}; //!) ({p_T}_2 - <{p_T}_2>) \f$ distribution vs \f$\Delta\eta,\;\Delta\phi\f$ distribution vs event centrality/multiplicity 1-1,1-2,2-1,2-2, combinations - /// \enum TrackPairs - /// \brief The track combinations hadled by the class - typedef enum { - kOO = 0, ///< one-one pairs - kOT, ///< one-two pairs - kTO, ///< two-one pairs - kTT, ///< two-two pairs - nTrackPairs ///< the number of track pairs - } trackpairs; - - std::vector tname = {"1", "2"}; ///< the external track names, one and two, for histogram creation std::vector> trackPairsNames = {{"OO", "OT"}, {"TO", "TT"}}; bool ccdbstored = false; @@ -204,8 +196,21 @@ struct DptDptCorrelationsTask { { LOGF(info, "Stored NUA&NUE corrections for %d track ids", corrs.size()); for (uint i = 0; i < corrs.size(); ++i) { - LOGF(info, " Stored NUA&NUE corrections for track id %s %s", corrs[i] != nullptr ? "yes" : "no"); + LOGF(info, " Stored NUA&NUE corrections %s for track id %d %s", corrs[i] != nullptr ? corrs[i]->GetName() : "nullptr", i, corrs[i] != nullptr ? "yes" : "no"); fhNuaNue_vsZEtaPhiPt[i] = corrs[i]; + if (fhNuaNue_vsZEtaPhiPt[i] != nullptr) { + int nbins = 0; + double avg = 0.0; + for (int ix = 0; ix < fhNuaNue_vsZEtaPhiPt[i]->GetNbinsX(); ++ix) { + for (int iy = 0; iy < fhNuaNue_vsZEtaPhiPt[i]->GetNbinsY(); ++iy) { + for (int iz = 0; iz < fhNuaNue_vsZEtaPhiPt[i]->GetNbinsZ(); ++iz) { + nbins++; + avg += fhNuaNue_vsZEtaPhiPt[i]->GetBinContent(ix + 1, iy + 1, iz + 1); + } + } + } + LOGF(info, "Average NUA&NUE correction for track id %d: %f", i, avg / nbins); + } } ccdbstored = true; } @@ -214,7 +219,7 @@ struct DptDptCorrelationsTask { { LOGF(info, "Stored pT average for %d track ids", ptavgs.size()); for (uint i = 0; i < ptavgs.size(); ++i) { - LOGF(info, " Stored pT average for track id %s %s", ptavgs[i] != nullptr ? "yes" : "no"); + LOGF(info, " Stored pT average for track id %d %s", i, ptavgs[i] != nullptr ? "yes" : "no"); fhPtAvg_vsEtaPhi[i] = ptavgs[i]; } ccdbstored = true; @@ -225,9 +230,9 @@ struct DptDptCorrelationsTask { { std::vector* corr = new std::vector(tracks.size(), 1.0f); int index = 0; - for (auto t : tracks) { + for (auto& t : tracks) { if (fhNuaNue_vsZEtaPhiPt[t.trackacceptedid()] != nullptr) { - (*corr)[index] = fhNuaNue_vsZEtaPhiPt[t.trackacceptedid()]->GetBinContent(zvtx, GetEtaPhiIndex(t) + 0.5, t.pt()); + (*corr)[index] = fhNuaNue_vsZEtaPhiPt[t.trackacceptedid()]->GetBinContent(fhNuaNue_vsZEtaPhiPt[t.trackacceptedid()]->FindFixBin(zvtx, GetEtaPhiIndex(t) + 0.5, t.pt())); } index++; } @@ -239,9 +244,9 @@ struct DptDptCorrelationsTask { { std::vector* ptavg = new std::vector(tracks.size(), 0.0f); int index = 0; - for (auto t : tracks) { + for (auto& t : tracks) { if (fhPtAvg_vsEtaPhi[t.trackacceptedid()] != nullptr) { - (*ptavg)[index] = fhPtAvg_vsEtaPhi[t.trackacceptedid()]->GetBinContent(fhPtAvg_vsEtaPhi[t.trackacceptedid()]->FindBin(t.eta(), t.phi())); + (*ptavg)[index] = fhPtAvg_vsEtaPhi[t.trackacceptedid()]->GetBinContent(fhPtAvg_vsEtaPhi[t.trackacceptedid()]->FindFixBin(t.eta(), t.phi())); index++; } } @@ -258,8 +263,13 @@ struct DptDptCorrelationsTask { for (auto& track : passedtracks) { float corr = (*corrs)[index]; fhN1_vsPt[track.trackacceptedid()]->Fill(track.pt(), corr); - fhN1_vsZEtaPhiPt[track.trackacceptedid()]->Fill(zvtx, GetEtaPhiIndex(track) + 0.5, track.pt(), corr); - fhSum1Pt_vsZEtaPhiPt[track.trackacceptedid()]->Fill(zvtx, GetEtaPhiIndex(track) + 0.5, track.pt(), track.pt() * corr); + if constexpr (smallsingles) { + fhN1_vsEtaPhi[track.trackacceptedid()]->Fill(track.eta(), GetShiftedPhi(track.phi()), corr); + fhSum1Pt_vsEtaPhi[track.trackacceptedid()]->Fill(track.eta(), GetShiftedPhi(track.phi()), track.pt() * corr); + } else { + fhN1_vsZEtaPhiPt[track.trackacceptedid()]->Fill(zvtx, GetEtaPhiIndex(track) + 0.5, track.pt(), corr); + fhSum1Pt_vsZEtaPhiPt[track.trackacceptedid()]->Fill(zvtx, GetEtaPhiIndex(track) + 0.5, track.pt(), track.pt() * corr); + } index++; } } @@ -371,7 +381,9 @@ struct DptDptCorrelationsTask { fhSum2PtPt_vsDEtaDPhi[track1.trackacceptedid()][track2.trackacceptedid()]->AddBinContent(globalbin, track1.pt() * track2.pt() * corr); } fhN2_vsPtPt[track1.trackacceptedid()][track2.trackacceptedid()]->Fill(track1.pt(), track2.pt(), corr); + index2++; } + index1++; } for (uint pid1 = 0; pid1 < nch; ++pid1) { for (uint pid2 = 0; pid2 < nch; ++pid2) { @@ -468,55 +480,78 @@ struct DptDptCorrelationsTask { ptbins, ptlow, ptup); /* we don't want the Sumw2 structure being created here */ bool defSumw2 = TH1::GetDefaultSumw2(); - TH1::SetDefaultSumw2(false); - fhN1_vsZEtaPhiPt[i] = new TH3F( - TString::Format("n1_%s_vsZ_vsEtaPhi_vsPt", tname[i].c_str()).Data(), - TString::Format("#LT n_{1} #GT;vtx_{z};#eta_{%s}#times#varphi_{%s};p_{t,%s} (GeV/c)", - tname[i].c_str(), - tname[i].c_str(), - tname[i].c_str()) - .Data(), - zvtxbins, - zvtxlow, - zvtxup, - etabins * phibins, - 0.0, - static_cast(etabins * phibins), - ptbins, - ptlow, - ptup); - fhSum1Pt_vsZEtaPhiPt[i] = new TH3F( - TString::Format("sumPt1_%s_vsZ_vsEtaPhi_vsPt", tname[i].c_str()).Data(), - TString::Format( - "#LT #Sigma p_{t,%s}#GT;vtx_{z};#eta_{%s}#times#varphi_{%s};p_{t,%s} (GeV/c)", - tname[i].c_str(), - tname[i].c_str(), - tname[i].c_str(), - tname[i].c_str()) - .Data(), - zvtxbins, - zvtxlow, - zvtxup, - etabins * phibins, - 0.0, - static_cast(etabins * phibins), - ptbins, - ptlow, - ptup); + if constexpr (smallsingles) { + fhN1_vsEtaPhi[i] = new TH2F(TString::Format("n1_%s_vsEtaPhi", tname[i].c_str()).Data(), + TString::Format("#LT n_{1} #GT;#eta_{%s};#varphi_{%s} (radian);#LT n_{1} #GT", tname[i].c_str(), tname[i].c_str()).Data(), + etabins, etalow, etaup, phibins, philow, phiup); + fhSum1Pt_vsEtaPhi[i] = new TH2F(TString::Format("sumPt_%s_vsEtaPhi", tname[i].c_str()).Data(), + TString::Format("#LT #Sigma p_{t,%s} #GT;#eta_{%s};#varphi_{%s} (radian);#LT #Sigma p_{t,%s} #GT (GeV/c)", + tname[i].c_str(), tname[i].c_str(), tname[i].c_str(), tname[i].c_str()) + .Data(), + etabins, etalow, etaup, phibins, philow, phiup); + } else { + TH1::SetDefaultSumw2(false); + fhN1_vsZEtaPhiPt[i] = new TH3F( + TString::Format("n1_%s_vsZ_vsEtaPhi_vsPt", tname[i].c_str()).Data(), + TString::Format("#LT n_{1} #GT;vtx_{z};#eta_{%s}#times#varphi_{%s};p_{t,%s} (GeV/c)", + tname[i].c_str(), + tname[i].c_str(), + tname[i].c_str()) + .Data(), + zvtxbins, + zvtxlow, + zvtxup, + etabins * phibins, + 0.0, + static_cast(etabins * phibins), + ptbins, + ptlow, + ptup); + fhSum1Pt_vsZEtaPhiPt[i] = new TH3F( + TString::Format("sumPt1_%s_vsZ_vsEtaPhi_vsPt", tname[i].c_str()).Data(), + TString::Format( + "#LT #Sigma p_{t,%s}#GT;vtx_{z};#eta_{%s}#times#varphi_{%s};p_{t,%s} (GeV/c)", + tname[i].c_str(), + tname[i].c_str(), + tname[i].c_str(), + tname[i].c_str()) + .Data(), + zvtxbins, + zvtxlow, + zvtxup, + etabins * phibins, + 0.0, + static_cast(etabins * phibins), + ptbins, + ptlow, + ptup); + } /* we return it back to previuos state */ TH1::SetDefaultSumw2(defSumw2); /* the statistical uncertainties will be estimated by the subsamples method so let's get rid of the error tracking */ - fhN1_vsZEtaPhiPt[i]->SetBit(TH1::kIsNotW); - fhN1_vsZEtaPhiPt[i]->Sumw2(false); - fhSum1Pt_vsZEtaPhiPt[i]->SetBit(TH1::kIsNotW); - fhSum1Pt_vsZEtaPhiPt[i]->Sumw2(false); + if constexpr (smallsingles) { + fhN1_vsEtaPhi[i]->SetBit(TH1::kIsNotW); + fhN1_vsEtaPhi[i]->Sumw2(false); + fhSum1Pt_vsEtaPhi[i]->SetBit(TH1::kIsNotW); + fhSum1Pt_vsEtaPhi[i]->Sumw2(false); + } else { + fhN1_vsZEtaPhiPt[i]->SetBit(TH1::kIsNotW); + fhN1_vsZEtaPhiPt[i]->Sumw2(false); + fhSum1Pt_vsZEtaPhiPt[i]->SetBit(TH1::kIsNotW); + fhSum1Pt_vsZEtaPhiPt[i]->Sumw2(false); + } fhNuaNue_vsZEtaPhiPt[i] = nullptr; fhPtAvg_vsEtaPhi[i] = nullptr; fOutputList->Add(fhN1_vsPt[i]); - fOutputList->Add(fhN1_vsZEtaPhiPt[i]); - fOutputList->Add(fhSum1Pt_vsZEtaPhiPt[i]); + if constexpr (smallsingles) { + fOutputList->Add(fhN1_vsEtaPhi[i]); + fOutputList->Add(fhSum1Pt_vsEtaPhi[i]); + } else { + fOutputList->Add(fhN1_vsZEtaPhiPt[i]); + fOutputList->Add(fhSum1Pt_vsZEtaPhiPt[i]); + } } } else { for (uint i = 0; i < nch; ++i) { @@ -625,8 +660,9 @@ struct DptDptCorrelationsTask { float* fCentMultMax = nullptr; /* the data collecting engine instances */ - DataCollectingEngine** dataCE; - DataCollectingEngine** dataCEME; + DataCollectingEngine** dataCE; + DataCollectingEngine** dataCE_small; + DataCollectingEngine** dataCEME; /* the input file structure from CCDB */ TList* ccdblst = nullptr; @@ -639,6 +675,7 @@ struct DptDptCorrelationsTask { Configurable cfgTwoTrackCut{"twotrackcut", -1, "Two-tracks cut: -1 = off; >0 otherwise distance value (suggested: 0.02"}; Configurable cfgTwoTrackCutMinRadius{"twotrackcutminradius", 0.8f, "Two-tracks cut: radius in m from which two-tracks cut is applied"}; + Configurable cfgSmallDCE{"smalldce", true, "Use small data collecting engine for singles processing, true = yes. Default = true"}; Configurable cfgProcessPairs{"processpairs", false, "Process pairs: false = no, just singles, true = yes, process pairs"}; Configurable cfgProcessME{"processmixedevents", false, "Process mixed events: false = no, just same event, true = yes, also process mixed events"}; Configurable cfgCentSpec{"centralities", "00-05,05-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80", "Centrality/multiplicity ranges in min-max separated by commas"}; @@ -697,20 +734,21 @@ struct DptDptCorrelationsTask { fOutput.setObject(fGlobalOutputList); /* incorporate configuration parameters to the output */ - fGlobalOutputList->Add(new TParameter("NoBinsVertexZ", zvtxbins, 'f')); - fGlobalOutputList->Add(new TParameter("NoBinsPt", ptbins, 'f')); - fGlobalOutputList->Add(new TParameter("NoBinsEta", etabins, 'f')); - fGlobalOutputList->Add(new TParameter("NoBinsPhi", phibins, 'f')); - fGlobalOutputList->Add(new TParameter("MinVertexZ", zvtxlow, 'f')); - fGlobalOutputList->Add(new TParameter("MaxVertexZ", zvtxup, 'f')); - fGlobalOutputList->Add(new TParameter("MinPt", ptlow, 'f')); - fGlobalOutputList->Add(new TParameter("MaxPt", ptup, 'f')); - fGlobalOutputList->Add(new TParameter("MinEta", etalow, 'f')); - fGlobalOutputList->Add(new TParameter("MaxEta", etaup, 'f')); - fGlobalOutputList->Add(new TParameter("MinPhi", philow, 'f')); - fGlobalOutputList->Add(new TParameter("MaxPhi", phiup, 'f')); - fGlobalOutputList->Add(new TParameter("PhiBinShift", phibinshift, 'f')); - fGlobalOutputList->Add(new TParameter("DifferentialOutput", true, 'f')); + fGlobalOutputList->Add(new TParameter("NoBinsPt", ptbins, 'f')); + fGlobalOutputList->Add(new TParameter("NoBinsEta", etabins, 'f')); + fGlobalOutputList->Add(new TParameter("NoBinsPhi", phibins, 'f')); + fGlobalOutputList->Add(new TParameter("NoBinsVertexZ", zvtxbins, 'f')); + fGlobalOutputList->Add(new TParameter("MinVertexZ", zvtxlow, 'f')); + fGlobalOutputList->Add(new TParameter("MaxVertexZ", zvtxup, 'f')); + fGlobalOutputList->Add(new TParameter("MinPt", ptlow, 'f')); + fGlobalOutputList->Add(new TParameter("MaxPt", ptup, 'f')); + fGlobalOutputList->Add(new TParameter("MinEta", etalow, 'f')); + fGlobalOutputList->Add(new TParameter("MaxEta", etaup, 'f')); + fGlobalOutputList->Add(new TParameter("MinPhi", philow, 'f')); + fGlobalOutputList->Add(new TParameter("MaxPhi", phiup, 'f')); + fGlobalOutputList->Add(new TParameter("PhiBinShift", phibinshift, 'f')); + fGlobalOutputList->Add(new TParameter("DifferentialOutput", true, 'f')); + fGlobalOutputList->Add(new TParameter("SmallDCE", cfgSmallDCE.value, 'f')); /* after the parameters dump the proper phi limits are set according to the phi shift */ phiup = phiup - phibinwidth * phibinshift; @@ -722,21 +760,34 @@ struct DptDptCorrelationsTask { ncmranges = tokens->GetEntries(); fCentMultMin = new float[ncmranges]; fCentMultMax = new float[ncmranges]; - dataCE = new DataCollectingEngine*[ncmranges]; + dataCE = new DataCollectingEngine*[ncmranges]; + if (cfgSmallDCE) { + dataCE_small = new DataCollectingEngine*[ncmranges]; + } else { + dataCE = new DataCollectingEngine*[ncmranges]; + } if (processmixedevents) { - dataCEME = new DataCollectingEngine*[ncmranges]; + dataCEME = new DataCollectingEngine*[ncmranges]; } for (int i = 0; i < ncmranges; ++i) { - auto buildCEInstance = [&fGlobalOutputList](auto rg, bool me = false) { - DataCollectingEngine* dce = new DataCollectingEngine(); + auto initializeCEInstance = [&fGlobalOutputList](auto dce, auto name) { /* crete the output list for the passed centrality/multiplicity range */ TList* fOutputList = new TList(); - fOutputList->SetName(TString::Format("DptDptCorrelationsData%s-%s", me ? "ME" : "", rg)); + fOutputList->SetName(name); fOutputList->SetOwner(true); /* init the data collection instance */ dce->init(fOutputList); fGlobalOutputList->Add(fOutputList); + }; + auto builSmallDCEInstance = [&initializeCEInstance](auto rg, bool me = false) { + DataCollectingEngine* dce = new DataCollectingEngine(); + initializeCEInstance(dce, TString::Format("DptDptCorrelationsData%s-%s", me ? "ME" : "", rg)); + return dce; + }; + auto buildCEInstance = [&initializeCEInstance](auto rg, bool me = false) { + DataCollectingEngine* dce = new DataCollectingEngine(); + initializeCEInstance(dce, TString::Format("DptDptCorrelationsData%s-%s", me ? "ME" : "", rg)); return dce; }; float cmmin = 0.0f; @@ -744,8 +795,19 @@ struct DptDptCorrelationsTask { sscanf(tokens->At(i)->GetName(), "%f-%f", &cmmin, &cmmax); fCentMultMin[i] = cmmin; fCentMultMax[i] = cmmax; - dataCE[i] = buildCEInstance(tokens->At(i)->GetName()); + if (cfgSmallDCE.value) { + if (processpairs) { + LOGF(fatal, "Processing pairs cannot be used with the small DCE, please configure properly!!"); + } + dataCE_small[i] = builSmallDCEInstance(tokens->At(i)->GetName()); + } else { + dataCE[i] = buildCEInstance(tokens->At(i)->GetName()); + } if (processmixedevents) { + /* consistency check */ + if (cfgSmallDCE.value) { + LOGF(fatal, "Mixed events cannot be used with the small DCE, please configure properly!!"); + } dataCEME[i] = buildCEInstance(tokens->At(i)->GetName(), true); } } @@ -842,41 +904,51 @@ struct DptDptCorrelationsTask { int ixDCE = getDCEindex(collision); if (!(ixDCE < 0)) { if (ccdblst != nullptr && !(dataCE[ixDCE]->isCCDBstored())) { - dataCE[ixDCE]->storeTrackCorrections( - std::vector{reinterpret_cast(ccdblst->FindObject( - TString::Format("correction_%02d-%02d_p1", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data())), - reinterpret_cast(ccdblst->FindObject( - TString::Format("correction_%02d-%02d_m1", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data()))}); if constexpr (gen) { - dataCE[ixDCE]->storePtAverages( - std::vector{reinterpret_cast(ccdblst->FindObject( - TString::Format("trueptavgetaphi_%02d-%02d_p", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data())), - reinterpret_cast(ccdblst->FindObject( - TString::Format("trueptavgetaphi_%02d-%02d_m", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data()))}); + std::vector ptavgs{tname.size(), nullptr}; + for (uint isp = 0; isp < tname.size(); ++isp) { + ptavgs[isp] = reinterpret_cast(ccdblst->FindObject( + TString::Format("trueptavgetaphi_%02d-%02d_%s", + static_cast(fCentMultMin[ixDCE]), + static_cast(fCentMultMax[ixDCE]), + tname[isp].c_str()) + .Data())); + } + if (cfgSmallDCE.value) { + dataCE_small[ixDCE]->storePtAverages(ptavgs); + } else { + dataCE[ixDCE]->storePtAverages(ptavgs); + } } else { - dataCE[ixDCE]->storePtAverages( - std::vector{reinterpret_cast(ccdblst->FindObject( - TString::Format("ptavgetaphi_%02d-%02d_p", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data())), - reinterpret_cast(ccdblst->FindObject( - TString::Format("ptavgetaphi_%02d-%02d_m", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data()))}); + std::vector corrs{tname.size(), nullptr}; + for (uint isp = 0; isp < tname.size(); ++isp) { + corrs[isp] = reinterpret_cast(ccdblst->FindObject( + TString::Format("correction_%02d-%02d_%s", + static_cast(fCentMultMin[ixDCE]), + static_cast(fCentMultMax[ixDCE]), + tname[isp].c_str()) + .Data())); + } + if (cfgSmallDCE.value) { + dataCE_small[ixDCE]->storeTrackCorrections(corrs); + } else { + dataCE[ixDCE]->storeTrackCorrections(corrs); + } + + std::vector ptavgs{tname.size(), nullptr}; + for (uint isp = 0; isp < tname.size(); ++isp) { + ptavgs[isp] = reinterpret_cast(ccdblst->FindObject( + TString::Format("ptavgetaphi_%02d-%02d_%s", + static_cast(fCentMultMin[ixDCE]), + static_cast(fCentMultMax[ixDCE]), + tname[isp].c_str()) + .Data())); + } + if (cfgSmallDCE.value) { + dataCE_small[ixDCE]->storePtAverages(ptavgs); + } else { + dataCE[ixDCE]->storePtAverages(ptavgs); + } } } @@ -896,7 +968,11 @@ struct DptDptCorrelationsTask { if constexpr (!gen) { bfield = (fUseConversionCuts || fUseTwoTrackCut) ? getMagneticField(timestamp) : 0; } - dataCE[ixDCE]->processCollision(tracks, tracks, collision.posZ(), collision.centmult(), bfield); + if (cfgSmallDCE.value) { + dataCE_small[ixDCE]->processCollision(tracks, tracks, collision.posZ(), collision.centmult(), bfield); + } else { + dataCE[ixDCE]->processCollision(tracks, tracks, collision.posZ(), collision.centmult(), bfield); + } } } @@ -916,40 +992,38 @@ struct DptDptCorrelationsTask { if (!(ixDCE < 0)) { if (ccdblst != nullptr && !(dataCEME[ixDCE]->isCCDBstored())) { if constexpr (gen) { - dataCEME[ixDCE]->storePtAverages( - std::vector{reinterpret_cast(ccdblst->FindObject( - TString::Format("trueptavgetaphi_%02d-%02d_p", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data())), - reinterpret_cast(ccdblst->FindObject( - TString::Format("trueptavgetaphi_%02d-%02d_m", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data()))}); + std::vector ptavgs{tname.size(), nullptr}; + for (uint isp = 0; isp < tname.size(); ++isp) { + ptavgs[isp] = reinterpret_cast(ccdblst->FindObject( + TString::Format("trueptavgetaphi_%02d-%02d_%s", + static_cast(fCentMultMin[ixDCE]), + static_cast(fCentMultMax[ixDCE]), + tname[isp].c_str()) + .Data())); + } + dataCEME[ixDCE]->storePtAverages(ptavgs); } else { - dataCEME[ixDCE]->storeTrackCorrections( - std::vector{reinterpret_cast(ccdblst->FindObject( - TString::Format("correction_%02d-%02d_p1", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data())), - reinterpret_cast(ccdblst->FindObject( - TString::Format("correction_%02d-%02d_m1", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data()))}); - dataCEME[ixDCE]->storePtAverages( - std::vector{reinterpret_cast(ccdblst->FindObject( - TString::Format("ptavgetaphi_%02d-%02d_p", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data())), - reinterpret_cast(ccdblst->FindObject( - TString::Format("ptavgetaphi_%02d-%02d_m", - static_cast(fCentMultMin[ixDCE]), - static_cast(fCentMultMax[ixDCE])) - .Data()))}); + std::vector corrs{tname.size(), nullptr}; + for (uint isp = 0; isp < tname.size(); ++isp) { + corrs[isp] = reinterpret_cast(ccdblst->FindObject( + TString::Format("correction_%02d-%02d_%s", + static_cast(fCentMultMin[ixDCE]), + static_cast(fCentMultMax[ixDCE]), + tname[isp].c_str()) + .Data())); + } + dataCEME[ixDCE]->storeTrackCorrections(corrs); + + std::vector ptavgs{tname.size(), nullptr}; + for (uint isp = 0; isp < tname.size(); ++isp) { + ptavgs[isp] = reinterpret_cast(ccdblst->FindObject( + TString::Format("ptavgetaphi_%02d-%02d_%s", + static_cast(fCentMultMin[ixDCE]), + static_cast(fCentMultMax[ixDCE]), + tname[isp].c_str()) + .Data())); + } + dataCEME[ixDCE]->storePtAverages(ptavgs); } } @@ -1011,6 +1085,33 @@ struct DptDptCorrelationsTask { } PROCESS_SWITCH(DptDptCorrelationsTask, processRecLevelCheck, "Process reco level checks", true); + void processGenLevelCheck(aod::McCollisions const& mccollisions, aod::McParticles& particles) + { + int nAssignedParticles = 0; + int nNotAssignedParticles = 0; + int64_t firstNotAssignedIndex = -1; + int64_t lastNotAssignedIndex = -1; + + for (auto particle : particles) { + if (particle.has_mcCollision()) { + nAssignedParticles++; + } else { + nNotAssignedParticles++; + if (firstNotAssignedIndex < 0) { + firstNotAssignedIndex = particle.globalIndex(); + } else { + lastNotAssignedIndex = particle.globalIndex(); + } + } + } + LOGF(info, "Received %d generated collisions and %d particles.", mccollisions.size(), particles.size()); + LOGF(info, " Assigned tracks %d", nAssignedParticles); + LOGF(info, " Not assigned tracks %d", nNotAssignedParticles); + LOGF(info, " First not assigned track index %d", firstNotAssignedIndex); + LOGF(info, " Last not assigned track index %d", lastNotAssignedIndex); + } + PROCESS_SWITCH(DptDptCorrelationsTask, processGenLevelCheck, "Process generator level checks", true); + void processRecLevelNotStored( soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, @@ -1033,9 +1134,9 @@ struct DptDptCorrelationsTask { void processGenLevelNotStored( soa::Filtered>::iterator const& collision, - soa::Filtered& tracks) + soa::Filtered>& particles) { - processSame(collision, tracks); + processSame(collision, particles); } PROCESS_SWITCH(DptDptCorrelationsTask, processGenLevelNotStored, diff --git a/PWGCF/Tasks/flowGenericFramework.cxx b/PWGCF/Tasks/flowGenericFramework.cxx index b44abb80aee..8aaff20ea6b 100644 --- a/PWGCF/Tasks/flowGenericFramework.cxx +++ b/PWGCF/Tasks/flowGenericFramework.cxx @@ -40,33 +40,38 @@ struct GenericFramework { O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 3.0f, "Maximal pT for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtRefMin, float, 0.2f, "Minimal pT for reference tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtRefMax, float, 3.0f, "Maximal pT for reference tracks") O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") + O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "Number of chi2 per TPC cluster") + O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 0.1f, "Maximum DCA xy") + O2_DEFINE_CONFIGURABLE(cfgEtaSep, float, 0.4f, "Eta gap for flow calculations") O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") - ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; + ConfigurableAxis axisVertex{"axisVertex", {22, -11, 11}, "vertex axis for histograms"}; ConfigurableAxis axisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.25, 0.30, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.20, 2.40, 2.60, 2.80, 3.00}, "pt axis for histograms"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.5, 4, 5, 6, 8, 10}, "pt axis for histograms"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100.1}, "multiplicity / centrality axis for histograms"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)); - using myTracks = soa::Filtered>; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (aod::track::dcaXY < cfgCutDCAxy); + using myTracks = soa::Filtered>; // Connect to ccdb Service ccdb; - Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; - Configurable url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; struct Config { TH1D* mEfficiency = nullptr; GFWWeights* mAcceptance = nullptr; + bool correctionsLoaded = false; } cfg; // Define output OutputObj fFC{FlowContainer("FlowContainer")}; + OutputObj fWeights{GFWWeights("weights")}; HistogramRegistry registry{"registry"}; // define global variables @@ -77,60 +82,127 @@ struct GenericFramework { void init(InitContext const&) { - - ccdb->setURL(url.value); + ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); - ccdb->setCreatedNotAfter(nolaterthan.value); + ccdb->setLocalObjectValidityChecking(); - // Global effiencies - if (cfgEfficiency.value.empty() == false) { - cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency.value, nolaterthan.value); - if (cfg.mEfficiency) - LOGF(info, "Loaded efficiency histogram %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); - else - LOGF(info, "Could not load efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); - } - registry.add("hPhi", "", {HistType::kTH1D, {axisPhi}}); - registry.add("hEta", "", {HistType::kTH1D, {axisEta}}); - registry.add("hVtxZ", "", {HistType::kTH1D, {axisVertex}}); + int64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); o2::framework::AxisSpec axis = axisPt; int nPtBins = axis.binEdges.size() - 1; double* PtBins = &(axis.binEdges)[0]; fPtAxis = new TAxis(nPtBins, PtBins); - TObjArray* oba = new TObjArray(); - // Reference flow - oba->Add(new TNamed("ChGap22", "ChGap22")); // for gap (|eta|>0.4) case - oba->Add(new TNamed("ChGap24", "ChGap24")); // for gap (|eta|>0.4) case - oba->Add(new TNamed("ChFull22", "ChFull22")); // no-gap case - oba->Add(new TNamed("ChFull24", "ChFull24")); // no-gap case - oba->Add(new TNamed("ChGap32", "ChGap32")); // gap-case - oba->Add(new TNamed("ChGap42", "ChGap42")); // gap case - oba->Add(new TNamed("ChSC244", "ChSC244")); // gap case - oba->Add(new TNamed("ChSC234", "ChSC234")); // gap case - fFC->SetName("FlowContainer"); - fFC->SetXAxis(fPtAxis); - fFC->Initialize(oba, axisMultiplicity, cfgNbootstrap); - delete oba; - - fGFW->AddRegion("refN", -0.8, -0.4, 1, 1); - fGFW->AddRegion("refP", 0.4, 0.8, 1, 1); - fGFW->AddRegion("full", -0.8, 0.8, 1, 2); - CreateCorrConfigs(); - fGFW->CreateRegions(); + if (doprocessWeights) { + fWeights->SetPtBins(nPtBins, PtBins); + fWeights->Init(true, false); + } + + if (doprocessData) { + registry.add("hPhi", "", {HistType::kTH1D, {axisPhi}}); + registry.add("hEta", "", {HistType::kTH1D, {axisEta}}); + registry.add("hPt", "", {HistType::kTH1D, {axisPt}}); + registry.add("hVtxZ", "", {HistType::kTH1D, {axisVertex}}); + registry.add("hPhiEtaVtxZ_corrected", "", {HistType::kTH3D, {axisPhi, axisEta, axisVertex}}); + registry.add("hCent", "", {HistType::kTH1D, {axisMultiplicity}}); + + TObjArray* oba = new TObjArray(); + // Reference flow + oba->Add(new TNamed("ChGapP22", "ChGapP22")); // for positive gap case + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("ChGapP22_pt_%i", i + 1), "ChGapP22_pTDiff")); + oba->Add(new TNamed("ChGapP32", "ChGapP32")); + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("ChGapP32_pt_%i", i + 1), "ChGapP32_pTDiff")); + oba->Add(new TNamed("ChGapP42", "ChGapP42")); + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("ChGapP42_pt_%i", i + 1), "ChGapP42_pTDiff")); + + oba->Add(new TNamed("ChGapN22", "ChGapN22")); // for negative gap case + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("ChGapN22_pt_%i", i + 1), "ChGapN22_pTDiff")); + oba->Add(new TNamed("ChGapN32", "ChGapN32")); + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("ChGapN32_pt_%i", i + 1), "ChGapN32_pTDiff")); + oba->Add(new TNamed("ChGapN42", "ChGapN42")); + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("ChGapN42_pt_%i", i + 1), "ChGapN42_pTDiff")); + + oba->Add(new TNamed("ChFull22", "ChFull22")); // no-gap case + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("ChFull22_pt_%i", i + 1), "ChFull22_pTDiff")); + oba->Add(new TNamed("ChFull24", "ChFull24")); // no-gap case + for (Int_t i = 0; i < fPtAxis->GetNbins(); i++) + oba->Add(new TNamed(Form("ChFull24_pt_%i", i + 1), "ChFull24_pTDiff")); + oba->Add(new TNamed("ChFull26", "ChFull26")); // no-gap case + oba->Add(new TNamed("ChFull28", "ChFull28")); // no-gap case + oba->Add(new TNamed("ChFull210", "ChFull210")); // no-gap case + fFC->SetName("FlowContainer"); + fFC->SetXAxis(fPtAxis); + fFC->Initialize(oba, axisMultiplicity, cfgNbootstrap); + delete oba; + + fGFW->AddRegion("refN", -cfgCutEta, cfgEtaSep, 1, 1); + fGFW->AddRegion("refP", cfgEtaSep, cfgCutEta, 1, 1); + fGFW->AddRegion("refFull", -cfgCutEta, cfgCutEta, 1, 1); + + fGFW->AddRegion("poiN", -cfgCutEta, -cfgEtaSep, nPtBins + 1, 2); + fGFW->AddRegion("poiP", cfgEtaSep, cfgCutEta, nPtBins + 1, 2); + fGFW->AddRegion("poiFull", -cfgCutEta, cfgCutEta, nPtBins + 1, 2); + + fGFW->AddRegion("olN", -cfgCutEta, -cfgEtaSep, nPtBins + 1, 4); + fGFW->AddRegion("olP", cfgEtaSep, cfgCutEta, nPtBins + 1, 4); + fGFW->AddRegion("olFull", -cfgCutEta, cfgCutEta, nPtBins + 1, 4); + + CreateCorrConfigs(); + fGFW->CreateRegions(); + } + } + + void loadCorrections(uint64_t timestamp) + { + if (cfg.correctionsLoaded) + return; + if (cfgAcceptance.value.empty() == false) { + cfg.mAcceptance = ccdb->getForTimeStamp(cfgAcceptance, timestamp); + if (cfg.mAcceptance) + LOGF(info, "Loaded acceptance weights from %s (%p)", cfgAcceptance.value.c_str(), (void*)cfg.mAcceptance); + else + LOGF(warning, "Could not load acceptance weights from %s (%p)", cfgAcceptance.value.c_str(), (void*)cfg.mAcceptance); + } + if (cfgEfficiency.value.empty() == false) { + cfg.mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); + if (cfg.mEfficiency == nullptr) { + LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", cfgEfficiency.value.c_str()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); + } + cfg.correctionsLoaded = true; } void CreateCorrConfigs() { - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {2} refN {-2}", "ChGap22", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {2 2} refN {-2 -2}", "ChGap24", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {2 -2}", "ChFull22", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("full {2 2 -2 -2}", "ChFull24", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {3} refN {-3}", "ChGap32", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {4} refN {-4}", "ChGap42", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {2 4} refN {-2 -4}", "ChSC244", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {2 3} refN {-2 -3}", "ChSC234", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {2} refN {-2}", "ChGapP22", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiP refP | olP {2} refN {-2}", "ChGapP22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN {2} refP {-2}", "ChGapN22", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN refN | olN {2} refP {-2}", "ChGapN22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {3} refN {-3}", "ChGapP32", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiP refP | olP {3} refN {-3}", "ChGapP32", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN {3} refP {-3}", "ChGapN32", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN refN | olN {3} refP {-3}", "ChGapN32", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP {4} refN {-4}", "ChGapP42", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiP refP | olP {4} refN {-4}", "ChGapP42", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN {4} refP {-4}", "ChGapN42", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN refN | olN {4} refP {-4}", "ChGapN42", kTRUE)); + + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refFull {2 -2}", "ChFull22", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiFull refFull | olFull {2 -2}", "ChFull22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refFull {2 2 -2 -2}", "ChFull24", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiFull refFull | olFull {2 2 -2 -2}", "ChFull24", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refFull {2 2 2 -2 -2 -2}", "ChFull26", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refFull {2 2 2 2 -2 -2 -2 -2}", "ChFull28", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refFull {2 2 2 2 2 -2 -2 -2 -2 -2}", "ChFull210", kFALSE)); } void FillFC(const GFW::CorrConfig& corrconf, const double& cent, const double& rndm) @@ -156,28 +228,21 @@ struct GenericFramework { return; } - void process(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, myTracks const& tracks) + void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, myTracks const& tracks) { auto bc = collision.bc_as(); + loadCorrections(bc.timestamp()); - if (cfgAcceptance.value.empty() == false) { - cfg.mAcceptance = ccdb->getForTimeStamp(cfgAcceptance.value, bc.timestamp()); - if (cfg.mAcceptance) - LOGF(info, "Loaded acceptance histogram from %s (%p)", cfgAcceptance.value.c_str(), (void*)cfg.mAcceptance); - else - LOGF(warning, "Could not load acceptance histogram from %s (%p)", cfgAcceptance.value.c_str(), (void*)cfg.mAcceptance); - } if (tracks.size() < 1) return; - if (!collision.sel7()) - return; - // LOGF(info, "Tracks for collision: %d | Vertex: %.1f | INT7: %d | V0M: %.1f", tracks.size(), collision.posZ(), collision.sel7(), collision.centV0M()); + float vtxz = collision.posZ(); registry.fill(HIST("hVtxZ"), vtxz); fGFW->Clear(); - const auto centrality = collision.centRun2V0M(); + const auto centrality = collision.centFT0C(); + registry.fill(HIST("hCent"), centrality); if (centrality > 100) return; float l_Random = fRndm->Rndm(); @@ -187,8 +252,9 @@ struct GenericFramework { registry.fill(HIST("hPhi"), track.phi()); registry.fill(HIST("hEta"), track.eta()); + double pt = track.pt(); if (cfg.mEfficiency) - weff = cfg.mEfficiency->GetBinContent(cfg.mEfficiency->FindBin(track.pt())); + weff = cfg.mEfficiency->GetBinContent(cfg.mEfficiency->FindBin(pt)); else weff = 1.0; if (weff == 0) @@ -198,13 +264,37 @@ struct GenericFramework { wacc = cfg.mAcceptance->GetNUA(track.phi(), track.eta(), vtxz); else wacc = 1; - - fGFW->Fill(track.eta(), 1, track.phi(), wacc * weff, 3); + registry.fill(HIST("hPhiEtaVtxZ_corrected"), track.phi(), track.eta(), vtxz, wacc); + registry.fill(HIST("hPt"), pt); + bool WithinPtPOI = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); // within POI pT range + bool WithinPtRef = (cfgCutPtRefMin < pt) && (pt < cfgCutPtRefMax); // within RF pT range + if (WithinPtRef) + fGFW->Fill(track.eta(), fPtAxis->FindBin(pt) - 1, track.phi(), wacc * weff, 1); + if (WithinPtPOI) + fGFW->Fill(track.eta(), fPtAxis->FindBin(pt) - 1, track.phi(), wacc * weff, 2); + if (WithinPtPOI && WithinPtRef) + fGFW->Fill(track.eta(), fPtAxis->FindBin(pt) - 1, track.phi(), wacc * weff, 4); } for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { FillFC(corrconfigs.at(l_ind), centrality, l_Random); } } + PROCESS_SWITCH(GenericFramework, processData, "Process analysis for data", true); + + void processWeights(soa::Filtered>::iterator const& collision, myTracks const& tracks) + { + const auto centrality = collision.centFT0C(); + if (centrality > 100) + return; + for (auto& track : tracks) { + if (track.tpcNClsCrossedRows() < 70) + continue; + if (track.dcaXY() > 7 * (0.0026 + 0.0050 / pow(track.pt(), 1.01))) + continue; + fWeights->Fill(track.phi(), track.eta(), collision.posZ(), track.pt(), centrality, 0); + } + } + PROCESS_SWITCH(GenericFramework, processWeights, "Process weights for acceptance corrections", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/Tasks/match-reco-gen.cxx b/PWGCF/Tasks/match-reco-gen.cxx index 04230168de5..30f7c723da5 100644 --- a/PWGCF/Tasks/match-reco-gen.cxx +++ b/PWGCF/Tasks/match-reco-gen.cxx @@ -456,7 +456,7 @@ struct CheckGeneratorLevelVsDetectorLevel { collectData(tracks, mcParticles, collisions); } - void processMapChecksWithCent(soa::Join const& tracks, + void processMapChecksWithCent(soa::Join const& tracks, soa::Join const& collisions, aod::McParticles const& mcParticles) { @@ -465,7 +465,7 @@ struct CheckGeneratorLevelVsDetectorLevel { } PROCESS_SWITCH(CheckGeneratorLevelVsDetectorLevel, processMapChecksWithCent, "Process detector <=> generator levels with centrality/multiplicity information", false); - void processMapChecksWithoutCent(soa::Join const& tracks, + void processMapChecksWithoutCent(soa::Join const& tracks, soa::Join const& collisions, aod::McParticles const& mcParticles) { diff --git a/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt index 91a202cf067..557f6dbb674 100644 --- a/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Core/CMakeLists.txt @@ -16,7 +16,7 @@ o2physics_add_library(TwoPartCorrCore PIDSelectionFilterAndAnalysis.cxx EventSelectionFilterAndAnalysis.cxx FilterAndAnalysisFramework.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore) o2physics_target_root_dictionary(TwoPartCorrCore HEADERS SkimmingConfigurableCuts.h diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index 5e4554d2bbc..dbf0e26f514 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -34,6 +34,12 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) cut->AddCut(GetAnalysisCut("jpsi_TPCPID_debug5")); return cut; } + if (!nameStr.compare("ElectronTight")) { + cut->AddCut(GetAnalysisCut("jpsiStandardKine3")); + cut->AddCut(GetAnalysisCut("electronStandardQualityForO2MCdebug")); + cut->AddCut(GetAnalysisCut("jpsi_TPCPID_debug1")); + return cut; + } if (!nameStr.compare("MuonLow")) { cut->AddCut(GetAnalysisCut("muonLowPt2")); cut->AddCut(GetAnalysisCut("muonQualityCuts")); @@ -143,7 +149,7 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) } if (!nameStr.compare("jpsiO2MCdebugCuts7_noCorr")) { - cut->AddCut(GetAnalysisCut("jpsiStandardKine1")); + cut->AddCut(GetAnalysisCut("jpsiStandardKine")); cut->AddCut(GetAnalysisCut("electronStandardQualityForO2MCdebug")); cut->AddCut(GetAnalysisCut("jpsi_TPCPID_debug5_noCorr")); @@ -295,12 +301,23 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare("coherentRho0")) { - cut->AddCut(GetAnalysisCut("lowMultTrackCut")); + if (!nameStr.compare("rho0Cuts")) { + cut->AddCut(GetAnalysisCut("rho0Kine")); + cut->AddCut(GetAnalysisCut("pionQuality")); cut->AddCut(GetAnalysisCut("pionPIDnsigma")); return cut; } + if (!nameStr.compare("rho0Kine")) { + cut->AddCut(GetAnalysisCut("rho0Kine")); + return cut; + } + + if (!nameStr.compare("openEtaSel")) { + cut->AddCut(GetAnalysisCut("openEtaSel")); + return cut; + } + if (!nameStr.compare("PIDCalib")) { cut->AddCut(GetAnalysisCut("PIDStandardKine")); // standard kine cuts usually are applied via Filter in the task cut->AddCut(GetAnalysisCut("electronStandardQuality")); @@ -316,6 +333,11 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("KineCutOnly")) { + cut->AddCut(GetAnalysisCut("PIDStandardKine")); // standard kine cuts usually are applied via Filter in the task + return cut; + } + if (!nameStr.compare("kaonPID")) { cut->AddCut(GetAnalysisCut("PIDStandardKine")); // standard kine cuts usually are applied via Filter in the task cut->AddCut(GetAnalysisCut("electronStandardQualityForO2MCdebug")); @@ -361,12 +383,53 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("Jpsi_TPCPost_calib_debug6")) { + cut->AddCut(GetAnalysisCut("jpsi_trackCut_debug2")); + cut->AddCut(GetAnalysisCut("jpsi_TPCPID_debug6")); + return cut; + } + + if (!nameStr.compare("Jpsi_TPCPost_calib_debug7")) { + cut->AddCut(GetAnalysisCut("jpsi_trackCut_debug2")); + cut->AddCut(GetAnalysisCut("jpsi_TPCPID_debug7")); + return cut; + } + if (!nameStr.compare("LMee_TPCPost_calib_debug1")) { cut->AddCut(GetAnalysisCut("lmee_trackCut_debug")); cut->AddCut(GetAnalysisCut("lmee_TPCPID_debug1")); return cut; } + if (!nameStr.compare("ITSalone_prefilter")) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + return cut; + } + + if (!nameStr.compare("ITSalonebAny_prefilter")) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualitybAnyITSOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + return cut; + } + + if (!nameStr.compare("TPCalone_prefilter")) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + return cut; + } + + if (!nameStr.compare("ITSTPC_prefilter")) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + return cut; + } + //--------------------------------------------------------------- // Cuts for the selection of legs from dalitz decay // @@ -464,64 +527,45 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - for (int i = 1; i <= 8; i++) { - if (!nameStr.compare(Form("DalitzCut1_dalitzSelected%d", i))) { - cut->AddCut(GetAnalysisCut("dalitzStandardKine")); - cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); - cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); - cut->AddCut(GetAnalysisCut("electronPIDOnly")); - cut->AddCut(GetAnalysisCut(Form("dalitzLeg%d", i))); - return cut; - } + if (!nameStr.compare("Dalitz_WithTOF_SPDfirst")) { + cut->AddCut(GetAnalysisCut("dalitzStandardKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut->AddCut(GetAnalysisCut("SPDfirst")); - if (!nameStr.compare(Form("DalitzCut2_dalitzSelected%d", i))) { - cut->AddCut(GetAnalysisCut("dalitzStandardKine")); - cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); - cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); - cut->AddCut(GetAnalysisCut("electronPIDPrKaPiRej")); - cut->AddCut(GetAnalysisCut(Form("dalitzLeg%d", i))); - return cut; - } + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPIDPrKaPiRejLoose")); - if (!nameStr.compare(Form("DalitzCut2_Corr_dalitzSelected%d", i))) { - cut->AddCut(GetAnalysisCut("dalitzStandardKine")); - cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); - cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); - cut->AddCut(GetAnalysisCut("electronPIDPrKaPiRej")); - cut->AddCut(GetAnalysisCut(Form("dalitzLeg%d", i))); - return cut; - } + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma")); - if (!nameStr.compare(Form("DalitzCut1SPDfirst_dalitzSelected%d", i))) { - cut->AddCut(GetAnalysisCut("dalitzStandardKine")); - cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); - cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); - cut->AddCut(GetAnalysisCut("SPDfirst")); - cut->AddCut(GetAnalysisCut("electronPIDOnly")); - cut->AddCut(GetAnalysisCut(Form("dalitzLeg%d", i))); - return cut; - } + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } - if (!nameStr.compare(Form("DalitzCut2SPDfirst_dalitzSelected%d", i))) { - cut->AddCut(GetAnalysisCut("dalitzStandardKine")); - cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); - cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); - cut->AddCut(GetAnalysisCut("SPDfirst")); - cut->AddCut(GetAnalysisCut("electronPIDPrKaPiRej")); - cut->AddCut(GetAnalysisCut(Form("dalitzLeg%d", i))); - return cut; - } + if (!nameStr.compare("Dalitz_WithTOF_SPDfirst_Corr")) { + cut->AddCut(GetAnalysisCut("dalitzStandardKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut->AddCut(GetAnalysisCut("SPDfirst")); - if (!nameStr.compare(Form("DalitzCut2SPDfirst_Corr_dalitzSelected%d", i))) { - cut->AddCut(GetAnalysisCut("dalitzStandardKine")); - cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); - cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); - cut->AddCut(GetAnalysisCut("SPDfirst")); - cut->AddCut(GetAnalysisCut("electronPIDPrKaPiRej")); - cut->AddCut(GetAnalysisCut(Form("dalitzLeg%d", i))); - return cut; - } + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPIDPrKaPiRejLoose_Corr")); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma_Corr")); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + for (int i = 1; i <= 8; i++) { if (!nameStr.compare(Form("dalitzSelected%d", i))) { cut->AddCut(GetAnalysisCut(Form("dalitzLeg%d", i))); return cut; @@ -721,99 +765,6 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare("lmee_eNSigmaRun3")) { - cut->AddCut(GetAnalysisCut("lmeeStandardKine")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma")); - - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma")); - - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } - - if (!nameStr.compare("lmee_eNSigmaRun3_corr")) { - cut->AddCut(GetAnalysisCut("lmeeStandardKine")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma_corr", "pid_TPCnSigma_corr", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma_corr")); - - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma")); - - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma_corr", "e_NSigma_corr", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } - - if (!nameStr.compare("lmee_eNSigmaRun3_tight")) { - cut->AddCut(GetAnalysisCut("lmeeStandardKine")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma_tight")); - - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma_tight")); - - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } - - if (!nameStr.compare("lmee_eNSigmaRun3_tight_pt04")) { - cut->AddCut(GetAnalysisCut("lmeeStandardKine_pt04")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma_tight")); - - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma_tight")); - - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } - - for (int i = 1; i <= 8; i++) { - if (!nameStr.compare(Form("lmee_eNSigmaRun3_tight_Prefilter%d", i))) { - cut->AddCut(GetAnalysisCut(Form("notDalitzLeg%d", i))); - cut->AddCut(GetAnalysisCut("lmeeStandardKine")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma_tight")); - - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma_tight")); - - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } - } - // 4 cuts to separate pos & neg tracks in pos & neg eta range if (!nameStr.compare("lmee_posTrack_posEta_selection")) { cut->AddCut(GetAnalysisCut("posTrack")); @@ -847,93 +798,567 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - // 4 cuts to separate pos & neg tracks in pos & neg eta range applying electron PID - if (!nameStr.compare("lmee_posNSigmaRun3_posEta_tight")) { - cut->AddCut(GetAnalysisCut("posTrack")); - cut->AddCut(GetAnalysisCut("posEtaSel")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + std::vector vecPIDcase; + vecPIDcase.emplace_back(""); // without post calibration + vecPIDcase.emplace_back("_Corr"); // case of using post calibrated PID spectra + vecPIDcase.emplace_back("_CorrWithKaon"); // case of using post calibrated PID spectra with also the kaons - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma_tight")); + // loop to define PID cuts with and without post calibration + for (int icase = 0; icase < vecPIDcase.size(); icase++) { + if (!nameStr.compare(Form("ITSTPC_TPCPID%s_prefilter", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + cut->AddCut(GetAnalysisCut(Form("electronPIDOnly%s", vecPIDcase.at(icase).Data()))); + return cut; + } - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma_tight")); + if (!nameStr.compare(Form("ITS_ifTPC_TPCPID%s_prefilter", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } + AnalysisCompositeCut* cut_notpc = new AnalysisCompositeCut("NoTPC", "NoTPC", kTRUE); + cut_notpc->AddCut(GetAnalysisCut("noTPC")); - if (!nameStr.compare("lmee_negNSigmaRun3_posEta_tight")) { - cut->AddCut(GetAnalysisCut("negTrack")); - cut->AddCut(GetAnalysisCut("posEtaSel")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + AnalysisCompositeCut* cut_tpcpid = new AnalysisCompositeCut("pid_TPC", "pid_TPC", kTRUE); + cut_tpcpid->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut_tpcpid->AddCut(GetAnalysisCut(Form("electronPIDOnly%s", vecPIDcase.at(icase).Data()))); - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma_tight")); + AnalysisCompositeCut* cut_OR = new AnalysisCompositeCut("OR", "OR", kFALSE); + cut_OR->AddCut(cut_notpc); + cut_OR->AddCut(cut_tpcpid); + cut->AddCut(cut_OR); + return cut; + } - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma_tight")); + if (!nameStr.compare(Form("ITS_ifTPCStandard_TPCPID%s_prefilter", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualityITSOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } + AnalysisCompositeCut* cut_notpcstandard = new AnalysisCompositeCut("NoTPCstandard", "NoTPCstandard", kTRUE); + cut_notpcstandard->AddCut(GetAnalysisCut("NoelectronStandardQualityTPCOnly")); - if (!nameStr.compare("lmee_posNSigmaRun3_negEta_tight")) { - cut->AddCut(GetAnalysisCut("posTrack")); - cut->AddCut(GetAnalysisCut("negEtaSel")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + AnalysisCompositeCut* cut_tpcpid = new AnalysisCompositeCut("pid_TPC", "pid_TPC", kTRUE); + cut_tpcpid->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut_tpcpid->AddCut(GetAnalysisCut(Form("electronPIDOnly%s", vecPIDcase.at(icase).Data()))); - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma_tight")); + AnalysisCompositeCut* cut_OR = new AnalysisCompositeCut("OR", "OR", kFALSE); + cut_OR->AddCut(cut_notpcstandard); + cut_OR->AddCut(cut_tpcpid); + cut->AddCut(cut_OR); + return cut; + } - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma_tight")); + if (!nameStr.compare(Form("ITSTPCbAny_TPCPID%s_prefilter", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualitybAnyITSOnly")); + cut->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + cut->AddCut(GetAnalysisCut(Form("electronPIDOnly%s", vecPIDcase.at(icase).Data()))); + return cut; + } - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } + if (!nameStr.compare(Form("ITSbAny_ifTPC_TPCPID%s_prefilter", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualitybAnyITSOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - if (!nameStr.compare("lmee_negNSigmaRun3_negEta_tight")) { - cut->AddCut(GetAnalysisCut("negTrack")); - cut->AddCut(GetAnalysisCut("negEtaSel")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + AnalysisCompositeCut* cut_notpc = new AnalysisCompositeCut("NoTPC", "NoTPC", kTRUE); + cut_notpc->AddCut(GetAnalysisCut("noTPC")); - AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); - cut_tpc_nSigma->AddCut(GetAnalysisCut("electronPID_TPCnsigma_tight")); + AnalysisCompositeCut* cut_tpcpid = new AnalysisCompositeCut("pid_TPC", "pid_TPC", kTRUE); + cut_tpcpid->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut_tpcpid->AddCut(GetAnalysisCut(Form("electronPIDOnly%s", vecPIDcase.at(icase).Data()))); - AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); - cut_tof_nSigma->AddCut(GetAnalysisCut("electronPID_TOFnsigma_tight")); + AnalysisCompositeCut* cut_OR = new AnalysisCompositeCut("OR", "OR", kFALSE); + cut_OR->AddCut(cut_notpc); + cut_OR->AddCut(cut_tpcpid); + cut->AddCut(cut_OR); + return cut; + } - AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); - cut_pid_OR->AddCut(cut_tpc_nSigma); - cut_pid_OR->AddCut(cut_tof_nSigma); - cut->AddCut(cut_pid_OR); - return cut; - } + if (!nameStr.compare(Form("ITSbAny_ifTPCStandard_TPCPID%s_prefilter", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeePrefilterKine")); + cut->AddCut(GetAnalysisCut("electronStandardQualitybAnyITSOnly")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - if (!nameStr.compare("lmee_GlobalTrackRun3")) { - cut->AddCut(GetAnalysisCut("lmeeStandardKine")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); - cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); - return cut; - } + AnalysisCompositeCut* cut_notpcstandard = new AnalysisCompositeCut("NoTPCstandard", "NoTPCstandard", kTRUE); + cut_notpcstandard->AddCut(GetAnalysisCut("NoelectronStandardQualityTPCOnly")); - if (!nameStr.compare("lmee_GlobalTrackRun3_lowPt")) { - cut->AddCut(GetAnalysisCut("lmeeLowBKine")); - cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + AnalysisCompositeCut* cut_tpcpid = new AnalysisCompositeCut("pid_TPC", "pid_TPC", kTRUE); + cut_tpcpid->AddCut(GetAnalysisCut("electronStandardQualityTPCOnly")); + cut_tpcpid->AddCut(GetAnalysisCut(Form("electronPIDOnly%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_OR = new AnalysisCompositeCut("OR", "OR", kFALSE); + cut_OR->AddCut(cut_notpcstandard); + cut_OR->AddCut(cut_tpcpid); + cut->AddCut(cut_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_loose", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_loose", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_loose", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_strongTPC", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3_strongTPC")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_strongHadRej", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongHadRej", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongHadRej", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_lowB_eNSigmaRun3%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeLowBKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); // to reject looper using DCAz + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_TPC_PID", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + cut->AddCut(cut_tpc_nSigma); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_TOF_PID", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + cut->AddCut(cut_tof_nSigma); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_strongNSigE_DCA05", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_DCA05")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + // 4 cuts to separate pos & neg tracks in pos & neg eta range applying electron PID + if (!nameStr.compare(Form("lmee_posNSigmaRun3_posEta%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("posTrack")); + cut->AddCut(GetAnalysisCut("posEtaSel")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_negNSigmaRun3_posEta%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("negTrack")); + cut->AddCut(GetAnalysisCut("posEtaSel")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_posNSigmaRun3_negEta%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("posTrack")); + cut->AddCut(GetAnalysisCut("negEtaSel")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_negNSigmaRun3_negEta%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("negTrack")); + cut->AddCut(GetAnalysisCut("negEtaSel")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + // 4 cuts to separate pos & neg tracks in pos & neg eta range applying electron PID for low B field + if (!nameStr.compare(Form("lmee_lowB_posNSigmaRun3_posEta%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("posTrack")); + cut->AddCut(GetAnalysisCut("posEtaSel")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_lowB_negNSigmaRun3_posEta%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("negTrack")); + cut->AddCut(GetAnalysisCut("posEtaSel")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_lowB_posNSigmaRun3_negEta%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("posTrack")); + cut->AddCut(GetAnalysisCut("negEtaSel")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_lowB_negNSigmaRun3_negEta%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("negTrack")); + cut->AddCut(GetAnalysisCut("negEtaSel")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_skimmingtesta_PID%s", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("LooseGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_TPCloose%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_TOFloose%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_skimmingtestb_PID%s", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("LooseGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_TPCloosenopkrej%s", vecPIDcase.at(icase).Data()))); + + cut->AddCut(cut_tpc_nSigma); + return cut; + } + + // some older cuts + if (!nameStr.compare(Form("lmee_pp502TeV_PID%s", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_TPC%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_TOF%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + for (int i = 1; i <= 8; i++) { + if (!nameStr.compare(Form("lmee_pp502TeV_PID%s_UsePrefilter%d", vecPIDcase.at(icase).Data(), i))) { + cut->AddCut(GetAnalysisCut(Form("notDalitzLeg%d", i))); + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_TPC%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_TOF%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + } + + if (!nameStr.compare(Form("lmee_pp502TeV_lowB_PID%s", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeLowBKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("standardPrimaryTrackDCAz")); // DCAz to reject loopers + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_lowB_TPC%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("lmee_pp_502TeV_lowB_TOF%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_pt04", vecPIDcase.at(icase).Data()))) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine_pt04")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + + for (int i = 1; i <= 8; i++) { + if (!nameStr.compare(Form("lmee_eNSigmaRun3%s_UsePrefilter%d", vecPIDcase.at(icase).Data(), i))) { + cut->AddCut(GetAnalysisCut(Form("notDalitzLeg%d", i))); + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + + AnalysisCompositeCut* cut_tpc_nSigma = new AnalysisCompositeCut("pid_TPCnSigma", "pid_TPCnSigma", kTRUE); + cut_tpc_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TPCnsigma%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_tof_nSigma = new AnalysisCompositeCut("pid_TOFnSigma", "pid_TOFnSigma", kTRUE); + cut_tof_nSigma->AddCut(GetAnalysisCut(Form("electronPID_TOFnsigma%s", vecPIDcase.at(icase).Data()))); + + AnalysisCompositeCut* cut_pid_OR = new AnalysisCompositeCut("e_NSigma", "e_NSigma", kFALSE); + cut_pid_OR->AddCut(cut_tpc_nSigma); + cut_pid_OR->AddCut(cut_tof_nSigma); + cut->AddCut(cut_pid_OR); + return cut; + } + } + } + + if (!nameStr.compare("lmee_GlobalTrackRun3")) { + cut->AddCut(GetAnalysisCut("lmeeStandardKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); + cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); + return cut; + } + + if (!nameStr.compare("lmee_GlobalTrackRun3_lowPt")) { + cut->AddCut(GetAnalysisCut("lmeeLowBKine")); + cut->AddCut(GetAnalysisCut("TightGlobalTrackRun3")); cut->AddCut(GetAnalysisCut("PrimaryTrack_looseDCA")); return cut; } @@ -989,6 +1414,27 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("muonLowPt10SigmaPDCA")) { + cut->AddCut(GetAnalysisCut("muonLowPt")); + cut->AddCut(GetAnalysisCut("muonQualityCuts10SigmaPDCA")); + cut->AddCut(GetAnalysisCut("MCHMID")); + return cut; + } + + if (!nameStr.compare("muonLowPt210SigmaPDCA")) { + cut->AddCut(GetAnalysisCut("muonLowPt2")); + cut->AddCut(GetAnalysisCut("muonQualityCuts10SigmaPDCA")); + cut->AddCut(GetAnalysisCut("MCHMID")); + return cut; + } + + if (!nameStr.compare("muonLowPt510SigmaPDCA")) { + cut->AddCut(GetAnalysisCut("muonLowPt5")); + cut->AddCut(GetAnalysisCut("muonQualityCuts10SigmaPDCA")); + cut->AddCut(GetAnalysisCut("MCHMID")); + return cut; + } + if (!nameStr.compare("muonLowPt")) { cut->AddCut(GetAnalysisCut("muonLowPt")); cut->AddCut(GetAnalysisCut("muonQualityCuts")); @@ -1134,6 +1580,26 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("Chi2MCHMFTCut1")) { + cut->AddCut(GetAnalysisCut("Chi2MCHMFTCut1")); + return cut; + } + + if (!nameStr.compare("Chi2MCHMFTCut2")) { + cut->AddCut(GetAnalysisCut("Chi2MCHMFTCut2")); + return cut; + } + + if (!nameStr.compare("Chi2MCHMFTCut3")) { + cut->AddCut(GetAnalysisCut("Chi2MCHMFTCut3")); + return cut; + } + + if (!nameStr.compare("Chi2MCHMFTCut4")) { + cut->AddCut(GetAnalysisCut("Chi2MCHMFTCut4")); + return cut; + } + // ----------------------------------------------------------- // Pair cuts if (!nameStr.compare("pairNoCut")) { @@ -1151,6 +1617,16 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("pairPtLow3")) { + cut->AddCut(GetAnalysisCut("pairPtLow3")); + return cut; + } + + if (!nameStr.compare("pairPtLow4")) { + cut->AddCut(GetAnalysisCut("pairPtLow4")); + return cut; + } + if (!nameStr.compare("pairMassLow3")) { cut->AddCut(GetAnalysisCut("pairMassLow3")); return cut; @@ -1186,13 +1662,13 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare("pairDalitz1")) { - cut->AddCut(GetAnalysisCut("pairDalitz1")); + if (!nameStr.compare("pairMassLow10")) { + cut->AddCut(GetAnalysisCut("pairMassLow10")); return cut; } - if (!nameStr.compare("pairDalitz1Neg")) { - cut->AddCut(GetAnalysisCut("pairDalitz1Neg")); + if (!nameStr.compare("pairDalitz1")) { + cut->AddCut(GetAnalysisCut("pairDalitz1")); return cut; } @@ -1201,11 +1677,6 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } - if (!nameStr.compare("pairDalitz1StrongNeg")) { - cut->AddCut(GetAnalysisCut("pairDalitz1StrongNeg")); - return cut; - } - if (!nameStr.compare("pairDalitz2")) { cut->AddCut(GetAnalysisCut("pairDalitz2")); return cut; @@ -1216,6 +1687,111 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("paira_prefilter1")) { + cut->AddCut(GetAnalysisCut("paira_prefilter1")); + return cut; + } + + if (!nameStr.compare("paira_prefilter2")) { + cut->AddCut(GetAnalysisCut("paira_prefilter2")); + return cut; + } + + if (!nameStr.compare("paira_prefilter3")) { + cut->AddCut(GetAnalysisCut("paira_prefilter3")); + return cut; + } + + if (!nameStr.compare("paira_prefilter4")) { + cut->AddCut(GetAnalysisCut("paira_prefilter4")); + return cut; + } + + if (!nameStr.compare("paira_prefilter5")) { + cut->AddCut(GetAnalysisCut("paira_prefilter5")); + return cut; + } + + if (!nameStr.compare("paira_prefilter6")) { + cut->AddCut(GetAnalysisCut("paira_prefilter6")); + return cut; + } + + if (!nameStr.compare("paira_prefilter7")) { + cut->AddCut(GetAnalysisCut("paira_prefilter7")); + return cut; + } + + if (!nameStr.compare("pairb_prefilter1")) { + cut->AddCut(GetAnalysisCut("pairb_prefilter1")); + return cut; + } + + if (!nameStr.compare("pairb_prefilter2")) { + cut->AddCut(GetAnalysisCut("pairb_prefilter2")); + return cut; + } + + if (!nameStr.compare("pairb_prefilter3")) { + cut->AddCut(GetAnalysisCut("pairb_prefilter3")); + return cut; + } + + if (!nameStr.compare("pairb_prefilter4")) { + cut->AddCut(GetAnalysisCut("pairb_prefilter4")); + return cut; + } + + if (!nameStr.compare("pairb_prefilter5")) { + cut->AddCut(GetAnalysisCut("pairb_prefilter5")); + return cut; + } + + if (!nameStr.compare("pairb_prefilter6")) { + cut->AddCut(GetAnalysisCut("pairb_prefilter6")); + return cut; + } + + if (!nameStr.compare("pairb_prefilter7")) { + cut->AddCut(GetAnalysisCut("pairb_prefilter7")); + return cut; + } + + if (!nameStr.compare("pairc_prefilter1")) { + cut->AddCut(GetAnalysisCut("pairc_prefilter1")); + return cut; + } + + if (!nameStr.compare("pairc_prefilter2")) { + cut->AddCut(GetAnalysisCut("pairc_prefilter2")); + return cut; + } + + if (!nameStr.compare("pairc_prefilter3")) { + cut->AddCut(GetAnalysisCut("pairc_prefilter3")); + return cut; + } + + if (!nameStr.compare("pairc_prefilter4")) { + cut->AddCut(GetAnalysisCut("pairc_prefilter4")); + return cut; + } + + if (!nameStr.compare("pairc_prefilter5")) { + cut->AddCut(GetAnalysisCut("pairc_prefilter5")); + return cut; + } + + if (!nameStr.compare("pairc_prefilter6")) { + cut->AddCut(GetAnalysisCut("pairc_prefilter6")); + return cut; + } + + if (!nameStr.compare("pairc_prefilter7")) { + cut->AddCut(GetAnalysisCut("pairc_prefilter7")); + return cut; + } + if (!nameStr.compare("pairJpsi")) { cut->AddCut(GetAnalysisCut("pairJpsi")); return cut; @@ -1249,7 +1825,7 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) } if (!nameStr.compare("pairCoherentRho0")) { - cut->AddCut(GetAnalysisCut("pairPtLow1")); + cut->AddCut(GetAnalysisCut("pairPtLow3")); return cut; } @@ -1402,13 +1978,28 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } - if (!nameStr.compare("eventMuonStandard")) { - cut->AddCut(VarManager::kIsMuonSingleLowPt7, 0.5, 1.5); + if (!nameStr.compare("eventMuonStandard")) { + cut->AddCut(VarManager::kIsMuonSingleLowPt7, 0.5, 1.5); + return cut; + } + + if (!nameStr.compare("eventTPCMultLow")) { + cut->AddCut(VarManager::kMultTPC, 0, 50); + return cut; + } + + if (!nameStr.compare("eventExclusivePair")) { + cut->AddCut(VarManager::kVtxNcontrib, 2, 2); + return cut; + } + + if (!nameStr.compare("eventVtxNContrib")) { + cut->AddCut(VarManager::kVtxNcontrib, 0, 10); return cut; } - if (!nameStr.compare("eventTPCMultLow")) { - cut->AddCut(VarManager::kMultTPC, 2, 50); + if (!nameStr.compare("eventTPCMult3")) { + cut->AddCut(VarManager::kMultTPC, 3, 3); return cut; } @@ -1482,9 +2073,24 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } - if (!nameStr.compare("lowMultTrackCut")) { - cut->AddCut(VarManager::kPt, 0.15, 1000.0); - cut->AddCut(VarManager::kTPCncls, 50.0, 159); + if (!nameStr.compare("openEtaSel")) { + cut->AddCut(VarManager::kEta, -1.5, 1.5); + return cut; + } + + if (!nameStr.compare("rho0Kine")) { + cut->AddCut(VarManager::kPt, 0.1, 1000.0); + cut->AddCut(VarManager::kEta, -1.1, 1.1); + return cut; + } + + if (!nameStr.compare("pionQuality")) { + cut->AddCut(VarManager::kTPCncls, 50.0, 1000.); + return cut; + } + + if (!nameStr.compare("primaryVertexContributor")) { + cut->AddCut(VarManager::kPVContributor, 0.5, 1.5); return cut; } @@ -1501,13 +2107,25 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare("jpsiStandardKine3")) { - cut->AddCut(VarManager::kPin, 1.0, 1000.0); + cut->AddCut(VarManager::kPin, 1.2, 1000.0); + cut->AddCut(VarManager::kEta, -0.9, 0.9); + return cut; + } + + if (!nameStr.compare("jpsiStandardKine4")) { + cut->AddCut(VarManager::kPin, 1.5, 1000.0); cut->AddCut(VarManager::kEta, -0.9, 0.9); return cut; } + if (!nameStr.compare("lmeePrefilterKine")) { + cut->AddCut(VarManager::kPt, 0., 20.0); + cut->AddCut(VarManager::kEta, -1.2, 1.2); + return cut; + } + if (!nameStr.compare("lmeeStandardKine")) { - cut->AddCut(VarManager::kPt, 0.2, 10.0); + cut->AddCut(VarManager::kPt, 0.2, 20.0); cut->AddCut(VarManager::kEta, -0.8, 0.8); return cut; } @@ -1519,7 +2137,7 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare("lmeeLowBKine")) { - cut->AddCut(VarManager::kPt, 0.075, 10.0); + cut->AddCut(VarManager::kPt, 0.075, 20.0); cut->AddCut(VarManager::kEta, -0.8, 0.8); return cut; } @@ -1600,6 +2218,17 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("jpsi_trackCut_debug2")) { + cut->AddCut(VarManager::kEta, -0.9, 0.9); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCncls, 90., 159); + cut->AddCut(VarManager::kITSncls, 2.5, 7.5); + cut->AddCut(VarManager::kIsSPDany, 0.5, 1.5); + cut->AddCut(VarManager::kTrackDCAxy, -1, 1); + cut->AddCut(VarManager::kTrackDCAz, -3.0, 3.0); + return cut; + } + if (!nameStr.compare("lmee_trackCut_debug")) { cut->AddCut(VarManager::kEta, -0.9, 0.9); cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); @@ -1627,6 +2256,25 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("LooseGlobalTrackRun3")) { + cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kITSchi2, 0.0, 6.0); + cut->AddCut(VarManager::kITSncls, 3.5, 7.5); + cut->AddCut(VarManager::kTPCncls, 70.0, 170.); + return cut; + } + + if (!nameStr.compare("TightGlobalTrackRun3_strongTPC")) { + cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); + cut->AddCut(VarManager::kITSncls, 4.5, 7.5); + cut->AddCut(VarManager::kTPCnclsCR, 140.0, 161.); + cut->AddCut(VarManager::kTPCncls, 120.0, 170.); + return cut; + } + if (!nameStr.compare("TightTPCTrackRun3")) { cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut->AddCut(VarManager::kTPCnclsCR, 80.0, 161.); @@ -1645,6 +2293,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("noTPC")) { + cut->AddCut(VarManager::kHasTPC, -0.5, 0.5); + return cut; + } + if (!nameStr.compare("SPDany")) { cut->AddCut(VarManager::kIsSPDany, 0.5, 1.5); return cut; @@ -1678,15 +2331,27 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("electronStandardQualitybAnyITSOnly")) { + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + cut->AddCut(VarManager::kITSchi2, 0.0, 5.0); + cut->AddCut(VarManager::kITSncls, 3.5, 7.5); + return cut; + } + if (!nameStr.compare("electronStandardQualityTPCOnly")) { cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); cut->AddCut(VarManager::kTPCncls, 70, 161.); return cut; } + if (!nameStr.compare("NoelectronStandardQualityTPCOnly")) { + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0, true, VarManager::kTPCncls, 70, 161.); + return cut; + } + if (!nameStr.compare("pidbasic")) { - cut->AddCut(VarManager::kTPCnclsCR, 70, 161); - cut->AddCut(VarManager::kTPCchi2, 0, 4); + cut->AddCut(VarManager::kEta, -0.9, 0.9); + cut->AddCut(VarManager::kTPCncls, 60, 161.); return cut; } @@ -1695,6 +2360,13 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) cut->AddCut(VarManager::kTrackDCAz, -3.0, 3.0); return cut; } + + if (!nameStr.compare("standardPrimaryTrackDCAz")) { + cut->AddCut(VarManager::kTrackDCAxy, -3.0, 3.0); + cut->AddCut(VarManager::kTrackDCAz, -1.0, 1.0); + return cut; + } + if (!nameStr.compare("standardPrimaryTrackDCA")) { cut->AddCut(VarManager::kTrackDCAxy, -0.1, 0.1); cut->AddCut(VarManager::kTrackDCAz, -0.15, 0.15); @@ -1713,6 +2385,12 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("PrimaryTrack_DCA05")) { + cut->AddCut(VarManager::kTrackDCAsigXY, -0.5, 0.5); + cut->AddCut(VarManager::kTrackDCAsigZ, -0.5, 0.5); + return cut; + } + // ----------------------------------------------------- // V0 and Dalitz legs selections @@ -1794,6 +2472,20 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("jpsi_TPCPID_debug6")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2.0, 3.0); + cut->AddCut(VarManager::kTPCnSigmaPi, 3.0, 999); + cut->AddCut(VarManager::kTPCnSigmaPr, 3.0, 999); + return cut; + } + + if (!nameStr.compare("jpsi_TPCPID_debug7")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2.0, 3.0); + cut->AddCut(VarManager::kTPCnSigmaPi, 3.5, 999); + cut->AddCut(VarManager::kTPCnSigmaPr, 3.5, 999); + return cut; + } + if (!nameStr.compare("lmee_TPCPID_debug1")) { cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -5.0, 5.0); return cut; @@ -1856,27 +2548,219 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } - if (!nameStr.compare("electronPID_TPCnsigma")) { - cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaPr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - return cut; - } + std::vector vecPIDcase; + vecPIDcase.emplace_back(""); // without post calibration + vecPIDcase.emplace_back("_Corr"); // case of using post calibrated PID spectra + vecPIDcase.emplace_back("_CorrWithKaon"); // case of using post calibrated PID spectra with also the kaons - if (!nameStr.compare("electronPID_TPCnsigma_corr")) { - cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - return cut; - } + // loop to define TPC PID cuts with and without post calibration + for (int icase = 0; icase < vecPIDcase.size(); icase++) { + if (!nameStr.compare(Form("electronPIDOnly%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3.0, 3.0); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3.0, 3.0); + } + return cut; + } - if (!nameStr.compare("electronPID_TPCnsigma_tight")) { - cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); - return cut; + if (!nameStr.compare(Form("electronPID_TPCnsigma%s_loose", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_TPCnsigma%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { // previously known as electronPID_TPCnsigma_tight + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_TPCnsigma%s_strongHadRej", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_lowB_TPCnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_TPCnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + } + cut->AddCut(VarManager::kTOFbeta, 0.0, 0.9, true, VarManager::kPin, 0.0, 1e+10, false); + return cut; + } + + if (!nameStr.compare(Form("lmee_pp_502TeV_TPC%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("lmee_pp_502TeV_lowB_TPC%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3.5, 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3.5, 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3.5, 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("lmee_pp_502TeV_TPCloosenopkrej%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("lmee_pp_502TeV_TPCloose%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaKa_Corr, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPr_Corr, -2., 2., true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } } if (!nameStr.compare("electronPIDnsigmaOpen")) { @@ -1949,16 +2833,6 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } - if (!nameStr.compare("electronPIDOnly")) { - cut->AddCut(VarManager::kTPCnSigmaEl, -3.0, 3.0); - return cut; - } - - if (!nameStr.compare("electronPIDOnly_Corr")) { - cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3.0, 3.0); - return cut; - } - if (!nameStr.compare("kaonPIDnsigma")) { cut->AddCut(VarManager::kTPCnSigmaKa, -3.0, 3.0); return cut; @@ -2060,18 +2934,130 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } - if (!nameStr.compare("electronPID_TOFnsigma")) { - cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.4, 1e+10, false); - return cut; - } + // loop to define TOF PID cuts with and without post calibration + for (int icase = 0; icase < vecPIDcase.size(); icase++) { + if (!nameStr.compare(Form("electronPID_TOFnsigma%s_loose", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } - if (!nameStr.compare("electronPID_TOFnsigma_tight")) { - cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3., true, VarManager::kPin, 0.0, 1e+10, false); - cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); - return cut; + if (!nameStr.compare(Form("electronPID_TOFnsigma%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { // previously known as electronPID_TOFnsigma_tight + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_TOFnsigma%s_strongHadRej", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_lowB_TOFnsigma%s_strongNSigE", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("electronPID_TOFnsigma%s_strongNSigE_rejBadTOF", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); + cut->AddCut(VarManager::kTOFbeta, 0.0, 0.9, true, VarManager::kPin, 0.0, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -2., 2., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 4., true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -2., 2., false, VarManager::kPin, 0.3, 1e+10, false); + cut->AddCut(VarManager::kTOFbeta, 0.0, 0.9, true, VarManager::kPin, 0.0, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("lmee_pp_502TeV_TOF%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("lmee_pp_502TeV_lowB_TOF%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3., 3., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaMu, -3., 3.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -3., 3., false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } + + if (!nameStr.compare(Form("lmee_pp_502TeV_TOFloose%s", vecPIDcase.at(icase).Data()))) { + if (icase == 0) { + cut->AddCut(VarManager::kTPCnSigmaEl, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -4., 4., false, VarManager::kPin, 0.3, 1e+10, false); + } else if (icase == 1 || icase == 2) { + cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -4., 4., false, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTPCnSigmaPi_Corr, -99., 2.5, true, VarManager::kPin, 0.0, 1e+10, false); + cut->AddCut(VarManager::kTOFnSigmaEl, -4., 4., false, VarManager::kPin, 0.3, 1e+10, false); + } + return cut; + } } // ------------------------------------------------------------------------------------------------- @@ -2106,6 +3092,16 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("muonQualityCuts10SigmaPDCA")) { + cut->AddCut(VarManager::kEta, -4.0, -2.5); + cut->AddCut(VarManager::kMuonRAtAbsorberEnd, 17.6, 89.5); + cut->AddCut(VarManager::kMuonPDca, 0.0, 990.0, false, VarManager::kMuonRAtAbsorberEnd, 17.6, 26.5); + cut->AddCut(VarManager::kMuonPDca, 0.0, 540.0, false, VarManager::kMuonRAtAbsorberEnd, 26.5, 89.5); + cut->AddCut(VarManager::kMuonChi2, 0.0, 1e6); + cut->AddCut(VarManager::kMuonChi2MatchMCHMID, 0.0, 1e6); // matching MCH-MID + return cut; + } + if (!nameStr.compare("matchedQualityCuts")) { cut->AddCut(VarManager::kEta, -4.0, -2.5); cut->AddCut(VarManager::kMuonRAtAbsorberEnd, 17.6, 89.5); @@ -2213,6 +3209,26 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("Chi2MCHMFTCut1")) { + cut->AddCut(VarManager::kMuonChi2MatchMCHMFT, 0, 30); + return cut; + } + + if (!nameStr.compare("Chi2MCHMFTCut2")) { + cut->AddCut(VarManager::kMuonChi2MatchMCHMFT, 0, 40); + return cut; + } + + if (!nameStr.compare("Chi2MCHMFTCut3")) { + cut->AddCut(VarManager::kMuonChi2MatchMCHMFT, 0, 50); + return cut; + } + + if (!nameStr.compare("Chi2MCHMFTCut4")) { + cut->AddCut(VarManager::kMuonChi2MatchMCHMFT, 0, 60); + return cut; + } + // ----------------------------------------------------------------------------------------------- // Pair cuts if (!nameStr.compare("pairDalitz1")) { @@ -2226,39 +3242,144 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } - if (!nameStr.compare("pairDalitz1Neg")) { // To be used when negative field + if (!nameStr.compare("pairDalitz1Strong")) { cut->AddCut(VarManager::kMass, 0.0, 0.015, false, VarManager::kPt, 0., 1.); cut->AddCut(VarManager::kMass, 0.0, 0.035, false, VarManager::kPt, 0., 1., true); - TF1* fcutHigh = new TF1("f1", "[0] + [0]/[1]*x", -1.5, 1.5); - fcutHigh->SetParameters(0.6, 0.12); - TF1* fcutLow = new TF1("f2", "-[0] - [0]/[1]*x", -1.5, 1.5); - fcutLow->SetParameters(0.6, 0.12); - cut->AddCut(VarManager::kPsiPair, fcutLow, fcutHigh, true, VarManager::kDeltaPhiPair, -0.12, 0.); + cut->AddCut(VarManager::kDeltaPhiPair, -1., 0.); return cut; } - if (!nameStr.compare("pairDalitz1Strong")) { + if (!nameStr.compare("pairDalitz2")) { cut->AddCut(VarManager::kMass, 0.0, 0.015, false, VarManager::kPt, 0., 1.); cut->AddCut(VarManager::kMass, 0.0, 0.035, false, VarManager::kPt, 0., 1., true); - cut->AddCut(VarManager::kDeltaPhiPair, -1., 0.); return cut; } - if (!nameStr.compare("pairDalitz1StrongNeg")) { // To be used when negative field - cut->AddCut(VarManager::kMass, 0.0, 0.015, false, VarManager::kPt, 0., 1.); - cut->AddCut(VarManager::kMass, 0.0, 0.035, false, VarManager::kPt, 0., 1., true); - cut->AddCut(VarManager::kDeltaPhiPair, 0., 1.); + if (!nameStr.compare("pairDalitz3")) { + cut->AddCut(VarManager::kMass, 0.0, 0.15); return cut; } - if (!nameStr.compare("pairDalitz2")) { - cut->AddCut(VarManager::kMass, 0.0, 0.015, false, VarManager::kPt, 0., 1.); - cut->AddCut(VarManager::kMass, 0.0, 0.035, false, VarManager::kPt, 0., 1., true); + if (!nameStr.compare("paira_prefilter1")) { + cut->AddCut(VarManager::kMass, 0.0, 0.06); return cut; } - if (!nameStr.compare("pairDalitz3")) { - cut->AddCut(VarManager::kMass, 0.0, 0.15); + if (!nameStr.compare("paira_prefilter2")) { + cut->AddCut(VarManager::kMass, 0.0, 0.06); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.025); + return cut; + } + + if (!nameStr.compare("paira_prefilter3")) { + cut->AddCut(VarManager::kMass, 0.0, 0.06); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.05); + return cut; + } + + if (!nameStr.compare("paira_prefilter4")) { + cut->AddCut(VarManager::kMass, 0.0, 0.06); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.075); + return cut; + } + + if (!nameStr.compare("paira_prefilter5")) { + cut->AddCut(VarManager::kMass, 0.0, 0.06); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.1); + return cut; + } + + if (!nameStr.compare("paira_prefilter6")) { + cut->AddCut(VarManager::kMass, 0.0, 0.06); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.125); + return cut; + } + + if (!nameStr.compare("paira_prefilter7")) { + cut->AddCut(VarManager::kMass, 0.0, 0.06); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.15); + return cut; + } + + if (!nameStr.compare("pairb_prefilter1")) { + cut->AddCut(VarManager::kMass, 0.0, 0.05); + return cut; + } + + if (!nameStr.compare("pairb_prefilter2")) { + cut->AddCut(VarManager::kMass, 0.0, 0.05); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.025); + return cut; + } + + if (!nameStr.compare("pairb_prefilter3")) { + cut->AddCut(VarManager::kMass, 0.0, 0.05); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.05); + return cut; + } + + if (!nameStr.compare("pairb_prefilter4")) { + cut->AddCut(VarManager::kMass, 0.0, 0.05); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.075); + return cut; + } + + if (!nameStr.compare("pairb_prefilter5")) { + cut->AddCut(VarManager::kMass, 0.0, 0.05); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.1); + return cut; + } + + if (!nameStr.compare("pairb_prefilter6")) { + cut->AddCut(VarManager::kMass, 0.0, 0.05); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.125); + return cut; + } + + if (!nameStr.compare("pairb_prefilter7")) { + cut->AddCut(VarManager::kMass, 0.0, 0.05); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.15); + return cut; + } + + if (!nameStr.compare("pairc_prefilter1")) { + cut->AddCut(VarManager::kMass, 0.0, 0.04); + return cut; + } + + if (!nameStr.compare("pairc_prefilter2")) { + cut->AddCut(VarManager::kMass, 0.0, 0.04); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.025); + return cut; + } + + if (!nameStr.compare("pairc_prefilter3")) { + cut->AddCut(VarManager::kMass, 0.0, 0.04); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.05); + return cut; + } + + if (!nameStr.compare("pairc_prefilter4")) { + cut->AddCut(VarManager::kMass, 0.0, 0.04); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.075); + return cut; + } + + if (!nameStr.compare("pairc_prefilter5")) { + cut->AddCut(VarManager::kMass, 0.0, 0.04); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.1); + return cut; + } + + if (!nameStr.compare("pairc_prefilter6")) { + cut->AddCut(VarManager::kMass, 0.0, 0.04); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.125); + return cut; + } + + if (!nameStr.compare("pairc_prefilter7")) { + cut->AddCut(VarManager::kMass, 0.0, 0.04); + cut->AddCut(VarManager::kOpeningAngle, 0.0, 0.15); return cut; } @@ -2278,31 +3399,41 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) } if (!nameStr.compare("pairMassLow3")) { - cut->AddCut(VarManager::kMass, 1.8, 1000.0); + cut->AddCut(VarManager::kMass, 1.6, 1000.0); + return cut; + } + + if (!nameStr.compare("pairMassLow4")) { + cut->AddCut(VarManager::kMass, 1.7, 1000.0); return cut; } if (!nameStr.compare("pairMassLow5")) { - cut->AddCut(VarManager::kMass, 1.85, 1000.0); + cut->AddCut(VarManager::kMass, 1.8, 1000.0); return cut; } if (!nameStr.compare("pairMassLow6")) { - cut->AddCut(VarManager::kMass, 1.9, 1000.0); + cut->AddCut(VarManager::kMass, 1.85, 1000.0); return cut; } if (!nameStr.compare("pairMassLow7")) { - cut->AddCut(VarManager::kMass, 2.0, 1000.0); + cut->AddCut(VarManager::kMass, 1.9, 1000.0); return cut; } if (!nameStr.compare("pairMassLow8")) { - cut->AddCut(VarManager::kMass, 2.2, 1000.0); + cut->AddCut(VarManager::kMass, 2.0, 1000.0); return cut; } if (!nameStr.compare("pairMassLow9")) { + cut->AddCut(VarManager::kMass, 2.2, 1000.0); + return cut; + } + + if (!nameStr.compare("pairMassLow10")) { cut->AddCut(VarManager::kMass, 2.5, 1000.0); return cut; } @@ -2337,6 +3468,11 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("pairPtLow4")) { + cut->AddCut(VarManager::kPt, 0, 10.0); + return cut; + } + if (!nameStr.compare("pairRapidityForward")) { cut->AddCut(VarManager::kRap, 2.5, 4.0); return cut; diff --git a/PWGDQ/Core/CutsLibrary.h b/PWGDQ/Core/CutsLibrary.h index e7c53f305aa..59079166b29 100644 --- a/PWGDQ/Core/CutsLibrary.h +++ b/PWGDQ/Core/CutsLibrary.h @@ -16,6 +16,7 @@ #define PWGDQ_CORE_CUTSLIBRARY_H_ #include +#include #include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/VarManager.h" diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 808ac8f622a..6b23fb19c18 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -29,7 +29,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h subGroupStr.ToLower(); if (groupStr.Contains("event")) { hm->AddHistogram(histClass, "VtxZ", "Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ); - + hm->AddHistogram(histClass, "VtxZ_Run", "Vtx Z", true, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, 60, -15.0, 15.0, VarManager::kVtxZ, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); if (subGroupStr.Contains("trigger")) { hm->AddHistogram(histClass, "IsINT7", "Is INT7", false, 2, -0.5, 1.5, VarManager::kIsINT7); if (subGroupStr.Contains("muon") || subGroupStr.Contains("all")) { @@ -66,21 +66,32 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "CentFT0C", "CentFT0C", false, 100, 0., 100., VarManager::kCentFT0C); hm->AddHistogram(histClass, "CentFT0C_vtxZ", "CentFT0C vs Vtx Z", false, 60, -15.0, 15.0, VarManager::kVtxZ, 20, 0., 100., VarManager::kCentFT0C); hm->AddHistogram(histClass, "CentFT0C_MultTPC", "CentFT0C vs MultTPC", false, 100, 0., 100., VarManager::kCentFT0C, 50, 0., 50., VarManager::kMultTPC); + hm->AddHistogram(histClass, "CentFT0C_Run", "Cent FT0C", true, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, 100, 0., 100., VarManager::kCentFT0C, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); } if (subGroupStr.Contains("mult")) { hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 100, 0.0, 25000.0, VarManager::kMultTPC); hm->AddHistogram(histClass, "MultTPCLow", "MultTPCLow", false, 50, 0.0, 50.0, VarManager::kMultTPC); hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 100, 0.0, 25000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "MultFV0ALow", "MultFV0ALow", false, 50, 0.0, 50.0, VarManager::kMultFV0A); hm->AddHistogram(histClass, "MultFV0C", "MultFV0C", false, 100, 0.0, 25000.0, VarManager::kMultFV0C); + hm->AddHistogram(histClass, "MultFV0CLow", "MultFV0CLow", false, 50, 0.0, 50.0, VarManager::kMultFV0C); hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 100, 0.0, 25000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "MultFT0ALow", "MultFT0ALow", false, 50, 0.0, 50.0, VarManager::kMultFT0A); hm->AddHistogram(histClass, "MultFT0C", "MultFT0C", false, 100, 0.0, 25000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "MultFT0CLow", "MultFT0CLow", false, 50, 0.0, 50.0, VarManager::kMultFT0C); hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 100, 0.0, 25000.0, VarManager::kMultFDDA); + hm->AddHistogram(histClass, "MultFDDALow", "MultFDDALow", false, 50, 0.0, 50.0, VarManager::kMultFDDA); hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 100, 0.0, 25000.0, VarManager::kMultFDDC); + hm->AddHistogram(histClass, "MultFDDCLow", "MultFDDCLow", false, 50, 0.0, 50.0, VarManager::kMultFDDC); hm->AddHistogram(histClass, "MultZNA", "MultZNA", false, 100, 0.0, 25000.0, VarManager::kMultZNA); hm->AddHistogram(histClass, "MultZNC", "MultZNC", false, 100, 0.0, 25000.0, VarManager::kMultZNC); hm->AddHistogram(histClass, "MultTracklets", "MultTracklets", false, 100, 0.0, 25000.0, VarManager::kMultTracklets); hm->AddHistogram(histClass, "VtxNContribReal", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontribReal); - hm->AddHistogram(histClass, "MultTPC_MultFV0A", "MultTPC vs MultFV0A", false, 100, 0, 20000.0, VarManager::kMultTPC, 100, 0, 20000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontrib); + hm->AddHistogram(histClass, "MultTPC_MultFV0A", "MultTPC vs MultFV0A", false, 400, 0, 800.0, VarManager::kMultTPC, 100, 0, 20000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "MultTPC_MultFT0A", "MultTPC vs MultFT0A", false, 400, 0, 800.0, VarManager::kMultTPC, 100, 0, 1000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "MultTPC_MultFT0C", "MultTPC vs MultFT0C", false, 400, 0, 800.0, VarManager::kMultTPC, 100, 0, 1000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "MultFT0A_MultFT0C", "MultFT0A vs MultFT0C", false, 100, 0, 1000.0, VarManager::kMultFT0A, 100, 0, 1000.0, VarManager::kMultFT0C); } if (subGroupStr.Contains("mc")) { hm->AddHistogram(histClass, "MCVtxX_VtxX", "Vtx X (MC vs rec)", false, 100, -0.5, 0.5, VarManager::kVtxX, 100, -0.5, 0.5, VarManager::kMCVtxX); @@ -147,7 +158,11 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Pt", "p_{T} distribution", false, 2000, 0.0, 20.0, VarManager::kPt); hm->AddHistogram(histClass, "Eta", "#eta distribution", false, 500, -5.0, 5.0, VarManager::kEta); hm->AddHistogram(histClass, "Phi", "#varphi distribution", false, 500, -2. * TMath::Pi(), 2. * TMath::Pi(), VarManager::kPhi); - + if (subGroupStr.Contains("cent")) { + hm->AddHistogram(histClass, "Pt_CentFT0C", "p_{T} distribution", false, 2000, 0.0, 20.0, VarManager::kPt, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "Eta_CentFT0C", "#eta distribution", false, 500, -5.0, 5.0, VarManager::kEta, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "Phi_CentFT0C", "#varphi distribution", false, 500, -2. * TMath::Pi(), 2. * TMath::Pi(), VarManager::kPhi, 20, 0.0, 100.0, VarManager::kCentFT0C); + } if (subGroupStr.Contains("kine")) { hm->AddHistogram(histClass, "Phi_Eta", "#phi vs #eta distribution", false, 200, -5.0, 5.0, VarManager::kEta, 200, -2. * TMath::Pi(), 2. * TMath::Pi(), VarManager::kPhi); hm->AddHistogram(histClass, "Eta_Pt", "", false, 20, -1.0, 1.0, VarManager::kEta, 100, 0.0, 20.0, VarManager::kPt); @@ -177,12 +192,16 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "IsSPDfirst", "", false, 2, -0.5, 1.5, VarManager::kIsSPDfirst); hm->AddHistogram(histClass, "ITSClusterMap", "", false, 128, -0.5, 127.5, VarManager::kITSClusterMap); hm->AddHistogram(histClass, "ITSClustermap_vs_pin", "ITSClustermap vs pin", false, 200, 0.0, 20.0, VarManager::kPin, 128, -0.5, 127.5, VarManager::kITSClusterMap); + hm->AddHistogram(histClass, "ITSClustermap_vs_SignedPin", "ITSClustermap vs SignedPin", false, 400, -20.0, 20.0, VarManager::kSignedPin, 128, -0.5, 127.5, VarManager::kITSClusterMap); hm->AddHistogram(histClass, "ITSClustermap_vs_pt", "ITSClustermap vs pt", false, 200, 0.0, 20.0, VarManager::kPt, 128, -0.5, 127.5, VarManager::kITSClusterMap); - hm->AddHistogram(histClass, "pin_vs_p", "", false, 200, 0.0, 20.0, VarManager::kPin, 200, 0.0, 20, VarManager::kP); hm->AddHistogram(histClass, "ITSClustermap_vs_eta", "ITSClustermap vs eta", false, 100, -1.0, 1.0, VarManager::kEta, 128, -0.5, 127.5, VarManager::kITSClusterMap); hm->AddHistogram(histClass, "ITSClustermap_vs_phi", "ITSClustermap vs phi", false, 315, 0.0, 6.3, VarManager::kPhi, 128, -0.5, 127.5, VarManager::kITSClusterMap); - hm->AddHistogram(histClass, "ITSClustermap_vs_dcaxy_vs_pt", "ITSClustermap vs dcaxy vs pt", false, 200, 0.0, 20.0, VarManager::kPt, 100, -1, 1, VarManager::kTrackDCAxy, 128, -0.5, 127.5, VarManager::kITSClusterMap); - hm->AddHistogram(histClass, "ITSClustermap_vs_dcaz_vs_pt", "ITSClustermap vs dcaxy vs pt", false, 200, 0.0, 20.0, VarManager::kPt, 100, -1, 1, VarManager::kTrackDCAz, 128, -0.5, 127.5, VarManager::kITSClusterMap); + hm->AddHistogram(histClass, "SignedPin_P_ITSMap", "SignedPin vs P vs ITSMap", false, 400, -20.0, 20.0, VarManager::kSignedPin, 200, 0.0, 20.0, VarManager::kP, 2, -0.5, 1.5, VarManager::kHasITS); + if (subGroupStr.Contains("cent")) { + hm->AddHistogram(histClass, "ITSncls_CentFT0C", "Number of cluster in ITS", false, 8, -0.5, 7.5, VarManager::kITSncls, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "ITSchi2_CentFT0C", "ITS chi2", false, 100, 0.0, 50.0, VarManager::kITSchi2, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "ITSClusterMap_CentFT0C", "", false, 128, -0.5, 127.5, VarManager::kITSClusterMap, 20, 0.0, 100.0, VarManager::kCentFT0C); + } } if (subGroupStr.Contains("itsvspt")) { hm->AddHistogram(histClass, "ITSncls_Pt", "Number of cluster in ITS vs Pt", false, 200, 0.0, 10.0, VarManager::kPt, 8, -0.5, 7.5, VarManager::kITSncls); @@ -200,6 +219,12 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "IsTPCrefit", "", false, 2, -0.5, 1.5, VarManager::kIsTPCrefit); hm->AddHistogram(histClass, "IsGoldenChi2", "", false, 2, -0.5, 1.5, VarManager::kIsGoldenChi2); hm->AddHistogram(histClass, "TPCchi2", "TPC chi2", false, 100, 0.0, 10.0, VarManager::kTPCchi2); + hm->AddHistogram(histClass, "pin_vs_p", "", false, 400, -20.0, 20.0, VarManager::kSignedPin, 200, 0.0, 20, VarManager::kP); + if (subGroupStr.Contains("cent")) { + hm->AddHistogram(histClass, "TPCncls_CentFT0C", "Number of cluster in TPC", false, 160, -0.5, 159.5, VarManager::kTPCncls, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "TPCnclsCR_CentFT0C", "Number of crossed rows in TPC", false, 160, -0.5, 159.5, VarManager::kTPCnclsCR, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "TPCchi2_CentFT0C", "TPC chi2", false, 100, 0.0, 10.0, VarManager::kTPCchi2, 20, 0.0, 100.0, VarManager::kCentFT0C); + } } if (subGroupStr.Contains("tpcvspt")) { hm->AddHistogram(histClass, "TPCncls_Pt", "Number of cluster in TPC vs Pt", false, 200, 0.0, 10.0, VarManager::kPt, 160, -0.5, 159.5, VarManager::kTPCncls); @@ -359,6 +384,24 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h 300, 0., 300., VarManager::kTPCsignal, 10, 0., 1., VarManager::kNothing, VarManager::GetRunStr().Data()); hm->AddHistogram(histClass, "TPCchi2_run", "TPCchi2 vs RunNumber", false, (VarManager::GetNRuns() > 0 ? VarManager::GetNRuns() : 1), -0.5, -0.5 + VarManager::GetNRuns(), VarManager::kRunIndex, 100, 0., 10., VarManager::kTPCchi2, 10, 0., 1., VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "Pt_Run", "p_{T} distribution", false, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 2000, 0.0, 20.0, VarManager::kPt, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "ITSncls_Run", "Number of cluster in ITS", false, 100, -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 8, -0.5, 7.5, VarManager::kITSncls, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "ITSchi2_Run", "ITS chi2", false, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 100, 0.0, 50.0, VarManager::kITSchi2, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "TPCncls_Run", "Number of cluster in TPC", false, 100, -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 160, -0.5, 159.5, VarManager::kTPCncls, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "TPCchi2_Run", "TPC chi2", false, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 100, 0.0, 10.0, VarManager::kTPCchi2, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "TPCdedx_Run", "TPC dE/dx", false, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 200, 0.0, 200., VarManager::kTPCsignal, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "TPCnSigEle_Run", "TPC n-#sigma(e)", false, 100, -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 100, -5.0, 5.0, VarManager::kTPCnSigmaEl, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "DCAxy_Run", "DCA_{xy}", false, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 400, -2.0, 2.0, VarManager::kTrackDCAxy, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); + hm->AddHistogram(histClass, "DCAz_Run", "DCA_{z}", false, VarManager::GetDummyNRuns(), -0.5 + VarManager::GetDummyFirst(), 0.5 + VarManager::GetDummyLast(), VarManager::kRunNo, + 800, -4.0, 4.0, VarManager::kTrackDCAz, 1, 0, 1, VarManager::kNothing, VarManager::GetRunStr().Data()); } if (subGroupStr.Contains("dca")) { hm->AddHistogram(histClass, "DCAxy", "DCA_{xy}", false, 400, -2.0, 2.0, VarManager::kTrackDCAxy); @@ -374,15 +417,19 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Pt_DCAresXY", "p_{T} vs #DeltaDCA_{XY}", false, 200, 0.0, 10.0, VarManager::kPt, 100, -0.03, 0.03, VarManager::kTrackDCAresXY); hm->AddHistogram(histClass, "Pt_DCAresZ", "p_{T} vs #DeltaDCA_{Z}", false, 200, 0.0, 10.0, VarManager::kPt, 100, -0.03, 0.03, VarManager::kTrackDCAresZ); if (subGroupStr.Contains("dca_fine")) { // Fine binning - hm->AddHistogram(histClass, "DCAxy_fine", "DCA_{xy}", false, 1000, -0.5, 0.5, VarManager::kTrackDCAxy); - hm->AddHistogram(histClass, "DCAz_fine", "DCA_{z}", false, 1000, -0.5, 0.5, VarManager::kTrackDCAz); - hm->AddHistogram(histClass, "IsSPDfirst_Pt_DCAxy_fine", "IsSPDfirst vs p_{T} vs DCA_{xy}", false, 200, 0.0, 20.0, VarManager::kPt, 1000, -0.5, 0.5, VarManager::kTrackDCAxy, 2, -0.5, 1.5, VarManager::kIsSPDfirst); - hm->AddHistogram(histClass, "IsSPDfirst_Pt_DCAz_fine", "IsSPDfirst vs p_{T} vs DCA_{z}", false, 200, 0.0, 20.0, VarManager::kPt, 1000, -0.5, 0.5, VarManager::kTrackDCAz, 2, -0.5, 1.5, VarManager::kIsSPDfirst); + hm->AddHistogram(histClass, "DCAxy_fine", "DCA_{xy}", false, 1000, -0.2, 0.2, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "DCAz_fine", "DCA_{z}", false, 1000, -0.2, 0.2, VarManager::kTrackDCAz); + hm->AddHistogram(histClass, "IsSPDfirst_Pt_DCAxy_fine", "IsSPDfirst vs p_{T} vs DCA_{xy}", false, 200, 0.0, 20.0, VarManager::kPt, 1000, -0.2, 0.2, VarManager::kTrackDCAxy, 2, -0.5, 1.5, VarManager::kIsSPDfirst); + hm->AddHistogram(histClass, "IsSPDfirst_Pt_DCAz_fine", "IsSPDfirst vs p_{T} vs DCA_{z}", false, 200, 0.0, 20.0, VarManager::kPt, 1000, -0.2, 0.2, VarManager::kTrackDCAz, 2, -0.5, 1.5, VarManager::kIsSPDfirst); + hm->AddHistogram(histClass, "PtLow_DCAxy_fine", "p_{T} vs DCA_{xy}", false, 100, 0.0, 2.0, VarManager::kPt, 1000, -0.2, 0.2, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "PtLow_DCAz_fine", "p_{T} vs DCA_{z}", false, 100, 0.0, 2.0, VarManager::kPt, 1000, -0.2, 0.2, VarManager::kTrackDCAz); + hm->AddHistogram(histClass, "PtHigh_DCAxy_fine", "p_{T} vs DCA_{xy}", false, 200, 0.0, 20.0, VarManager::kPt, 1000, -0.05, 0.05, VarManager::kTrackDCAxy); + hm->AddHistogram(histClass, "PtHigh_DCAz_fine", "p_{T} vs DCA_{z}", false, 200, 0.0, 20.0, VarManager::kPt, 1000, -0.05, 0.05, VarManager::kTrackDCAz); } } if (subGroupStr.Contains("muon")) { hm->AddHistogram(histClass, "MuonNClusters", "", false, 100, 0.0, 10.0, VarManager::kMuonNClusters); - hm->AddHistogram(histClass, "pdca", "", false, 100, 0.0, 500., VarManager::kMuonPDca); + hm->AddHistogram(histClass, "pdca", "", false, 200, 0.0, 1000., VarManager::kMuonPDca); hm->AddHistogram(histClass, "RAtAbsorberEnd", "", false, 100, 0.0, 200., VarManager::kMuonRAtAbsorberEnd); hm->AddHistogram(histClass, "Chi2", "", false, 100, 0.0, 200.0, VarManager::kMuonChi2); hm->AddHistogram(histClass, "Chi2MCHMID", "", false, 100, 0.0, 200.0, VarManager::kMuonChi2MatchMCHMID); @@ -396,9 +443,19 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "MCHBitMap_vs_pt", "MCH vs pt", false, 1025, 0.0, 1025.0, VarManager::kMCHBitMap, 400, 0, 100, VarManager::kPt); hm->AddHistogram(histClass, "MuonTime", "", false, 100, -1.0, 1.0, VarManager::kMuonTime); hm->AddHistogram(histClass, "MuonTimeRes", "", false, 100, -1.0, 1.0, VarManager::kMuonTimeRes); + hm->AddHistogram(histClass, "MuonDcaX_vs_phi", "", false, 1000, -1.0, 1.0, VarManager::kMuonDCAx, 200, -2. * TMath::Pi(), 2. * TMath::Pi(), VarManager::kPhi); + hm->AddHistogram(histClass, "MuonDcaY_vs_phi", "", false, 1000, -1.0, 1.0, VarManager::kMuonDCAy, 200, -2. * TMath::Pi(), 2. * TMath::Pi(), VarManager::kPhi); + hm->AddHistogram(histClass, "MuonDcaX_vs_eta", "", false, 1000, -1.0, 1.0, VarManager::kMuonDCAx, 500, -5.0, 5.0, VarManager::kEta); + hm->AddHistogram(histClass, "MuonDcaY_vs_eta", "", false, 1000, -1.0, 1.0, VarManager::kMuonDCAy, 500, -5.0, 5.0, VarManager::kEta); + } + if (subGroupStr.Contains("muon-pdca")) { + hm->AddHistogram(histClass, "p", "p", false, 200, 0.0, 20.0, VarManager::kP); + hm->AddHistogram(histClass, "pdca_vs_p", "pDCA vs p", false, 2000, 0.0, 20.0, VarManager::kP, 200, 0.0, 1000., VarManager::kMuonPDca); + hm->AddHistogram(histClass, "pdca_vs_pt", "pDCA vs pt", false, 2000, 0.0, 20.0, VarManager::kPt, 200, 0.0, 1000., VarManager::kMuonPDca); + hm->AddHistogram(histClass, "pdca_vs_Rabs", "pDCA vs R_{abs}", false, 100, 0., 200., VarManager::kMuonRAtAbsorberEnd, 200, 0.0, 1000., VarManager::kMuonPDca); } if (subGroupStr.Contains("mc")) { - hm->AddHistogram(histClass, "Pt_vs_PtMC", "pT vs MC pT", false, 50, 0.0, 10.0, VarManager::kPt, 50, 0.0, 10.0, VarManager::kMCPt); + hm->AddHistogram(histClass, "Pt_vs_PtMC", "pT vs MC pT", false, 200, 0.0, 20.0, VarManager::kPt, 200, 0.0, 20.0, VarManager::kMCPt); hm->AddHistogram(histClass, "Eta_vs_EtaMC", "#eta vs MC #eta", false, 50, -1.0, 1.0, VarManager::kEta, 50, -1.0, 1.0, VarManager::kMCEta); hm->AddHistogram(histClass, "Phi_vs_PhiMC", "#varphi vs MC #varphi", false, 50, 0.0, 2. * TMath::Pi(), VarManager::kPhi, 50, 0.0, 2. * TMath::Pi(), VarManager::kMCPhi); hm->AddHistogram(histClass, "TrackPDGcode", "PDG code of track", false, 10001, -5000, 5000, VarManager::kMCPdgCode); @@ -427,12 +484,26 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h if (subGroupStr.Contains("barrel")) { hm->AddHistogram(histClass, "Mass", "", false, 500, 0.0, 5.0, VarManager::kMass); hm->AddHistogram(histClass, "Pt", "", false, 500, 0.0, 1.5, VarManager::kPt); - hm->AddHistogram(histClass, "Mass_Pt", "", false, 500, 0.0, 5.0, VarManager::kMass, 200, 0.0, 10.0, VarManager::kPt); + hm->AddHistogram(histClass, "Mass_Pt", "", false, 500, 0.0, 5.0, VarManager::kMass, 400, 0.0, 40.0, VarManager::kPt); hm->AddHistogram(histClass, "Eta_Pt", "", false, 40, -2.0, 2.0, VarManager::kEta, 200, 0.0, 20.0, VarManager::kPt); hm->AddHistogram(histClass, "Mass_VtxZ", "", true, 30, -15.0, 15.0, VarManager::kVtxZ, 500, 0.0, 5.0, VarManager::kMass); - hm->AddHistogram(histClass, "cosThetaHE", "", false, 100, -1., 1., VarManager::kCosThetaHE); + if (subGroupStr.Contains("pbpb")) { + hm->AddHistogram(histClass, "Mass_CentFT0C", "", false, 500, 0.0, 5.0, VarManager::kMass, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "Pt_CentFT0C", "", false, 500, 0.0, 1.5, VarManager::kPt, 20, 0.0, 100.0, VarManager::kCentFT0C); + hm->AddHistogram(histClass, "Mass_Pt_CentFT0C", "", false, 500, 0.0, 5.0, VarManager::kMass, 400, 0.0, 40.0, VarManager::kPt, 20, 0.0, 100.0, VarManager::kCentFT0C); + } if (subGroupStr.Contains("polarization")) { - hm->AddHistogram(histClass, "Mass_Pt_cosThetaHE", "", false, 500, 0.0, 5.0, VarManager::kMass, 250, 0.0, 25.0, VarManager::kPt, 40, -1., 1., VarManager::kCosThetaHE); + hm->AddHistogram(histClass, "cosThetaHE", "", false, 100, -1., 1., VarManager::kCosThetaHE); + hm->AddHistogram(histClass, "cosThetaCS", "", false, 100, -1., 1., VarManager::kCosThetaCS); + hm->AddHistogram(histClass, "PhiHE", "", false, 100, -TMath::Pi(), TMath::Pi(), VarManager::kPhiHE); + hm->AddHistogram(histClass, "PhiCS", "", false, 100, -TMath::Pi(), TMath::Pi(), VarManager::kPhiCS); + hm->AddHistogram(histClass, "Mass_Pt_cosThetaHE", "", false, 100, 1.0, 5.0, VarManager::kMass, 250, 0.0, 25.0, VarManager::kPt, 40, -1., 1., VarManager::kCosThetaHE); + hm->AddHistogram(histClass, "Mass_Pt_cosThetaCS", "", false, 100, 1.0, 5.0, VarManager::kMass, 250, 0.0, 25.0, VarManager::kPt, 40, -1., 1., VarManager::kCosThetaCS); + hm->AddHistogram(histClass, "Mass_Pt_PhiHE", "", false, 100, 1.0, 5.0, VarManager::kMass, 250, 0.0, 25.0, VarManager::kPt, 40, -TMath::Pi(), TMath::Pi(), VarManager::kPhiHE); + hm->AddHistogram(histClass, "Mass_Pt_PhiCS", "", false, 100, 1.0, 5.0, VarManager::kMass, 250, 0.0, 25.0, VarManager::kPt, 40, -TMath::Pi(), TMath::Pi(), VarManager::kPhiCS); + } + if (subGroupStr.Contains("upsilon")) { + hm->AddHistogram(histClass, "MassUpsilon_Pt", "", false, 500, 7.0, 12.0, VarManager::kMass, 400, 0.0, 40.0, VarManager::kPt); } if (subGroupStr.Contains("dalitz")) { hm->AddHistogram(histClass, "MassLow", "", false, 500, 0.0, 0.05, VarManager::kMass); @@ -485,6 +556,22 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "cosThetaHE", "", false, 100, -1., 1., VarManager::kCosThetaHE); hm->AddHistogram(histClass, "DeltaPtotTracks", "", false, 2000, -100., 100., VarManager::kDeltaPtotTracks); hm->AddHistogram(histClass, "Mass_DeltaPtotTracks", "", false, 150, 2.0, 5.0, VarManager::kMass, 200, -100., 100., VarManager::kDeltaPtotTracks); + if (subGroupStr.Contains("dimuon-polarization")) { + int varspTHE[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaHE, VarManager::kPhiHE}; + int varspTCS[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaCS, VarManager::kPhiCS}; + int varsMulHE[4] = {VarManager::kMass, VarManager::kMultFV0A, VarManager::kCosThetaHE, VarManager::kPhiHE}; + int varsMulCS[4] = {VarManager::kMass, VarManager::kMultFV0A, VarManager::kCosThetaCS, VarManager::kPhiCS}; + int binspT[4] = {100, 20, 20, 20}; + int binsMul[4] = {100, 10, 20, 20}; + double xminpT[4] = {1., 0., -1., -3.14}; + double xmaxpT[4] = {5., 20., 1., +3.14}; + double xminMul[4] = {1., 0., -1., -3.14}; + double xmaxMul[4] = {5., 1000., 1., +3.14}; + hm->AddHistogram(histClass, "Mass_Pt_cosThetaHE_phiHE", "", 4, varspTHE, binspT, xminpT, xmaxpT, 0, -1, kFALSE); + hm->AddHistogram(histClass, "Mass_Pt_cosThetaCS_phiCS", "", 4, varspTCS, binspT, xminpT, xmaxpT, 0, -1, kFALSE); + hm->AddHistogram(histClass, "Mass_V0AMul_cosThetaHE_phiHE", "", 4, varsMulHE, binsMul, xminMul, xmaxMul, 0, -1, kFALSE); + hm->AddHistogram(histClass, "Mass_V0AMul_cosThetaCS_phiCS", "", 4, varsMulCS, binsMul, xminMul, xmaxMul, 0, -1, kFALSE); + } if (subGroupStr.Contains("vertexing-forward")) { hm->AddHistogram(histClass, "Lxyz", "", false, 100, 0.0, 10.0, VarManager::kVertexingLxyz); hm->AddHistogram(histClass, "Lz", "", false, 100, 0.0, 10.0, VarManager::kVertexingLz); @@ -521,6 +608,9 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_VtxZ", "", true, 30, -15.0, 15.0, VarManager::kVtxZ, 750, 0.0, 30.0, VarManager::kMass); } if (subGroupStr.Contains("dielectrons")) { + if (subGroupStr.Contains("prefilter")) { + hm->AddHistogram(histClass, "MassLow_OpeningAngle", "", false, 150, 0., 0.15, VarManager::kMass, 80, 0., 0.8, VarManager::kOpeningAngle); + } if (subGroupStr.Contains("phiv")) { hm->AddHistogram(histClass, "Mass_Pt_PhiV", "", false, 20, 0.0, 0.2, VarManager::kMass, 100, 0.0, 10.0, VarManager::kPt, 100, 0.0, TMath::Pi(), VarManager::kPairPhiv); } @@ -528,7 +618,6 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_Pt_PhiV", "", false, 20, 0.0, 0.2, VarManager::kMass, 100, 0.0, 10.0, VarManager::kPt, 100, 0.0, TMath::Pi(), VarManager::kPairPhiv); hm->AddHistogram(histClass, "Mass_QuadDCAsigXY", "", false, 50, 0.0, 5.0, VarManager::kMass, 50, 0.0, 20.0, VarManager::kQuadDCAsigXY); hm->AddHistogram(histClass, "Mass_QuadDCAsigZ", "", false, 50, 0.0, 5.0, VarManager::kMass, 50, 0.0, 20.0, VarManager::kQuadDCAsigZ); - hm->AddHistogram(histClass, "Mass_QuadDCAsigXYZ", "", false, 50, 0.0, 5.0, VarManager::kMass, 50, 0.0, 20.0, VarManager::kQuadDCAsigXYZ); hm->AddHistogram(histClass, "Mass_Pt_QuadDCAsigXYZ", "", false, 500, 0.0, 5.0, VarManager::kMass, 100, 0.0, 10.0, VarManager::kPt, 50, 0.0, 20.0, VarManager::kQuadDCAsigXYZ); } if (subGroupStr.Contains("largescale")) { @@ -536,15 +625,15 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h // every 10 MeV from 0 to 1.1 GeV/c2 // every 50 MeV from 1.1 to 2.7 GeV/c2 // every 10 MeV from 2.7 to 3.2 GeV/c2 - // every 50 MeV from 3.2 to 10 GeV/c2 - double mee_bins[329]; + // every 50 MeV from 3.2 to 12 GeV/c2 + double mee_bins[369]; for (int i = 0; i <= 110; i++) mee_bins[i] = 0.01 * i; for (int i = 1; i <= 32; i++) mee_bins[110 + i] = 1.1 + 0.05 * i; for (int i = 1; i <= 50; i++) mee_bins[142 + i] = 2.7 + 0.01 * i; - for (int i = 1; i <= 136; i++) + for (int i = 1; i <= 176; i++) mee_bins[192 + i] = 3.2 + 0.05 * i; int nbins_mee = sizeof(mee_bins) / sizeof(*mee_bins) - 1; @@ -574,7 +663,6 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_Pt_PhiV", "", false, 20, 0.0, 0.2, VarManager::kMass, 100, 0.0, 10.0, VarManager::kPt, 100, 0.0, TMath::Pi(), VarManager::kPairPhiv); hm->AddHistogram(histClass, "Mass_QuadDCAsigXY", "", false, nbins_mee, mee_bins, VarManager::kMass, nbins_dca, dca_bins, VarManager::kQuadDCAsigXY); hm->AddHistogram(histClass, "Mass_QuadDCAsigZ", "", false, nbins_mee, mee_bins, VarManager::kMass, nbins_dca, dca_bins, VarManager::kQuadDCAsigZ); - hm->AddHistogram(histClass, "Mass_QuadDCAsigXYZ", "", false, nbins_mee, mee_bins, VarManager::kMass, nbins_dca, dca_bins, VarManager::kQuadDCAsigXYZ); hm->AddHistogram(histClass, "Mass_Pt_QuadDCAsigXYZ", "", false, nbins_mee, mee_bins, VarManager::kMass, nbins_ptee, ptee_bins, VarManager::kPt, nbins_dca, dca_bins, VarManager::kQuadDCAsigXYZ); } } @@ -605,4 +693,34 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "DeltaEta_DeltaPhi", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -8.0, 8.0, VarManager::kDeltaPhi); hm->AddHistogram(histClass, "DeltaEta_DeltaPhiSym", "", false, 20, -2.0, 2.0, VarManager::kDeltaEta, 50, -8.0, 8.0, VarManager::kDeltaPhiSym); } + + if (groupStr.Contains("dilepton-charmhadron")) { + if (subGroupStr.EqualTo("jpsitomumu")) { + hm->AddHistogram(histClass, "hMassVsPtJPsi", "", false, 100, 0.f, 50.f, VarManager::kPt, 300, 2.f, 5.f, VarManager::kMass); + hm->AddHistogram(histClass, "hRapVsPtJPsi", "", false, 100, 0.f, 50.f, VarManager::kPt, 50, -4.5f, -2.0f, VarManager::kRap); + hm->AddHistogram(histClass, "hPhiJPsi", "", false, 180, -constants::math::PI, constants::math::PI, VarManager::kPhi); + } else if (subGroupStr.EqualTo("jpsitoee")) { + hm->AddHistogram(histClass, "hMassVsPtJPsi", "", false, 100, 0.f, 50.f, VarManager::kPt, 300, 2.f, 5.f, VarManager::kMass); + hm->AddHistogram(histClass, "hRapVsPtJPsi", "", false, 100, 0.f, 50.f, VarManager::kPt, 60, -1.5f, 1.5f, VarManager::kRap); + hm->AddHistogram(histClass, "hPhiJPsi", "", false, 180, -constants::math::PI, constants::math::PI, VarManager::kPhi); + } else if (subGroupStr.EqualTo("dmeson")) { + hm->AddHistogram(histClass, "hMassVsPtDmeson", "", false, 100, 0.f, 50.f, VarManager::kPtCharmHadron, 200, 1.7f, 2.1f, VarManager::kMassCharmHadron); + hm->AddHistogram(histClass, "hRapVsPtDmeson", "", false, 100, 0.f, 50.f, VarManager::kPtCharmHadron, 60, -1.5f, 1.5f, VarManager::kRapCharmHadron); + hm->AddHistogram(histClass, "hPhiDmeson", "", false, 180, 0., 2 * constants::math::PI, VarManager::kPhiCharmHadron); + } else if (subGroupStr.EqualTo("jpsitomumudmeson")) { + hm->AddHistogram(histClass, "hMassVsPtJPsiWithDmeson", "", false, 100, 0.f, 50.f, VarManager::kPt, 300, 2.f, 5.f, VarManager::kMass); + hm->AddHistogram(histClass, "hRapVsPtJPsiWithDmeson", "", false, 100, 0.f, 50.f, VarManager::kPt, 50, -4.5f, -2.0f, VarManager::kRap); + hm->AddHistogram(histClass, "hPhiJPsiWithDmeson", "", false, 180, -constants::math::PI, constants::math::PI, VarManager::kPhi); + hm->AddHistogram(histClass, "hMassVsPtDmesonWithJPsi", "", false, 100, 0.f, 50.f, VarManager::kPtCharmHadron, 200, 1.7f, 2.1f, VarManager::kMassCharmHadron); + hm->AddHistogram(histClass, "hRapVsPtDmesonWithJPsi", "", false, 100, 0.f, 50.f, VarManager::kPtCharmHadron, 60, -1.5f, 1.5f, VarManager::kRapCharmHadron); + hm->AddHistogram(histClass, "hPhiDmesonWithJPsi", "", false, 180, 0., 2 * constants::math::PI, VarManager::kPhiCharmHadron); + } else if (subGroupStr.EqualTo("jpsitoeedmeson")) { + hm->AddHistogram(histClass, "hMassVsPtJPsiWithDmeson", "", false, 100, 0.f, 50.f, VarManager::kPt, 300, 2.f, 5.f, VarManager::kMass); + hm->AddHistogram(histClass, "hRapVsPtJPsiWithDmeson", "", false, 100, 0.f, 50.f, VarManager::kPt, 60, -1.5f, 1.5f, VarManager::kRap); + hm->AddHistogram(histClass, "hPhiJPsiWithDmeson", "", false, 180, -constants::math::PI, constants::math::PI, VarManager::kPhi); + hm->AddHistogram(histClass, "hMassVsPtDmesonWithJPsi", "", false, 100, 0.f, 50.f, VarManager::kPtCharmHadron, 200, 1.7f, 2.1f, VarManager::kMassCharmHadron); + hm->AddHistogram(histClass, "hRapVsPtDmesonWithJPsi", "", false, 100, 0.f, 50.f, VarManager::kPtCharmHadron, 60, -1.5f, 1.5f, VarManager::kRapCharmHadron); + hm->AddHistogram(histClass, "hPhiDmesonWithJPsi", "", false, 180, 0., 2 * constants::math::PI, VarManager::kPhiCharmHadron); + } + } } diff --git a/PWGDQ/Core/MCProng.cxx b/PWGDQ/Core/MCProng.cxx index b77fb469252..38e1fa30801 100644 --- a/PWGDQ/Core/MCProng.cxx +++ b/PWGDQ/Core/MCProng.cxx @@ -24,7 +24,9 @@ MCProng::MCProng() : fNGenerations(0), fSourceBits({}), fExcludeSource({}), fUseANDonSourceBitMap({}), - fCheckGenerationsInTime(0) + fCheckGenerationsInTime(0), + fPDGInHistory({}), + fExcludePDGInHistory({}) { } @@ -48,17 +50,46 @@ MCProng::MCProng(int n) : fNGenerations(n), } } +//________________________________________________________________________________________________________________ +MCProng::MCProng(int n, int m) : fNGenerations(n), + fCheckGenerationsInTime(0) +{ + fPDGcodes.reserve(n); + fCheckBothCharges.reserve(n); + fExcludePDG.reserve(n); + fSourceBits.reserve(n); + fExcludeSource.reserve(n); + fUseANDonSourceBitMap.reserve(n); + fPDGInHistory.reserve(m); + fExcludePDGInHistory.reserve(m); + for (int i = 0; i < n; i++) { + fPDGcodes.push_back(kPDGCodeNotAssigned); + fCheckBothCharges.push_back(false); + fExcludePDG.push_back(false); + fSourceBits.push_back(0); + fExcludeSource.push_back(0); + fUseANDonSourceBitMap.push_back(true); + } + for (int j = 0; j < m; j++) { + fPDGInHistory.push_back(0); + fExcludePDGInHistory.push_back(0); + } +} + //________________________________________________________________________________________________________________ MCProng::MCProng(int n, const std::vector pdgs, const std::vector checkBothCharges, const std::vector excludePDG, const std::vector sourceBits, const std::vector excludeSource, - const std::vector useANDonSourceBitMap, bool checkGenerationsInTime) : fNGenerations(n), - fPDGcodes(pdgs), - fCheckBothCharges(checkBothCharges), - fExcludePDG(excludePDG), - fSourceBits(sourceBits), - fExcludeSource(excludeSource), - fUseANDonSourceBitMap(useANDonSourceBitMap), - fCheckGenerationsInTime(checkGenerationsInTime){}; + const std::vector useANDonSourceBitMap, bool checkGenerationsInTime, + const std::vector checkIfPDGInHistory, const std::vector excludePDGInHistory) : fNGenerations(n), + fPDGcodes(pdgs), + fCheckBothCharges(checkBothCharges), + fExcludePDG(excludePDG), + fSourceBits(sourceBits), + fExcludeSource(excludeSource), + fUseANDonSourceBitMap(useANDonSourceBitMap), + fCheckGenerationsInTime(checkGenerationsInTime), + fPDGInHistory(checkIfPDGInHistory), + fExcludePDGInHistory(excludePDGInHistory) {} //________________________________________________________________________________________________________________ void MCProng::SetPDGcode(int generation, int code, bool checkBothCharges /*= false*/, bool exclude /*= false*/) @@ -115,7 +146,7 @@ void MCProng::Print() const for (int i = 0; i < fNGenerations; i++) { std::cout << "Generation #" << i << " PDGcode(" << fPDGcodes[i] << ") CheckBothCharges(" << fCheckBothCharges[i] << ") ExcludePDG(" << fExcludePDG[i] << ") SourceBits(" << fSourceBits[i] << ") ExcludeSource(" << fExcludeSource[i] - << ") UseANDonSource(" << fUseANDonSourceBitMap[i] << ") CheckGenerationsInTime(" << fCheckGenerationsInTime << ")" << std::endl; + << ") UseANDonSource(" << fUseANDonSourceBitMap[i] << ") CheckGenerationsInTime(" << fCheckGenerationsInTime << ") PDGInHistory(" << fPDGInHistory[i] << ") ExcludePDGInHistory(" << fExcludePDGInHistory[i] << ")" << std::endl; } } diff --git a/PWGDQ/Core/MCProng.h b/PWGDQ/Core/MCProng.h index 8a7b732ee29..df36f1a316c 100644 --- a/PWGDQ/Core/MCProng.h +++ b/PWGDQ/Core/MCProng.h @@ -52,8 +52,8 @@ A few non-existent PYTHIA codes are used to select more than one PYTHIA code. 5001 - open beauty baryons 5000-5499 */ -#ifndef MCProng_H -#define MCProng_H +#ifndef PWGDQ_CORE_MCPRONG_H_ +#define PWGDQ_CORE_MCPRONG_H_ #include "TNamed.h" @@ -78,8 +78,10 @@ class MCProng MCProng(); MCProng(int n); + MCProng(int n, int m); MCProng(int n, std::vector pdgs, std::vector checkBothCharges, std::vector excludePDG, - std::vector sourceBits, std::vector excludeSource, std::vector useANDonSourceBitMap, bool fCheckGenerationsInTime = false); + std::vector sourceBits, std::vector excludeSource, std::vector useANDonSourceBitMap, + bool checkGenerationsInTime = false, std::vector checkIfPDGInHistory = {}, std::vector excludePDGInHistory = {}); MCProng(const MCProng& c) = default; virtual ~MCProng() = default; @@ -100,7 +102,9 @@ class MCProng std::vector fExcludeSource; std::vector fUseANDonSourceBitMap; bool fCheckGenerationsInTime; + std::vector fPDGInHistory; + std::vector fExcludePDGInHistory; ClassDef(MCProng, 2); }; -#endif +#endif // PWGDQ_CORE_MCPRONG_H_ diff --git a/PWGDQ/Core/MCSignal.cxx b/PWGDQ/Core/MCSignal.cxx index 9d9e8520dfb..a86b0f8aa8d 100644 --- a/PWGDQ/Core/MCSignal.cxx +++ b/PWGDQ/Core/MCSignal.cxx @@ -11,6 +11,9 @@ #include "PWGDQ/Core/MCSignal.h" +using std::cout; +using std::endl; + ClassImp(MCSignal); //________________________________________________________________________________________________ diff --git a/PWGDQ/Core/MCSignal.h b/PWGDQ/Core/MCSignal.h index d223669eb3c..eb12c883ba1 100644 --- a/PWGDQ/Core/MCSignal.h +++ b/PWGDQ/Core/MCSignal.h @@ -53,16 +53,14 @@ process(aod::McParticles const& mcTracks) { } } */ -#ifndef MCSignal_H -#define MCSignal_H +#ifndef PWGDQ_CORE_MCSIGNAL_H_ +#define PWGDQ_CORE_MCSIGNAL_H_ #include "MCProng.h" #include "TNamed.h" #include #include -using std::cout; -using std::endl; class MCSignal : public TNamed { @@ -85,15 +83,15 @@ class MCSignal : public TNamed return fProngs[0].fNGenerations; } - template - bool CheckSignal(bool checkSources, const U& mcStack, const T&... args) + template + bool CheckSignal(bool checkSources, const T&... args) { // Make sure number of tracks provided is equal to the number of prongs if (sizeof...(args) != fNProngs) { // TODO: addd a proper error message return false; } - return CheckMC(0, checkSources, mcStack, args...); + return CheckMC(0, checkSources, args...); }; void PrintConfig(); @@ -104,33 +102,32 @@ class MCSignal : public TNamed std::vector fCommonAncestorIdxs; int fTempAncestorLabel; - template - bool CheckProng(int i, bool checkSources, const U& mcStack, const T& track); + template + bool CheckProng(int i, bool checkSources, const T& track); - template - bool CheckMC(int, bool, U) + bool CheckMC(int, bool) { return true; }; - template - bool CheckMC(int i, bool checkSources, const U& mcStack, const T& track, const Ts&... args) + template + bool CheckMC(int i, bool checkSources, const T& track, const Ts&... args) { // recursive call of CheckMC for all args - if (!CheckProng(i, checkSources, mcStack, track)) { + if (!CheckProng(i, checkSources, track)) { return false; } else { - return CheckMC(i + 1, checkSources, mcStack, args...); + return CheckMC(i + 1, checkSources, args...); } }; - - ClassDef(MCSignal, 1); }; -template -bool MCSignal::CheckProng(int i, bool checkSources, const U& mcStack, const T& track) +template +bool MCSignal::CheckProng(int i, bool checkSources, const T& track) { + using P = typename T::parent_t; auto currentMCParticle = track; + // loop over the generations specified for this prong for (int j = 0; j < fProngs[i].fNGenerations; j++) { // check the PDG code @@ -148,20 +145,15 @@ bool MCSignal::CheckProng(int i, bool checkSources, const U& mcStack, const T& t } } - // if checking back in time: look for mother - // else (checking in time): look for daughter + // Update the currentMCParticle by moving either back in time (towards mothers, grandmothers, etc) + // or in time (towards daughters) depending on how this was configured in the MSignal if (!fProngs[i].fCheckGenerationsInTime) { // make sure that a mother exists in the stack before moving one generation further in history if (!currentMCParticle.has_mothers() && j < fProngs[i].fNGenerations - 1) { return false; } - /*for (auto& m : mcParticle.mothers_as()) { - LOGF(debug, "M2 %d %d", mcParticle.globalIndex(), m.globalIndex()); - }*/ if (currentMCParticle.has_mothers() && j < fProngs[i].fNGenerations - 1) { - // currentMCParticle = currentMCParticle.template mothers_first_as(); - currentMCParticle = mcStack.iteratorAt(currentMCParticle.mothersIds()[0]); - // currentMCParticle = currentMCParticle.template mother0_as(); + currentMCParticle = currentMCParticle.template mothers_first_as

(); } } else { // make sure that a daughter exists in the stack before moving one generation younger @@ -169,11 +161,10 @@ bool MCSignal::CheckProng(int i, bool checkSources, const U& mcStack, const T& t return false; } if (currentMCParticle.has_daughters() && j < fProngs[i].fNGenerations - 1) { - const auto& daughtersSlice = currentMCParticle.template daughters_as(); + const auto& daughtersSlice = currentMCParticle.template daughters_as

(); for (auto& d : daughtersSlice) { if (fProngs[i].TestPDG(j + 1, d.pdgCode())) { - // currentMCParticle = d; - currentMCParticle = mcStack.iteratorAt(currentMCParticle.daughtersIds()[0]); + currentMCParticle = d; break; } } @@ -181,11 +172,12 @@ bool MCSignal::CheckProng(int i, bool checkSources, const U& mcStack, const T& t } } + // check the various specified sources if (checkSources) { currentMCParticle = track; for (int j = 0; j < fProngs[i].fNGenerations; j++) { + // check whether sources are required for this generation if (!fProngs[i].fSourceBits[j]) { - // no sources required for this generation continue; } // check each source @@ -223,39 +215,27 @@ bool MCSignal::CheckProng(int i, bool checkSources, const U& mcStack, const T& t return false; } - // if checking back in time: look for mother - // else (checking in time): look for daughter + // Update the currentMCParticle by moving either back in time (towards mothers, grandmothers, etc) + // or in time (towards daughters) depending on how this was configured in the MSignal if (!fProngs[i].fCheckGenerationsInTime) { - // move one generation back in history // make sure that a mother exists in the stack before moving one generation further in history if (!currentMCParticle.has_mothers() && j < fProngs[i].fNGenerations - 1) { return false; } if (currentMCParticle.has_mothers() && j < fProngs[i].fNGenerations - 1) { - /*for (auto& m : mcParticle.mothers_as()) { - LOGF(debug, "M2 %d %d", mcParticle.globalIndex(), m.globalIndex()); - }*/ - // currentMCParticle = currentMCParticle.template mothers_first_as(); - currentMCParticle = mcStack.iteratorAt(currentMCParticle.mothersIds()[0]); - // currentMCParticle = currentMCParticle.template mother0_as(); + currentMCParticle = currentMCParticle.template mothers_first_as

(); } - /*if (j < fProngs[i].fNGenerations - 1) { - currentMCParticle = mcStack.iteratorAt(currentMCParticle.mother0Id()); - //currentMCParticle = currentMCParticle.template mother0_as(); - }*/ } else { - // move one generation further in history - // pong history will be moved to the branch of the first daughter that matches the PDG requirement + // prong history will be moved to the branch of the first daughter that matches the PDG requirement // make sure that a daughter exists in the stack before moving one generation younger if (!currentMCParticle.has_daughters() && j < fProngs[i].fNGenerations - 1) { return false; } if (currentMCParticle.has_daughters() && j < fProngs[i].fNGenerations - 1) { - const auto& daughtersSlice = currentMCParticle.template daughters_as(); + const auto& daughtersSlice = currentMCParticle.template daughters_as

(); for (auto& d : daughtersSlice) { if (fProngs[i].TestPDG(j + 1, d.pdgCode())) { - // currentMCParticle = d; - currentMCParticle = mcStack.iteratorAt(currentMCParticle.daughtersIds()[0]); + currentMCParticle = d; break; } } @@ -264,7 +244,57 @@ bool MCSignal::CheckProng(int i, bool checkSources, const U& mcStack, const T& t } } + if (fProngs[i].fPDGInHistory.size() == 0) + return true; + else { // check if mother pdg is in history + std::vector pdgInHistory; + + // while find mothers, check if the provided PDG codes are included or excluded in the particle decay history + unsigned int nIncludedPDG = 0; + for (unsigned int k = 0; k < fProngs[i].fPDGInHistory.size(); k++) { + currentMCParticle = track; + if (!fProngs[i].fExcludePDGInHistory[k]) + nIncludedPDG++; + int ith = 0; + if (!fProngs[i].fCheckGenerationsInTime) { // check generation back in time + while (currentMCParticle.has_mothers()) { + auto mother = currentMCParticle.template mothers_first_as

(); + if (!fProngs[i].fExcludePDGInHistory[k] && fProngs[i].ComparePDG(mother.pdgCode(), fProngs[i].fPDGInHistory[k], true, fProngs[i].fExcludePDGInHistory[k])) { + pdgInHistory.emplace_back(mother.pdgCode()); + break; + } + if (fProngs[i].fExcludePDGInHistory[k] && !fProngs[i].ComparePDG(mother.pdgCode(), fProngs[i].fPDGInHistory[k], true, fProngs[i].fExcludePDGInHistory[k])) { + return false; + } + ith++; + currentMCParticle = mother; + if (ith > 10) { // need error message. Given pdg code was not found within 10 generations of the particles decay chain. + break; + } + } + } else { // check generation in time + if (!currentMCParticle.has_daughters()) + return false; + const auto& daughtersSlice = currentMCParticle.template daughters_as

(); + for (auto& d : daughtersSlice) { + if (!fProngs[i].fExcludePDGInHistory[k] && fProngs[i].ComparePDG(d.pdgCode(), fProngs[i].fPDGInHistory[k], true, fProngs[i].fExcludePDGInHistory[k])) { + pdgInHistory.emplace_back(d.pdgCode()); + break; + } + if (fProngs[i].fExcludePDGInHistory[k] && !fProngs[i].ComparePDG(d.pdgCode(), fProngs[i].fPDGInHistory[k], true, fProngs[i].fExcludePDGInHistory[k])) { + return false; + } + ith++; + if (ith > 10) { // need error message. Given pdg code was not found within 10 generations of the particles decay chain. + break; + } + } + } + } + if (pdgInHistory.size() != nIncludedPDG) // vector has as many entries as mothers (daughters) defined for prong + return false; + } return true; } -#endif +#endif // PWGDQ_CORE_MCSIGNAL_H_ diff --git a/PWGDQ/Core/MCSignalLibrary.cxx b/PWGDQ/Core/MCSignalLibrary.cxx index 698946fafb4..8a66393453c 100644 --- a/PWGDQ/Core/MCSignalLibrary.cxx +++ b/PWGDQ/Core/MCSignalLibrary.cxx @@ -285,6 +285,12 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "Electrons from pi0 decays", {prong}, {-1}); return signal; } + if (!nameStr.compare("ePrimaryFromPromptPi0")) { + MCProng prong(2, {11, 111}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502, 402}, {true, true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "All prompt charm hadrons (not from beauty)", {prong}, {-1}); + return signal; + } if (!nameStr.compare("eFromEta")) { MCProng prong(2, {11, 221}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); signal = new MCSignal(name, "Electrons from eta decays", {prong}, {-1}); @@ -346,42 +352,68 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) } if (!nameStr.compare("eFromHc")) { MCProng prong(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "Electrons from open charmed hadron decays", {prong}, {-1}); return signal; } + if (!nameStr.compare("eFromAnyHc")) { + MCProng prong(1, {11}, {true}, {false}, {0}, {0}, {false}, false, {402}, {false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary, false); + signal = new MCSignal(name, "Electrons from any open charm hadron decays", {prong}, {-1}); + return signal; + } if (!nameStr.compare("eFromHb")) { MCProng prong(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "Electrons from open beauty hadron decays", {prong}, {-1}); return signal; } + if (!nameStr.compare("eFromAnyHb")) { + MCProng prong(1, {11}, {true}, {false}, {0}, {0}, {false}, false, {502}, {false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary, false); + signal = new MCSignal(name, "Electrons from any open beauty hadron decays", {prong}, {-1}); + return signal; + } + if (!nameStr.compare("eFromHbc")) { + MCProng prong(2, {11, 902}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "Electrons from open charm or beauty hadron decays", {prong}, {-1}); + return signal; + } if (!nameStr.compare("eFromMc")) { MCProng prong(2, {11, 401}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "Electrons from open charmed meson decays", {prong}, {-1}); return signal; } if (!nameStr.compare("eFromMb")) { MCProng prong(2, {11, 501}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "Electrons from open beauty meson decays", {prong}, {-1}); return signal; } if (!nameStr.compare("eFromBc")) { MCProng prong(2, {11, 4001}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "Electrons from open charmed baryon decays", {prong}, {-1}); return signal; } if (!nameStr.compare("eFromBb")) { MCProng prong(2, {11, 5001}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "Electrons from open beauty baryon decays", {prong}, {-1}); return signal; } if (!nameStr.compare("eFromPromptHc")) { - MCProng prong(3, {11, 402, 502}, {true, true, true}, {false, false, true}, {0, 0, 0}, {0, 0, 0}, {false, false, false}); + MCProng prong(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "Electrons from open charmed hadron decays", {prong}, {-1}); return signal; } - if (!nameStr.compare("eFromNonPromptHc")) { - MCProng prong(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}); - signal = new MCSignal(name, "Electrons from open charmed hadron decays from b hadron decays", {prong}, {-1}); + if (!nameStr.compare("eFromHbtoHc")) { + MCProng prong(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "Electrons from open charmed hadron decays with b hadron in decay history", {prong}, {-1}); return signal; } @@ -467,6 +499,13 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "Open charm and beauty to electrons", {prong}, {-1}); return signal; } + if (!nameStr.compare("AnyHFdecayToE")) { + MCProng prong(1, {902}, {true}, {false}, {0}, {0}, {false}, true, {11}, {false}); + // prong.SetSourceBit(0, MCProng::kPhysicalPrimary, false); // set source to be ALICE primary particles + prong.SetSignalInTime(true); // set direction to check for daughters (true, in time) or for mothers (false, back in time) + signal = new MCSignal(name, "Open charm and beauty to electrons", {prong}, {-1}); + return signal; + } // if (!nameStr.compare("LFQtoPC")) { // MCProng prong(3, {900, 22, 11}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}); // prong.SetSignalInTime(true); // set direction to check for daughters (true, in time) or for mothers (false, back in time) @@ -478,39 +517,64 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) // LMEE pair signals for LF, same mother if (!nameStr.compare("eeFromPi0")) { MCProng prong(2, {11, 111}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from pi0 decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } + if (!nameStr.compare("eePrimaryFromPromptPi0")) { + MCProng prong(2, {11, 111}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502, 402}, {true, true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from prompt pi0 decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } if (!nameStr.compare("eeFromEta")) { MCProng prong(2, {11, 221}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from eta decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } if (!nameStr.compare("eeFromEtaprime")) { MCProng prong(2, {11, 331}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from eta' decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } if (!nameStr.compare("eeFromRho")) { MCProng prong(2, {11, 113}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from rho decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } if (!nameStr.compare("eeFromOmega")) { MCProng prong(2, {11, 223}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from omega decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } if (!nameStr.compare("eeFromPhi")) { MCProng prong(2, {11, 333}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from phi decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } if (!nameStr.compare("eeFromJpsi")) { MCProng prong(2, {11, 443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from j/psi decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } + if (!nameStr.compare("eePrimaryFromPromptJPsi")) { + MCProng prong(2, {11, 443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {503}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from prompt j/psi decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } + if (!nameStr.compare("eePrimaryFromNonPromptJPsi")) { + MCProng prong(2, {11, 443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {503}, {false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from non-prompt j/psi decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } if (!nameStr.compare("mumuFromJpsi")) { MCProng prong(2, {13, 443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); signal = new MCSignal(name, "mumu pairs from j/psi decays", {prong, prong}, {1, 1}); // signal at pair level @@ -518,6 +582,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) } if (!nameStr.compare("eeFromPsi2S")) { MCProng prong(2, {11, 100443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from psi2s decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } @@ -528,11 +593,13 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) } if (!nameStr.compare("eeFromLMeeLFQ")) { MCProng prong(2, {11, 900}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from light flavor meson + quarkonia decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } if (!nameStr.compare("eeFromLMeeLF")) { MCProng prong(2, {11, 901}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from light flavor meson decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } @@ -553,6 +620,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) // c->e and c->e (no check) if (!nameStr.compare("eeFromCCNoCheck")) { MCProng prong(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from c->e and c->e without check", {prong, prong}, {-1, -1}); // signal at pair level return signal; } @@ -560,20 +628,51 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) // ee from HF in general if (!nameStr.compare("eeFromHF")) { MCProng prong(2, {11, 902}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from b,c->e and b,c->e without check", {prong, prong}, {-1, -1}); // signal at pair level return signal; } - // c->e and c->e (prompt) - if (!nameStr.compare("eeFromCC")) { - MCProng prong(3, {11, 402, 502}, {true, true, true}, {false, false, true}, {0, 0, 0}, {0, 0, 0}, {false, false, false}); - signal = new MCSignal(name, "ee pairs from c->e and c->e", {prong, prong}, {-1, -1}); // signal at pair level + // Any c in history but no b -> c -> e + if (!nameStr.compare("eeFromPromptCandPromptC")) { + MCProng prong(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {true}); // check if mother pdg code is in history + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs with any charm but no beauty in decay chain", {prong, prong}, {-1, -1}); // signal at pair level + return signal; + } + + // Any b to any c in history b -> c -> e + if (!nameStr.compare("eeFromBtoCandBtoC")) { + MCProng prong(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {false}); // check if mother pdg code is in history + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs with any beauty to charm in decay chain", {prong, prong}, {-1, -1}); // signal at pair level + return signal; + } + + // Any b->e and Any b->c->e + if (!nameStr.compare("eeFromBandBtoC")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); // check if mother pdg code is in history + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng prongBtoC(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {false}); // check if mother pdg code is in history + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from b->e and b->c->e", {prongB, prongBtoC}, {-1, -1}); // signal at pair level + return signal; + } + + // Any b->e and Any b->c->e + if (!nameStr.compare("eeFromBandBtoCBis")) { + MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); // check if mother pdg code is in history + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); + MCProng prongBtoC(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {502}, {false}); // check if mother pdg code is in history + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "ee pairs from b->e and b->c->e", {prongBtoC, prongB}, {-1, -1}); // signal at pair level return signal; } // b->e and b->e if (!nameStr.compare("eeFromBB")) { MCProng prong(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from b->e and b->e", {prong, prong}, {-1, -1}); // signal at pair level return signal; } @@ -581,7 +680,9 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) // b->e and c->e no check if (!nameStr.compare("eeFromBandFromC")) { MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); MCProng prongC(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongC.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from b->e and c->e", {prongB, prongC}, {-1, -1}); // signal at pair level return signal; } @@ -589,30 +690,19 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) // b->e and c->e no check if (!nameStr.compare("eeFromBandFromCBis")) { MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); MCProng prongC(2, {11, 402}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongC.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from b->e and c->e", {prongC, prongB}, {-1, -1}); // signal at pair level return signal; } - // b->c->e and b->c->e - if (!nameStr.compare("eeFromBtoC")) { - MCProng prong(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}); - signal = new MCSignal(name, "ee pairs from b->c->e and b->c->e", {prong, prong}, {-1, -1}); // signal at pair level - return signal; - } - - // b->e and b->c->e - if (!nameStr.compare("eeFromBandBtoC")) { - MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); - MCProng prongBtoC(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}); - signal = new MCSignal(name, "ee pairs from b->e and b->c->e", {prongB, prongBtoC}, {-1, -1}); // signal at pair level - return signal; - } - // b->e and b->c->e (single b) if (!nameStr.compare("eeFromSingleBandBtoC")) { MCProng prongB(2, {11, 502}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prongB.SetSourceBit(0, MCProng::kPhysicalPrimary); MCProng prongBtoC(3, {11, 402, 502}, {true, true, true}, {false, false, false}, {0, 0, 0}, {0, 0, 0}, {false, false, false}); + prongBtoC.SetSourceBit(0, MCProng::kPhysicalPrimary); signal = new MCSignal(name, "ee pairs from b->e and b->c->e (single b)", {prongB, prongBtoC}, {1, 2}); // signal at pair level return signal; } diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index 87ac93d739b..77156e1aa1d 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -8,11 +8,13 @@ // 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. - +#include #include "PWGDQ/Core/VarManager.h" #include "Tools/KFparticle/KFUtilities.h" -#include +using std::cout; +using std::endl; +using namespace o2::constants::physics; ClassImp(VarManager); @@ -20,10 +22,13 @@ TString VarManager::fgVariableNames[VarManager::kNVars] = {""}; TString VarManager::fgVariableUnits[VarManager::kNVars] = {""}; bool VarManager::fgUsedVars[VarManager::kNVars] = {false}; bool VarManager::fgUsedKF = false; +float VarManager::fgMagField = 0.5; float VarManager::fgValues[VarManager::kNVars] = {0.0f}; std::map VarManager::fgRunMap; TString VarManager::fgRunStr = ""; std::vector VarManager::fgRunList = {0}; +float VarManager::fgCenterOfMassEnergy = 13600; // GeV +float VarManager::fgMassofCollidingParticle = 9.382720; // GeV o2::vertexing::DCAFitterN<2> VarManager::fgFitterTwoProngBarrel; o2::vertexing::DCAFitterN<3> VarManager::fgFitterThreeProngBarrel; o2::vertexing::FwdDCAFitterN<2> VarManager::fgFitterTwoProngFwd; @@ -155,7 +160,32 @@ void VarManager::SetRunlist(TString period) SetRunNumbers(LHC22t); } } +//__________________________________________________________________ +void VarManager::SetDummyRunlist(int InitRunnumber) +{ + // + // runlist for the different periods + fgRunList.clear(); + fgRunList.push_back(InitRunnumber); + fgRunList.push_back(InitRunnumber + 100); +} +//__________________________________________________________________ +int VarManager::GetDummyFirst() +{ + // + // Get the fist index of the vector of run numbers + // + return fgRunList[0]; +} +//__________________________________________________________________ +int VarManager::GetDummyLast() +{ + // + // Get the last index of the vector of run numbers + // + return fgRunList[fgRunList.size() - 1]; +} //_________________________________________________________________ float VarManager::GetRunIndex(double Runnumber) { @@ -167,6 +197,22 @@ float VarManager::GetRunIndex(double Runnumber) float index = std::distance(fgRunList.begin(), runIndex); return index; } +//__________________________________________________________________ +void VarManager::SetCollisionSystem(TString system, float energy) +{ + // + // Set the collision system and the center of mass energy + // + fgCenterOfMassEnergy = energy; + + if (system.Contains("PbPb")) { + fgMassofCollidingParticle = MassProton * 208; + } + if (system.Contains("pp")) { + fgMassofCollidingParticle = MassProton; + } + // TO Do: add more systems +} //__________________________________________________________________ void VarManager::FillEventDerived(float* values) @@ -304,6 +350,8 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kCharge] = ""; fgVariableNames[kPin] = "p_{IN}"; fgVariableUnits[kPin] = "GeV/c"; + fgVariableNames[kSignedPin] = "p_{IN} x charge"; + fgVariableUnits[kSignedPin] = "GeV/c"; fgVariableNames[kTOFExpMom] = "TOF expected momentum"; fgVariableUnits[kTOFExpMom] = "GeV/c"; fgVariableNames[kTrackTime] = "Track time wrt collision().bc()"; @@ -571,10 +619,18 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kDeltaPhiSym] = "rad."; fgVariableNames[kCosThetaHE] = "cos#it{#theta}"; fgVariableUnits[kCosThetaHE] = ""; + fgVariableNames[kPhiHE] = "#varphi_{HE}"; + fgVariableUnits[kPhiHE] = "rad."; + fgVariableNames[kCosThetaCS] = "cos#it{#theta}_{CS}"; + fgVariableUnits[kCosThetaCS] = ""; + fgVariableNames[kPhiCS] = "#varphi_{CS}"; + fgVariableUnits[kPhiCS] = "rad."; fgVariableNames[kPsiPair] = "#Psi_{pair}"; fgVariableUnits[kPsiPair] = "rad."; fgVariableNames[kDeltaPhiPair] = "#Delta#phi"; fgVariableUnits[kDeltaPhiPair] = "rad."; + fgVariableNames[kOpeningAngle] = "Opening angle"; + fgVariableUnits[kOpeningAngle] = "rad."; fgVariableNames[kQuadDCAabsXY] = "DCA_{xy}^{quad}"; fgVariableUnits[kQuadDCAabsXY] = "cm"; fgVariableNames[kQuadDCAsigXY] = "DCA_{xy}^{quad}"; @@ -595,4 +651,12 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kTrackDCAresZ] = "cm"; fgVariableNames[kBitMapIndex] = " "; fgVariableUnits[kBitMapIndex] = ""; + fgVariableNames[kMassCharmHadron] = "mass (charm hadron)"; + fgVariableUnits[kMassCharmHadron] = "GeV/c2"; + fgVariableNames[kPtCharmHadron] = "p_{T} (charm hadron)"; + fgVariableUnits[kPtCharmHadron] = "GeV/c"; + fgVariableNames[kRapCharmHadron] = "y (charm hadron)"; + fgVariableUnits[kRapCharmHadron] = " "; + fgVariableNames[kPhiCharmHadron] = "#varphi (charm hadron)"; + fgVariableUnits[kPhiCharmHadron] = "rad."; } diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 1b7a3922a3f..809404fcca2 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -53,12 +53,9 @@ #include "KFParticleBase.h" #include "KFVertex.h" -using std::cout; -using std::endl; using SMatrix55 = ROOT::Math::SMatrix>; using SMatrix5 = ROOT::Math::SVector; using Vec3D = ROOT::Math::SVector; -using namespace o2::constants::physics; //_________________________________________________________________________ class VarManager : public TObject @@ -103,7 +100,8 @@ class VarManager : public TObject AmbiMuon = BIT(20), DalitzBits = BIT(21), TrackTPCPID = BIT(22), - TrackMFT = BIT(23) + TrackMFT = BIT(23), + ReducedTrackCollInfo = BIT(24) // TODO: remove it once new reduced data tables are produced for dielectron with ReducedTracksBarrelInfo }; enum PairCandidateType { @@ -209,8 +207,18 @@ class VarManager : public TObject kUsedKF, kKFMass, + kPt1, + kEta1, + kPhi1, + kCharge1, + kPt2, + kEta2, + kPhi2, + kCharge2, + // Barrel track variables kPin, + kSignedPin, kTOFExpMom, kTrackTime, kTrackTimeRes, @@ -226,6 +234,9 @@ class VarManager : public TObject kIsSPDany, kIsSPDfirst, kIsSPDboth, + kIsITSibAny, + kIsITSibFirst, + kIsITSibAll, kITSncls, kITSchi2, kITSlayerHit, @@ -344,8 +355,12 @@ class VarManager : public TObject kVertexingProcCode, kVertexingChi2PCA, kCosThetaHE, + kCosThetaCS, + kPhiHE, + kPhiCS, kPsiPair, kDeltaPhiPair, + kOpeningAngle, kQuadDCAabsXY, kQuadDCAsigXY, kQuadDCAabsZ, @@ -391,6 +406,12 @@ class VarManager : public TObject kDeltaPhiSym, kNCorrelationVariables, + // DQ-HF correlation variables + kMassCharmHadron, + kPtCharmHadron, + kRapCharmHadron, + kPhiCharmHadron, + // Index used to scan bit maps kBitMapIndex, @@ -409,6 +430,12 @@ class VarManager : public TObject kNCalibObjects }; + enum DileptonCharmHadronTypes { + kJPsi = 0, + kD0ToPiK, + kD0barToKPi + }; + static TString fgVariableNames[kNVars]; // variable names static TString fgVariableUnits[kNVars]; // variable units static void SetDefaultVarNames(); @@ -447,6 +474,17 @@ class VarManager : public TObject static void SetRunNumbers(std::vector runs); static float GetRunIndex(double); static void SetRunlist(TString period); + static void SetDummyRunlist(int InitRunnumber); + static int GetDummyFirst(); + static int GetDummyLast(); + static int GetDummyNRuns() + { + if (fgRunMap.size() == 0) { + return 101; + } else { + return fgRunMap.size(); + } + } static int GetNRuns() { return fgRunMap.size(); @@ -456,6 +494,14 @@ class VarManager : public TObject return fgRunStr; } + // Setup the collision system + static void SetCollisionSystem(TString system, float energy); + + static void SetMagneticField(float magField) + { + fgMagField = magField; + } + // Setup the 2 prong KFParticle static void SetupTwoProngKFParticle(float magField) { @@ -523,13 +569,17 @@ class VarManager : public TObject template static void FillPairMC(T1 const& t1, T2 const& t2, float* values = nullptr, PairCandidateType pairType = kDecayToEE); template - static void FillPairVertexing(C const& collision, T const& t1, T const& t2, float* values = nullptr); + static void FillPairVertexing(C const& collision, T const& t1, T const& t2, bool propToSV = false, float* values = nullptr); template static void FillDileptonTrackVertexing(C const& collision, T1 const& lepton1, T1 const& lepton2, T1 const& track, float* values); template static void FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* values = nullptr, float hadronMass = 0.0f); template static void FillHadron(T const& hadron, float* values = nullptr, float hadronMass = 0.0f); + template + static void FillSingleDileptonCharmHadron(Cand const& candidate, H hfHelper, float* values = nullptr); + template + static void FillDileptonCharmHadron(DQ const& dilepton, HF const& charmHadron, H hfHelper, float* values = nullptr); template static void FillQVectorFromGFW(C const& collision, A const& compA2, A const& compB2, A const& compC2, A const& compA3, A const& compB3, A const& compC3, float normA = 1.0, float normB = 1.0, float normC = 1.0, float* values = nullptr); template @@ -574,9 +624,12 @@ class VarManager : public TObject static bool fgUsedKF; static void SetVariableDependencies(); // toggle those variables on which other used variables might depend - static std::map fgRunMap; // map of runs to be used in histogram axes - static TString fgRunStr; // semi-colon separated list of runs, to be used for histogram axis labels - static std::vector fgRunList; // vector of runs, to be used for histogram axis + static float fgMagField; + static std::map fgRunMap; // map of runs to be used in histogram axes + static TString fgRunStr; // semi-colon separated list of runs, to be used for histogram axis labels + static std::vector fgRunList; // vector of runs, to be used for histogram axis + static float fgCenterOfMassEnergy; // collision energy + static float fgMassofCollidingParticle; // mass of the colliding particle static void FillEventDerived(float* values = nullptr); static void FillTrackDerived(float* values = nullptr); @@ -585,6 +638,8 @@ class VarManager : public TObject template static KFPTrack createKFPTrackFromTrack(const T& track); template + static KFPTrack createKFPFwdTrackFromFwdTrack(const T& muon); + template static KFPVertex createKFPVertexFromCollision(const T& collision); static float calculateCosPA(KFParticle kfp, KFParticle PV); @@ -646,6 +701,34 @@ KFPTrack VarManager::createKFPTrackFromTrack(const T& track) return kfpTrack; } +template +KFPTrack VarManager::createKFPFwdTrackFromFwdTrack(const T& muon) +{ + double chi2 = muon.chi2(); + SMatrix5 tpars(muon.x(), muon.y(), muon.phi(), muon.tgl(), muon.signed1Pt()); + std::vector v1{muon.cXX(), muon.cXY(), muon.cYY(), muon.cPhiX(), muon.cPhiY(), + muon.cPhiPhi(), muon.cTglX(), muon.cTglY(), muon.cTglPhi(), muon.cTglTgl(), + muon.c1PtX(), muon.c1PtY(), muon.c1PtPhi(), muon.c1PtTgl(), muon.c1Pt21Pt2()}; + SMatrix55 tcovs(v1.begin(), v1.end()); + o2::track::TrackParCovFwd trackparCov{muon.z(), tpars, tcovs, chi2}; + + std::array trk_cov; + trackparCov.getCovXYZPxPyPzGlo(trk_cov); + double trkpar_KF[6] = {trackparCov.getX(), trackparCov.getY(), trackparCov.getZ(), + trackparCov.getPx(), trackparCov.getPy(), trackparCov.getPz()}; + float trkcov_KF[21]; + for (int i = 0; i < 21; i++) { + trkcov_KF[i] = trk_cov[i]; + } + KFPTrack kfpTrack; + kfpTrack.SetParameters(trkpar_KF); + kfpTrack.SetCovarianceMatrix(trkcov_KF); + kfpTrack.SetCharge(muon.sign()); + kfpTrack.SetNDF(muon.nClusters() - 5); + kfpTrack.SetChi2(chi2); + return kfpTrack; +} + template KFPVertex VarManager::createKFPVertexFromCollision(const T& collision) { @@ -859,6 +942,9 @@ void VarManager::FillTrack(T const& track, float* values) // Quantities based on the basic table (contains just kine information and filter bits) if constexpr ((fillMap & Track) > 0 || (fillMap & Muon) > 0 || (fillMap & ReducedTrack) > 0 || (fillMap & ReducedMuon) > 0) { values[kPt] = track.pt(); + if (fgUsedVars[kP]) { + values[kP] = track.p(); + } if (fgUsedVars[kPx]) { values[kPx] = track.px(); } @@ -897,6 +983,7 @@ void VarManager::FillTrack(T const& track, float* values) // Quantities based on the barrel tables if constexpr ((fillMap & TrackExtra) > 0 || (fillMap & ReducedTrackBarrel) > 0) { values[kPin] = track.tpcInnerParam(); + values[kSignedPin] = track.tpcInnerParam() * track.sign(); if (fgUsedVars[kIsITSrefit]) { values[kIsITSrefit] = (track.flags() & o2::aod::track::ITSrefit) > 0; // NOTE: This is just for Run-2 } @@ -927,6 +1014,17 @@ void VarManager::FillTrack(T const& track, float* values) if (fgUsedVars[kITSClusterMap]) { values[kITSClusterMap] = track.itsClusterMap(); } + + if (fgUsedVars[kIsITSibFirst]) { + values[kIsITSibFirst] = (track.itsClusterMap() & uint8_t(1)) > 0; + } + if (fgUsedVars[kIsITSibAny]) { + values[kIsITSibAny] = (track.itsClusterMap() & (1 << uint8_t(0))) > 0 || (track.itsClusterMap() & (1 << uint8_t(1))) > 0 || (track.itsClusterMap() & (1 << uint8_t(2))) > 0; + } + if (fgUsedVars[kIsITSibAll]) { + values[kIsITSibAll] = (track.itsClusterMap() & (1 << uint8_t(0))) > 0 && (track.itsClusterMap() & (1 << uint8_t(1))) > 0 && (track.itsClusterMap() & (1 << uint8_t(2))) > 0; + } + values[kTrackTime] = track.trackTime(); values[kTrackTimeRes] = track.trackTimeRes(); values[kTrackTimeResRelative] = track.trackTimeRes() / track.trackTime(); @@ -1216,20 +1314,20 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) values = fgValues; } - float m1 = MassElectron; - float m2 = MassElectron; + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; if constexpr (pairType == kDecayToMuMu) { - m1 = MassMuon; - m2 = MassMuon; + m1 = o2::constants::physics::MassMuon; + m2 = o2::constants::physics::MassMuon; } if constexpr (pairType == kDecayToPiPi) { - m1 = MassPionCharged; - m2 = MassPionCharged; + m1 = o2::constants::physics::MassPionCharged; + m2 = o2::constants::physics::MassPionCharged; } if constexpr (pairType == kElectronMuon) { - m2 = MassMuon; + m2 = o2::constants::physics::MassMuon; } ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), m1); @@ -1245,19 +1343,62 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) values[kDeltaPtotTracks] = Ptot1 - Ptot2; if (fgUsedVars[kPsiPair]) { - values[kDeltaPhiPair] = (t1.sign() > 0) ? (v1.Phi() - v2.Phi()) : (v2.Phi() - v1.Phi()); + values[kDeltaPhiPair] = (t1.sign() * fgMagField > 0.) ? (v1.Phi() - v2.Phi()) : (v2.Phi() - v1.Phi()); double xipair = TMath::ACos((v1.Px() * v2.Px() + v1.Py() * v2.Py() + v1.Pz() * v2.Pz()) / v1.P() / v2.P()); - values[kPsiPair] = (t1.sign() > 0) ? TMath::ASin((v1.Theta() - v2.Theta()) / xipair) : TMath::ASin((v2.Theta() - v1.Theta()) / xipair); + values[kPsiPair] = (t1.sign() * fgMagField > 0.) ? TMath::ASin((v1.Theta() - v2.Theta()) / xipair) : TMath::ASin((v2.Theta() - v1.Theta()) / xipair); + } + + if (fgUsedVars[kOpeningAngle]) { + double scalar = v1.Px() * v2.Px() + v1.Py() * v2.Py() + v1.Pz() * v2.Pz(); + double Ptot12 = Ptot1 * Ptot2; + if (Ptot12 <= 0) { + values[kOpeningAngle] = 0.; + } else { + double arg = scalar / Ptot12; + if (arg > 1.) + arg = 1.; + if (arg < -1) + arg = -1; + values[kOpeningAngle] = TMath::ACos(arg); + } } - // CosTheta Helicity calculation + // TO DO: get the correct values from CCDB + double BeamMomentum = TMath::Sqrt(fgCenterOfMassEnergy * fgCenterOfMassEnergy / 4 - fgMassofCollidingParticle * fgMassofCollidingParticle); // GeV + ROOT::Math::PxPyPzEVector Beam1(0., 0., -BeamMomentum, fgCenterOfMassEnergy / 2); + ROOT::Math::PxPyPzEVector Beam2(0., 0., BeamMomentum, fgCenterOfMassEnergy / 2); + + // Boost to center of mass frame ROOT::Math::Boost boostv12{v12.BoostToCM()}; ROOT::Math::XYZVectorF v1_CM{(boostv12(v1).Vect()).Unit()}; ROOT::Math::XYZVectorF v2_CM{(boostv12(v2).Vect()).Unit()}; - ROOT::Math::XYZVectorF zaxis{(v12.Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam1_CM{(boostv12(Beam1).Vect()).Unit()}; + ROOT::Math::XYZVectorF Beam2_CM{(boostv12(Beam2).Vect()).Unit()}; + + // Helicity frame + ROOT::Math::XYZVectorF zaxis_HE{(v12.Vect()).Unit()}; + ROOT::Math::XYZVectorF yaxis_HE{(Beam1_CM.Cross(Beam2_CM)).Unit()}; + ROOT::Math::XYZVectorF xaxis_HE{(yaxis_HE.Cross(zaxis_HE)).Unit()}; + + // Collins-Soper frame + ROOT::Math::XYZVectorF zaxis_CS{((Beam1_CM.Unit() - Beam2_CM.Unit()).Unit())}; + ROOT::Math::XYZVectorF yaxis_CS{(Beam1_CM.Cross(Beam2_CM)).Unit()}; + ROOT::Math::XYZVectorF xaxis_CS{(yaxis_CS.Cross(zaxis_CS)).Unit()}; if (fgUsedVars[kCosThetaHE]) { - values[kCosThetaHE] = (t1.sign() > 0 ? zaxis.Dot(v1_CM) : zaxis.Dot(v2_CM)); + values[kCosThetaHE] = (t1.sign() > 0 ? zaxis_HE.Dot(v1_CM) : zaxis_HE.Dot(v2_CM)); + } + + if (fgUsedVars[kPhiHE]) { + values[kPhiHE] = (t1.sign() > 0 ? TMath::ATan2(yaxis_HE.Dot(v1_CM), xaxis_HE.Dot(v1_CM)) : TMath::ATan2(yaxis_HE.Dot(v2_CM), xaxis_HE.Dot(v2_CM))); + } + + if (fgUsedVars[kCosThetaCS]) { + values[kCosThetaCS] = (t1.sign() > 0 ? zaxis_CS.Dot(v1_CM) : zaxis_CS.Dot(v2_CM)); + } + + if (fgUsedVars[kPhiCS]) { + values[kPhiCS] = (t1.sign() > 0 ? TMath::ATan2(yaxis_CS.Dot(v1_CM), xaxis_CS.Dot(v1_CM)) : TMath::ATan2(yaxis_CS.Dot(v2_CM), xaxis_CS.Dot(v2_CM))); } if constexpr ((pairType == kDecayToEE) && ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0)) { @@ -1394,20 +1535,20 @@ void VarManager::FillPairME(T1 const& t1, T2 const& t2, float* values) values = fgValues; } - float m1 = MassElectron; - float m2 = MassElectron; + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; if constexpr (pairType == kDecayToMuMu) { - m1 = MassMuon; - m2 = MassMuon; + m1 = o2::constants::physics::MassMuon; + m2 = o2::constants::physics::MassMuon; } if constexpr (pairType == kDecayToPiPi) { - m1 = MassPionCharged; - m2 = MassPionCharged; + m1 = o2::constants::physics::MassPionCharged; + m2 = o2::constants::physics::MassPionCharged; } if constexpr (pairType == kElectronMuon) { - m2 = MassMuon; + m2 = o2::constants::physics::MassMuon; } ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), m1); @@ -1427,20 +1568,20 @@ void VarManager::FillPairMC(T1 const& t1, T2 const& t2, float* values, PairCandi values = fgValues; } - float m1 = MassElectron; - float m2 = MassElectron; + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; if (pairType == kDecayToMuMu) { - m1 = MassMuon; - m2 = MassMuon; + m1 = o2::constants::physics::MassMuon; + m2 = o2::constants::physics::MassMuon; } if (pairType == kDecayToPiPi) { - m1 = MassPionCharged; - m2 = MassPionCharged; + m1 = o2::constants::physics::MassPionCharged; + m2 = o2::constants::physics::MassPionCharged; } if (pairType == kElectronMuon) { - m2 = MassMuon; + m2 = o2::constants::physics::MassMuon; } // TODO : implement resolution smearing. @@ -1455,7 +1596,7 @@ void VarManager::FillPairMC(T1 const& t1, T2 const& t2, float* values, PairCandi } template -void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, float* values) +void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, bool propToSV, float* values) { // check at compile time that the event and cov matrix have the cov matrix constexpr bool eventHasVtxCov = ((collFillMap & Collision) > 0 || (collFillMap & ReducedEventVtxCov) > 0); @@ -1465,6 +1606,15 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, if (!values) { values = fgValues; } + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; + if constexpr (pairType == kDecayToMuMu && muonHasCov) { + m1 = o2::constants::physics::MassMuon; + m2 = o2::constants::physics::MassMuon; + } + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), m1); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), m2); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; values[kUsedKF] = fgUsedKF; if (!fgUsedKF) { @@ -1525,17 +1675,11 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, return; } - float m1 = MassElectron; - float m2 = MassElectron; Vec3D secondaryVertex; - float bz = 0; - std::array pvec0; - std::array pvec1; if constexpr (eventHasVtxCov) { + std::array covMatrixPCA; - o2::dataformats::DCA impactParameter0; - o2::dataformats::DCA impactParameter1; // get track impact parameters // This modifies track momenta! o2::math_utils::Point3D vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); @@ -1546,40 +1690,35 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, if constexpr (pairType == kDecayToEE && trackHasCov) { secondaryVertex = fgFitterTwoProngBarrel.getPCACandidate(); - bz = fgFitterTwoProngBarrel.getBz(); covMatrixPCA = fgFitterTwoProngBarrel.calcPCACovMatrixFlat(); auto chi2PCA = fgFitterTwoProngBarrel.getChi2AtPCACandidate(); auto trackParVar0 = fgFitterTwoProngBarrel.getTrack(0); auto trackParVar1 = fgFitterTwoProngBarrel.getTrack(1); values[kVertexingChi2PCA] = chi2PCA; - trackParVar0.getPxPyPzGlo(pvec0); - trackParVar1.getPxPyPzGlo(pvec1); - trackParVar0.propagateToDCA(primaryVertex, bz, &impactParameter0); - trackParVar1.propagateToDCA(primaryVertex, bz, &impactParameter1); + v1 = {trackParVar0.getPt(), trackParVar0.getEta(), trackParVar0.getPhi(), m1}; + v2 = {trackParVar1.getPt(), trackParVar1.getEta(), trackParVar1.getPhi(), m2}; + v12 = v1 + v2; + } else if constexpr (pairType == kDecayToMuMu && muonHasCov) { // Get pca candidate from forward DCA fitter - m1 = MassMuon; - m2 = MassMuon; - secondaryVertex = fgFitterTwoProngFwd.getPCACandidate(); - bz = fgFitterTwoProngFwd.getBz(); covMatrixPCA = fgFitterTwoProngFwd.calcPCACovMatrixFlat(); auto chi2PCA = fgFitterTwoProngFwd.getChi2AtPCACandidate(); auto trackParVar0 = fgFitterTwoProngFwd.getTrack(0); auto trackParVar1 = fgFitterTwoProngFwd.getTrack(1); values[kVertexingChi2PCA] = chi2PCA; - pvec0[0] = trackParVar0.getPx(); - pvec0[1] = trackParVar0.getPy(); - pvec0[2] = trackParVar0.getPz(); - pvec1[0] = trackParVar1.getPx(); - pvec1[1] = trackParVar1.getPy(); - pvec1[2] = trackParVar1.getPz(); - trackParVar0.propagateToZlinear(primaryVertex.getZ()); - trackParVar1.propagateToZlinear(primaryVertex.getZ()); + v1 = {trackParVar0.getPt(), trackParVar0.getEta(), trackParVar0.getPhi(), m1}; + v2 = {trackParVar1.getPt(), trackParVar1.getEta(), trackParVar1.getPhi(), m2}; + v12 = v1 + v2; + + values[kPt1] = trackParVar0.getPt(); + values[kEta1] = trackParVar0.getEta(); + values[kPhi1] = trackParVar0.getPhi(); + + values[kPt2] = trackParVar1.getPt(); + values[kEta2] = trackParVar1.getEta(); + values[kPhi2] = trackParVar1.getPhi(); } - // get uncertainty of the decay length - // double phi, theta; - // getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, phi, theta); double phi = std::atan2(secondaryVertex[1] - collision.posY(), secondaryVertex[0] - collision.posX()); double theta = std::atan2(secondaryVertex[2] - collision.posZ(), std::sqrt((secondaryVertex[0] - collision.posX()) * (secondaryVertex[0] - collision.posX()) + @@ -1597,47 +1736,59 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, values[kVertexingLz] = std::sqrt(values[kVertexingLz]); values[kVertexingLxyz] = std::sqrt(values[kVertexingLxyz]); - ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), m1); - ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), m2); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - values[kVertexingTauz] = (collision.posZ() - secondaryVertex[2]) * v12.M() / (TMath::Abs(v12.Pz()) * o2::constants::physics::LightSpeedCm2NS); values[kVertexingTauxy] = values[kVertexingLxy] * v12.M() / (v12.P() * o2::constants::physics::LightSpeedCm2NS); values[kVertexingTauzErr] = values[kVertexingLzErr] * v12.M() / (TMath::Abs(v12.Pz()) * o2::constants::physics::LightSpeedCm2NS); values[kVertexingTauxyErr] = values[kVertexingLxyErr] * v12.M() / (v12.P() * o2::constants::physics::LightSpeedCm2NS); + + values[kCosPointingAngle] = ((collision.posX() - secondaryVertex[0]) * v12.Px() + + (collision.posY() - secondaryVertex[1]) * v12.Py() + + (collision.posZ() - secondaryVertex[2]) * v12.Pz()) / + (v12.P() * values[VarManager::kVertexingLxyz]); } } else { KFParticle trk0KF; KFParticle trk1KF; - KFParticle KFGeoTwoProngBarrel; + KFParticle KFGeoTwoProng; if constexpr ((pairType == kDecayToEE) && trackHasCov) { KFPTrack kfpTrack0 = createKFPTrackFromTrack(t1); trk0KF = KFParticle(kfpTrack0, -11 * t1.sign()); KFPTrack kfpTrack1 = createKFPTrackFromTrack(t2); trk1KF = KFParticle(kfpTrack1, -11 * t2.sign()); - KFGeoTwoProngBarrel.SetConstructMethod(2); - KFGeoTwoProngBarrel.AddDaughter(trk0KF); - KFGeoTwoProngBarrel.AddDaughter(trk1KF); + KFGeoTwoProng.SetConstructMethod(2); + KFGeoTwoProng.AddDaughter(trk0KF); + KFGeoTwoProng.AddDaughter(trk1KF); - if (fgUsedVars[kKFMass]) - values[kKFMass] = KFGeoTwoProngBarrel.GetMass(); + } else if constexpr ((pairType == kDecayToMuMu) && muonHasCov) { + KFPTrack kfpTrack0 = createKFPFwdTrackFromFwdTrack(t1); + trk0KF = KFParticle(kfpTrack0, -13 * t1.sign()); + KFPTrack kfpTrack1 = createKFPFwdTrackFromFwdTrack(t2); + trk1KF = KFParticle(kfpTrack1, -13 * t2.sign()); + + KFGeoTwoProng.SetConstructMethod(2); + KFGeoTwoProng.AddDaughter(trk0KF); + KFGeoTwoProng.AddDaughter(trk1KF); + } + if (fgUsedVars[kKFMass]) { + values[kKFMass] = KFGeoTwoProng.GetMass(); } + if constexpr (eventHasVtxCov) { KFPVertex kfpVertex = createKFPVertexFromCollision(collision); values[kKFNContributorsPV] = kfpVertex.GetNContributors(); KFParticle KFPV(kfpVertex); if (fgUsedVars[kVertexingLxy] || fgUsedVars[kVertexingLz] || fgUsedVars[kVertexingLxyz] || fgUsedVars[kVertexingLxyErr] || fgUsedVars[kVertexingLzErr] || fgUsedVars[kVertexingTauxy] || fgUsedVars[kVertexingLxyOverErr] || fgUsedVars[kVertexingLzOverErr] || fgUsedVars[kVertexingLxyzOverErr]) { - double dxPair2PV = KFGeoTwoProngBarrel.GetX() - KFPV.GetX(); - double dyPair2PV = KFGeoTwoProngBarrel.GetY() - KFPV.GetY(); - double dzPair2PV = KFGeoTwoProngBarrel.GetZ() - KFPV.GetZ(); + double dxPair2PV = KFGeoTwoProng.GetX() - KFPV.GetX(); + double dyPair2PV = KFGeoTwoProng.GetY() - KFPV.GetY(); + double dzPair2PV = KFGeoTwoProng.GetZ() - KFPV.GetZ(); values[kVertexingLxy] = std::sqrt(dxPair2PV * dxPair2PV + dyPair2PV * dyPair2PV); values[kVertexingLz] = std::sqrt(dzPair2PV * dzPair2PV); values[kVertexingLxyz] = std::sqrt(dxPair2PV * dxPair2PV + dyPair2PV * dyPair2PV + dzPair2PV * dzPair2PV); - values[kVertexingLxyErr] = (KFPV.GetCovariance(0) + KFGeoTwoProngBarrel.GetCovariance(0)) * dxPair2PV * dxPair2PV + (KFPV.GetCovariance(2) + KFGeoTwoProngBarrel.GetCovariance(2)) * dyPair2PV * dyPair2PV + 2 * ((KFPV.GetCovariance(1) + KFGeoTwoProngBarrel.GetCovariance(1)) * dxPair2PV * dyPair2PV); - values[kVertexingLzErr] = (KFPV.GetCovariance(5) + KFGeoTwoProngBarrel.GetCovariance(5)) * dzPair2PV * dzPair2PV; - values[kVertexingLxyzErr] = (KFPV.GetCovariance(0) + KFGeoTwoProngBarrel.GetCovariance(0)) * dxPair2PV * dxPair2PV + (KFPV.GetCovariance(2) + KFGeoTwoProngBarrel.GetCovariance(2)) * dyPair2PV * dyPair2PV + (KFPV.GetCovariance(5) + KFGeoTwoProngBarrel.GetCovariance(5)) * dzPair2PV * dzPair2PV + 2 * ((KFPV.GetCovariance(1) + KFGeoTwoProngBarrel.GetCovariance(1)) * dxPair2PV * dyPair2PV + (KFPV.GetCovariance(3) + KFGeoTwoProngBarrel.GetCovariance(3)) * dxPair2PV * dzPair2PV + (KFPV.GetCovariance(4) + KFGeoTwoProngBarrel.GetCovariance(4)) * dyPair2PV * dzPair2PV); + values[kVertexingLxyErr] = (KFPV.GetCovariance(0) + KFGeoTwoProng.GetCovariance(0)) * dxPair2PV * dxPair2PV + (KFPV.GetCovariance(2) + KFGeoTwoProng.GetCovariance(2)) * dyPair2PV * dyPair2PV + 2 * ((KFPV.GetCovariance(1) + KFGeoTwoProng.GetCovariance(1)) * dxPair2PV * dyPair2PV); + values[kVertexingLzErr] = (KFPV.GetCovariance(5) + KFGeoTwoProng.GetCovariance(5)) * dzPair2PV * dzPair2PV; + values[kVertexingLxyzErr] = (KFPV.GetCovariance(0) + KFGeoTwoProng.GetCovariance(0)) * dxPair2PV * dxPair2PV + (KFPV.GetCovariance(2) + KFGeoTwoProng.GetCovariance(2)) * dyPair2PV * dyPair2PV + (KFPV.GetCovariance(5) + KFGeoTwoProng.GetCovariance(5)) * dzPair2PV * dzPair2PV + 2 * ((KFPV.GetCovariance(1) + KFGeoTwoProng.GetCovariance(1)) * dxPair2PV * dyPair2PV + (KFPV.GetCovariance(3) + KFGeoTwoProng.GetCovariance(3)) * dxPair2PV * dzPair2PV + (KFPV.GetCovariance(4) + KFGeoTwoProng.GetCovariance(4)) * dyPair2PV * dzPair2PV); if (fabs(values[kVertexingLxy]) < 1.e-8f) values[kVertexingLxy] = 1.e-8f; values[kVertexingLxyErr] = values[kVertexingLxyErr] < 0. ? 1.e8f : std::sqrt(values[kVertexingLxyErr]) / values[kVertexingLxy]; @@ -1647,10 +1798,16 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, if (fabs(values[kVertexingLxyz]) < 1.e-8f) values[kVertexingLxyz] = 1.e-8f; values[kVertexingLxyzErr] = values[kVertexingLxyzErr] < 0. ? 1.e8f : std::sqrt(values[kVertexingLxyzErr]) / values[kVertexingLxyz]; - values[kVertexingTauxy] = KFGeoTwoProngBarrel.GetPseudoProperDecayTime(KFPV, KFGeoTwoProngBarrel.GetMass()) / (o2::constants::physics::LightSpeedCm2NS); - values[kVertexingTauz] = dzPair2PV * KFGeoTwoProngBarrel.GetMass() / (TMath::Abs(KFGeoTwoProngBarrel.GetPz()) * o2::constants::physics::LightSpeedCm2NS); - values[kVertexingTauxyErr] = values[kVertexingLxyErr] * KFGeoTwoProngBarrel.GetMass() / (KFGeoTwoProngBarrel.GetPt() * o2::constants::physics::LightSpeedCm2NS); - values[kVertexingTauzErr] = values[kVertexingLzErr] * KFGeoTwoProngBarrel.GetMass() / (TMath::Abs(KFGeoTwoProngBarrel.GetPz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauxy] = KFGeoTwoProng.GetPseudoProperDecayTime(KFPV, KFGeoTwoProng.GetMass()) / (o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauz] = dzPair2PV * KFGeoTwoProng.GetMass() / (TMath::Abs(KFGeoTwoProng.GetPz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauxyErr] = values[kVertexingLxyErr] * KFGeoTwoProng.GetMass() / (KFGeoTwoProng.GetPt() * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauzErr] = values[kVertexingLzErr] * KFGeoTwoProng.GetMass() / (TMath::Abs(KFGeoTwoProng.GetPz()) * o2::constants::physics::LightSpeedCm2NS); + if (fgUsedVars[kCosPointingAngle]) { + values[kCosPointingAngle] = (std::sqrt(dxPair2PV * dxPair2PV) * v12.Px() + + std::sqrt(dyPair2PV * dyPair2PV) * v12.Py() + + std::sqrt(dzPair2PV * dzPair2PV) * v12.Pz()) / + (v12.P() * values[VarManager::kVertexingLxyz]); + } } if (fgUsedVars[kVertexingLxyOverErr] || fgUsedVars[kVertexingLzOverErr] || fgUsedVars[kVertexingLxyzOverErr]) { values[kVertexingLxyOverErr] = values[kVertexingLxy] / values[kVertexingLxyErr]; @@ -1659,9 +1816,9 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, } if (fgUsedVars[kKFChi2OverNDFGeo]) - values[kKFChi2OverNDFGeo] = KFGeoTwoProngBarrel.GetChi2() / KFGeoTwoProngBarrel.GetNDF(); + values[kKFChi2OverNDFGeo] = KFGeoTwoProng.GetChi2() / KFGeoTwoProng.GetNDF(); if (fgUsedVars[kKFCosPA]) - values[kKFCosPA] = calculateCosPA(KFGeoTwoProngBarrel, KFPV); + values[kKFCosPA] = calculateCosPA(KFGeoTwoProng, KFPV); // in principle, they should be in FillTrack if (fgUsedVars[kKFTrack0DCAxyz] || fgUsedVars[kKFTrack1DCAxyz]) { @@ -1683,8 +1840,58 @@ void VarManager::FillPairVertexing(C const& collision, T const& t1, T const& t2, if (fgUsedVars[kKFTracksDCAxyMax]) { values[kKFTracksDCAxyMax] = TMath::Abs(values[kKFTrack0DCAxy]) > TMath::Abs(values[kKFTrack1DCAxy]) ? values[kKFTrack0DCAxy] : values[kKFTrack1DCAxy]; } + if (propToSV) { + if constexpr ((pairType == kDecayToMuMu) && muonHasCov) { + double chi21 = t1.chi2(); + double chi22 = t2.chi2(); + SMatrix5 t1pars(t1.x(), t1.y(), t1.phi(), t1.tgl(), t1.signed1Pt()); + std::vector c1{t1.cXX(), t1.cXY(), t1.cYY(), t1.cPhiX(), t1.cPhiY(), + t1.cPhiPhi(), t1.cTglX(), t1.cTglY(), t1.cTglPhi(), t1.cTglTgl(), + t1.c1PtX(), t1.c1PtY(), t1.c1PtPhi(), t1.c1PtTgl(), t1.c1Pt21Pt2()}; + SMatrix55 t1covs(c1.begin(), c1.end()); + o2::track::TrackParCovFwd pars1{t1.z(), t1pars, t1covs, chi21}; + SMatrix5 t2pars(t2.x(), t2.y(), t2.phi(), t2.tgl(), t2.signed1Pt()); + std::vector c2{t2.cXX(), t2.cXY(), t2.cYY(), t2.cPhiX(), t2.cPhiY(), + t2.cPhiPhi(), t2.cTglX(), t2.cTglY(), t2.cTglPhi(), t2.cTglTgl(), + t2.c1PtX(), t2.c1PtY(), t2.c1PtPhi(), t2.c1PtTgl(), t2.c1Pt21Pt2()}; + SMatrix55 t2covs(c2.begin(), c2.end()); + o2::track::TrackParCovFwd pars2{t2.z(), t2pars, t2covs, chi22}; + + auto geoMan1 = o2::base::GeometryManager::meanMaterialBudget(t1.x(), t1.y(), t1.z(), KFGeoTwoProng.GetX(), KFGeoTwoProng.GetY(), KFGeoTwoProng.GetZ()); + auto geoMan2 = o2::base::GeometryManager::meanMaterialBudget(t2.x(), t2.y(), t2.z(), KFGeoTwoProng.GetX(), KFGeoTwoProng.GetY(), KFGeoTwoProng.GetZ()); + auto x2x01 = static_cast(geoMan1.meanX2X0); + auto x2x02 = static_cast(geoMan2.meanX2X0); + pars1.propagateToVtxhelixWithMCS(KFGeoTwoProng.GetZ(), {KFGeoTwoProng.GetX(), KFGeoTwoProng.GetY()}, {KFGeoTwoProng.GetCovariance(0, 0), KFGeoTwoProng.GetCovariance(1, 1)}, fgFitterTwoProngFwd.getBz(), x2x01); + pars2.propagateToVtxhelixWithMCS(KFGeoTwoProng.GetZ(), {KFGeoTwoProng.GetX(), KFGeoTwoProng.GetY()}, {KFGeoTwoProng.GetCovariance(0, 0), KFGeoTwoProng.GetCovariance(1, 1)}, fgFitterTwoProngFwd.getBz(), x2x02); + v1 = {pars1.getPt(), pars1.getEta(), pars1.getPhi(), m1}; + v2 = {pars2.getPt(), pars2.getEta(), pars2.getPhi(), m2}; + v12 = v1 + v2; + + values[kPt1] = pars1.getPt(); + values[kEta1] = pars1.getEta(); + values[kPhi1] = pars1.getPhi(); + + values[kPt2] = pars2.getPt(); + values[kEta2] = pars2.getEta(); + values[kPhi2] = pars2.getPhi(); + } + } } } + if (propToSV) { + values[kMass] = v12.M(); + values[kPt] = v12.Pt(); + values[kEta] = v12.Eta(); + values[kPhi] = v12.Phi(); + } else { + values[kPt1] = t1.pt(); + values[kEta1] = t1.eta(); + values[kPhi1] = t1.phi(); + + values[kPt2] = t2.pt(); + values[kEta2] = t2.eta(); + values[kPhi2] = t2.phi(); + } } template @@ -1705,8 +1912,8 @@ void VarManager::FillDileptonTrackVertexing(C const& collision, T1 const& lepton int procCodeJpsi = 0; if constexpr ((candidateType == kBcToThreeMuons) && muonHasCov) { - mlepton = MassMuon; - mtrack = MassMuon; + mlepton = o2::constants::physics::MassMuon; + mtrack = o2::constants::physics::MassMuon; double chi21 = lepton1.chi2(); double chi22 = lepton2.chi2(); @@ -1734,8 +1941,8 @@ void VarManager::FillDileptonTrackVertexing(C const& collision, T1 const& lepton procCode = VarManager::fgFitterThreeProngFwd.process(pars1, pars2, pars3); procCodeJpsi = VarManager::fgFitterTwoProngFwd.process(pars1, pars2); } else if constexpr ((candidateType == kBtoJpsiEEK) && trackHasCov) { - mlepton = MassElectron; - mtrack = MassKaonCharged; + mlepton = o2::constants::physics::MassElectron; + mtrack = o2::constants::physics::MassKaonCharged; std::array lepton1pars = {lepton1.y(), lepton1.z(), lepton1.snp(), lepton1.tgl(), lepton1.signed1Pt()}; std::array lepton1covs = {lepton1.cYY(), lepton1.cZY(), lepton1.cZZ(), lepton1.cSnpY(), lepton1.cSnpZ(), lepton1.cSnpSnp(), lepton1.cTglY(), lepton1.cTglZ(), lepton1.cTglSnp(), lepton1.cTglTgl(), @@ -1887,20 +2094,20 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) values = fgValues; } - float m1 = MassElectron; - float m2 = MassElectron; + float m1 = o2::constants::physics::MassElectron; + float m2 = o2::constants::physics::MassElectron; if constexpr (pairType == kDecayToMuMu) { - m1 = MassMuon; - m2 = MassMuon; + m1 = o2::constants::physics::MassMuon; + m2 = o2::constants::physics::MassMuon; } if constexpr (pairType == kDecayToPiPi) { - m1 = MassPionCharged; - m2 = MassPionCharged; + m1 = o2::constants::physics::MassPionCharged; + m2 = o2::constants::physics::MassPionCharged; } if constexpr (pairType == kElectronMuon) { - m2 = MassMuon; + m2 = o2::constants::physics::MassMuon; } // Fill dilepton information @@ -1962,6 +2169,7 @@ void VarManager::FillDileptonHadron(T1 const& dilepton, T2 const& hadron, float* values[kDeltaEta] = dilepton.eta() - hadron.eta(); } } + template void VarManager::FillHadron(T const& hadron, float* values, float hadronMass) { @@ -1976,4 +2184,39 @@ void VarManager::FillHadron(T const& hadron, float* values, float hadronMass) values[kPhi] = hadron.phi(); values[kRap] = vhadron.Rapidity(); } + +template +void VarManager::FillSingleDileptonCharmHadron(Cand const& candidate, H hfHelper, float* values) +{ + if (!values) { + values = fgValues; + } + + if constexpr (partType == kJPsi) { + values[kMass] = candidate.mass(); + values[kPt] = candidate.pt(); + values[kPhi] = candidate.phi(); + values[kRap] = candidate.rap(); + } + if constexpr (partType == kD0ToPiK) { + values[kMassCharmHadron] = hfHelper.invMassD0ToPiK(candidate); + values[kPtCharmHadron] = candidate.pt(); + values[kPhiCharmHadron] = candidate.phi(); + values[kRapCharmHadron] = hfHelper.yD0(candidate); + } + if constexpr (partType == kD0barToKPi) { + values[kMassCharmHadron] = hfHelper.invMassD0barToKPi(candidate); + values[kPtCharmHadron] = candidate.pt(); + values[kPhiCharmHadron] = candidate.phi(); + values[kRapCharmHadron] = hfHelper.yD0(candidate); + } +} + +template +void VarManager::FillDileptonCharmHadron(DQ const& dilepton, HF const& charmHadron, H hfHelper, float* values) +{ + FillSingleDileptonCharmHadron(dilepton, hfHelper, values); + FillSingleDileptonCharmHadron(charmHadron, hfHelper, values); +} + #endif // PWGDQ_CORE_VARMANAGER_H_ diff --git a/PWGDQ/DataModel/MchTrkEffTables.h b/PWGDQ/DataModel/MchTrkEffTables.h new file mode 100644 index 00000000000..1ce05ad5ca0 --- /dev/null +++ b/PWGDQ/DataModel/MchTrkEffTables.h @@ -0,0 +1,46 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MchTrkEffTables.h +/// \brief MCH tracking efficiency table definition. +/// \author +/// + +#ifndef PWGDQ_DATAMODEL_MCHTRKEFFTABLES_H_ +#define PWGDQ_DATAMODEL_MCHTRKEFFTABLES_H_ + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ + +namespace mch_trk_eff +{ +// Define the selection columns +DECLARE_SOA_COLUMN(Eta, eta, float); //! reconstructed eta +DECLARE_SOA_COLUMN(Pt, pt, float); //! reconstructed pt +DECLARE_SOA_COLUMN(Phi, phi, float); //! reconstructed phi +DECLARE_SOA_COLUMN(MchBitMap, mchBitMap, uint16_t); //! mch bit map +DECLARE_SOA_COLUMN(EtaGen, etaGen, float); //! simulated eta +DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! simulated pt +DECLARE_SOA_COLUMN(PhiGen, phiGen, float); //! simulated phi +} // namespace mch_trk_eff + +// Table +DECLARE_SOA_TABLE(MchTrkEffBase, "AOD", "MCHTRKEFFBASE", //! table with muon track properties and mch bit map + mch_trk_eff::Eta, mch_trk_eff::Pt, mch_trk_eff::Phi, mch_trk_eff::MchBitMap); + +DECLARE_SOA_TABLE(MchTrkEffGen, "AOD", "MCHTRKEFFGEN", //! table with simulated muon track properties + mch_trk_eff::EtaGen, mch_trk_eff::PtGen, mch_trk_eff::PhiGen); + +} // namespace o2::aod + +#endif // PWGDQ_DATAMODEL_MCHTRKEFFTABLES_H_ diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index d408ba432ab..86659770e4c 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -123,6 +123,7 @@ DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, int); //! DECLARE_SOA_COLUMN(DcaXY, dcaXY, float); //! DECLARE_SOA_COLUMN(DcaZ, dcaZ, float); //! DECLARE_SOA_COLUMN(DetectorMap, detectorMap, uint8_t); //! Detector map: see enum DetectorMapEnum +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! DECLARE_SOA_DYNAMIC_COLUMN(HasITS, hasITS, //! Flag to check if track has a ITS match [](uint8_t detectorMap) -> bool { return detectorMap & o2::aod::track::ITS; }); DECLARE_SOA_DYNAMIC_COLUMN(HasTPC, hasTPC, //! Flag to check if track has a TPC match @@ -182,10 +183,15 @@ DECLARE_SOA_TABLE(ReducedTracksBarrelPID, "AOD", "RTBARRELPID", //! pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, track::TRDSignal); +// barrel collision information (joined with ReducedTracks) allowing to connect different tables (cross PWGs) +DECLARE_SOA_TABLE(ReducedTracksBarrelInfo, "AOD", "RTBARRELINFO", + reducedtrack::CollisionId, collision::PosX, collision::PosY, collision::PosZ); + using ReducedTrack = ReducedTracks::iterator; using ReducedTrackBarrel = ReducedTracksBarrel::iterator; using ReducedTrackBarrelCov = ReducedTracksBarrelCov::iterator; using ReducedTrackBarrelPID = ReducedTracksBarrelPID::iterator; +using ReducedTrackBarrelInfo = ReducedTracksBarrelInfo::iterator; namespace reducedtrackMC { @@ -441,6 +447,7 @@ DECLARE_SOA_COLUMN(TauxyErr, tauxyErr, float); //! Error on transverse p DECLARE_SOA_COLUMN(Lz, lz, float); //! Longitudinal projection of decay length DECLARE_SOA_COLUMN(Lxy, lxy, float); //! Transverse projection of decay length DECLARE_SOA_COLUMN(Chi2pca, chi2pca, float); //! Chi2 for PCA of the dilepton +DECLARE_SOA_COLUMN(CosPointingAngle, cosPointingAngle, float); //! Cosine of the pointing angle DECLARE_SOA_COLUMN(U2Q2, u2q2, float); //! Scalar product between unitary vector with event flow vector (harmonic 2) DECLARE_SOA_COLUMN(U3Q3, u3q3, float); //! Scalar product between unitary vector with event flow vector (harmonic 3) DECLARE_SOA_COLUMN(Cos2DeltaPhi, cos2deltaphi, float); //! Cosinus term using event plane angle (harmonic 2) @@ -488,15 +495,17 @@ DECLARE_SOA_TABLE(DileptonsInfo, "AOD", "RTDILEPTONINFO", reducedpair::CollisionId, collision::PosX, collision::PosY, collision::PosZ); DECLARE_SOA_TABLE(DimuonsAll, "AOD", "RTDIMUONALL", //! - collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib, dilepton_track_index::FwdDcaX1, dilepton_track_index::FwdDcaY1, dilepton_track_index::FwdDcaX2, dilepton_track_index::FwdDcaY2, + collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib, reducedevent::MCPosX, reducedevent::MCPosY, reducedevent::MCPosZ, reducedpair::Mass, reducedpair::McDecision, reducedpair::Pt, reducedpair::Eta, reducedpair::Phi, reducedpair::Sign, reducedpair::Chi2pca, reducedpair::Tauz, reducedpair::TauzErr, reducedpair::Tauxy, reducedpair::TauxyErr, + reducedpair::CosPointingAngle, dilepton_track_index::Pt1, dilepton_track_index::Eta1, dilepton_track_index::Phi1, dilepton_track_index::Sign1, dilepton_track_index::Pt2, dilepton_track_index::Eta2, dilepton_track_index::Phi2, dilepton_track_index::Sign2, + dilepton_track_index::FwdDcaX1, dilepton_track_index::FwdDcaY1, dilepton_track_index::FwdDcaX2, dilepton_track_index::FwdDcaY2, dilepton_track_index::McMask1, dilepton_track_index::McMask2, dilepton_track_index::Chi2MatchMCHMID1, dilepton_track_index::Chi2MatchMCHMID2, dilepton_track_index::Chi2MatchMCHMFT1, dilepton_track_index::Chi2MatchMCHMFT2, @@ -558,6 +567,68 @@ DECLARE_SOA_COLUMN(DALITZBits, dalitzBits, uint8_t); //! // bit information for particle species. DECLARE_SOA_TABLE(DalitzBits, "AOD", "DALITZBITS", DalBits::DALITZBits); + +DECLARE_SOA_TABLE(RedJpDmColls, "AOD", "REDJPDMCOLL", //! + o2::soa::Index<>, + collision::PosX, + collision::PosY, + collision::PosZ, + collision::NumContrib); + +namespace jpsidmescorr +{ +DECLARE_SOA_INDEX_COLUMN(RedJpDmColl, redJpDmColl); //! +DECLARE_SOA_COLUMN(MassD0, massD0, float); //! +DECLARE_SOA_COLUMN(MassD0bar, massD0bar, float); //! +DECLARE_SOA_COLUMN(Px, px, float); //! +DECLARE_SOA_COLUMN(Py, py, float); //! +DECLARE_SOA_COLUMN(Pz, pz, float); //! +DECLARE_SOA_COLUMN(DecVtxX, decVtxX, float); //! +DECLARE_SOA_COLUMN(DecVtxY, decVtxY, float); //! +DECLARE_SOA_COLUMN(DecVtxZ, decVtxZ, float); //! +DECLARE_SOA_COLUMN(BdtBkg, bdtBkg, float); //! +DECLARE_SOA_COLUMN(BdtPrompt, bdtPrompt, float); //! +DECLARE_SOA_COLUMN(BdtNonprompt, bdtNonprompt, float); //! +DECLARE_SOA_COLUMN(NumColls, numColls, uint64_t); //! +} // namespace jpsidmescorr + +DECLARE_SOA_TABLE(RedJpDmDileptons, "AOD", "REDJPDMDILEPTON", //! + o2::soa::Index<>, + jpsidmescorr::RedJpDmCollId, + jpsidmescorr::Px, + jpsidmescorr::Py, + jpsidmescorr::Pz, + reducedpair::Mass, + reducedpair::Sign, + reducedpair::McDecision, + reducedpair::Tauz, + reducedpair::Lz, + reducedpair::Lxy); + +DECLARE_SOA_TABLE(RedJpDmColCounts, "AOD", "REDJPDMCOLCOUNT", //! + jpsidmescorr::NumColls); + +DECLARE_SOA_TABLE(RedJpDmDmesons, "AOD", "REDJPDMDMESON", //! + o2::soa::Index<>, + jpsidmescorr::RedJpDmCollId, + jpsidmescorr::Px, + jpsidmescorr::Py, + jpsidmescorr::Pz, + jpsidmescorr::DecVtxX, + jpsidmescorr::DecVtxY, + jpsidmescorr::DecVtxZ, + reducedpair::Sign, + reducedpair::McDecision); + +DECLARE_SOA_TABLE(RedJpDmD0Masss, "AOD", "REDJPDMD0MASS", //! + jpsidmescorr::MassD0, + jpsidmescorr::MassD0bar); + +DECLARE_SOA_TABLE(RedJpDmDmesBdts, "AOD", "REDJPDMDMESBDT", //! + jpsidmescorr::BdtBkg, + jpsidmescorr::BdtPrompt, + jpsidmescorr::BdtNonprompt); + } // namespace o2::aod #endif // PWGDQ_DATAMODEL_REDUCEDINFOTABLES_H_ diff --git a/PWGDQ/TableProducer/CMakeLists.txt b/PWGDQ/TableProducer/CMakeLists.txt index afcc614f333..7c8f33e8c87 100644 --- a/PWGDQ/TableProducer/CMakeLists.txt +++ b/PWGDQ/TableProducer/CMakeLists.txt @@ -18,3 +18,13 @@ o2physics_add_dpl_workflow(table-maker-mc SOURCES tableMakerMC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2Physics::AnalysisCCDB O2Physics::PWGDQCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(table-maker-jpsi-hf + SOURCES tableMakerJpsiHf.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore KFParticle::KFParticle + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(table-maker-muon-mch-trk-eff + SOURCES tableMakerMuonMchTrkEfficiency.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) diff --git a/PWGDQ/TableProducer/tableMaker.cxx b/PWGDQ/TableProducer/tableMaker.cxx index a1481cffbff..5e76a91ae84 100644 --- a/PWGDQ/TableProducer/tableMaker.cxx +++ b/PWGDQ/TableProducer/tableMaker.cxx @@ -30,6 +30,7 @@ #include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/MftmchMatchingML.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/Core/HistogramManager.h" @@ -126,6 +127,7 @@ struct TableMaker { Produces trackBarrel; Produces trackBarrelCov; Produces trackBarrelPID; + Produces trackBarrelInfo; Produces muonBasic; Produces muonExtra; Produces muonCov; @@ -143,6 +145,7 @@ struct TableMaker { Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; Configurable fConfigAddMuonHistogram{"cfgAddMuonHistogram", "", "Comma separated list of histograms"}; Configurable fConfigBarrelTrackPtLow{"cfgBarrelLowPt", 1.0f, "Low pt cut for tracks in the barrel"}; + Configurable fConfigBarrelTrackMaxAbsEta{"cfgBarrelMaxAbsEta", 0.9f, "Eta absolute value cut for tracks in the barrel"}; Configurable fConfigMuonPtLow{"cfgMuonLowPt", 1.0f, "Low pt cut for muons"}; Configurable fConfigMinTpcSignal{"cfgMinTpcSignal", 30.0, "Minimum TPC signal"}; Configurable fConfigMaxTpcSignal{"cfgMaxTpcSignal", 300.0, "Maximum TPC signal"}; @@ -151,13 +154,15 @@ struct TableMaker { Configurable fIsRun2{"cfgIsRun2", false, "Whether we analyze Run-2 or Run-3 data"}; Configurable fIsAmbiguous{"cfgIsAmbiguous", false, "Whether we enable QA plots for ambiguous tracks"}; Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/Postcalib/pass4/apass3BB", "base path to the ccdb object"}; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas(electrons, pions, protons)"}; Configurable fConfigComputeTPCpostCalibKaon{"cfgTPCpostCalibKaon", false, "If true, compute TPC post-calibrated n-sigmas for kaons"}; Configurable fConfigRunPeriods{"cfgRunPeriods", "LHC22f", "run periods for used data"}; Configurable fConfigIsOnlyforMaps{"cfgIsforMaps", false, "If true, run for postcalibration maps only"}; - + Configurable fConfigSaveElectronSample{"cfgSaveElectronSample", false, "If true, only save electron sample"}; + Configurable fConfigDummyRunlist{"cfgDummyRunlist", false, "If true, use dummy runlist"}; + Configurable fConfigInitRunNumber{"cfgInitRunNumber", 543215, "Initial run number used in run by run checks"}; Service fCCDB; AnalysisCompositeCut* fEventCut; //! Event selection cut @@ -173,7 +178,7 @@ struct TableMaker { int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. // TODO: filter on TPC dedx used temporarily until electron PID will be improved - Filter barrelSelectedTracks = ifnode(fIsRun2.node() == true, aod::track::trackType == uint8_t(aod::track::Run2Track), aod::track::trackType == uint8_t(aod::track::Track)) && o2::aod::track::pt >= fConfigBarrelTrackPtLow && nabs(o2::aod::track::eta) <= 0.9f && o2::aod::track::tpcSignal >= fConfigMinTpcSignal && o2::aod::track::tpcSignal <= fConfigMaxTpcSignal && o2::aod::track::tpcChi2NCl < 4.0f && o2::aod::track::itsChi2NCl < 36.0f; + Filter barrelSelectedTracks = ifnode(fIsRun2.node() == true, aod::track::trackType == uint8_t(aod::track::Run2Track), aod::track::trackType == uint8_t(aod::track::Track)) && o2::aod::track::pt >= fConfigBarrelTrackPtLow && nabs(o2::aod::track::eta) <= fConfigBarrelTrackMaxAbsEta && o2::aod::track::tpcSignal >= fConfigMinTpcSignal && o2::aod::track::tpcSignal <= fConfigMaxTpcSignal && o2::aod::track::tpcChi2NCl < 4.0f && o2::aod::track::itsChi2NCl < 36.0f; Filter muonFilter = o2::aod::fwdtrack::pt >= fConfigMuonPtLow; @@ -202,18 +207,22 @@ struct TableMaker { bool enableBarrelHistos = (context.mOptions.get("processFull") || context.mOptions.get("processFullWithCov") || context.mOptions.get("processFullWithCent") || context.mOptions.get("processFullWithCovAndEventFilter") || + context.mOptions.get("processFullWithCovMultsAndEventFilter") || context.mOptions.get("processBarrelOnly") || context.mOptions.get("processBarrelOnlyWithCent") || + context.mOptions.get("processBarrelOnlyWithMults") || context.mOptions.get("processBarrelOnlyWithCov") || context.mOptions.get("processBarrelOnlyWithEventFilter") || context.mOptions.get("processBarrelOnlyWithMultsAndEventFilter") || context.mOptions.get("processBarrelOnlyWithCovAndEventFilter") || context.mOptions.get("processBarrelOnlyWithDalitzBits") || context.mOptions.get("processBarrelOnlyWithV0Bits") || context.mOptions.get("processBarrelOnlyWithV0BitsAndMaps") || context.mOptions.get("processAmbiguousBarrelOnly")); bool enableMuonHistos = (context.mOptions.get("processFull") || context.mOptions.get("processFullWithCov") || context.mOptions.get("processFullWithCent") || context.mOptions.get("processFullWithCovAndEventFilter") || + context.mOptions.get("processFullWithCovMultsAndEventFilter") || context.mOptions.get("processMuonOnly") || context.mOptions.get("processMuonOnlyWithCent") || context.mOptions.get("processMuonOnlyWithMults") || context.mOptions.get("processMuonOnlyWithCentAndMults") || context.mOptions.get("processMuonOnlyWithCovAndCent") || context.mOptions.get("processMuonOnlyWithCov") || context.mOptions.get("processMuonOnlyWithFilter") || - context.mOptions.get("processAmbiguousMuonOnlyWithCov") || context.mOptions.get("processAmbiguousMuonOnly")); + context.mOptions.get("processAmbiguousMuonOnlyWithCov") || context.mOptions.get("processAmbiguousMuonOnly") || + context.mOptions.get("processMuonMLOnly") || context.mOptions.get("processMuonMLOnly")); if (enableBarrelHistos) { if (fDoDetailedQA) { @@ -257,6 +266,12 @@ struct TableMaker { } VarManager::SetRunlist((TString)fConfigRunPeriods); + if (fConfigDummyRunlist) { + VarManager::SetDummyRunlist(fConfigInitRunNumber); + } else { + VarManager::SetRunlist((TString)fConfigRunPeriods); + } + DefineHistograms(histClasses); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); @@ -325,7 +340,7 @@ struct TableMaker { // store the selection decisions uint64_t tag = collision.selection_raw(); if (collision.sel7()) { - tag |= (uint64_t(1) << kNsel); //! SEL7 stored at position kNsel in the tag bit map + tag |= (uint64_t(1) << evsel::kNsel); //! SEL7 stored at position kNsel in the tag bit map } // TODO: Add the event level decisions from the filtering task into the tag @@ -389,6 +404,7 @@ struct TableMaker { if constexpr (static_cast(TTrackFillMap)) { trackBasic.reserve(tracksBarrel.size()); trackBarrel.reserve(tracksBarrel.size()); + trackBarrelInfo.reserve(tracksBarrel.size()); if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackCov)) { trackBarrelCov.reserve(tracksBarrel.size()); } @@ -470,6 +486,12 @@ struct TableMaker { } trackFilteringTag |= (uint64_t(trackTempFilterMap) << 15); // BIT15-...: user track filters + if (fConfigSaveElectronSample) { // only save electron sample + if (!(trackFilteringTag & (uint64_t(1) << 2))) { + continue; + } + } + // create the track tables trackBasic(event.lastIndex(), trackFilteringTag, track.pt(), track.eta(), track.phi(), track.sign(), isAmbiguous); trackBarrel(track.tpcInnerParam(), track.flags(), track.itsClusterMap(), track.itsChi2NCl(), @@ -479,6 +501,7 @@ struct TableMaker { track.length(), track.dcaXY(), track.dcaZ(), track.trackTime(), track.trackTimeRes(), track.tofExpMom(), track.detectorMap()); + trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ()); if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackCov)) { trackBarrelCov(track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt(), track.cYY(), track.cZY(), track.cZZ(), track.cSnpY(), track.cSnpZ(), @@ -675,10 +698,11 @@ struct TableMaker { // get the trigger aliases uint32_t triggerAliases = collision.alias_raw(); + // store the selection decisions uint64_t tag = collision.selection_raw(); if (collision.sel7()) { - tag |= (uint64_t(1) << kNsel); //! SEL7 stored at position kNsel in the tag bit map + tag |= (uint64_t(1) << evsel::kNsel); //! SEL7 stored at position kNsel in the tag bit map } // TODO: Add the event level decisions from the filtering task into the tag @@ -742,6 +766,7 @@ struct TableMaker { if constexpr (static_cast(TTrackFillMap)) { trackBasic.reserve(tracksBarrel.size()); trackBarrel.reserve(tracksBarrel.size()); + trackBarrelInfo.reserve(tracksBarrel.size()); if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackCov)) { trackBarrelCov.reserve(tracksBarrel.size()); } @@ -826,6 +851,7 @@ struct TableMaker { track.length(), track.dcaXY(), track.dcaZ(), track.trackTime(), track.trackTimeRes(), track.tofExpMom(), track.detectorMap()); + trackBarrelInfo(track.collisionId(), collision.posX(), collision.posY(), collision.posZ()); if constexpr (static_cast(TTrackFillMap & VarManager::ObjTypes::TrackCov)) { trackBarrelCov(track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt(), track.cYY(), track.cZY(), track.cZZ(), track.cSnpY(), track.cSnpZ(), @@ -1081,6 +1107,21 @@ struct TableMaker { } } + // Produce barrel + muon tables, with track covariance matrix and event filtering, with multiplicity ------------------------------------------- + void processFullWithCovMultsAndEventFilter(MyEventsWithMultsAndFilter::iterator const& collision, aod::BCsWithTimestamps const& bcs, + soa::Filtered const& tracksBarrel, soa::Filtered const& tracksMuon) + { + for (int i = 0; i < kNaliases; i++) { + if (collision.alias_bit(i) > 0) { + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(i)); + } + } + (reinterpret_cast(fStatsList->At(0)))->Fill(1.0, static_cast(kNaliases)); + if (collision.eventFilter()) { + fullSkimming(collision, bcs, tracksBarrel, tracksMuon, nullptr, nullptr); + } + } + // Produce barrel only tables, with V0Bits ------------------------------------------------------------------------------------------------ void processBarrelOnlyWithV0Bits(MyEvents::iterator const& collision, aod::BCsWithTimestamps const& bcs, soa::Filtered const& tracksBarrel) @@ -1217,6 +1258,13 @@ struct TableMaker { fullSkimming(collision, bcs, nullptr, tracksMuon, nullptr, nullptr); } + // Produce muon tables only ------------------------------------------------------------------------------------------------------------------ + void processMuonMLOnly(MyEvents::iterator const& collision, aod::BCsWithTimestamps const& bcs, + soa::Filtered const& tracksMuon) + { + fullSkimming(collision, bcs, nullptr, tracksMuon, nullptr, nullptr); + } + // Produce muon tables only ------------------------------------------------------------------------------------------------------------------ void processMuonOnly(MyEvents::iterator const& collision, aod::BCsWithTimestamps const& bcs, soa::Filtered const& tracksMuon) @@ -1349,6 +1397,7 @@ struct TableMaker { PROCESS_SWITCH(TableMaker, processFull, "Build full DQ skimmed data model, w/o centrality", false); PROCESS_SWITCH(TableMaker, processFullWithCov, "Build full DQ skimmed data model, w/ track and fwdtrack covariance tables", false); PROCESS_SWITCH(TableMaker, processFullWithCovAndEventFilter, "Build full DQ skimmed data model, w/ track and fwdtrack covariance tables, w/ event filter", false); + PROCESS_SWITCH(TableMaker, processFullWithCovMultsAndEventFilter, "Build full DQ skimmed data model, w/ track and fwdtrack covariance tables, w/ event filter and multiplicities", false); PROCESS_SWITCH(TableMaker, processFullWithCent, "Build full DQ skimmed data model, w/ centrality", false); PROCESS_SWITCH(TableMaker, processFullWithCentAndMults, "Build full DQ skimmed data model, w/ centrality and multiplicities", false); PROCESS_SWITCH(TableMaker, processBarrelOnlyWithV0Bits, "Build full DQ skimmed data model, w/o centrality, w/ V0Bits", false); @@ -1369,6 +1418,7 @@ struct TableMaker { PROCESS_SWITCH(TableMaker, processMuonOnlyWithCov, "Build muon-only DQ skimmed data model, w/ muon cov matrix", false); PROCESS_SWITCH(TableMaker, processMuonOnly, "Build muon-only DQ skimmed data model", false); PROCESS_SWITCH(TableMaker, processMuonOnlyWithFilter, "Build muon-only DQ skimmed data model, w/ event filter", false); + PROCESS_SWITCH(TableMaker, processMuonMLOnly, "Build muon-only DQ skimmed data model with global muon track by ML matching", false); PROCESS_SWITCH(TableMaker, processOnlyBCs, "Analyze the BCs to store sampled lumi", false); PROCESS_SWITCH(TableMaker, processAmbiguousMuonOnly, "Build muon-only DQ skimmed data model with QA plots for ambiguous muons", false); PROCESS_SWITCH(TableMaker, processAmbiguousMuonOnlyWithCov, "Build muon-only with cov DQ skimmed data model with QA plots for ambiguous muons", false); diff --git a/PWGDQ/TableProducer/tableMakerJpsiHf.cxx b/PWGDQ/TableProducer/tableMakerJpsiHf.cxx new file mode 100644 index 00000000000..260f2cb97e5 --- /dev/null +++ b/PWGDQ/TableProducer/tableMakerJpsiHf.cxx @@ -0,0 +1,250 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file tableMakerJpsiHf.cxx +/// \brief Task for the production of the derived data of J/psi - open HF associate production +/// \author Luca Micheletti , INFN +/// \author Fabrizio Grosa , CERN + +#include + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/Core/HistogramManager.h" +#include "PWGDQ/Core/HistogramsLibrary.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; +using namespace o2::aod::hf_cand_2prong; + +// Declarations of various short names +using MyEvents = soa::Join; +using MyDileptonCandidatesSelected = soa::Join; +using MyDileptonCandidatesSelectedWithDca = soa::Join; +using MyD0CandidatesSelected = soa::Join; +using MyD0CandidatesSelectedWithBdt = soa::Join; + +constexpr float cutsBdt[1][3] = {{1., 0., 0.}}; // background, prompt, nonprompt +static const std::vector labelsBdt = {"Background", "Prompt", "Nonprompt"}; +static const std::vector labelsEmpty{}; + +HfHelper hfHelper; + +struct tableMakerJpsiHf { + // + // This task combines dilepton candidates with a open charm hadron + // + + // Produce derived tables + Produces redCollisions; + Produces redDmesons; + Produces redDmesBdts; + Produces redD0Masses; + Produces redDileptons; + Produces redCollCounter; + + // HF configurables + // cuts on BDT output scores to be applied only for the histograms + Configurable> bdtCutsForHistos{"bdtCutsForHistos", {cutsBdt[0], 1, 3, labelsEmpty, labelsBdt}, "Additional bdt cut values only for histograms"}; + Configurable yCandDmesonMax{"yCandDmesonMax", -1., "max. cand. rapidity"}; + // DQ configurables + Configurable dileptonDecayChannel{"dileptonDecayChannel", "JPsiToMuMu", "Dilepton decay channel (JPsiToMuMu/JPsiToEE)"}; + Configurable massDileptonCandMin{"massDileptonCandMin", 1, "minimum dilepton mass"}; + Configurable massDileptonCandMax{"massDileptonCandMax", 5, "maximum dilepton mass"}; + // General configurables + Configurable configDebug{"configDebug", true, "If true, fill D0 - J/psi histograms separately"}; + + SliceCache cache; + Partition selectedDileptonCandidates = aod::reducedpair::mass > 1.0f && aod::reducedpair::mass < 5.0f && aod::reducedpair::sign == 0; + Partition selectedDileptonCandidatesWithDca = aod::reducedpair::mass > 1.0f && aod::reducedpair::mass < 5.0f && aod::reducedpair::sign == 0; + Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; + Partition selectedD0CandidatesWithBdt = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; + + Preslice perCollisionDmeson = aod::hf_cand::collisionId; + Preslice perCollisionDilepton = aod::reducedpair::collisionId; + + // Define histograms manager + float* fValuesDileptonCharmHadron{}; + HistogramManager* fHistMan{}; + OutputObj fOutputList{"output"}; + + void init(o2::framework::InitContext& context) + { + fValuesDileptonCharmHadron = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(true); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + fHistMan->AddHistClass("Dmeson"); + fHistMan->AddHistClass("JPsi"); + fHistMan->AddHistClass("JPsiDmeson"); + dqhistograms::DefineHistograms(fHistMan, "Dmeson", "dilepton-charmhadron", "dmeson"); + if (dileptonDecayChannel.value == "JPsiToMuMu") { + dqhistograms::DefineHistograms(fHistMan, "JPsi", "dilepton-charmhadron", "jpsitomumu"); + dqhistograms::DefineHistograms(fHistMan, "JPsiDmeson", "dilepton-charmhadron", "jpsitomumudmeson"); + } + if (dileptonDecayChannel.value == "JPsiToEE") { + dqhistograms::DefineHistograms(fHistMan, "JPsi", "dilepton-charmhadron", "jpsitoee"); + dqhistograms::DefineHistograms(fHistMan, "JPsiDmeson", "dilepton-charmhadron", "jpsitoeedmeson"); + } + VarManager::SetUseVars(fHistMan->GetUsedVars()); + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + // Template function to run pair - hadron combinations + // TODO: generalise to all charm-hadron species + template + void runDileptonDmeson(TDqTrack const& dileptons, THfTrack const& dmesons, MyEvents::iterator const& collision) + { + VarManager::ResetValues(0, VarManager::kNVars, fValuesDileptonCharmHadron); + + std::vector scores{-1., 2., 2.}; + bool isCollSel{false}; + if (configDebug) { + for (auto& dmeson : dmesons) { + if (!TESTBIT(dmeson.hfflag(), DecayType::D0ToPiK)) { + continue; + } + + if constexpr (withBdt) { + scores[0] = dmeson.mlProbD0()[0]; + scores[1] = dmeson.mlProbD0()[1]; + scores[2] = dmeson.mlProbD0()[2]; + } + + auto rapD0 = hfHelper.yD0(dmeson); + + if (yCandDmesonMax >= 0. && std::abs(rapD0) > yCandDmesonMax) { + continue; + } + + if (scores[0] < bdtCutsForHistos->get(0u, 0u) && scores[1] > bdtCutsForHistos->get(0u, 1u) && scores[2] > bdtCutsForHistos->get(0u, 2u)) { + if (dmeson.isSelD0() >= 1) { + VarManager::FillSingleDileptonCharmHadron(dmeson, hfHelper, fValuesDileptonCharmHadron); + fHistMan->FillHistClass("Dmeson", fValuesDileptonCharmHadron); + VarManager::ResetValues(0, VarManager::kNVars, fValuesDileptonCharmHadron); + } + if (dmeson.isSelD0bar() >= 1) { + VarManager::FillSingleDileptonCharmHadron(dmeson, hfHelper, fValuesDileptonCharmHadron); + fHistMan->FillHistClass("Dmeson", fValuesDileptonCharmHadron); + VarManager::ResetValues(0, VarManager::kNVars, fValuesDileptonCharmHadron); + } + } + } + } + + // loop over dileptons + for (auto dilepton : dileptons) { + auto massJPsi = dilepton.mass(); + + if (massJPsi < massDileptonCandMin || massJPsi > massDileptonCandMax) { + continue; + } + + if (configDebug) { + VarManager::FillSingleDileptonCharmHadron(dilepton, hfHelper, fValuesDileptonCharmHadron); + fHistMan->FillHistClass("JPsi", fValuesDileptonCharmHadron); + VarManager::ResetValues(0, VarManager::kNVars, fValuesDileptonCharmHadron); + } + + // loop over D mesons + for (auto& dmeson : dmesons) { + if (!TESTBIT(dmeson.hfflag(), DecayType::D0ToPiK)) { + continue; + } + + auto rapD0 = hfHelper.yD0(dmeson); + + if (yCandDmesonMax >= 0. && std::abs(rapD0) > yCandDmesonMax) { + continue; + } + + auto massD0 = -1.; + auto massD0bar = -1.; + + if (dmeson.isSelD0() >= 1 || dmeson.isSelD0bar() >= 1) { + if (!isCollSel) { + redCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib()); + isCollSel = true; + } + auto indexRed = redCollisions.lastIndex(); + if constexpr (withDca) { + redDileptons(indexRed, dilepton.px(), dilepton.py(), dilepton.pz(), dilepton.mass(), dilepton.sign(), dilepton.mcDecision(), dilepton.tauz(), dilepton.lz(), dilepton.lxy()); + } else { + redDileptons(indexRed, dilepton.px(), dilepton.py(), dilepton.pz(), dilepton.mass(), dilepton.sign(), dilepton.mcDecision(), 0, 0, 0); + } + redDmesons(indexRed, dmeson.px(), dmeson.py(), dmeson.pz(), dmeson.xSecondaryVertex(), dmeson.ySecondaryVertex(), dmeson.zSecondaryVertex(), 0, 0); + if constexpr (withBdt) { + auto scores = dmeson.mlProbD0(); + redDmesBdts(scores[0], scores[1], scores[2]); + } + + if (dmeson.isSelD0() >= 1) { + massD0 = hfHelper.invMassD0ToPiK(dmeson); + if (scores[0] < bdtCutsForHistos->get(0u, 0u) && scores[1] > bdtCutsForHistos->get(0u, 1u) && scores[2] > bdtCutsForHistos->get(0u, 2u)) { + VarManager::FillDileptonCharmHadron(dilepton, dmeson, hfHelper, fValuesDileptonCharmHadron); + fHistMan->FillHistClass("JPsiDmeson", fValuesDileptonCharmHadron); + VarManager::ResetValues(0, VarManager::kNVars, fValuesDileptonCharmHadron); + } + } + if (dmeson.isSelD0bar() >= 1) { + massD0bar = hfHelper.invMassD0barToKPi(dmeson); + if (scores[0] < bdtCutsForHistos->get(0u, 0u) && scores[1] > bdtCutsForHistos->get(0u, 1u) && scores[2] > bdtCutsForHistos->get(0u, 2u)) { + VarManager::FillDileptonCharmHadron(dilepton, dmeson, hfHelper, fValuesDileptonCharmHadron); + fHistMan->FillHistClass("JPsiDmeson", fValuesDileptonCharmHadron); + VarManager::ResetValues(0, VarManager::kNVars, fValuesDileptonCharmHadron); + } + } + redD0Masses(massD0, massD0bar); + } + } + } + } + + // process J/psi - D0 + void processJspiD0(MyEvents const& collisions, MyDileptonCandidatesSelected const& dileptons, MyD0CandidatesSelected const& dmesons) + { + redCollCounter(collisions.size()); + for (auto& collision : collisions) { + auto groupedDmesonCandidates = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + auto groupedDileptonCandidates = selectedDileptonCandidates->sliceByCached(aod::reducedpair::collisionId, collision.globalIndex(), cache); + runDileptonDmeson(groupedDileptonCandidates, groupedDmesonCandidates, collision); + } + } + PROCESS_SWITCH(tableMakerJpsiHf, processJspiD0, "Process J/psi - D0", true); + + // process J/psi - D0 adding the BDT output scores to the D0 table + void processJspiD0WithBdt(MyEvents const& collisions, MyDileptonCandidatesSelected const& dileptons, MyD0CandidatesSelectedWithBdt const& dmesons) + { + redCollCounter(collisions.size()); + for (auto& collision : collisions) { + auto groupedDmesonCandidates = selectedD0CandidatesWithBdt->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + auto groupedDileptonCandidates = selectedDileptonCandidates->sliceByCached(aod::reducedpair::collisionId, collision.globalIndex(), cache); + runDileptonDmeson(groupedDileptonCandidates, groupedDmesonCandidates, collision); + } + } + PROCESS_SWITCH(tableMakerJpsiHf, processJspiD0WithBdt, "Process J/psi - D0", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGDQ/TableProducer/tableMakerMC.cxx b/PWGDQ/TableProducer/tableMakerMC.cxx index 33ef5bdadb5..b848c7f9114 100644 --- a/PWGDQ/TableProducer/tableMakerMC.cxx +++ b/PWGDQ/TableProducer/tableMakerMC.cxx @@ -197,7 +197,7 @@ struct TableMakerMC { bool enableBarrelHistos = (context.mOptions.get("processFull") || context.mOptions.get("processFullWithCov") || context.mOptions.get("processBarrelOnly") || context.mOptions.get("processBarrelOnlyWithDalitzBits") || context.mOptions.get("processBarrelOnlyWithCent") || context.mOptions.get("processBarrelOnlyWithCov") || - context.mOptions.get("processAmbiguousBarrelOnly")); + context.mOptions.get("processBarrelOnlyWithMults") || context.mOptions.get("processAmbiguousBarrelOnly")); bool enableMuonHistos = (context.mOptions.get("processFull") || context.mOptions.get("processFullWithCov") || context.mOptions.get("processMuonOnlyWithCent") || context.mOptions.get("processMuonOnlyWithCov") || context.mOptions.get("processAmbiguousMuonOnlyWithCov") || context.mOptions.get("processAmbiguousMuonOnly")); @@ -254,13 +254,11 @@ struct TableMakerMC { } if (fDoDetailedQA) { if (enableBarrelHistos) { - histClasses += Form("TrackBarrel_BeforeCuts_%s;", objArray->At(isig)->GetName()); for (auto& cut : fTrackCuts) { histClasses += Form("TrackBarrel_%s_%s;", cut.GetName(), objArray->At(isig)->GetName()); } } if (enableMuonHistos) { - histClasses += Form("Muons_BeforeCuts_%s;", objArray->At(isig)->GetName()); for (auto& cut : fMuonCuts) { histClasses += Form("Muons_%s_%s;", cut.GetName(), objArray->At(isig)->GetName()); } @@ -343,7 +341,7 @@ struct TableMakerMC { // store the selection decisions uint64_t tag = collision.selection_raw(); if (collision.sel7()) { - tag |= (uint64_t(1) << kNsel); //! SEL7 stored at position kNsel in the tag bit map + tag |= (uint64_t(1) << evsel::kNsel); //! SEL7 stored at position kNsel in the tag bit map } auto mcCollision = collision.mcCollision(); @@ -388,6 +386,14 @@ struct TableMakerMC { collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), collision.centFT0C()); + } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { + eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], + collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), + collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), + -1); + } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { + eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); } else { eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } @@ -408,7 +414,14 @@ struct TableMakerMC { mcflags = 0; int i = 0; for (auto& sig : fMCSignals) { - if (sig.CheckSignal(true, mcTracks, mctrack)) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto mctrack_raw = groupedMcTracks.rawIteratorAt(mctrack.globalIndex()); + checked = sig.CheckSignal(false, mctrack_raw); + } else { + checked = sig.CheckSignal(false, mctrack); + } + if (checked) { mcflags |= (uint16_t(1) << i); } i++; @@ -523,11 +536,10 @@ struct TableMakerMC { int j = 0; // runs over the track cuts // check all the specified signals and fill histograms for MC truth matched tracks for (auto& sig : fMCSignals) { - if (sig.CheckSignal(true, mcTracks, mctrack)) { + if (sig.CheckSignal(true, mctrack)) { mcflags |= (uint16_t(1) << i); if (fDoDetailedQA) { j = 0; - fHistMan->FillHistClass(Form("TrackBarrel_BeforeCuts_%s", sig.GetName()), VarManager::fgValues); // fill the reconstructed truth BeforeCuts for (auto& cut : fTrackCuts) { if (trackTempFilterMap & (uint8_t(1) << j)) { fHistMan->FillHistClass(Form("TrackBarrel_%s_%s", cut.GetName(), sig.GetName()), VarManager::fgValues); // fill the reconstructed truth @@ -680,10 +692,9 @@ struct TableMakerMC { int j = 0; // runs over the track cuts // check all the specified signals and fill histograms for MC truth matched tracks for (auto& sig : fMCSignals) { - if (sig.CheckSignal(true, mcTracks, mctrack)) { + if (sig.CheckSignal(true, mctrack)) { mcflags |= (uint16_t(1) << i); if (fDoDetailedQA) { - fHistMan->FillHistClass(Form("Muons_BeforeCuts_%s", sig.GetName()), VarManager::fgValues); // fill the reconstructed truth BeforeCuts for (auto& cut : fMuonCuts) { if (trackTempFilterMap & (uint8_t(1) << j)) { fHistMan->FillHistClass(Form("Muons_%s_%s", cut.GetName(), sig.GetName()), VarManager::fgValues); // fill the reconstructed truth diff --git a/PWGDQ/TableProducer/tableMakerMuonMchTrkEfficiency.cxx b/PWGDQ/TableProducer/tableMakerMuonMchTrkEfficiency.cxx new file mode 100644 index 00000000000..609b53c423a --- /dev/null +++ b/PWGDQ/TableProducer/tableMakerMuonMchTrkEfficiency.cxx @@ -0,0 +1,645 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file tableMakerMuonMchTrkEfficiency.cxx +/// \brief task to prepare the tables and some plots required for evaluating the muon tracking efficiency uncertainty +/// +/// @param muon MCH tracking efficiency table +/// Struct for filling the histos and writing the table needed to compute the +/// muon tracking efficiency in the MCH detector +/// +/// \author Zaida Conesa del Valle +/// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "TDatabasePDG.h" +// +#include "Common/DataModel/TrackSelectionTables.h" +// +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/Logger.h" +#include "Framework/runDataProcessing.h" +// +#include "PWGDQ/Core/AnalysisCut.h" +#include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGDQ/DataModel/MchTrkEffTables.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// default histogram output binning +namespace muon_trk_eff_bins +{ +static constexpr int nBinsPt = 24; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double binsPt[nBinsPt + 1] = { + 0., 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, + 2.5, 3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, + 15.0, 18.0, 25.0, 35.0, 45.0, 55.0, 65.0, 75.0}; +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; + +// row labels +static const std::vector labelsPtTrack{ + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9", + "pT bin 10", + "pT bin 11", + "pT bin 12", + "pT bin 13", + "pT bin 14", + "pT bin 15", + "pT bin 16", + "pT bin 17", + "pT bin 18", + "pT bin 19", + "pT bin 20", + "pT bin 21", + "pT bin 22", + "pT bin 23", + "pT bin 24"}; + +} // namespace muon_trk_eff_bins +// Constants +static const double muonMass = 0.105658; // in GeV from PDG +static const int muonPDG = 13; + +/// muon tracking efficiency task +struct tableMakerMuonMchTrkEfficiency { + + // Declare tables + Produces rowCandidateBase; + Produces rowCandidateGen; + + /// Configure the task variables + Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; /// Event selection list + Configurable fConfigMuonCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; /// List of muon selections + + Configurable ptMuonMin{"ptMin", 0., "Lower bound of pT"}; /// Muon minimum pt to be studied + Configurable etaMuonMin{"etaMin", 2.5, "Lower bound of |eta|"}; /// Muon minimum |eta| to be studied + Configurable etaMuonMax{"etaMax", 4.0, "Upper bound of |eta|"}; /// Muon maximum |eta| to be studied + /// + Configurable> binsMuonPt{"binsPt", std::vector{muon_trk_eff_bins::vecBinsPt}, "pT bin limits"}; /// Pt intervals for the histograms + Configurable nEtaBins{"nEtaBins", 8, "Number of Eta bins"}; /// Number of eta bins for output histograms + Configurable nPhiBins{"nPhiBins", 6, "Number of Phi bins"}; /// Number of phi bins for output histograms + Configurable fillBitMapCorr{"fillCorr", false, "Fill bit map correlation sparse"}; /// Boolean to fill or not the THnSparse of correlations + + AnalysisCompositeCut* fEventCut; //! Event selection cut + std::vector fMuonCuts; //! Muon track cuts + + /// Declarations of various short names + using myEvents = soa::Join; + using myEventsMC = soa::Join; + using myReducedEvents = soa::Join; + using myReducedEventsMC = soa::Join; + + using myMuons = soa::Join; + using myMuonsMC = soa::Join; + using myReducedMuons = soa::Join; + using myReducedMuonsMC = soa::Join; + + // bit maps used for the Fill functions of the VarManager + constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision; + constexpr static uint32_t gkReducedEventFillMap = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended; + constexpr static uint32_t gkEventMCFillMap = VarManager::ObjTypes::CollisionMC; + constexpr static uint32_t gkReducedEventMCFillMap = VarManager::ObjTypes::ReducedEventMC; + + constexpr static uint32_t gkMuonFillMap = VarManager::ObjTypes::Muon; + constexpr static uint32_t gkReducedMuonFillMap = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra; + constexpr static uint32_t gkParticleMCFillMap = VarManager::ObjTypes::ParticleMC; + + /// Histogram registry: an object to hold your histograms + HistogramRegistry registry{ + "registry", + {}, + OutputObjHandlingPolicy::AnalysisObject}; + + /// Initialize: configure, create specifics + void init(o2::framework::InitContext&) + { + LOGF(debug, "Initialization"); + + /// set event cuts + fEventCut = new AnalysisCompositeCut(true); + TString eventCutStr = fConfigEventCuts.value; + fEventCut->AddCut(dqcuts::GetAnalysisCut(eventCutStr.Data())); + LOGF(debug, ">> Event cut: %s", eventCutStr.Data()); + + /// set muon cuts + TString cutNamesStr = fConfigMuonCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + LOGF(debug, ">> Muon cut added: %s", objArray->At(icut)->GetName()); + fMuonCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + } + } + + VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetDefaultVarNames(); + + // define histograms to be added + LOGF(debug, " Creating histograms"); + const AxisSpec axisEvt{10, -0.5, 9.5, ""}; + const char* elabels[6] = {"all", "selected", "sel >0 muon", "sel >1 muon", "sel >2 muon", "sel >3 muon"}; + registry.add("hEventCounter", "hEventCounter", {HistType::kTH1F, {axisEvt}}); + auto hEvent = registry.get(HIST("hEventCounter")); + for (int i = 0; i < 6; i++) + hEvent->GetXaxis()->SetBinLabel(i + 1, elabels[i]); + + // define axes to be used + // and the correspondent histograms + auto vbins = (std::vector)binsMuonPt; + const AxisSpec axisEta{190, 2.3, 4.2, "|#eta|"}; + const AxisSpec axisEtaRed{nEtaBins, 2.5, 4., "|#eta|"}; + const AxisSpec axisEtaGenRed{nEtaBins, 2.5, 4., "|#eta| Gen"}; + const AxisSpec axisPt{vbins, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisPtGen{vbins, "#it{p}_{T} (GeV/#it{c}) Gen"}; + const AxisSpec axisPhi{120, -3.14, 3.14, "#varphi"}; + const AxisSpec axisPhiRed{nPhiBins, -3.14, 3.14, "#varphi"}; + const AxisSpec axisPhiGenRed{nPhiBins, -3.14, 3.14, "#varphi Gen"}; + const AxisSpec axisBitMap{1031, -0.5, 1030.5, "mchbitMap"}; + const int nChHitBins = 4; + // Number of hits in chamber i = (Nij, Ni0, N0j) correspond to hit on i-j, hit on i not on j, hit on j not on i + const AxisSpec axisNhits{nChHitBins, 0.5, nChHitBins + 0.5, "isHitInChamber"}; + const AxisSpec axisX{60, -3., 3., "X"}; + const AxisSpec axisY{60, -3., 3., "Y"}; + + HistogramConfigSpec defaultNhitsPerChamber({HistType::kTH3F, {{axisNhits}, {axisX}, {axisY}}}); + HistogramConfigSpec defaultMchBitmap({HistType::kTHnF, {axisBitMap, axisEtaRed, axisPt, axisPhiRed}}); + + registry.add("hEta", "hEta", {HistType::kTH1F, {axisEta}}); + registry.add("hPt", "hPt", {HistType::kTH1F, {axisPt}}); + registry.add("hPhi", "hPhi", {HistType::kTH1F, {axisPhi}}); + registry.add("hMchBitMap", "hMchBitMap", {HistType::kTH1F, {axisBitMap}}); + + // keep also histos per muon selection + registry.add("selected/hEta", Form("hEta_%s", cutNamesStr.Data()), {HistType::kTH1F, {axisEta}}); + registry.add("selected/hPt", Form("hPt_%s", cutNamesStr.Data()), {HistType::kTH1F, {axisPt}}); + registry.add("selected/hPhi", Form("hPhi_%s", cutNamesStr.Data()), {HistType::kTH1F, {axisPhi}}); + registry.add("selected/hMchBitMap", Form("hMchBitMap_%s", cutNamesStr.Data()), {HistType::kTH1F, {axisBitMap}}); + + registry.add("hPtRecPtGen", "hPtRecPtGen", {HistType::kTH2F, {{axisPt}, {axisPtGen}}}); + registry.add("hEtaRecEtaGen", "hEtaRecEtaGen", {HistType::kTH2F, {{axisEtaRed}, {axisEtaGenRed}}}); + registry.add("hPhiRecPhiGen", "hPhiRecPhiGen", {HistType::kTH2F, {{axisPhiRed}, {axisPhiGenRed}}}); + registry.add("selected/hPtRecPtGen", "hPtRecPtGen", {HistType::kTH2F, {{axisPt}, {axisPtGen}}}); + registry.add("selected/hEtaRecEtaGen", "hEtaRecEtaGen", {HistType::kTH2F, {{axisEtaRed}, {axisEtaGenRed}}}); + registry.add("selected/hPhiRecPhiGen", "hPhiRecPhiGen", {HistType::kTH2F, {{axisPhiRed}, {axisPhiGenRed}}}); + + registry.add("hEtaPtPhi", "hEtaPtPhi", {HistType::kTH3F, {{axisEtaRed}, {axisPt}, {axisPhiRed}}}); + registry.add("selected/hEtaPtPhi", Form("hEtaPtPhi_%s", cutNamesStr.Data()), {HistType::kTH3F, {{axisEtaRed}, {axisPt}, {axisPhiRed}}}); + + for (int i = 0; i < 10; i++) { + registry.add(Form("selected/hNhitsPerChamber_%i", i), Form("hNhitsPerChamber_%i_%s", i, cutNamesStr.Data()), defaultNhitsPerChamber, false); + } + + registry.add("selected/hMchBitMapEtaPtPhi", Form("hMchBitMapEtaPtPhi_%s", cutNamesStr.Data()), defaultMchBitmap); + + LOGF(debug, "End of initialization"); + + }; //! end of Initialize: configure, create specifics + + /// check whether a given chamber has hits + bool ischamberhit(uint16_t map, int ich) + { // i = 0..9 + LOGF(debug, " map %i --> %i", map, (map >> ich) & 1); + return (map >> ich) & 1; + } + + /// extrapolate tracks to a given r value (spherical coordinates) + /// to mimic the (x,y) position in a given chamber + void extrapolate(TLorentzVector vec, int ich, double& x, double& y) + { // i = 0..9 + double zposCh[10] = {5, 5, 7, 7, 10, 10, 12.5, 12.5, 14.5, 14.5}; + double theta = vec.Theta(); + double phi = vec.Phi(); + double r = zposCh[ich] / TMath::Cos(theta); + double myx = r * TMath::Sin(theta) * TMath::Cos(phi); + double myy = r * TMath::Sin(theta) * TMath::Sin(phi); + x = myx; + y = myy; + } + + /// process to fill histograms + void FillHistos(double mEta, double mPhi, double mPt, uint16_t mchBitmap, bool isSel) + { + + /// fill histograms + registry.fill(HIST("hEta"), mEta); + registry.fill(HIST("hPt"), mPt); + registry.fill(HIST("hPhi"), mPhi); + registry.fill(HIST("hMchBitMap"), (double)mchBitmap); + registry.fill(HIST("hEtaPtPhi"), mEta, mPt, mPhi); + + /// fill histograms only for selected candidates + if (isSel) { + + registry.fill(HIST("selected/hEta"), mEta); + registry.fill(HIST("selected/hPt"), mPt); + registry.fill(HIST("selected/hPhi"), mPhi); + registry.fill(HIST("selected/hMchBitMap"), (double)mchBitmap); + registry.fill(HIST("selected/hEtaPtPhi"), mEta, mPt, mPhi); + if (fillBitMapCorr) + registry.fill(HIST("selected/hMchBitMapEtaPtPhi"), mchBitmap, mEta, mPt, mPhi); + + /// Study the Nhit distribution vs X-Y + const int nChambers = 10; + bool isNChamberHit[nChambers] = {0}; + double xCh[nChambers], yCh[nChambers]; + TLorentzVector mvector; + mvector.SetPtEtaPhiM(mPt, mEta, mPhi, muonMass); + for (int i = 0; i < nChambers; i++) { + xCh[i] = 0.; + yCh[i] = 0.; + isNChamberHit[i] = false; + isNChamberHit[i] = ischamberhit(mchBitmap, i); + extrapolate(mvector, i, xCh[i], yCh[i]); + } + + // Fill histos station 1, Chambers 1 & 2 + if (isNChamberHit[0] && isNChamberHit[1]) { + registry.fill(HIST("selected/hNhitsPerChamber_0"), 1., xCh[0], yCh[0]); + registry.fill(HIST("selected/hNhitsPerChamber_1"), 1., xCh[1], yCh[1]); + } + if (isNChamberHit[0] && (!isNChamberHit[1])) { + registry.fill(HIST("selected/hNhitsPerChamber_0"), 2., xCh[0], yCh[0]); + registry.fill(HIST("selected/hNhitsPerChamber_1"), 3., xCh[1], yCh[1]); + } + if ((!isNChamberHit[0]) && isNChamberHit[1]) { + registry.fill(HIST("selected/hNhitsPerChamber_0"), 3., xCh[0], yCh[0]); + registry.fill(HIST("selected/hNhitsPerChamber_1"), 2., xCh[1], yCh[1]); + } + // Fill histos station 2, Chambers 3 & 4 + if (isNChamberHit[2] && isNChamberHit[3]) { + registry.fill(HIST("selected/hNhitsPerChamber_2"), 1., xCh[2], yCh[2]); + registry.fill(HIST("selected/hNhitsPerChamber_3"), 1., xCh[3], yCh[3]); + } + if (isNChamberHit[2] && (!isNChamberHit[3])) { + registry.fill(HIST("selected/hNhitsPerChamber_2"), 2., xCh[2], yCh[2]); + registry.fill(HIST("selected/hNhitsPerChamber_3"), 3., xCh[3], yCh[3]); + } + if ((!isNChamberHit[2]) && isNChamberHit[3]) { + registry.fill(HIST("selected/hNhitsPerChamber_2"), 3., xCh[2], yCh[2]); + registry.fill(HIST("selected/hNhitsPerChamber_3"), 2., xCh[3], yCh[3]); + } + // Fill histos station 3, Chambers 5 & 6 + if (isNChamberHit[4] && isNChamberHit[5]) { + registry.fill(HIST("selected/hNhitsPerChamber_4"), 1., xCh[4], yCh[4]); + registry.fill(HIST("selected/hNhitsPerChamber_5"), 1., xCh[5], yCh[5]); + } + if (isNChamberHit[4] && (!isNChamberHit[5])) { + registry.fill(HIST("selected/hNhitsPerChamber_4"), 2., xCh[4], yCh[4]); + registry.fill(HIST("selected/hNhitsPerChamber_5"), 3., xCh[5], yCh[5]); + } + if ((!isNChamberHit[4]) && isNChamberHit[5]) { + registry.fill(HIST("selected/hNhitsPerChamber_4"), 3., xCh[4], yCh[4]); + registry.fill(HIST("selected/hNhitsPerChamber_5"), 2., xCh[5], yCh[5]); + } + // Fill histos station 4, Chambers 7 & 8 + if (isNChamberHit[6] && isNChamberHit[7]) { + registry.fill(HIST("selected/hNhitsPerChamber_6"), 1., xCh[6], yCh[6]); + registry.fill(HIST("selected/hNhitsPerChamber_7"), 1., xCh[7], yCh[7]); + } + if (isNChamberHit[6] && (!isNChamberHit[7])) { + registry.fill(HIST("selected/hNhitsPerChamber_6"), 2., xCh[6], yCh[6]); + registry.fill(HIST("selected/hNhitsPerChamber_7"), 3., xCh[7], yCh[7]); + } + if ((!isNChamberHit[6]) && isNChamberHit[7]) { + registry.fill(HIST("selected/hNhitsPerChamber_6"), 3., xCh[6], yCh[6]); + registry.fill(HIST("selected/hNhitsPerChamber_7"), 2., xCh[7], yCh[7]); + } + // Fill histos station 5, Chambers 9 & 10 + if (isNChamberHit[8] && isNChamberHit[9]) { + registry.fill(HIST("selected/hNhitsPerChamber_8"), 1., xCh[8], yCh[8]); + registry.fill(HIST("selected/hNhitsPerChamber_9"), 1., xCh[9], yCh[9]); + } + if (isNChamberHit[8] && (!isNChamberHit[9])) { + registry.fill(HIST("selected/hNhitsPerChamber_8"), 2., xCh[8], yCh[8]); + registry.fill(HIST("selected/hNhitsPerChamber_9"), 3., xCh[9], yCh[9]); + } + if ((!isNChamberHit[8]) && isNChamberHit[9]) { + registry.fill(HIST("selected/hNhitsPerChamber_8"), 3., xCh[8], yCh[8]); + registry.fill(HIST("selected/hNhitsPerChamber_9"), 2., xCh[9], yCh[9]); + } + + } // end filling info for selected candidates + } + + /// process to fill histograms + void FillHistosMC(double mEta, double mPhi, double mPt, uint16_t mchBitmap, bool isSel, double mGenEta, double mGenPt, double mGenPhi) + { + + registry.fill(HIST("hPtRecPtGen"), mPt, mGenPt); + registry.fill(HIST("hEtaRecEtaGen"), mEta, mGenEta); + registry.fill(HIST("hPhiRecPhiGen"), mPhi, mGenPhi); + + /// fill histograms only for selected candidates + /// + if (isSel) { + registry.fill(HIST("selected/hPtRecPtGen"), mPt, mGenPt); + registry.fill(HIST("selected/hEtaRecEtaGen"), mEta, mGenEta); + registry.fill(HIST("selected/hPhiRecPhiGen"), mPhi, mGenPhi); + } // end filling info for selected candidates + } + + /// Kinematic selection + bool IsInKinematics(double eta, double pt) + { + bool isSelected = true; + + if (pt < ptMuonMin) { + return false; + } + if ((eta < etaMuonMin) || (eta > etaMuonMax)) { + return false; + } + return isSelected; + } + + /// Event selection + template + void runEventSelection(TEvent event) + { + VarManager::ResetValues(0, VarManager::kNEventWiseVariables); + VarManager::FillEvent(event); // extract event information and place it in the fValues array + + /// Analyse only selected events + registry.fill(HIST("hEventCounter"), 0); + if (!fEventCut->IsSelected(VarManager::fgValues)) { + return; + } + registry.fill(HIST("hEventCounter"), 1); + } + + /// Muon selection and info filling + template + void runMuonSelection(TMuons const& tracksMuon) + { + /// loop on all muons + LOGF(debug, " muon fwd tracks %i", tracksMuon.size()); + const int ncuts = fMuonCuts.size(); + int nselmuons[ncuts]; + for (int i = 0; i < ncuts; i++) + nselmuons[i] = 0; + + rowCandidateBase.reserve(tracksMuon.size()); + for (auto& muon : tracksMuon) { + + VarManager::FillTrack(muon); + + LOGF(debug, " %i / %f / %f / %f", muon.trackType(), muon.eta(), muon.pt(), muon.p()); + double mPt = muon.pt(); + double mEta = TMath::Abs(muon.eta()); + double mPhi = muon.phi(); + uint16_t mchBitmap = muon.mchBitMap(); + + /// select muons passing criteria + bool isMuonSelected[ncuts]; + bool isMuonSelectedAny = false; + int j = 0; + + /// check the cuts and filters + for (auto cut = fMuonCuts.begin(); cut != fMuonCuts.end(); cut++, j++) { + isMuonSelected[j] = false; + LOGF(debug, " checking muon selected for cut %i", j); + if ((*cut).IsSelected(VarManager::fgValues)) { + LOGF(debug, " muon IS selected for cut %i", j); + isMuonSelected[j] = true; + isMuonSelectedAny = true; + nselmuons[j]++; + } + } + + bool isKineAcc = IsInKinematics(mEta, mPt); + if (!isKineAcc) + isMuonSelectedAny = false; + + FillHistos(mEta, mPhi, mPt, mchBitmap, isMuonSelectedAny); + + if (isMuonSelectedAny) + rowCandidateBase(mEta, mPt, mPhi, mchBitmap); + + } // end loop on muons + LOGF(debug, "end muon loop"); + + // fill counter histo with number of muons with more than x muons selected + if (nselmuons[0] > 0) + registry.fill(HIST("hEventCounter"), 2); + if (nselmuons[0] > 1) + registry.fill(HIST("hEventCounter"), 3); + if (nselmuons[0] > 2) + registry.fill(HIST("hEventCounter"), 4); + if (nselmuons[0] > 3) + registry.fill(HIST("hEventCounter"), 5); + } + + /// Muon selection and info filling + template + void runSimulatedMuonSelection(TMuons const& tracksMuon) + { + /// loop on all muons + LOGF(debug, " muon fwd tracks %i", tracksMuon.size()); + const int ncuts = fMuonCuts.size(); + int nselmuons[ncuts]; + for (int i = 0; i < ncuts; i++) + nselmuons[i] = 0; + + rowCandidateBase.reserve(tracksMuon.size()); + rowCandidateGen.reserve(tracksMuon.size()); + for (auto& muon : tracksMuon) { + /// + /// First compute MC matched quantities using either the DQ skimmed or the Framework data models + double mGenPt = 0., mGenEta = 0., mGenPhi = 0.; + LOGF(debug, " Looking for the correspondent MC particle"); + if constexpr ((TMuonFillMap & VarManager::ObjTypes::ReducedMuon) > 0) { + auto particle = muon.reducedMCTrack(); + VarManager::FillTrack(particle); + + auto pdgParticle = particle.pdgCode(); + if (!pdgParticle) { + LOGF(warning, "MC particle PDG code not found, skip..."); + continue; + } + if (TMath::Abs(particle.pdgCode()) != muonPDG) { + LOGF(warning, "MC particle does not correspond to a muon, skip..."); + continue; + } + mGenPt = particle.pt(); + mGenEta = TMath::Abs(particle.eta()); + mGenPhi = particle.phi(); + } + if constexpr ((TMuonFillMap & VarManager::ObjTypes::Muon) > 0) { + /// Check if the correspondent MC particle is really a muon + /// otherwise reject + if (!muon.has_mcParticle()) { + LOGF(warning, "No MC particle for track, skip..."); + continue; + } + + auto particle = muon.mcParticle(); + VarManager::FillTrack(particle); + LOGF(debug, " filled mc particle map"); + + auto particlePdgCode = particle.pdgCode(); + + if (TMath::Abs(particlePdgCode) != muonPDG) { + LOGF(warning, "MC particle does not correspond to a muon, skip..."); + continue; + } + mGenPt = particle.pt(); + mGenEta = TMath::Abs(particle.eta()); + mGenPhi = particle.phi(); + } + + LOGF(debug, "now fill muon map"); + /// look the reconstructed quantities + VarManager::FillTrack(muon); + + LOGF(debug, " %i / %f / %f / %f", muon.trackType(), muon.eta(), muon.pt(), muon.p()); + double mPt = muon.pt(); + double mEta = TMath::Abs(muon.eta()); + double mPhi = muon.phi(); + uint16_t mchBitmap = muon.mchBitMap(); + + /// select muons passing criteria + bool isMuonSelected[ncuts]; + bool isMuonSelectedAny = false; + int j = 0; + + /// check the cuts and filters + for (auto cut = fMuonCuts.begin(); cut != fMuonCuts.end(); cut++, j++) { + isMuonSelected[j] = false; + if ((*cut).IsSelected(VarManager::fgValues)) { + isMuonSelected[j] = true; + isMuonSelectedAny = true; + nselmuons[j]++; + } + } + + bool isKineAcc = IsInKinematics(mEta, mPt); + if (!isKineAcc) + isMuonSelectedAny = false; + + /// fill histograms + FillHistos(mEta, mPhi, mPt, mchBitmap, isMuonSelectedAny); + FillHistosMC(mEta, mPhi, mPt, mchBitmap, isMuonSelectedAny, mGenEta, mGenPt, mGenPhi); + + if (isMuonSelectedAny) { + rowCandidateBase(mEta, mPt, mPhi, mchBitmap); + rowCandidateGen(mGenEta, mGenPt, mGenPhi); + } + + } // end loop on muons + LOGF(debug, "end muon loop"); + + // fill counter histo with number of muons with more than x muons selected + if (nselmuons[0] > 0) + registry.fill(HIST("hEventCounter"), 2); + if (nselmuons[0] > 1) + registry.fill(HIST("hEventCounter"), 3); + if (nselmuons[0] > 2) + registry.fill(HIST("hEventCounter"), 4); + if (nselmuons[0] > 3) + registry.fill(HIST("hEventCounter"), 5); + } + + //! process function for full muon information + void processReco(myEvents::iterator const& collision, aod::BCsWithTimestamps const& bcs, myMuons const& muons) + { + /// Run event selection + runEventSelection(collision); + /// Run muon selection and fill output histograms + runMuonSelection(muons); + } + PROCESS_SWITCH(tableMakerMuonMchTrkEfficiency, processReco, "process reconstructed information", false); + + //! process function for reduced muon information + void processRecoReduced(myReducedEvents::iterator const& event, myReducedMuons const& muons) + { + /// Run event selection + runEventSelection(event); + /// Run muon selection and fill output histograms + runMuonSelection(muons); + } + PROCESS_SWITCH(tableMakerMuonMchTrkEfficiency, processRecoReduced, "process reconstructed reduced information", true); + + //! process function for simulated muon information + //! group according to reconstructed Collisions + void processSim(myEventsMC::iterator const& collision, aod::BCsWithTimestamps const& bcs, myMuonsMC const& muons, + aod::McParticles_001 const& mcParticles, aod::McCollisions const& mcCollisions) + { + // TODO: investigate the collisions without corresponding mcCollision + if (!collision.has_mcCollision()) { + return; + } + /// Run event selection + /// + /// fill mc collision map + auto mcCollision = collision.mcCollision(); + VarManager::FillEvent(mcCollision); + /// event selection + runEventSelection(collision); + + /// Run muon selection and histo filling + runSimulatedMuonSelection(muons); + } + PROCESS_SWITCH(tableMakerMuonMchTrkEfficiency, processSim, "process simulation information", false); + + //! process function for reducedsimulated muon information + //! group according to reconstructed Collisions + void processSimReduced(myReducedEventsMC::iterator const& collision, myReducedMuonsMC const& muons, + aod::McParticles_001 const& mcParticles, aod::McCollisions const& mcCollisions) + { + + /// Run event selection + /// + /// fill mc collision map + auto mcCollision = collision.reducedMCevent(); + VarManager::FillEvent(mcCollision); + /// event selection + runEventSelection(collision); + + /// Run muon selection and histo filling + // VarManager::ResetValues(0, VarManager::kNMCParticleVariables); + runSimulatedMuonSelection(muons); + } + PROCESS_SWITCH(tableMakerMuonMchTrkEfficiency, processSimReduced, "process reconstructed reduced information", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGDQ/Tasks/CMakeLists.txt b/PWGDQ/Tasks/CMakeLists.txt index 88e6b801cb2..190732ef36a 100644 --- a/PWGDQ/Tasks/CMakeLists.txt +++ b/PWGDQ/Tasks/CMakeLists.txt @@ -49,7 +49,7 @@ o2physics_add_dpl_workflow(flow PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore O2Physics::GFWCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(task-jpsi-hf - SOURCES taskJpsiHf.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore +o2physics_add_dpl_workflow(task-muon-mch-trk-eff + SOURCES taskMuonMchTrkEfficiency.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGDQ/Tasks/DalitzSelection.cxx b/PWGDQ/Tasks/DalitzSelection.cxx index 80ebf8bdbf7..ae5f9e13eda 100755 --- a/PWGDQ/Tasks/DalitzSelection.cxx +++ b/PWGDQ/Tasks/DalitzSelection.cxx @@ -32,6 +32,7 @@ #include "PWGDQ/Core/AnalysisCompositeCut.h" #include "PWGDQ/Core/HistogramsLibrary.h" #include "PWGDQ/Core/CutsLibrary.h" +#include "DataFormatsParameters/GRPMagField.h" using namespace o2; using namespace o2::framework; @@ -70,9 +71,12 @@ struct dalitzPairing { Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas"}; + Configurable fUseRemoteField{"cfgUseRemoteField", false, "Chose whether to fetch the magnetic field from ccdb or set it manually"}; + Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Service fCCDB; - + o2::parameters::GRPMagField* grpmag = nullptr; int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. Filter filterBarrelTrack = o2::aod::track::tpcInnerParam >= fConfigBarrelTrackPINLow && nabs(o2::aod::track::eta) <= fConfigEtaCut && o2::aod::pidtpc::tpcNSigmaEl <= fConfigTPCNSigHigh && o2::aod::pidtpc::tpcNSigmaEl >= fConfigTPCNSigLow; @@ -246,7 +250,7 @@ struct dalitzPairing { auto trackCut = fTrackCuts.begin(); for (auto pairCut = fPairCuts.begin(); pairCut != fPairCuts.end(); pairCut++, trackCut++, icut++) { if (filterMap & (uint8_t(1) << icut)) { - ((TH1I*)fStatsList->At(0))->Fill(icut + 1); + reinterpret_cast(fStatsList->At(0))->Fill(icut + 1); fHistMan->FillHistClass(Form("TrackBarrel_%s_%s", (*trackCut).GetName(), (*pairCut).GetName()), VarManager::fgValues); } } @@ -261,23 +265,46 @@ struct dalitzPairing { for (auto& collision : collisions) { fTrackmap.clear(); - VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); + VarManager::ResetValues(VarManager::kNRunWiseVariables, VarManager::kNBarrelTrackVariables); VarManager::FillEvent(collision); bool isEventSelected = fEventCut->IsSelected(VarManager::fgValues); if (isEventSelected) { - ((TH1I*)fStatsList->At(0))->Fill(0); + reinterpret_cast(fStatsList->At(0))->Fill(0); auto bc = collision.template bc_as(); - if (fConfigComputeTPCpostCalib && fCurrentRun != bc.runNumber()) { - auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, bc.timestamp()); - VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); - VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); - VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); - VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); - VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); - VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); + + if (fCurrentRun != bc.runNumber()) { + VarManager::ResetValues(0, VarManager::kNRunWiseVariables); + + // We setup the magnetic field, because the conversion rejection cut might depend on it + float magField = 0.; + if (fUseRemoteField.value) { + grpmag = fCCDB->getForTimeStamp(grpmagPath, bc.timestamp()); + if (grpmag != nullptr) { + magField = grpmag->getNominalL3Field(); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", bc.timestamp()); + } + } else { + magField = fConfigMagField.value; + } + LOGF(info, "setting mag field to %f", magField); + if (magField == 0.) { + LOGF(fatal, "magnetic field not set correctly, please check"); + } + VarManager::SetMagneticField(magField); + + if (fConfigComputeTPCpostCalib) { + auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, bc.timestamp()); + VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); + VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); + VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); + } fCurrentRun = bc.runNumber(); } diff --git a/PWGDQ/Tasks/dqEfficiency.cxx b/PWGDQ/Tasks/dqEfficiency.cxx index 3339f8036d0..00d9a08cb5c 100644 --- a/PWGDQ/Tasks/dqEfficiency.cxx +++ b/PWGDQ/Tasks/dqEfficiency.cxx @@ -22,7 +22,6 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGDQ/Core/VarManager.h" #include "PWGDQ/Core/HistogramManager.h" @@ -32,12 +31,8 @@ #include "PWGDQ/Core/CutsLibrary.h" #include "PWGDQ/Core/MCSignal.h" #include "PWGDQ/Core/MCSignalLibrary.h" -#include "DataFormatsParameters/GRPObject.h" #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" -#include "Field/MagneticField.h" -#include "TGeoGlobalMagField.h" -#include "DetectorsBase/Propagator.h" #include "DetectorsBase/GeometryManager.h" using std::cout; @@ -281,12 +276,12 @@ struct AnalysisTrackSelection { int isig = 0; for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrack) > 0) { - if ((*sig).CheckSignal(false, tracksMC, track.reducedMCTrack())) { + if ((*sig).CheckSignal(false, track.reducedMCTrack())) { mcDecision |= (uint32_t(1) << isig); } } if constexpr ((TTrackFillMap & VarManager::ObjTypes::Track) > 0) { - if ((*sig).CheckSignal(false, tracksMC, track.template mcParticle_as())) { + if ((*sig).CheckSignal(false, track.template mcParticle_as())) { mcDecision |= (uint32_t(1) << isig); } } @@ -445,12 +440,12 @@ struct AnalysisMuonSelection { int isig = 0; for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { if constexpr ((TMuonFillMap & VarManager::ObjTypes::ReducedMuon) > 0) { - if ((*sig).CheckSignal(false, muonsMC, muon.reducedMCTrack())) { + if ((*sig).CheckSignal(false, muon.reducedMCTrack())) { mcDecision |= (uint32_t(1) << isig); } } if constexpr ((TMuonFillMap & VarManager::ObjTypes::Muon) > 0) { - if ((*sig).CheckSignal(false, muonsMC, muon.template mcParticle_as())) { + if ((*sig).CheckSignal(false, muon.template mcParticle_as())) { mcDecision |= (uint32_t(1) << isig); } } @@ -756,7 +751,7 @@ struct AnalysisSameEventPairing { VarManager::FillPair(t1, t2); // secondary vertexing is not implemented for e-mu pairs so we need to hide this function from the e-mu analysis for now if constexpr ((TPairType == VarManager::kDecayToEE) || (TPairType == VarManager::kDecayToMuMu)) { - VarManager::FillPairVertexing(event, t1, t2, VarManager::fgValues); + VarManager::FillPairVertexing(event, t1, t2, fPropToPCA, VarManager::fgValues); } // run MC matching for this pair @@ -764,12 +759,12 @@ struct AnalysisSameEventPairing { int isig = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { if constexpr (TTrackFillMap & VarManager::ObjTypes::ReducedTrack || TTrackFillMap & VarManager::ObjTypes::ReducedMuon) { // for skimmed DQ model - if ((*sig).CheckSignal(false, tracksMC, t1.reducedMCTrack(), t2.reducedMCTrack())) { + if ((*sig).CheckSignal(false, t1.reducedMCTrack(), t2.reducedMCTrack())) { mcDecision |= (uint32_t(1) << isig); } } if constexpr (TTrackFillMap & VarManager::ObjTypes::Track || TTrackFillMap & VarManager::ObjTypes::Muon) { // for Framework data model - if ((*sig).CheckSignal(false, tracksMC, t1.template mcParticle_as(), t2.template mcParticle_as())) { + if ((*sig).CheckSignal(false, t1.template mcParticle_as(), t2.template mcParticle_as())) { mcDecision |= (uint32_t(1) << isig); } } @@ -783,7 +778,26 @@ struct AnalysisSameEventPairing { constexpr bool muonHasCov = ((TTrackFillMap & VarManager::ObjTypes::MuonCov) > 0 || (TTrackFillMap & VarManager::ObjTypes::ReducedMuonCov) > 0); if constexpr ((TPairType == VarManager::kDecayToMuMu) && muonHasCov) { if (fConfigFlatTables.value) { - dimuonAllList(event.posX(), event.posY(), event.posZ(), event.numContrib(), t1.fwdDcaX(), t1.fwdDcaY(), t2.fwdDcaX(), t2.fwdDcaY(), event.reducedMCevent().mcPosX(), event.reducedMCevent().mcPosY(), event.reducedMCevent().mcPosZ(), VarManager::fgValues[VarManager::kMass], dileptonMcDecision, VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), VarManager::fgValues[VarManager::kVertexingChi2PCA], VarManager::fgValues[VarManager::kVertexingTauz], VarManager::fgValues[VarManager::kVertexingTauzErr], VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], t1.pt(), t1.eta(), t1.phi(), t1.sign(), t2.pt(), t2.eta(), t2.phi(), t2.sign(), t1.mcMask(), t2.mcMask(), t1.chi2MatchMCHMID(), t2.chi2MatchMCHMID(), t1.chi2MatchMCHMFT(), t2.chi2MatchMCHMFT(), t1.chi2(), t2.chi2(), t1.reducedMCTrack().pt(), t1.reducedMCTrack().eta(), t1.reducedMCTrack().phi(), t1.reducedMCTrack().e(), t2.reducedMCTrack().pt(), t2.reducedMCTrack().eta(), t2.reducedMCTrack().phi(), t2.reducedMCTrack().e(), t1.reducedMCTrack().vx(), t1.reducedMCTrack().vy(), t1.reducedMCTrack().vz(), t1.reducedMCTrack().vt(), t2.reducedMCTrack().vx(), t2.reducedMCTrack().vy(), t2.reducedMCTrack().vz(), t2.reducedMCTrack().vt(), t1.isAmbiguous(), t2.isAmbiguous()); + dimuonAllList(event.posX(), event.posY(), event.posZ(), event.numContrib(), + event.reducedMCevent().mcPosX(), event.reducedMCevent().mcPosY(), event.reducedMCevent().mcPosZ(), + VarManager::fgValues[VarManager::kMass], + dileptonMcDecision, + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), VarManager::fgValues[VarManager::kVertexingChi2PCA], + VarManager::fgValues[VarManager::kVertexingTauz], VarManager::fgValues[VarManager::kVertexingTauzErr], + VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], + VarManager::fgValues[VarManager::kCosPointingAngle], + VarManager::fgValues[VarManager::kPt1], VarManager::fgValues[VarManager::kEta1], VarManager::fgValues[VarManager::kPhi1], t1.sign(), + VarManager::fgValues[VarManager::kPt2], VarManager::fgValues[VarManager::kEta2], VarManager::fgValues[VarManager::kPhi2], t2.sign(), + t1.fwdDcaX(), t1.fwdDcaY(), t2.fwdDcaX(), t2.fwdDcaY(), + t1.mcMask(), t2.mcMask(), + t1.chi2MatchMCHMID(), t2.chi2MatchMCHMID(), + t1.chi2MatchMCHMFT(), t2.chi2MatchMCHMFT(), + t1.chi2(), t2.chi2(), + t1.reducedMCTrack().pt(), t1.reducedMCTrack().eta(), t1.reducedMCTrack().phi(), t1.reducedMCTrack().e(), + t2.reducedMCTrack().pt(), t2.reducedMCTrack().eta(), t2.reducedMCTrack().phi(), t2.reducedMCTrack().e(), + t1.reducedMCTrack().vx(), t1.reducedMCTrack().vy(), t1.reducedMCTrack().vz(), t1.reducedMCTrack().vt(), + t2.reducedMCTrack().vx(), t2.reducedMCTrack().vy(), t2.reducedMCTrack().vz(), t2.reducedMCTrack().vt(), + t1.isAmbiguous(), t2.isAmbiguous()); } } @@ -810,7 +824,7 @@ struct AnalysisSameEventPairing { } // end runPairing template - void runMCGen(TTracksMC const& groupedMCTracks) + void runMCGen(TTracksMC& groupedMCTracks) { // loop over mc stack and fill histograms for pure MC truth signals // group all the MC tracks which belong to the MC event corresponding to the current reconstructed event @@ -824,7 +838,14 @@ struct AnalysisSameEventPairing { if (sig.GetNProngs() != 1) { // NOTE: 1-prong signals required continue; } - if (sig.CheckSignal(false, groupedMCTracks, mctrack)) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto mctrack_raw = groupedMCTracks.rawIteratorAt(mctrack.globalIndex()); + checked = sig.CheckSignal(false, mctrack_raw); + } else { + checked = sig.CheckSignal(false, mctrack); + } + if (checked) { fHistMan->FillHistClass(Form("MCTruthGen_%s", sig.GetName()), VarManager::fgValues); } } @@ -836,7 +857,15 @@ struct AnalysisSameEventPairing { continue; } for (auto& [t1, t2] : combinations(groupedMCTracks, groupedMCTracks)) { - if (sig.CheckSignal(false, groupedMCTracks, t1, t2)) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto t1_raw = groupedMCTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = groupedMCTracks.rawIteratorAt(t2.globalIndex()); + checked = sig.CheckSignal(false, t1_raw, t2_raw); + } else { + checked = sig.CheckSignal(false, t1, t2); + } + if (checked) { VarManager::FillPairMC(t1, t2); fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig.GetName()), VarManager::fgValues); } @@ -1052,14 +1081,23 @@ struct AnalysisDileptonTrack { // Set the global index offset to find the proper lepton // TO DO: remove it once the issue with lepton index is solved int indexOffset = -999; + std::vector trackGlobalIndexes; + + if (dileptons.size() > 0) { + for (auto track : tracks) { + trackGlobalIndexes.push_back(track.globalIndex()); + // std::cout << track.index() << " " << track.globalIndex() << std::endl; + } + } for (auto dilepton : dileptons) { int indexLepton1 = dilepton.index0Id(); int indexLepton2 = dilepton.index1Id(); if (indexOffset == -999) { - indexOffset = indexLepton1; + indexOffset = trackGlobalIndexes.at(0); } + trackGlobalIndexes.clear(); auto lepton1 = tracks.iteratorAt(indexLepton1 - indexOffset); auto lepton2 = tracks.iteratorAt(indexLepton2 - indexOffset); @@ -1085,7 +1123,7 @@ struct AnalysisDileptonTrack { int isig = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { if constexpr (TTrackFillMap & VarManager::ObjTypes::ReducedTrack || TTrackFillMap & VarManager::ObjTypes::ReducedMuon) { // for skimmed DQ model - if ((*sig).CheckSignal(false, tracksMC, lepton1MC, lepton2MC)) { + if ((*sig).CheckSignal(false, lepton1MC, lepton2MC)) { mcDecision |= (uint32_t(1) << isig); } } @@ -1117,7 +1155,7 @@ struct AnalysisDileptonTrack { isig = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { if constexpr (TTrackFillMap & VarManager::ObjTypes::ReducedTrack || TTrackFillMap & VarManager::ObjTypes::ReducedMuon || TTrackFillMap & VarManager::ObjTypes::ReducedMuon) { // for skimmed DQ model - if ((*sig).CheckSignal(false, tracksMC, lepton1MC, lepton2MC, trackMC)) { + if ((*sig).CheckSignal(false, lepton1MC, lepton2MC, trackMC)) { mcDecision |= (uint32_t(1) << isig); } } @@ -1151,7 +1189,14 @@ struct AnalysisDileptonTrack { if (sig.GetNProngs() != 1) { // NOTE: 1-prong signals required continue; } - if (sig.CheckSignal(false, groupedMCTracks, mctrack)) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto mctrack_raw = groupedMCTracks.rawIteratorAt(mctrack.globalIndex()); + checked = sig.CheckSignal(false, mctrack_raw); + } else { + checked = sig.CheckSignal(false, mctrack); + } + if (checked) { fHistMan->FillHistClass(Form("MCTruthGen_%s", sig.GetName()), VarManager::fgValues); } } diff --git a/PWGDQ/Tasks/dqFlow.cxx b/PWGDQ/Tasks/dqFlow.cxx index 5867bb01fef..07ea30e70e7 100644 --- a/PWGDQ/Tasks/dqFlow.cxx +++ b/PWGDQ/Tasks/dqFlow.cxx @@ -45,6 +45,7 @@ #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" +using std::complex; using std::cout; using std::endl; using std::string; diff --git a/PWGDQ/Tasks/filterPPwithAssociation.cxx b/PWGDQ/Tasks/filterPPwithAssociation.cxx index 4592f111f6a..48c7ff249ea 100644 --- a/PWGDQ/Tasks/filterPPwithAssociation.cxx +++ b/PWGDQ/Tasks/filterPPwithAssociation.cxx @@ -191,6 +191,7 @@ struct DQBarrelTrackSelection { Configurable fConfigMaxTpcSignal{"cfgMaxTpcSignal", 110.0, "Maximum TPC signal"}; Configurable fConfigCollisionTrackAssoc{"cfgCollisionTrackAssoc", 0, "0 - standard association, 1 - time compatibility, 2 - ambiguous"}; Configurable fConfigAssocTimeMargin{"cfgAssocTimeMargin", 0.0f, "Extra time margin to be considered when doing collision - track matching (in ns)"}; + Configurable fConfigSigmaForTimeCompat{"cfgSigmaForTimeCompat", 4.0, "nSigma window when doing collision - track matching "}; Service fCCDB; // o2::ccdb::CcdbApi fCCDB_api; /// API to access CCDB headers @@ -289,7 +290,7 @@ struct DQBarrelTrackSelection { return; } float timeMargin = fConfigAssocTimeMargin.value; - float nSigmaForTimeCompat = 4.0; + float nSigmaForTimeCompat = fConfigSigmaForTimeCompat.value; auto trackBegin = fSelectedTracks.begin(); const auto bOffsetMax = 241; // 6 mus (ITS) @@ -556,6 +557,7 @@ struct DQMuonsSelection { Configurable fConfigMuonPtLow{"cfgMuonLowPt", 0.5f, "Low pt cut for muons"}; Configurable fConfigCollisionMuonAssoc{"cfgCollisionMuonAssoc", 0, "0 - standard association, 1 - time compatibility, 2 - ambiguous"}; Configurable fConfigAssocTimeMargin{"cfgAssocTimeMargin", 0.0f, "Extra time margin to be considered when doing collision - muon matching (in ns)"}; + Configurable fConfigSigmaForTimeCompat{"cfgSigmaForTimeCompat", 4.0, "nSigma window when doing collision - track matching "}; Configurable fSigmaTrack{"cfgSigmaTrack", 1.0, "Number of sigma for track time window"}; Configurable fSigmaVtx{"cfgSigmaVtx", 4.0, "Number of sigma for vertex time window"}; Configurable fTimeMarginTrack{"cfgTimeMarginTrack", 0.0, "Number of sigma for track time window"}; @@ -685,7 +687,7 @@ struct DQMuonsSelection { return; } float timeMargin = fConfigAssocTimeMargin.value; - float nSigmaForTimeCompat = 4.0; + float nSigmaForTimeCompat = fConfigSigmaForTimeCompat.value; auto trackBegin = fSelectedMuons.begin(); const auto bOffsetMax = 200; // check 200 BCs in past and future diff --git a/PWGDQ/Tasks/filterPbPb.cxx b/PWGDQ/Tasks/filterPbPb.cxx index 6b0fc10e70d..4907411570c 100644 --- a/PWGDQ/Tasks/filterPbPb.cxx +++ b/PWGDQ/Tasks/filterPbPb.cxx @@ -10,6 +10,7 @@ // or submit itself to any jurisdiction. // #include +#include #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" @@ -30,27 +31,6 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; -/* -namespace o2::aod -{ -namespace dppbpbfilter -{ -DECLARE_SOA_COLUMN(IsDQBarrelSelected, isDQBarrelSelected, uint32_t); -} // namespace dqpbpbfilter - -DECLARE_SOA_TABLE(DQBarrelTrackCuts, "AOD", "DQBARRELCUTS", dqpbpbfilter::IsDQBarrelSelected); -} // namespace o2::aod -*/ -namespace o2::aod -{ -namespace dqppfilter -{ -DECLARE_SOA_COLUMN(IsDQBarrelSelected, isDQBarrelSelected, uint32_t); -} // namespace dqppfilter - -DECLARE_SOA_TABLE(DQBarrelTrackCuts, "AOD", "DQBARRELCUTS", dqppfilter::IsDQBarrelSelected); -} // namespace o2::aod - using MyEvents = soa::Join; using MyBCs = soa::Join; using MyBarrelTracks = soa::Join; -using MyBarrelTracksSelected = soa::Join; using MyMuons = aod::FwdTracks; constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision; -constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::Track | VarManager::ObjTypes::TrackExtra | VarManager::ObjTypes::TrackDCA | VarManager::ObjTypes::TrackSelection | VarManager::ObjTypes::TrackPID; void DefineHistograms(HistogramManager* histMan, TString histClasses); -struct DQBarrelTrackSelection { - Produces trackSel; - OutputObj fOutputList{"output"}; - HistogramManager* fHistMan; - - Configurable fConfigCuts{"cfgBarrelTrackCuts", "jpsiPID1", "Comma separated list of barrel track cuts"}; - Configurable fConfigQA{"cfgWithQA", false, "If true, fill QA histograms"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; - Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; - Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas"}; - - Service fCCDB; - - std::vector fTrackCuts; - std::vector fCutHistNames; - - int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. - - void init(o2::framework::InitContext&) - { - TString cutNamesStr = fConfigCuts.value; - if (!cutNamesStr.IsNull()) { - std::unique_ptr objArray(cutNamesStr.Tokenize(",")); - for (int icut = 0; icut < objArray->GetEntries(); ++icut) { - AnalysisCompositeCut* cut = dqcuts::GetCompositeCut(objArray->At(icut)->GetName()); - if (cut) { - fTrackCuts.push_back(*cut); - } else { - LOGF(fatal, "Invalid barrel track cut provided: %s", objArray->At(icut)->GetName()); - } - } - } - VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill - - if (fConfigQA) { - VarManager::SetDefaultVarNames(); - fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); - fHistMan->SetUseDefaultVariableNames(kTRUE); - fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); - - TString cutNames = "TrackBarrel_BeforeCuts;"; - for (auto& cut : fTrackCuts) { - cutNames += Form("TrackBarrel_%s;", cut.GetName()); - fCutHistNames.push_back(Form("TrackBarrel_%s", cut.GetName())); - } - - DefineHistograms(fHistMan, cutNames.Data()); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill - fOutputList.setObject(fHistMan->GetMainHistogramList()); - - // CCDB configuration - if (fConfigComputeTPCpostCalib) { - fCCDB->setURL(fConfigCcdbUrl.value); - fCCDB->setCaching(true); - fCCDB->setLocalObjectValidityChecking(); - // Not later than now objects - fCCDB->setCreatedNotAfter(fConfigNoLaterThan.value); - } - } - } - - // Templated function instantianed for all of the process functions - template - void runTrackSelection(aod::BCsWithTimestamps const& bcs, TTracks const& tracksBarrel) - { - auto bc = bcs.begin(); // check just the first bc to get the run number - if (fConfigComputeTPCpostCalib && fCurrentRun != bc.runNumber()) { - auto calibList = fCCDB->getForTimeStamp(fConfigCcdbPathTPC.value, bc.timestamp()); - VarManager::SetCalibrationObject(VarManager::kTPCElectronMean, calibList->FindObject("mean_map_electron")); - VarManager::SetCalibrationObject(VarManager::kTPCElectronSigma, calibList->FindObject("sigma_map_electron")); - VarManager::SetCalibrationObject(VarManager::kTPCPionMean, calibList->FindObject("mean_map_pion")); - VarManager::SetCalibrationObject(VarManager::kTPCPionSigma, calibList->FindObject("sigma_map_pion")); - VarManager::SetCalibrationObject(VarManager::kTPCProtonMean, calibList->FindObject("mean_map_proton")); - VarManager::SetCalibrationObject(VarManager::kTPCProtonSigma, calibList->FindObject("sigma_map_proton")); - fCurrentRun = bc.runNumber(); - } - - uint32_t filterMap = uint32_t(0); - trackSel.reserve(tracksBarrel.size()); - - VarManager::ResetValues(0, VarManager::kNBarrelTrackVariables); - for (auto& track : tracksBarrel) { - filterMap = uint32_t(0); - if (!track.has_collision()) { - trackSel(uint32_t(0)); - } else { - VarManager::FillTrack(track); - if (fConfigQA) { - fHistMan->FillHistClass("TrackBarrel_BeforeCuts", VarManager::fgValues); - } - int i = 0; - for (auto cut = fTrackCuts.begin(); cut != fTrackCuts.end(); ++cut, ++i) { - if ((*cut).IsSelected(VarManager::fgValues)) { - filterMap |= (uint32_t(1) << i); - if (fConfigQA) { - fHistMan->FillHistClass(fCutHistNames[i].Data(), VarManager::fgValues); - } - } - } - trackSel(filterMap); - } - } // end loop over tracks - } - - void processSelection(aod::BCsWithTimestamps const& bcs, MyBarrelTracks const& tracks) - { - runTrackSelection(bcs, tracks); - } - void processDummy(MyBarrelTracks&) - { - // do nothing - } - - PROCESS_SWITCH(DQBarrelTrackSelection, processSelection, "Run barrel track selection", true); - PROCESS_SWITCH(DQBarrelTrackSelection, processDummy, "Dummy function", false); -}; - struct DQFilterPbPbTask { Produces eventFilter; OutputObj fStats{"Statistics"}; + OutputObj fIsEventDGOutcome{TH1F("Filter outcome", "Filter outcome", 14, -1.5, 6.5)}; Configurable fConfigBarrelSelections{"cfgBarrelSels", "jpsiPID1:2:5", "::,[::],..."}; Configurable fConfigNDtColl{"cfgNDtColl", 4, "Number of standard deviations to consider in BC range"}; Configurable fConfigMinNBCs{"cfgMinNBCs", 7, "Minimum number of BCs to consider in BC range"}; - Configurable fConfigFV0AmpLimit{"cfgFV0AmpLimit", 0, "FV0 amplitude limit for double gap event selection"}; - Configurable fConfigFT0AAmpLimit{"cfgFT0AAmpLimit", 0, "FT0A amplitude limit for double gap event selection"}; - Configurable fConfigFT0CAmpLimit{"cfgFT0CAmpLimit", 0, "FT0C amplitude limit for double gap event selection"}; - Configurable fConfigFDDAAmpLimit{"cfgFDDAAmpLimit", 0, "FDDA amplitude limit for double gap event selection"}; - Configurable fConfigFDDCAmpLimit{"cfgFDDCAmpLimit", 0, "FDDC amplitude limit for double gap event selection"}; - Configurable fConfigUseFV0{"cfgUseFV0", true, "Whether to use FV0 for DG veto"}; - Configurable fConfigUseFT0{"cfgUseFT0", true, "Whether to use FT0 for DG veto"}; - Configurable fConfigUseFDD{"cfgUseFDD", true, "Whether to use FDD for DG veto"}; - - Filter filterBarrelTrackSelected = aod::dqppfilter::isDQBarrelSelected > uint32_t(0); + Configurable fConfigMinNPVCs{"cfgMinNPVCs", 2, "Minimum number of PV contributors"}; + Configurable fConfigMaxNPVCs{"cfgMaxNPVCs", 5, "Maximum number of PV contributors"}; + Configurable fConfigMaxFITTime{"cfgMaxFITTime", 4, "Maximum time in FIT"}; + Configurable fConfigFV0AmpLimit{"cfgFV0AmpLimit", 0, "FV0 amplitude limit for event selection"}; + Configurable fConfigFT0AAmpLimit{"cfgFT0AAmpLimit", 0, "FT0A amplitude limit for event selection"}; + Configurable fConfigFT0CAmpLimit{"cfgFT0CAmpLimit", 0, "FT0C amplitude limit for event selection"}; + Configurable fConfigFDDAAmpLimit{"cfgFDDAAmpLimit", 0, "FDDA amplitude limit for event selection"}; + Configurable fConfigFDDCAmpLimit{"cfgFDDCAmpLimit", 0, "FDDC amplitude limit for event selection"}; + Configurable fConfigUseFV0{"cfgUseFV0", true, "Whether to use FV0 for veto"}; + Configurable fConfigUseFT0{"cfgUseFT0", true, "Whether to use FT0 for veto"}; + Configurable fConfigUseFDD{"cfgUseFDD", true, "Whether to use FDD for veto"}; + Configurable fConfigFITSides{"cfgFITSides", "both", "both, either, A, C, neither"}; + Configurable fConfigVetoForward{"cfgVetoForward", true, "Whether to veto on forward tracks"}; + Configurable fConfigVetoBarrel{"cfgVetoBarrel", false, "Whether to veto on barrel tracks"}; + + // Filter filterBarrelTrackSelected = aod::dqppfilter::isDQBarrelSelected > uint32_t(0); int fNBarrelCuts; // number of barrel selections std::vector fBarrelNminTracks; // minimal number of tracks in barrel std::vector fBarrelNmaxTracks; // maximal number of tracks in barrel + int FITVetoSides = -1; // Integer to encode which side(s) of the FIT to use for veto + std::vector FITVetoSidesOptions = {"both", "either", "A", "C", "neither"}; + // Helper function for selecting DG events - bool isEventDG(MyEvents::iterator const& collision, MyBCs const& bcs, MyBarrelTracksSelected const& tracks, MyMuons const& muons, - aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds, - std::vector FITAmpLimits, int nDtColl, int minNBCs, bool useFV0, bool useFT0, bool useFDD) + template + int isEventDG(TEvent const& collision, TBCs const& bcs, TTracks const& tracks, TMuons const& muons, + aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds, + std::vector FITAmpLimits, int nDtColl, int minNBCs, int minNPVCs, int maxNPVCs, float maxFITTime, + bool useFV0, bool useFT0, bool useFDD, int FITSide, bool doVetoFwd, bool doVetoBarrel) { + fIsEventDGOutcome->Fill(0., 1.); // Find BC associated with collision if (!collision.has_foundBC()) { - return 0; + return -1; } // foundBCId is stored in EvSels - auto bc = collision.foundBC_as(); + auto bc = collision.template foundBC_as(); // Obtain slice of compatible BCs uint64_t mostProbableBC = bc.globalBC(); @@ -236,38 +104,52 @@ struct DQFilterPbPbTask { uint64_t minBC = (uint64_t)deltaBC < meanBC ? meanBC - (uint64_t)deltaBC : 0; uint64_t maxBC = meanBC + (uint64_t)deltaBC; - // find slice of BCs table with BC in [minBC, maxBC] - int64_t minBCId = bc.globalIndex(); - int64_t maxBCId = bc.globalIndex(); - - // lower limit - if (bc.globalBC() < minBC) { - while (bc != bcs.end() && bc.globalBC() < minBC) { - ++bc; - minBCId = bc.globalIndex(); - } - } else { - while (bc.globalIndex() > 0 && bc.globalBC() >= minBC) { - minBCId = bc.globalIndex(); - --bc; - } - } - // upper limit - if (bc.globalBC() < maxBC) { - while (bc != bcs.end() && bc.globalBC() <= maxBC) { - maxBCId = bc.globalIndex(); - ++bc; + int slicemin = 0; + int slicemax = 0; + // Check if there is overlap between acceptable and possible BCs + if (maxBC > bcs.iteratorAt(0).globalBC() && minBC < bcs.iteratorAt(bcs.size() - 1).globalBC()) { + // find slice of BCs table with BC in [minBC, maxBC] + int moveCount = 0; + int64_t minBCId = bc.globalIndex(); + int64_t maxBCId = bc.globalIndex(); + // lower limit + if (bc.globalBC() < minBC) { + while (bc != bcs.end() && bc.globalBC() < minBC) { + ++bc; + ++moveCount; + minBCId = bc.globalIndex(); + } + } else { + while (bc.globalIndex() > 0 && bc.globalBC() >= minBC) { + minBCId = bc.globalIndex(); + --bc; + --moveCount; + } } - } else { - while (bc.globalIndex() > 0 && bc.globalBC() > maxBC) { - --bc; - maxBCId = bc.globalIndex(); + // upper limit + if (bc.globalBC() < maxBC) { + while (bc != bcs.end() && bc.globalBC() <= maxBC) { + maxBCId = bc.globalIndex(); + ++bc; + ++moveCount; + } + } else { + while (bc.globalIndex() > 0 && bc.globalBC() > maxBC) { + --bc; + --moveCount; + maxBCId = bc.globalIndex(); + } } + // reset bc + bc.moveByIndex(-moveCount); + // Create BC slice + slicemin = minBCId; + slicemax = maxBCId - minBCId + 1; } - MyBCs bcrange{{bcs.asArrowTable()->Slice(minBCId, maxBCId - minBCId + 1)}, (uint64_t)minBCId}; - + MyBCs bcrange{{bcs.asArrowTable()->Slice(slicemin, slicemax)}, (uint16_t)slicemin}; // DG condition: Check FIT activity in BC range - bool cleanFIT = true; + bool isSideAClean = true; + bool isSideCClean = true; for (auto const& bc : bcrange) { if (useFV0) { @@ -277,8 +159,9 @@ struct DQFilterPbPbTask { for (auto amp : fv0a.amplitude()) { FV0Amplitude += amp; } - if (FV0Amplitude > FITAmpLimits[0]) { - cleanFIT = false; + float FV0Time = std::abs(fv0a.time()); + if (FV0Amplitude > FITAmpLimits[0] || FV0Time > maxFITTime) { + isSideAClean = false; } } } @@ -293,8 +176,13 @@ struct DQFilterPbPbTask { for (auto amp : ft0.amplitudeC()) { FT0CAmplitude += amp; } - if (FT0AAmplitude > FITAmpLimits[1] || FT0CAmplitude > FITAmpLimits[2]) { - cleanFIT = false; + float FT0ATime = std::abs(ft0.timeA()); + float FT0CTime = std::abs(ft0.timeC()); + if (FT0AAmplitude > FITAmpLimits[1] || FT0ATime > maxFITTime) { + isSideAClean = false; + } + if (FT0CAmplitude > FITAmpLimits[2] || FT0CTime > maxFITTime) { + isSideCClean = false; } } } @@ -309,29 +197,64 @@ struct DQFilterPbPbTask { for (auto amp : fdd.chargeC()) { FDDCAmplitude += amp; } - if (FDDAAmplitude > FITAmpLimits[3] || FDDCAmplitude > FITAmpLimits[4]) { - cleanFIT = false; + float FDDATime = std::abs(fdd.timeA()); + float FDDCTime = std::abs(fdd.timeC()); + if (FDDAAmplitude > FITAmpLimits[3] || FDDATime > maxFITTime) { + isSideAClean = false; + } + if (FDDCAmplitude > FITAmpLimits[4] || FDDCTime > maxFITTime) { + isSideCClean = false; } } } } - // DG condition: Veto on activiy in either forward or barrel region. Save info on both cases - bool muonsEmpty = true; - if (muons.size() > 0) { - muonsEmpty = false; + // Compute FIT decision + bool FITDecision = 0; + if (FITSide == 0) { + FITDecision = isSideAClean && isSideCClean; + } else if (FITSide == 1) { + FITDecision = isSideAClean ^ isSideCClean; + } else if (FITSide == 2) { + FITDecision = isSideAClean; + } else if (FITSide == 3) { + FITDecision = isSideCClean; + } else if (FITSide == 4) { + FITDecision = 1; } - bool barrelEmpty = true; - if (tracks.size() > 0) { - barrelEmpty = false; + if (!FITDecision) { + return 1; } - // Compute decision. For now only check if FIT is empty and there are no forward tracks - if (cleanFIT && muonsEmpty) { - return 1; - } else { - return 0; + // Veto on activiy in either forward or barrel region + if (doVetoFwd) { + for (auto& muon : muons) { + // Only care about muons with good timing (MID) + if (muon.trackType() == 0 || muon.trackType() == 3) { + return 2; + } + } + } + if (doVetoBarrel) { + if (tracks.size() > 0) { + return 3; + } + } + + // No global tracks which are not vtx tracks + for (auto& track : tracks) { + if (track.isGlobalTrack() && !track.isPVContributor()) { + return 4; + } + } + + // Number of primary vertex contributors + if (collision.numContrib() < minNPVCs || collision.numContrib() > maxNPVCs) { + return 5; } + + // If we made it here, the event passed + return 0; } void DefineCuts() @@ -367,42 +290,41 @@ struct DQFilterPbPbTask { void init(o2::framework::InitContext&) { DefineCuts(); + + for (int i = 0; i < 5; i++) { + if (fConfigFITSides.value == FITVetoSidesOptions[i]) { + FITVetoSides = i; + } + } + if (FITVetoSides == -1) { + LOGF(fatal, "Invalid choice of FIT side(s) for veto: %s", fConfigFITSides.value); + } } template - void runFilterPbPb(MyEvents::iterator const& collision, MyBCs const& bcs, MyBarrelTracksSelected const& tracks, MyMuons const& muons, + void runFilterPbPb(MyEvents::iterator const& collision, MyBCs const& bcs, MyBarrelTracks const& tracks, MyMuons const& muons, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { fStats->Fill(-2.0); std::vector FITAmpLimits = {fConfigFV0AmpLimit, fConfigFT0AAmpLimit, fConfigFT0CAmpLimit, fConfigFDDAAmpLimit, fConfigFDDCAmpLimit}; - bool isDG = isEventDG(collision, bcs, tracks, muons, ft0s, fv0as, fdds, FITAmpLimits, fConfigNDtColl, fConfigMinNBCs, fConfigUseFV0, fConfigUseFT0, fConfigUseFDD); - fStats->Fill(-1.0, isDG); + int filterOutcome = isEventDG(collision, bcs, tracks, muons, ft0s, fv0as, fdds, + FITAmpLimits, fConfigNDtColl, fConfigMinNBCs, fConfigMinNPVCs, fConfigMaxNPVCs, fConfigMaxFITTime, + fConfigUseFV0, fConfigUseFT0, fConfigUseFDD, FITVetoSides, fConfigVetoForward, fConfigVetoBarrel); + fIsEventDGOutcome->Fill(filterOutcome + 1, 1); - std::vector objCountersBarrel(fNBarrelCuts, 0); // init all counters to zero - // Count the number of barrel tracks fulfilling each cut - for (auto track : tracks) { - for (int i = 0; i < fNBarrelCuts; ++i) { - if (track.isDQBarrelSelected() & (uint32_t(1) << i)) { - objCountersBarrel[i] += 1; - } - } - } + // Don't need info on filter outcome anymore; reduce to a boolean + bool isDG = !filterOutcome; + fStats->Fill(-1.0, isDG); // Compute event filter uint64_t filter = 0; filter |= isDG; - for (int i = 0; i < fNBarrelCuts; i++) { - if (objCountersBarrel[i] >= fBarrelNminTracks[i] && objCountersBarrel[i] <= fBarrelNmaxTracks[i]) { - filter |= (uint64_t(1) << i + 1); - fStats->Fill(static_cast(i)); - } - } eventFilter(filter); } void processFilterPbPb(MyEvents::iterator const& collision, MyBCs const& bcs, - soa::Filtered const& tracks, MyMuons const& muons, + MyBarrelTracks const& tracks, MyMuons const& muons, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { runFilterPbPb(collision, bcs, tracks, muons, ft0s, fv0as, fdds); @@ -420,7 +342,6 @@ struct DQFilterPbPbTask { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; } diff --git a/PWGDQ/Tasks/tableReader.cxx b/PWGDQ/Tasks/tableReader.cxx index b2d61f6be55..a769ba715f5 100644 --- a/PWGDQ/Tasks/tableReader.cxx +++ b/PWGDQ/Tasks/tableReader.cxx @@ -88,6 +88,7 @@ using MyBarrelTracksWithCov = soa::Join; using MyBarrelTracksSelectedWithPrefilter = soa::Join; using MyBarrelTracksSelectedWithCov = soa::Join; +using MyBarrelTracksSelectedWithColl = soa::Join; using MyPairCandidatesSelected = soa::Join; using MyMuonTracks = soa::Join; using MyMuonTracksSelected = soa::Join; @@ -101,6 +102,7 @@ constexpr static uint32_t gkEventFillMapWithQvector = VarManager::ObjTypes::Redu constexpr static uint32_t gkEventFillMapWithCovQvector = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov | VarManager::ObjTypes::ReducedEventQvector; constexpr static uint32_t gkTrackFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID; constexpr static uint32_t gkTrackFillMapWithCov = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelCov | VarManager::ObjTypes::ReducedTrackBarrelPID; +constexpr static uint32_t gkTrackFillMapWithColl = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::ReducedTrackBarrel | VarManager::ObjTypes::ReducedTrackBarrelPID | VarManager::ObjTypes::ReducedTrackCollInfo; constexpr static uint32_t gkMuonFillMap = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra; constexpr static uint32_t gkMuonFillMapWithCov = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra | VarManager::ObjTypes::ReducedMuonCov; @@ -210,6 +212,9 @@ struct AnalysisTrackSelection { Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas"}; Configurable fConfigRunPeriods{"cfgRunPeriods", "LHC22f", "run periods for used data"}; + Configurable fConfigDummyRunlist{"cfgDummyRunlist", false, "If true, use dummy runlist"}; + Configurable fConfigInitRunNumber{"cfgInitRunNumber", 543215, "Initial run number used in run by run checks"}; + Service fCCDB; HistogramManager* fHistMan; @@ -248,7 +253,11 @@ struct AnalysisTrackSelection { VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } - + if (fConfigDummyRunlist) { + VarManager::SetDummyRunlist(fConfigInitRunNumber); + } else { + VarManager::SetRunlist((TString)fConfigRunPeriods); + } if (fConfigComputeTPCpostCalib) { // CCDB configuration fCCDB->setURL(fConfigCcdbUrl.value); @@ -742,6 +751,8 @@ struct AnalysisSameEventPairing { Configurable fNoCorr{"cfgNoCorrFwdProp", false, "Do not correct for MCS effects in track propagation"}; Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable fCollisionSystem{"syst", "pp", "Collision system, pp or PbPb"}; + Configurable fCenterMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; Service ccdb; Filter filterEventSelected = aod::dqanalysisflags::isEventSelected == 1; @@ -898,6 +909,8 @@ struct AnalysisSameEventPairing { // ccdb->setLocalObjectValidityChecking(); // ccdb->setCreatedNotAfter(nolaterthan.value); + VarManager::SetCollisionSystem((TString)fCollisionSystem, fCenterMassEnergy); // set collision system and center of mass energy + DefineHistograms(fHistMan, histNames.Data(), fConfigAddSEPHistogram); // define all histograms VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); @@ -972,7 +985,7 @@ struct AnalysisSameEventPairing { // TODO: FillPair functions need to provide a template argument to discriminate between cases when cov matrix is available or not VarManager::FillPair(t1, t2); if constexpr ((TPairType == pairTypeEE) || (TPairType == pairTypeMuMu)) { // call this just for ee or mumu pairs - VarManager::FillPairVertexing(event, t1, t2); + VarManager::FillPairVertexing(event, t1, t2, fPropToPCA); if constexpr (eventHasQvector) { VarManager::FillPairVn(t1, t2); } @@ -982,6 +995,9 @@ struct AnalysisSameEventPairing { dileptonFilterMap = twoTrackFilter; dileptonList(event, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision); + if constexpr ((TPairType == pairTypeMuMu) || (TPairType == pairTypeEE && ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackCollInfo) > 0))) { + dileptonInfoList(t1.collisionId(), event.posX(), event.posY(), event.posZ()); + } constexpr bool trackHasCov = ((TTrackFillMap & VarManager::ObjTypes::TrackCov) > 0 || (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelCov) > 0); if constexpr ((TPairType == pairTypeEE) && trackHasCov) { @@ -991,9 +1007,27 @@ struct AnalysisSameEventPairing { if constexpr ((TPairType == pairTypeMuMu) && muonHasCov) { // LOGP(info, "mu1 collId = {}, mu2 collId = {}", t1.collisionId(), t2.collisionId()); dileptonExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauz], VarManager::fgValues[VarManager::kVertexingLz], VarManager::fgValues[VarManager::kVertexingLxy]); - dileptonInfoList(t1.collisionId(), event.posX(), event.posY(), event.posZ()); if (fConfigFlatTables.value) { - dimuonAllList(event.posX(), event.posY(), event.posZ(), event.numContrib(), t1.fwdDcaX(), t1.fwdDcaY(), t2.fwdDcaX(), t2.fwdDcaY(), -999., -999., -999., VarManager::fgValues[VarManager::kMass], false, VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), VarManager::fgValues[VarManager::kVertexingChi2PCA], VarManager::fgValues[VarManager::kVertexingTauz], VarManager::fgValues[VarManager::kVertexingTauzErr], VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], t1.pt(), t1.eta(), t1.phi(), t1.sign(), t2.pt(), t2.eta(), t2.phi(), t2.sign(), 0., 0., t1.chi2MatchMCHMID(), t2.chi2MatchMCHMID(), t1.chi2MatchMCHMFT(), t2.chi2MatchMCHMFT(), t1.chi2(), t2.chi2(), -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., -999., t1.isAmbiguous(), t2.isAmbiguous()); + dimuonAllList(event.posX(), event.posY(), event.posZ(), event.numContrib(), + -999., -999., -999., + VarManager::fgValues[VarManager::kMass], + false, + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), VarManager::fgValues[VarManager::kVertexingChi2PCA], + VarManager::fgValues[VarManager::kVertexingTauz], VarManager::fgValues[VarManager::kVertexingTauzErr], + VarManager::fgValues[VarManager::kVertexingTauxy], VarManager::fgValues[VarManager::kVertexingTauxyErr], + VarManager::fgValues[VarManager::kCosPointingAngle], + VarManager::fgValues[VarManager::kPt1], VarManager::fgValues[VarManager::kEta1], VarManager::fgValues[VarManager::kPhi1], t1.sign(), + VarManager::fgValues[VarManager::kPt2], VarManager::fgValues[VarManager::kEta2], VarManager::fgValues[VarManager::kPhi2], t2.sign(), + t1.fwdDcaX(), t1.fwdDcaY(), t2.fwdDcaX(), t2.fwdDcaY(), + 0., 0., + t1.chi2MatchMCHMID(), t2.chi2MatchMCHMID(), + t1.chi2MatchMCHMFT(), t2.chi2MatchMCHMFT(), + t1.chi2(), t2.chi2(), + -999., -999., -999., -999., + -999., -999., -999., -999., + -999., -999., -999., -999., + -999., -999., -999., -999., + t1.isAmbiguous(), t2.isAmbiguous()); } } @@ -1063,6 +1097,13 @@ struct AnalysisSameEventPairing { VarManager::FillEvent(event, VarManager::fgValues); runSameEventPairing(event, tracks, tracks); } + void processDecayToEESkimmedWithColl(soa::Filtered::iterator const& event, soa::Filtered const& tracks) + { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event, VarManager::fgValues); + runSameEventPairing(event, tracks, tracks); + } void processDecayToMuMuSkimmed(soa::Filtered::iterator const& event, soa::Filtered const& muons) { // Reset the fValues array @@ -1124,6 +1165,7 @@ struct AnalysisSameEventPairing { PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToEESkimmedWithCov, "Run electron-electron pairing, with skimmed covariant tracks", false); PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToEEVertexingSkimmed, "Run electron-electron pairing and vertexing, with skimmed electrons", false); PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToEEPrefilterSkimmed, "Run electron-electron pairing, with skimmed tracks and prefilter from AnalysisPrefilterSelection", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToEESkimmedWithColl, "Run electron-electron pairing, with skimmed tracks and with collision information", false); PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToMuMuSkimmed, "Run muon-muon pairing, with skimmed muons", false); PROCESS_SWITCH(AnalysisSameEventPairing, processDecayToMuMuVertexingSkimmed, "Run muon-muon pairing and vertexing, with skimmed muons", false); PROCESS_SWITCH(AnalysisSameEventPairing, processVnDecayToEESkimmed, "Run electron-electron pairing, with skimmed tracks for vn", false); @@ -1151,9 +1193,13 @@ struct AnalysisDileptonHadron { Configurable fConfigTrackCuts{"cfgLeptonCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; // comment: add list of subgroups (must define subgroups under ) Configurable fConfigAddDileptonHadHistogram{"cfgAddDileptonHadHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigMixingDepth{"cfgMixingDepth", 5, "Event mixing pool depth"}; + Configurable fConfigDileptonLowMass{"cfgDileptonLowMass", 2.8, "Low mass cut for the dileptons used in analysis"}; + Configurable fConfigDileptonHighMass{"cfgDileptonHighMass", 3.2, "High mass cut for the dileptons used in analysis"}; Filter eventFilter = aod::dqanalysisflags::isEventSelected == 1; - Filter dileptonFilter = aod::reducedpair::mass > 2.92f && aod::reducedpair::mass < 3.16f && aod::reducedpair::sign == 0; + Filter dileptonFilter = aod::reducedpair::mass > fConfigDileptonLowMass.value&& aod::reducedpair::mass < fConfigDileptonHighMass.value&& aod::reducedpair::sign == 0; + Filter filterBarrelTrackSelected = aod::dqanalysisflags::isBarrelSelected > 0; constexpr static uint32_t fgDileptonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::Pair; // fill map @@ -1167,6 +1213,8 @@ struct AnalysisDileptonHadron { // The current condition should be replaced when bitwise operators will become available in Filter expressions int fNHadronCutBit; + NoBinningPolicy hashBin; + void init(o2::framework::InitContext& context) { fValuesDilepton = new float[VarManager::kNVars]; @@ -1180,9 +1228,13 @@ struct AnalysisDileptonHadron { // TODO: Implement possibly multiple selections for the associated track ? if (context.mOptions.get("processSkimmed")) { DefineHistograms(fHistMan, "DileptonsSelected;DileptonHadronInvMass;DileptonHadronCorrelation", fConfigAddDileptonHadHistogram); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); - fOutputList.setObject(fHistMan->GetMainHistogramList()); } + if (context.mOptions.get("processMixedEvent")) { + DefineHistograms(fHistMan, "DileptonHadronInvMassME", fConfigAddDileptonHadHistogram); // define all histograms + } + + VarManager::SetUseVars(fHistMan->GetUsedVars()); + fOutputList.setObject(fHistMan->GetMainHistogramList()); TString configCutNamesStr = fConfigTrackCuts.value; if (!configCutNamesStr.IsNull()) { @@ -1205,6 +1257,14 @@ struct AnalysisDileptonHadron { // Set the global index offset to find the proper lepton // TO DO: remove it once the issue with lepton index is solved int indexOffset = -999; + std::vector trackGlobalIndexes; + + if (dileptons.size() > 0) { + for (auto track : tracks) { + trackGlobalIndexes.push_back(track.globalIndex()); + // std::cout << track.index() << " " << track.globalIndex() << std::endl; + } + } // loop once over dileptons for QA purposes for (auto dilepton : dileptons) { VarManager::FillTrack(dilepton, fValuesDilepton); @@ -1215,10 +1275,13 @@ struct AnalysisDileptonHadron { int indexLepton2 = dilepton.index1Id(); if (indexOffset == -999) { - indexOffset = indexLepton1; + indexOffset = trackGlobalIndexes.at(0); } + trackGlobalIndexes.clear(); // get full track info of tracks based on the index + std::cout << indexLepton1 - indexOffset << std::endl; + std::cout << indexLepton2 - indexOffset << std::endl; auto lepton1 = tracks.iteratorAt(indexLepton1 - indexOffset); auto lepton2 = tracks.iteratorAt(indexLepton2 - indexOffset); @@ -1256,12 +1319,47 @@ struct AnalysisDileptonHadron { { runDileptonHadron(event, tracks, dileptons); } + + Preslice> perEventPairs = aod::reducedpair::reducedeventId; + Preslice> perEventTracks = aod::reducedtrack::reducedeventId; + + void processMixedEvent(soa::Filtered& events, soa::Filtered const& dileptons, soa::Filtered const& tracks) + { + events.bindExternalIndices(&dileptons); + events.bindExternalIndices(&tracks); + + for (auto& [event1, event2] : selfCombinations(hashBin, fConfigMixingDepth.value, -1, events, events)) { + VarManager::ResetValues(0, VarManager::kNVars); + VarManager::FillEvent(event1, VarManager::fgValues); + + auto evDileptons = dileptons.sliceBy(perEventPairs, event1.globalIndex()); + evDileptons.bindExternalIndices(&events); + + auto evTracks = tracks.sliceBy(perEventTracks, event2.globalIndex()); + evTracks.bindExternalIndices(&events); + + for (auto dilepton : evDileptons) { + for (auto& track : evTracks) { + + if (!(uint32_t(track.isBarrelSelected()) & (uint32_t(1) << fNHadronCutBit))) { + continue; + } + + VarManager::FillDileptonHadron(dilepton, track, VarManager::fgValues); + fHistMan->FillHistClass("DileptonHadronInvMassME", VarManager::fgValues); + } // end for (track) + } // end for (dilepton) + + } // end event loop + } + void processDummy(MyEvents&) { // do nothing } PROCESS_SWITCH(AnalysisDileptonHadron, processSkimmed, "Run dilepton-hadron pairing, using skimmed data", false); + PROCESS_SWITCH(AnalysisDileptonHadron, processMixedEvent, "Run dilepton-hadron mixed event pairing", false); PROCESS_SWITCH(AnalysisDileptonHadron, processDummy, "Dummy function", false); }; diff --git a/PWGDQ/Tasks/taskJpsiHf.cxx b/PWGDQ/Tasks/taskJpsiHf.cxx index 1e0bfa855c9..967ed9e7c75 100644 --- a/PWGDQ/Tasks/taskJpsiHf.cxx +++ b/PWGDQ/Tasks/taskJpsiHf.cxx @@ -21,6 +21,7 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGDQ/DataModel/ReducedInfoTables.h" @@ -29,7 +30,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod; -using namespace o2::aod::hf_cand_2prong; // Declarations of various short names using MyEvents = soa::Join; @@ -61,8 +61,10 @@ struct taskJPsiHf { Configurable configDebug{"configDebug", true, "If true, fill D0 - J/psi histograms separately"}; SliceCache cache; + HfHelper hfHelper; + Partition selectedDileptonCandidates = aod::reducedpair::mass > 1.0f && aod::reducedpair::mass < 5.0f && aod::reducedpair::sign == 0; - Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar > selectionFlagD0bar; + Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; Preslice perCollisionDmeson = aod::hf_cand::collisionId; Preslice perCollisionDilepton = aod::reducedpair::collisionId; @@ -108,13 +110,13 @@ struct taskJPsiHf { { if (configDebug) { for (auto& dmeson : dmesons) { - if (!TESTBIT(dmeson.hfflag(), DecayType::D0ToPiK)) { + if (!TESTBIT(dmeson.hfflag(), hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - auto rapD0 = yD0(dmeson); + auto rapD0 = hfHelper.yD0(dmeson); - if (yCandMax >= 0. && std::abs(yD0(dmeson)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(dmeson)) > yCandMax) { continue; } @@ -124,7 +126,7 @@ struct taskJPsiHf { auto massD0bar = -1.; if (dmeson.isSelD0() >= selectionFlagD0) { - massD0 = invMassD0ToPiK(dmeson); + massD0 = hfHelper.invMassD0ToPiK(dmeson); registry.fill(HIST("Dmeson/hMassDmeson"), massD0); registry.fill(HIST("Dmeson/hPtDmeson"), ptD0); registry.fill(HIST("Dmeson/hRapDmeson"), rapD0); @@ -132,7 +134,7 @@ struct taskJPsiHf { } if (dmeson.isSelD0bar() >= selectionFlagD0bar) { - massD0bar = invMassD0ToPiK(dmeson); + massD0bar = hfHelper.invMassD0ToPiK(dmeson); registry.fill(HIST("Dmeson/hMassDmeson"), massD0bar); registry.fill(HIST("Dmeson/hPtDmeson"), ptD0); registry.fill(HIST("Dmeson/hRapDmeson"), rapD0); @@ -161,11 +163,11 @@ struct taskJPsiHf { // loop over D mesons for (auto& dmeson : dmesons) { - if (!TESTBIT(dmeson.hfflag(), DecayType::D0ToPiK)) { + if (!TESTBIT(dmeson.hfflag(), hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - auto rapD0 = yD0(dmeson); + auto rapD0 = hfHelper.yD0(dmeson); if (yCandMax >= 0. && std::abs(rapD0) > yCandMax) { continue; @@ -179,7 +181,7 @@ struct taskJPsiHf { auto phiDelta = std::abs(phiJPsi - phiD0); if (dmeson.isSelD0() >= selectionFlagD0) { - massD0 = invMassD0ToPiK(dmeson); + massD0 = hfHelper.invMassD0ToPiK(dmeson); registry.fill(HIST("JPsiDmeson/hSparseJPsiDmeson"), ptJPsi, ptD0, massJPsi, massD0, rapDelta, phiDelta); registry.fill(HIST("JPsiDmeson/hMassJPsiWithDmeson"), massJPsi); registry.fill(HIST("JPsiDmeson/hPtJPsiWithDmeson"), ptJPsi); @@ -191,7 +193,7 @@ struct taskJPsiHf { registry.fill(HIST("JPsiDmeson/hPhiDmesonWithJPsi"), phiD0); } if (dmeson.isSelD0bar() >= selectionFlagD0bar) { - massD0bar = invMassD0barToKPi(dmeson); + massD0bar = hfHelper.invMassD0barToKPi(dmeson); registry.fill(HIST("JPsiDmeson/hSparseJPsiDmeson"), ptJPsi, ptD0, massJPsi, massD0bar, rapDelta, phiDelta); registry.fill(HIST("JPsiDmeson/hMassJPsiWithDmeson"), massJPsi); registry.fill(HIST("JPsiDmeson/hPtJPsiWithDmeson"), ptJPsi); diff --git a/PWGDQ/Tasks/taskMuonMchTrkEfficiency.cxx b/PWGDQ/Tasks/taskMuonMchTrkEfficiency.cxx new file mode 100644 index 00000000000..f1bd0e9ef06 --- /dev/null +++ b/PWGDQ/Tasks/taskMuonMchTrkEfficiency.cxx @@ -0,0 +1,243 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file taskMuonMchTrkEfficiency.cxx +/// \brief task to read the table created by muonMchEfficiency.cxx and build the plots for evaluating the muon tracking efficiency +/// +/// @param muon MCH tracking efficiency table +/// Struct for reading the table created by muonMchEfficiency.cxx and filling the histos needed to compute the +/// muon tracking efficiency in the MCH detector +/// +/// \author Zaida Conesa del Valle +/// + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include "PWGDQ/DataModel/MchTrkEffTables.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// default histogram output binning +namespace muon_trk_eff_bins +{ +static constexpr int nBinsPt = 24; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double binsPt[nBinsPt + 1] = { + 0., 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, + 2.5, 3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 12.0, + 15.0, 18.0, 25.0, 35.0, 45.0, 55.0, 65.0, 75.0}; +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; + +// row labels +static const std::vector labelsPtTrack{ + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9", + "pT bin 10", + "pT bin 11", + "pT bin 12", + "pT bin 13", + "pT bin 14", + "pT bin 15", + "pT bin 16", + "pT bin 17", + "pT bin 18", + "pT bin 19", + "pT bin 20", + "pT bin 21", + "pT bin 22", + "pT bin 23", + "pT bin 24"}; + +} // namespace muon_trk_eff_bins + +struct taskMuonMchTrkEfficiency { + + Configurable ptMuonMin{"ptMin", 0., "Lower bound of pT"}; /// Muon minimum pt to be studied + Configurable etaMuonMin{"etaMin", 2.5, "Lower bound of |eta|"}; /// Muon minimum |eta| to be studied + Configurable etaMuonMax{"etaMax", 4.0, "Upper bound of |eta|"}; /// Muon maximum |eta| to be studied + + Configurable> binsMuonPt{"binsPt", std::vector{muon_trk_eff_bins::vecBinsPt}, "pT bin limits"}; /// Pt intervals for the histograms + Configurable nEtaBins{"nEtaBins", 8, "Number of Eta bins"}; /// Number of eta bins for output histograms + Configurable nPhiBins{"nPhiBins", 6, "Number of Phi bins"}; /// Number of phi bins for output histograms + + using muonFull = soa::Join; + + /// Histogram registry: an object to hold your histograms + HistogramRegistry registry{ + "registry", + {}, + OutputObjHandlingPolicy::AnalysisObject}; + + /// Initialize: configure, create specifics + void init(o2::framework::InitContext&) + { + LOGF(debug, "Initialization"); + + // define axes to be used + // and the correspondent histograms + auto vbins = (std::vector)binsMuonPt; + const AxisSpec axisEta{nEtaBins, 2.3, 4.2, "|#eta|"}; + const AxisSpec axisPt{vbins, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisPhi{nPhiBins, -3.14, 3.14, "#varphi"}; + + const AxisSpec axisEtaGen{nEtaBins, 2.5, 4., "|#eta| Gen"}; + const AxisSpec axisPtGen{vbins, "#it{p}_{T} (GeV/#it{c}) Gen"}; + const AxisSpec axisPhiGen{nPhiBins, -3.14, 3.14, "#varphi Gen"}; + const AxisSpec axismchBitmap{1031, -0.5, 1030.5, "mchBitmap"}; + + const AxisSpec axisNhits{16, -0.5, 15.5, ""}; + // Labels for the chambers hit per station, numbering starting from 1 + // i.e. (Nij, N0j, Ni0) correspond to hit on i-j, hit on j not on i, hit on i not on j + const char* elabels[15] = {"N12", "N10", "N02", "N34", "N30", "N04", "N56", "N50", "N06", "N78", "N70", "N08", "N910", "N90", "N010"}; + + HistogramConfigSpec defaultNhitsEtaPtPhi({HistType::kTHnF, {{axisNhits}, {axisEta}, {axisPt}, {axisPhi}}}); + + // define histograms to be added + LOGF(debug, " Creating histograms"); + + registry.add("hmchBitmap", "hmchBitmap", {HistType::kTH1F, {axismchBitmap}}); + + registry.add("hPtRecPtGen", "hPtRecPtGen", {HistType::kTH2F, {{axisPt}, {axisPtGen}}}); + registry.add("hEtaRecEtaGen", "hEtaRecEtaGen", {HistType::kTH2F, {{axisEta}, {axisEtaGen}}}); + registry.add("hPhiRecPhiGen", "hPhiRecPhiGen", {HistType::kTH2F, {{axisPhi}, {axisPhiGen}}}); + + registry.add("hHitsEtaPtPhi", "hHitsEtaPtPhi", defaultNhitsEtaPtPhi, false); + auto hHitsEtaPtPhi = registry.get(HIST("hHitsEtaPtPhi")); + for (int i = 0; i < 16; i++) + hHitsEtaPtPhi->GetAxis(0)->SetBinLabel(i + 1, elabels[i]); + + }; //! end of Initialize: configure, create specifics + + /// check whether a given chamber has hits + bool ischamberhit(uint16_t map, int ich) + { // i = 0..9 + LOGF(debug, " map %i --> %i", map, (map >> ich) & 1); + return (map >> ich) & 1; + } + + /// Kinematic selection + bool IsInKinematics(double eta, double pt) + { + bool isSelected = true; + + if (pt < ptMuonMin) { + return false; + } + if ((eta < etaMuonMin) || (eta > etaMuonMax)) { + return false; + } + return isSelected; + } + + /// Method to define and apply the weight required to optimise the generated distributions + /// TO BE UPDATED with realistic distributions and probably using input TF1 as weights + void FillHistosWeight(double eta, double pt, double phi, uint16_t map, double etaGen, double ptGen, double phiGen) + { + double weighteta = 1, weightpt = 1, weightphi = 1; // default weight set to unity for now: no effect + double etaw = eta * weighteta; + double ptw = pt * weightpt; + double phiw = phi * weightphi; + FillHistos(etaw, ptw, phiw, map); + } + + /// Filling histograms from generated & reconstructed information + void FillHistosMC(double eta, double pt, double phi, uint16_t map, double etaGen, double ptGen, double phiGen) + { + registry.fill(HIST("hPtRecPtGen"), pt, ptGen); + registry.fill(HIST("hEtaRecEtaGen"), eta, etaGen); + registry.fill(HIST("hPhiRecPhiGen"), phi, phiGen); + FillHistosWeight(eta, pt, phi, map, etaGen, ptGen, phiGen); + } + + /// Filling histograms from reconstructed quantities + void FillHistos(double eta, double pt, double phi, uint16_t map) + { + registry.fill(HIST("hmchBitmap"), (double)map); + + bool iN[10]; + for (int i = 0; i < 10; i++) { + bool ishit = ischamberhit(map, i); + iN[i] = false; + if (ishit) + iN[i] = true; + } + if (iN[0] && iN[1]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(0., eta, pt, phi); + if (iN[0] && (!iN[1])) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(1., eta, pt, phi); + if ((!iN[0]) && iN[1]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(2., eta, pt, phi); + if (iN[2] && iN[3]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(3., eta, pt, phi); + if (iN[2] && (!iN[3])) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(4., eta, pt, phi); + if ((!iN[2]) && iN[3]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(5., eta, pt, phi); + if (iN[4] && iN[5]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(6., eta, pt, phi); + if (iN[4] && (!iN[5])) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(7., eta, pt, phi); + if ((!iN[4]) && iN[5]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(8., eta, pt, phi); + if (iN[6] && iN[7]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(9., eta, pt, phi); + if (iN[6] && (!iN[7])) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(10., eta, pt, phi); + if ((!iN[6]) && iN[7]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(11., eta, pt, phi); + if (iN[8] && iN[9]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(12., eta, pt, phi); + if (iN[8] && (!iN[9])) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(13., eta, pt, phi); + if ((!iN[8]) && iN[9]) + registry.get(HIST("hHitsEtaPtPhi"))->Fill(14., eta, pt, phi); + } + + //! process function for reconstructed muon information + void processReco(aod::MchTrkEffBase const& mchtrkeffbases) + { + for (auto& mchtrkeffbase : mchtrkeffbases) { + if (IsInKinematics(mchtrkeffbase.eta(), mchtrkeffbase.pt())) + FillHistos(mchtrkeffbase.eta(), mchtrkeffbase.pt(), mchtrkeffbase.phi(), mchtrkeffbase.mchBitMap()); + } + } + PROCESS_SWITCH(taskMuonMchTrkEfficiency, processReco, "process reconstructed information", true); + + //! process function for simulated muon information + void processSim(muonFull const& mchtrkeffbases) + { + for (auto& mchtrkeffbase : mchtrkeffbases) { + if (IsInKinematics(mchtrkeffbase.eta(), mchtrkeffbase.pt())) + FillHistosMC(mchtrkeffbase.eta(), mchtrkeffbase.pt(), mchtrkeffbase.phi(), mchtrkeffbase.mchBitMap(), mchtrkeffbase.etaGen(), mchtrkeffbase.ptGen(), mchtrkeffbase.phiGen()); + } + } + PROCESS_SWITCH(taskMuonMchTrkEfficiency, processSim, "process reconstructed information", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGEM/Dilepton/Tasks/MCtemplates.cxx b/PWGEM/Dilepton/Tasks/MCtemplates.cxx index 3e1c9248b71..63fe7507778 100644 --- a/PWGEM/Dilepton/Tasks/MCtemplates.cxx +++ b/PWGEM/Dilepton/Tasks/MCtemplates.cxx @@ -60,11 +60,11 @@ DECLARE_SOA_TABLE(BarrelTrackCuts, "AOD", "BARRELTRACKCUTS", dqanalysisflags::Is using MyEvents = soa::Join; using MyEventsSelected = soa::Join; // TODO: make secondary vertexing optional -using MyEventsVtxCov = soa::Join; +// using MyEventsVtxCov = soa::Join; using MyEventsVtxCovSelected = soa::Join; using MyBarrelTracks = soa::Join; -using MyBarrelTracksWithCov = soa::Join; +// using MyBarrelTracksWithCov = soa::Join; using MyBarrelTracksSelected = soa::Join; using MyBarrelTracksSelectedWithCov = soa::Join; @@ -165,7 +165,7 @@ struct AnalysisTrackSelection { if (!cutNamesStr.IsNull()) { std::unique_ptr objArray(cutNamesStr.Tokenize(",")); for (int icut = 0; icut < objArray->GetEntries(); ++icut) { - fTrackCuts.push_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); + fTrackCuts.emplace_back(*dqcuts::GetCompositeCut(objArray->At(icut)->GetName())); } } VarManager::SetUseVars(AnalysisCut::fgUsedVars); // provide the list of required variables so that VarManager knows what to fill @@ -180,7 +180,7 @@ struct AnalysisTrackSelection { if (sig->GetNProngs() != 1) { // NOTE: only 1 prong signals continue; } - fMCSignals.push_back(*sig); + fMCSignals.emplace_back(*sig); } } @@ -189,16 +189,16 @@ struct AnalysisTrackSelection { TString histClasses = "TrackBarrel_BeforeCuts;"; for (auto& cut : fTrackCuts) { TString nameStr = Form("TrackBarrel_%s", cut.GetName()); - fHistNamesReco.push_back(nameStr); + fHistNamesReco.emplace_back(nameStr); histClasses += Form("%s;", nameStr.Data()); std::vector mcnames; for (auto& sig : fMCSignals) { TString nameStr2 = Form("TrackBarrel_%s_%s", cut.GetName(), sig.GetName()); printf("Adding my histogram class %s\n", nameStr2.Data()); - mcnames.push_back(nameStr2); + mcnames.emplace_back(nameStr2); histClasses += Form("%s;", nameStr2.Data()); } - fHistNamesMCMatched.push_back(mcnames); + fHistNamesMCMatched.emplace_back(mcnames); } if (fConfigQA) { @@ -267,12 +267,12 @@ struct AnalysisTrackSelection { int isig = 0; for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrack) > 0) { - if ((*sig).CheckSignal(false, tracksMC, track.reducedMCTrack())) { + if ((*sig).CheckSignal(true, track.reducedMCTrack())) { mcDecision |= (uint32_t(1) << isig); } } if constexpr ((TTrackFillMap & VarManager::ObjTypes::Track) > 0) { - if ((*sig).CheckSignal(false, tracksMC, track.template mcParticle_as())) { + if ((*sig).CheckSignal(true, track.template mcParticle_as())) { mcDecision |= (uint32_t(1) << isig); } } @@ -322,7 +322,7 @@ struct AnalysisSameEventPairing { HistogramManager* fHistMan; std::vector> fBarrelHistNames; - std::vector> fBarrelHistNamesMCmatched; + std::vector>> fBarrelHistNamesMCmatched; std::vector fRecMCSignals; std::vector fGenMCSignals; @@ -350,7 +350,7 @@ struct AnalysisSameEventPairing { if (sig->GetNProngs() != 2) { // NOTE: 2-prong signals required continue; } - fRecMCSignals.push_back(*sig); + fRecMCSignals.emplace_back(*sig); } } @@ -364,16 +364,19 @@ struct AnalysisSameEventPairing { Form("PairsBarrelSEPP_%s", objArray->At(icut)->GetName()), Form("PairsBarrelSEMM_%s", objArray->At(icut)->GetName())}; histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); - fBarrelHistNames.push_back(names); - std::vector mcSigClasses; + fBarrelHistNames.emplace_back(names); + std::vector> mcSigClasses; if (!sigNamesStr.IsNull()) { for (auto& sig : fRecMCSignals) { - TString histName = Form("PairsBarrelSEPM_%s_%s", objArray->At(icut)->GetName(), sig.GetName()); - histNames += Form("%s;", histName.Data()); - mcSigClasses.push_back(histName); + std::vector names = { + Form("PairsBarrelSEPM_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), + Form("PairsBarrelSEPP_%s_%s", objArray->At(icut)->GetName(), sig.GetName()), + Form("PairsBarrelSEMM_%s_%s", objArray->At(icut)->GetName(), sig.GetName())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + mcSigClasses.emplace_back(names); } // end loop over MC signals } - fBarrelHistNamesMCmatched.push_back(mcSigClasses); + fBarrelHistNamesMCmatched.emplace_back(mcSigClasses); } // end loop over cuts } // end if(cutNames.IsNull()) } // end if processBarrel @@ -386,10 +389,10 @@ struct AnalysisSameEventPairing { MCSignal* sig = o2::aod::dqmcsignals::GetMCSignal(objGenSigArray->At(isig)->GetName()); if (sig) { if (sig->GetNProngs() == 1) { // NOTE: 1-prong signals required - fGenMCSignals.push_back(*sig); + fGenMCSignals.emplace_back(*sig); histNames += Form("MCTruthGen_%s;", sig->GetName()); // TODO: Add these names to a std::vector to avoid using Form in the process function } else if (sig->GetNProngs() == 2) { // NOTE: 2-prong signals required - fGenMCSignals.push_back(*sig); + fGenMCSignals.emplace_back(*sig); histNames += Form("MCTruthGenPair_%s;", sig->GetName()); } } @@ -409,7 +412,7 @@ struct AnalysisSameEventPairing { // establish the right histogram classes to be filled depending on TPairType (ee,mumu,emu) unsigned int ncuts = fBarrelHistNames.size(); std::vector> histNames = fBarrelHistNames; - std::vector> histNamesMCmatched = fBarrelHistNamesMCmatched; + std::vector>> histNamesMCmatched = fBarrelHistNamesMCmatched; // Loop over two track combinations uint8_t twoTrackFilter = 0; @@ -436,12 +439,12 @@ struct AnalysisSameEventPairing { int isig = 0; for (auto sig = fRecMCSignals.begin(); sig != fRecMCSignals.end(); sig++, isig++) { if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrack) > 0) { // for skimmed DQ model - if ((*sig).CheckSignal(false, tracksMC, t1.reducedMCTrack(), t2.reducedMCTrack())) { + if ((*sig).CheckSignal(true, t1.reducedMCTrack(), t2.reducedMCTrack())) { mcDecision |= (uint32_t(1) << isig); } } if constexpr ((TTrackFillMap & VarManager::ObjTypes::Track) > 0) { // for Framework data model - if ((*sig).CheckSignal(false, tracksMC, t1.template mcParticle_as(), t2.template mcParticle_as())) { + if ((*sig).CheckSignal(true, t1.template mcParticle_as(), t2.template mcParticle_as())) { mcDecision |= (uint32_t(1) << isig); } } @@ -459,14 +462,24 @@ struct AnalysisSameEventPairing { fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { if (mcDecision & (uint32_t(1) << isig)) { - fHistMan->FillHistClass(histNamesMCmatched[icut][isig].Data(), VarManager::fgValues); + fHistMan->FillHistClass(histNamesMCmatched[icut][isig][0].Data(), VarManager::fgValues); } } } else { if (t1.sign() > 0) { fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { + if (mcDecision & (uint32_t(1) << isig)) { + fHistMan->FillHistClass(histNamesMCmatched[icut][isig][1].Data(), VarManager::fgValues); + } + } } else { fHistMan->FillHistClass(histNames[icut][2].Data(), VarManager::fgValues); + for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { + if (mcDecision & (uint32_t(1) << isig)) { + fHistMan->FillHistClass(histNamesMCmatched[icut][isig][2].Data(), VarManager::fgValues); + } + } } } } @@ -489,7 +502,14 @@ struct AnalysisSameEventPairing { if (sig.GetNProngs() != 1) { // NOTE: 1-prong signals required continue; } - if (sig.CheckSignal(false, groupedMCTracks, mctrack)) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto mctrack_raw = groupedMCTracks.rawIteratorAt(mctrack.globalIndex()); + checked = sig.CheckSignal(true, mctrack_raw); + } else { + checked = sig.CheckSignal(true, mctrack); + } + if (checked) { fHistMan->FillHistClass(Form("MCTruthGen_%s", sig.GetName()), VarManager::fgValues); } } @@ -501,7 +521,15 @@ struct AnalysisSameEventPairing { continue; } for (auto& [t1, t2] : combinations(groupedMCTracks, groupedMCTracks)) { - if (sig.CheckSignal(false, groupedMCTracks, t1, t2)) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto t1_raw = groupedMCTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = groupedMCTracks.rawIteratorAt(t2.globalIndex()); + checked = sig.CheckSignal(true, t1_raw, t2_raw); + } else { + checked = sig.CheckSignal(true, t1, t2); + } + if (checked) { VarManager::FillPairMC(t1, t2); fHistMan->FillHistClass(Form("MCTruthGenPair_%s", sig.GetName()), VarManager::fgValues); } diff --git a/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx b/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx index c972663cbc4..dac157ab454 100644 --- a/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx +++ b/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx @@ -716,7 +716,14 @@ struct AnalysisTrackSelection { VarManager::FillTrackMC(groupedMCTracks, mctrack); int isig = 0; for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { - if ((*sig).CheckSignal(true, groupedMCTracks, mctrack)) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto mctrack_raw = groupedMCTracks.rawIteratorAt(mctrack.globalIndex()); + checked = (*sig).CheckSignal(true, mctrack_raw); + } else { + checked = (*sig).CheckSignal(true, mctrack); + } + if (checked) { if (mctrack.pdgCode() > 0) { fHistGenNegPart[isig]->Fill(mctrack.pt(), mctrack.eta(), mctrack.phi()); if constexpr (smeared) @@ -784,14 +791,14 @@ struct AnalysisTrackSelection { for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrack) > 0) { - if ((*sig).CheckSignal(true, tracksMC, track.reducedMCTrack())) { + if ((*sig).CheckSignal(true, track.reducedMCTrack())) { mcDecision |= (uint32_t(1) << isig); } } if constexpr ((TTrackFillMap & VarManager::ObjTypes::Track) > 0) { if (track.has_mcParticle()) { auto mctrack = track.template mcParticle_as(); - if ((*sig).CheckSignal(true, tracksMC, mctrack)) { + if ((*sig).CheckSignal(true, mctrack)) { mcDecision |= (uint32_t(1) << isig); } } @@ -1188,7 +1195,15 @@ struct AnalysisSameEventPairing { int isig = 0; for (auto sig = fMCSignals.begin(); sig != fMCSignals.end(); sig++, isig++) { - if ((*sig).CheckSignal(true, groupedMCTracks, t1, t2)) { + bool checked = false; + if constexpr (soa::is_soa_filtered_v) { + auto t1_raw = groupedMCTracks.rawIteratorAt(t1.globalIndex()); + auto t2_raw = groupedMCTracks.rawIteratorAt(t2.globalIndex()); + checked = (*sig).CheckSignal(true, t1_raw, t2_raw); + } else { + checked = (*sig).CheckSignal(true, t1, t2); + } + if (checked) { // not smeared after fiducial cuts if (genfidcut) { @@ -1266,7 +1281,7 @@ struct AnalysisSameEventPairing { if (!t1.reducedMCTrack().isPhysicalPrimary() || !t2.reducedMCTrack().isPhysicalPrimary()) continue; } - if ((*sig).CheckSignal(true, tracksMC, t1.reducedMCTrack(), t2.reducedMCTrack())) { + if ((*sig).CheckSignal(true, t1.reducedMCTrack(), t2.reducedMCTrack())) { mcDecision |= (uint32_t(1) << isig); } } @@ -1279,7 +1294,7 @@ struct AnalysisSameEventPairing { if (!mct1.isPhysicalPrimary() || !mct2.isPhysicalPrimary()) continue; } - if ((*sig).CheckSignal(true, tracksMC, mct1, mct2)) { + if ((*sig).CheckSignal(true, mct1, mct2)) { mcDecision |= (uint32_t(1) << isig); } } diff --git a/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx b/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx index ca760249fd4..57f6761aa65 100644 --- a/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx +++ b/PWGEM/Dilepton/Tasks/lmeeLFCocktail.cxx @@ -100,11 +100,6 @@ struct lmeelfcocktail { TH1F* fhwMultmT2; TH1F* fhKW; TF1* ffVPHpT; - TObjArray* fArr; - TObjArray* fArrResoPt; - TObjArray* fArrResoEta; - TObjArray* fArrResoPhi_Pos; - TObjArray* fArrResoPhi_Neg; std::vector> fmee_orig, fmotherpT_orig, fphi_orig, frap_orig, fmee_orig_wALT, fmotherpT_orig_wALT, fmee, fphi, frap, fmee_wALT; std::vector> fpteevsmee_wALT, fpteevsmee_orig_wALT, fpteevsmee_orig, fpteevsmee; @@ -135,14 +130,9 @@ struct lmeelfcocktail { Configurable fConfigResFileName{"cfgResFileName", "", "name of resolution file"}; Configurable fConfigEffFileName{"cfgEffFileName", "", "name of efficiency file"}; Configurable fConfigMinOpAng{"cfgMinOpAng", 0.050, "minimum opening angle"}; - Configurable fConfigDoRapidityCut{"cfgDoRapidityCut", false, "apply rapidity cut"}; - Configurable fConfigRapidityCut{"cfgRapidityCut", 1.0, "rapdity cut"}; Configurable fConfigNBinsPhi{"cfgNBinsPhi", 240, "number of bins in phi"}; - Configurable fConfigMinPhi{"cfgMinPhi", 0.0, "lowerst bin in phi"}; - Configurable fConfigMaxPhi{"cfgMaxPhi", TMath::TwoPi(), "hightest bin in phi"}; Configurable fConfigNBinsRap{"cfgNBinsRap", 240, "number of bins in rap"}; - Configurable fConfigMinRap{"cfgMinRap", -1.2, "lowest bin in rap"}; - Configurable fConfigMaxRap{"cfgMaxRap", 1.2, "hightest bin in rap"}; + Configurable fConfigMaxAbsRap{"cfgMaxAbsRap", 1.2, "bin range in rap"}; Configurable fConfigEffHistName{"cfgEffHistName", "fhwEffpT", "hisogram name in efficiency file"}; Configurable fConfigResPHistName{"cfgResPHistName", "ptSlices", "histogram name for p in resolution file"}; Configurable fConfigResPtHistName{"cfgResPtHistName", "RelPtResArrCocktail", "histogram name for pt in resolution file"}; @@ -156,17 +146,15 @@ struct lmeelfcocktail { Configurable fConfigMultHistPt2Name{"cfgMultHistPt2Name", "fhwMultpT_upperlimit", "histogram name for pt 2 in multiplicity file"}; Configurable fConfigMultHistMtName{"cfgMultHistMtName", "fhwMultmT", "histogram name for mt in multiplicity file"}; Configurable fConfigMultHistMt2Name{"cfgMultHistMt2Name", "fhwMultmT_upperlimit", "histogram name for mt 2 in multiplicity file"}; - Configurable fConfigKWNBins{"cfgKWNBins", 10000, "number of bins for Kroll-Wada"}; Configurable fConfigKWMax{"cfgKWMax", 1.1, "upper bound of Kroll-Wada"}; Configurable fConfigDoVirtPh{"cfgDoVirtPh", false, "generate one virt. photon for each pion"}; Configurable fConfigPhotonPtFileName{"cfgPhotonPtFileName", "", "file name for photon pT parametrization"}; Configurable fConfigPhotonPtDirName{"cfgPhotonPtDirName", "", "directory name for photon pT parametrization"}; Configurable fConfigPhotonPtFuncName{"cfgPhotonPtFuncName", "111_pt", "function name for photon pT parametrization"}; - // Configurable axes crashed the task. Take them out for the moment - // ConfigurableAxis fConfigPtBins{"cfgPtBins", {VARIABLE_WIDTH, 0., 0.5, 1, 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8.}, "pT bins"}; - // ConfigurableAxis fConfigMBins{"cfgMBins", {VARIABLE_WIDTH, 0., 0.08, 0.14, 0.2, 1.1, 2.7, 2.8, 3.2, 5.0}, "mee bins"}; - // ConfigurableAxis fConfigDCABins{"cfgDCABins", {VARIABLE_WIDTH, 0., 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 3., 4., 5., 7., 10.}, "DCA bins"}; + ConfigurableAxis fConfigPtBins{"cfgPtBins", {VARIABLE_WIDTH, 0., 0.5, 1, 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8.}, "pT bins"}; + ConfigurableAxis fConfigMBins{"cfgMBins", {VARIABLE_WIDTH, 0., 0.08, 0.14, 0.2, 1.1, 2.7, 2.8, 3.2, 5.0}, "mee bins"}; + ConfigurableAxis fConfigDCABins{"cfgDCABins", {VARIABLE_WIDTH, 0., 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 3., 4., 5., 7., 10.}, "DCA bins"}; Configurable> fConfigDCATemplateEdges{"cfgDCATemplateEdges", {0., .3, .4, .6, 1., 2.}, "DCA template edges"}; @@ -186,9 +174,7 @@ struct lmeelfcocktail { } GetEffHisto(TString(fConfigEffFileName), TString(fConfigEffHistName)); - InitSmearer(TString(fConfigResFileName), TString(fConfigResPtHistName), TString(fConfigResEtaHistName), TString(fConfigResPhiPosHistName), TString(fConfigResPhiNegHistName)); - GetDCATemplates(TString(fConfigDCAFileName), TString(fConfigDCAHistName)); GetMultHisto(TString(fConfigMultFileName), TString(fConfigMultHistPtName), TString(fConfigMultHistPt2Name), TString(fConfigMultHistMtName), TString(fConfigMultHistMt2Name)); if (fConfigDoVirtPh) { @@ -202,500 +188,506 @@ struct lmeelfcocktail { void run(o2::framework::ProcessingContext& pc) { - // get the tracks - auto mctracks = pc.inputs().get>("mctracks"); - registry.fill(HIST("NEvents"), 0.5); - - std::vector eBuff; - std::vector echBuff; - std::vector eweightBuff; - - bool skipNext = false; - - int trackID = -1; - // Loop over all MC particle - for (auto& mctrack : mctracks) { - trackID++; - if (o2::mcgenstatus::getHepMCStatusCode(mctrack.getStatusCode()) != 1) - continue; - if (abs(mctrack.GetPdgCode()) == 11) { - // get the electron - //--------------- - if (fConfigDoPairing) { - // LS and ULS spectra - PxPyPzEVector e, dielectron; - Char_t ech, dielectron_ch; - Double_t eweight, dielectron_weight; - e.SetPxPyPzE(mctrack.Px(), mctrack.Py(), mctrack.Pz(), - mctrack.GetEnergy()); - if (mctrack.GetPdgCode() > 0) { - ech = 1.; - } else { - ech = -1.; - } - eweight = mctrack.getWeight(); - // put in the buffer - //----------------- - eBuff.push_back(e); - echBuff.push_back(ech); - eweightBuff.push_back(eweight); - // loop the buffer and pair - //------------------------ - for (Int_t jj = eBuff.size() - 2; jj >= 0; jj--) { - dielectron = eBuff.at(jj) + e; - dielectron_ch = (echBuff.at(jj) + ech) / 2; - dielectron_weight = eweightBuff.at(jj) * eweight; - - if (dielectron_ch == 0) - registry.fill(HIST("ULS_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); - if (dielectron_ch > 0) - registry.fill(HIST("LSpp_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); - if (dielectron_ch < 0) - registry.fill(HIST("LSmm_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); - if (e.Pt() > fConfigMinPt && eBuff.at(jj).Pt() > fConfigMinPt && e.Pt() < fConfigMaxPt && eBuff.at(jj).Pt() < fConfigMaxPt && TMath::Abs(e.Eta()) < fConfigMaxEta && TMath::Abs(eBuff.at(jj).Eta()) < fConfigMaxEta && e.Vect().Unit().Dot(eBuff.at(jj).Vect().Unit()) < TMath::Cos(fConfigMinOpAng)) { + // get number of events per timeframe + auto Nparts = pc.inputs().getNofParts(0); + + for (auto i = 0U; i < Nparts; ++i) { + registry.fill(HIST("NEvents"), 0.5); + // get the tracks + auto mctracks = pc.inputs().get>("mctracks", i); + + std::vector eBuff; + std::vector echBuff; + std::vector eweightBuff; + + bool skipNext = false; + + int trackID = -1; + // Loop over all MC particle + for (auto& mctrack : mctracks) { + trackID++; + if (o2::mcgenstatus::getHepMCStatusCode(mctrack.getStatusCode()) != 1) + continue; + if (abs(mctrack.GetPdgCode()) == 11) { + // get the electron + //--------------- + if (fConfigDoPairing) { + // LS and ULS spectra + PxPyPzEVector e, dielectron; + Char_t ech, dielectron_ch; + Double_t eweight, dielectron_weight; + e.SetPxPyPzE(mctrack.Px(), mctrack.Py(), mctrack.Pz(), + mctrack.GetEnergy()); + if (mctrack.GetPdgCode() > 0) { + ech = 1.; + } else { + ech = -1.; + } + eweight = mctrack.getWeight(); + // put in the buffer + //----------------- + eBuff.push_back(e); + echBuff.push_back(ech); + eweightBuff.push_back(eweight); + // loop the buffer and pair + //------------------------ + for (Int_t jj = eBuff.size() - 2; jj >= 0; jj--) { + dielectron = eBuff.at(jj) + e; + dielectron_ch = (echBuff.at(jj) + ech) / 2; + dielectron_weight = eweightBuff.at(jj) * eweight; + if (dielectron_ch == 0) - registry.fill(HIST("ULS"), dielectron.M(), dielectron.Pt(), dielectron_weight); + registry.fill(HIST("ULS_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); if (dielectron_ch > 0) - registry.fill(HIST("LSpp"), dielectron.M(), dielectron.Pt(), dielectron_weight); + registry.fill(HIST("LSpp_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); if (dielectron_ch < 0) - registry.fill(HIST("LSmm"), dielectron.M(), dielectron.Pt(), dielectron_weight); + registry.fill(HIST("LSmm_orig"), dielectron.M(), dielectron.Pt(), dielectron_weight); + if (e.Pt() > fConfigMinPt && eBuff.at(jj).Pt() > fConfigMinPt && e.Pt() < fConfigMaxPt && eBuff.at(jj).Pt() < fConfigMaxPt && TMath::Abs(e.Eta()) < fConfigMaxEta && TMath::Abs(eBuff.at(jj).Eta()) < fConfigMaxEta && e.Vect().Unit().Dot(eBuff.at(jj).Vect().Unit()) < TMath::Cos(fConfigMinOpAng)) { + if (dielectron_ch == 0) + registry.fill(HIST("ULS"), dielectron.M(), dielectron.Pt(), dielectron_weight); + if (dielectron_ch > 0) + registry.fill(HIST("LSpp"), dielectron.M(), dielectron.Pt(), dielectron_weight); + if (dielectron_ch < 0) + registry.fill(HIST("LSmm"), dielectron.M(), dielectron.Pt(), dielectron_weight); + } } } - } - - if (skipNext) { - skipNext = false; - continue; // skip if marked as second electron - } - if (!(mctrack.getMotherTrackId() > -1)) - continue; // has no mother - - auto const& mother = mctracks[mctrack.getMotherTrackId()]; - - if (mother.getMotherTrackId() > -1) - continue; // mother is not primary - - if (mctrack.getSecondMotherTrackId() - mctrack.getMotherTrackId() > 0) - continue; // more than one mother - - // skip for the moment other particles rather than pi0, eta, etaprime, - // omega, rho, phi. - switch (mother.GetPdgCode()) { - case 111: - break; - case 221: - break; - case 331: - break; - case 113: - break; - case 223: - break; - case 333: - break; - case 443: - break; - default: - continue; - } + if (skipNext) { + skipNext = false; + continue; // skip if marked as second electron + } - // Not sure about this cut. From GammaConv group. Harmless a priori. - if (!(fabs(mctrack.GetEnergy() - mctrack.Pz()) > 0.)) - continue; + if (!(mctrack.getMotherTrackId() > -1)) + continue; // has no mother + + auto const& mother = mctracks[mctrack.getMotherTrackId()]; + + if (mother.getMotherTrackId() > -1) + continue; // mother is not primary + + if (mctrack.getSecondMotherTrackId() - mctrack.getMotherTrackId() > 0) + continue; // more than one mother + + // skip for the moment other particles rather than pi0, eta, etaprime, + // omega, rho, phi. + switch (mother.GetPdgCode()) { + case 111: + break; + case 221: + break; + case 331: + break; + case 113: + break; + case 223: + break; + case 333: + break; + case 443: + break; + default: + continue; + } - // ???? this applied only to first daughter! - Double_t yPre = (mctrack.GetEnergy() + mctrack.Pz()) / (mctrack.GetEnergy() - mctrack.Pz()); - Double_t y = 0.5 * TMath::Log(yPre); - if (fConfigDoRapidityCut) { // Apply rapidity cut on mother consistent with GammaConv group. (??? but it is not applied on mother?) - if (yPre <= 0.) - continue; - if (TMath::Abs(y) > fConfigRapidityCut) - continue; - } else { - if (yPre == 0.) + /* + // Not sure about this cut. From GammaConv group. Harmless a priori. + if (!(fabs(mctrack.GetEnergy() - mctrack.Pz()) > 0.)) continue; - } - treeWords.fdectyp = mother.getLastDaughterTrackId() - mother.getFirstDaughterTrackId() + 1; // fdectyp: decay type (based on number of daughters). - if (treeWords.fdectyp > 4) - continue; // exclude five or more particles decay - - if (trackID == mctracks.size()) - continue; // no particle left in the list - auto mctrack2 = mctracks[trackID + 1]; - if (!(mctrack2.getMotherTrackId() == mctrack.getMotherTrackId())) - continue; // no matching second electron - if (!(mctrack.getSecondMotherTrackId() == -1)) - continue; // second daughter has more than one mother - if (!(abs(mctrack2.GetPdgCode()) == 11)) - continue; // not an electron - - skipNext = true; // is matching electron --> next particle in list will be skipped - - PxPyPzEVector dau1, dau2, ee; - dau1.SetPxPyPzE(mctrack.Px(), mctrack.Py(), mctrack.Pz(), mctrack.GetEnergy()); - dau2.SetPxPyPzE(mctrack2.Px(), mctrack2.Py(), mctrack2.Pz(), mctrack2.GetEnergy()); - - // create dielectron before resolution effects: - ee = dau1 + dau2; - - // get info of the other particles in the decay: - treeWords.fdau3pdg = 0; - for (Int_t jj = mother.getFirstDaughterTrackId(); jj <= mother.getLastDaughterTrackId(); jj++) { - if (jj == trackID || jj == trackID + 1) { - continue; // first or second electron + // ???? this applied only to first daughter! + Double_t yPre = (mctrack.GetEnergy() + mctrack.Pz()) / (mctrack.GetEnergy() - mctrack.Pz()); + Double_t y = 0.5 * TMath::Log(yPre); + if (fConfigDoRapidityCut) { // Apply rapidity cut on mother consistent with GammaConv group. (??? but it is not applied on mother?) + if (yPre <= 0.) + continue; + if (TMath::Abs(y) > fConfigRapidityCut) + continue; + } else { + if (yPre == 0.) + continue; + }*/ + + treeWords.fdectyp = mother.getLastDaughterTrackId() - mother.getFirstDaughterTrackId() + 1; // fdectyp: decay type (based on number of daughters). + if (treeWords.fdectyp > 4) + continue; // exclude five or more particles decay + + if (trackID == mctracks.size()) + continue; // no particle left in the list + auto mctrack2 = mctracks[trackID + 1]; + if (!(mctrack2.getMotherTrackId() == mctrack.getMotherTrackId())) + continue; // no matching second electron + if (!(mctrack.getSecondMotherTrackId() == -1)) + continue; // second daughter has more than one mother + if (!(abs(mctrack2.GetPdgCode()) == 11)) + continue; // not an electron + + skipNext = true; // is matching electron --> next particle in list will be skipped + + PxPyPzEVector dau1, dau2, ee; + dau1.SetPxPyPzE(mctrack.Px(), mctrack.Py(), mctrack.Pz(), mctrack.GetEnergy()); + dau2.SetPxPyPzE(mctrack2.Px(), mctrack2.Py(), mctrack2.Pz(), mctrack2.GetEnergy()); + + // create dielectron before resolution effects: + ee = dau1 + dau2; + + // get info of the other particles in the decay: + treeWords.fdau3pdg = 0; + for (Int_t jj = mother.getFirstDaughterTrackId(); jj <= mother.getLastDaughterTrackId(); jj++) { + if (jj == trackID || jj == trackID + 1) { + continue; // first or second electron + } + auto mctrack3 = mctracks[jj]; + treeWords.fdau3pdg = abs(mctrack3.GetPdgCode()); } - auto mctrack3 = mctracks[jj]; - treeWords.fdau3pdg = abs(mctrack3.GetPdgCode()); - } - - // get index for histograms - Int_t hindex[3]; - for (Int_t jj = 0; jj < 3; jj++) { - hindex[jj] = -1; - } - switch (mother.GetPdgCode()) { - case 111: - hindex[0] = 0; - break; - case 221: - hindex[0] = 1; - break; - case 331: - hindex[0] = 2; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 22) - hindex[1] = 3; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 223) - hindex[1] = 4; - break; - case 113: - hindex[0] = 5; - break; - case 223: - hindex[0] = 6; - if (treeWords.fdectyp == 2) - hindex[1] = 7; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 111) - hindex[1] = 8; - break; - case 333: - hindex[0] = 9; - if (treeWords.fdectyp == 2) - hindex[1] = 10; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 221) - hindex[1] = 11; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 111) - hindex[1] = 12; - break; - case 443: - hindex[0] = 13; - if (treeWords.fdectyp == 2) - hindex[1] = 14; - if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 22) - hindex[1] = 15; - break; - } - hindex[2] = nInputParticles; - - if (hindex[0] < 0) { - LOGP(error, "hindex[0]<0"); - continue; - } - - // Fill tree words before resolution/acceptance - treeWords.fd1origpt = dau1.Pt(); - treeWords.fd1origp = dau1.P(); - treeWords.fd1origeta = dau1.Eta(); - treeWords.fd1origphi = dau1.Phi(); - treeWords.fd2origpt = dau2.Pt(); - treeWords.fd2origp = dau2.P(); - treeWords.fd2origeta = dau2.Eta(); - treeWords.fd2origphi = dau2.Phi(); - treeWords.feeorigpt = ee.Pt(); - treeWords.feeorigp = ee.P(); - treeWords.feeorigm = ee.M(); - treeWords.feeorigeta = ee.Eta(); - treeWords.feeorigrap = ee.Rapidity(); - treeWords.feeorigphi = ee.Phi(); - if (mctrack.GetPdgCode() > 0) { - treeWords.feeorigphiv = PhiV(dau1, dau2); - } else { - treeWords.feeorigphiv = PhiV(dau2, dau1); - } - - // get the efficiency weight - Int_t effbin = fhwEffpT->FindBin(treeWords.fd1origpt); - treeWords.fwEffpT = fhwEffpT->GetBinContent(effbin); - effbin = fhwEffpT->FindBin(treeWords.fd2origpt); - treeWords.fwEffpT = treeWords.fwEffpT * fhwEffpT->GetBinContent(effbin); - - // Resolution and acceptance - //------------------------- - int ch1 = 1; - int ch2 = 1; - if (mctrack.GetPdgCode() > 0) { - ch1 = -1; - } - if (mctrack2.GetPdgCode() > 0) { - ch2 = -1; - } - dau1 = applySmearingPxPyPzE(ch1, dau1); - dau2 = applySmearingPxPyPzE(ch2, dau2); - - treeWords.fpass = true; - if (dau1.Pt() < fConfigMinPt || dau2.Pt() < fConfigMinPt) - treeWords.fpass = false; // leg pT cut - if (dau1.Pt() > fConfigMaxPt || dau2.Pt() > fConfigMaxPt) - treeWords.fpass = false; // leg pT cut - if (dau1.Vect().Unit().Dot(dau2.Vect().Unit()) > TMath::Cos(fConfigMinOpAng)) - treeWords.fpass = false; // opening angle cut - if (TMath::Abs(dau1.Eta()) > fConfigMaxEta || TMath::Abs(dau2.Eta()) > fConfigMaxEta) - treeWords.fpass = false; - - // get the pair DCA (based in smeared pT) - for (int jj = 0; jj < nbDCAtemplate; jj++) { // loop over DCA templates - if (dau1.Pt() >= DCATemplateEdges[jj] && dau1.Pt() < DCATemplateEdges[jj + 1]) { - treeWords.fd1DCA = fh_DCAtemplates[jj]->GetRandom(); + // get index for histograms + Int_t hindex[3]; + for (Int_t jj = 0; jj < 3; jj++) { + hindex[jj] = -1; } - if (dau2.Pt() >= DCATemplateEdges[jj] && dau2.Pt() < DCATemplateEdges[jj + 1]) { - treeWords.fd2DCA = fh_DCAtemplates[jj]->GetRandom(); + switch (mother.GetPdgCode()) { + case 111: + hindex[0] = 0; + break; + case 221: + hindex[0] = 1; + break; + case 331: + hindex[0] = 2; + if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 22) + hindex[1] = 3; + if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 223) + hindex[1] = 4; + break; + case 113: + hindex[0] = 5; + break; + case 223: + hindex[0] = 6; + if (treeWords.fdectyp == 2) + hindex[1] = 7; + if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 111) + hindex[1] = 8; + break; + case 333: + hindex[0] = 9; + if (treeWords.fdectyp == 2) + hindex[1] = 10; + if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 221) + hindex[1] = 11; + if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 111) + hindex[1] = 12; + break; + case 443: + hindex[0] = 13; + if (treeWords.fdectyp == 2) + hindex[1] = 14; + if (treeWords.fdectyp == 3 && treeWords.fdau3pdg == 22) + hindex[1] = 15; + break; } - } - treeWords.fpairDCA = sqrt((pow(treeWords.fd1DCA, 2) + pow(treeWords.fd2DCA, 2)) / 2); - - // Fill tree words after resolution/acceptance - ee = dau1 + dau2; - treeWords.fd1pt = dau1.Pt(); - treeWords.fd1p = dau1.P(); - treeWords.fd1eta = dau1.Eta(); - treeWords.fd1phi = dau1.Phi(); - treeWords.fd2pt = dau2.Pt(); - treeWords.fd2p = dau2.P(); - treeWords.fd2eta = dau2.Eta(); - treeWords.fd2phi = dau2.Phi(); - treeWords.feept = ee.Pt(); - treeWords.feemt = ee.Mt(); - treeWords.feep = ee.P(); - treeWords.feem = ee.M(); - treeWords.feeeta = ee.Eta(); - treeWords.feerap = ee.Rapidity(); - treeWords.feephi = ee.Phi(); - if (mctrack.GetPdgCode() > 0) { - treeWords.feephiv = PhiV(dau1, dau2); - } else { - treeWords.feephiv = PhiV(dau2, dau1); - } - treeWords.fmotherpt = mother.GetPt(); - treeWords.fmotherm = sqrt(pow(mother.GetEnergy(), 2) + pow(mother.GetP(), 2)); - treeWords.fmothermt = sqrt(pow(treeWords.fmotherm, 2) + pow(treeWords.fmotherpt, 2)); - treeWords.fmotherp = mother.GetP(); - treeWords.fmothereta = mother.GetEta(); - treeWords.fmotherphi = mother.GetPhi(); - treeWords.fID = mother.GetPdgCode(); - treeWords.fweight = mctrack.getWeight(); // get particle weight from generator - - // get multiplicity based weight: - int iwbin = fhwMultpT->FindBin(treeWords.fmotherpt); - treeWords.fwMultpT = fhwMultpT->GetBinContent(iwbin); // pT weight - treeWords.fwMultpT2 = fhwMultpT2->GetBinContent(iwbin); // pT weight - double min_mT = fhwMultmT->GetBinLowEdge(1); // consider as minimum valid mT value the edge of the weight histo. - if (treeWords.fmothermt > min_mT) { - iwbin = fhwMultmT->FindBin(treeWords.fmothermt); - treeWords.fwMultmT = fhwMultmT->GetBinContent(iwbin); // mT weight - treeWords.fwMultmT2 = fhwMultmT2->GetBinContent(iwbin); // mT weight - } else { - LOGP(error, "Generated particle with mT < Pion mass cannot be weighted"); - treeWords.fwMultmT = 0.; - treeWords.fwMultmT2 = 0.; - } - // Which ALT weight to use?: - Double_t fwALT = treeWords.fwEffpT; // by default use pt efficiency weight - if (fConfigALTweight == 1) - fwALT = treeWords.fwMultmT; // mT multiplicity weight - if (fConfigALTweight == 11) - fwALT = treeWords.fwMultmT2; // mT multiplicity weight, higher mult - if (fConfigALTweight == 2) - fwALT = treeWords.fwMultpT; // pT multiplicity weight - if (fConfigALTweight == 22) - fwALT = treeWords.fwMultpT2; // pT multiplicity weight, higher mult - - // fill the tree - if (fConfigWriteTTree) { - tree->Fill(); - } + hindex[2] = nInputParticles; - // fill the histograms - if (treeWords.fdectyp < 4) { // why here <4 and before <5 ??? - for (Int_t jj = 0; jj < 3; jj++) { // fill the different hindex -> particles - if (hindex[jj] > -1) { - fmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.fweight); - if (fConfigALTweight == 1 || fConfigALTweight == 11) { - fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmothermt, treeWords.fweight); - } else if (fConfigALTweight == 2 || fConfigALTweight == 22 || fConfigALTweight == 0) { - fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight); - } - fpteevsmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, treeWords.fweight); - fphi_orig[hindex[jj]]->Fill(treeWords.feeorigphi, treeWords.fweight); - frap_orig[hindex[jj]]->Fill(treeWords.feeorigrap, treeWords.fweight); - fmee_orig_wALT[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.fweight * fwALT); - fpteevsmee_orig_wALT[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, treeWords.fweight * fwALT); - if (fConfigALTweight == 1 || fConfigALTweight == 11) { - fmotherpT_orig_wALT[hindex[jj]]->Fill(treeWords.fmothermt, treeWords.fweight * fwALT); - } else if (fConfigALTweight == 2 || fConfigALTweight == 22 || fConfigALTweight == 0) { - fmotherpT_orig_wALT[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight * fwALT); - } - if (treeWords.fpass) { - fmee[hindex[jj]]->Fill(treeWords.feem, treeWords.fweight); - fpteevsmee[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, treeWords.fweight); - fphi[hindex[jj]]->Fill(treeWords.feephi, treeWords.fweight); - frap[hindex[jj]]->Fill(treeWords.feerap, treeWords.fweight); - registry.fill(HIST("DCAeevsmee"), treeWords.feem, treeWords.fpairDCA, treeWords.fweight); - registry.fill(HIST("DCAeevsptee"), treeWords.feept, treeWords.fpairDCA, treeWords.fweight); - fmee_wALT[hindex[jj]]->Fill(treeWords.feem, treeWords.fweight * fwALT); - fpteevsmee_wALT[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, treeWords.fweight * fwALT); - } - } + if (hindex[0] < 0) { + LOGP(error, "hindex[0]<0"); + continue; } - } - if (fConfigDoVirtPh) { - // Virtual photon generation - //------------------------- - // We will generate one virtual photon per histogrammed pion - if (mother.GetPdgCode() == 111) { - // get mass and pt from histos and flat eta and phi - Double_t VPHpT = ffVPHpT->GetRandom(); - Double_t VPHmass = fhKW->GetRandom(); - Double_t VPHeta = -1. + gRandom->Rndm() * 2.; - Double_t VPHphi = 2.0 * TMath::ACos(-1.) * gRandom->Rndm(); - TLorentzVector beam; - beam.SetPtEtaPhiM(VPHpT, VPHeta, VPHphi, VPHmass); - Double_t decaymasses[2] = {(TDatabasePDG::Instance()->GetParticle(11))->Mass(), (TDatabasePDG::Instance()->GetParticle(11))->Mass()}; - TGenPhaseSpace VPHgen; - Bool_t SetDecay; - SetDecay = VPHgen.SetDecay(beam, 2, decaymasses); - if (SetDecay == 0) - LOGP(error, "Decay not permitted by kinematics"); - Double_t VPHweight = VPHgen.Generate(); - // get electrons from the decay - TLorentzVector *decay1, *decay2; - decay1 = VPHgen.GetDecay(0); - decay2 = VPHgen.GetDecay(1); - dau1.SetPxPyPzE(decay1->Px(), decay1->Py(), decay1->Pz(), decay1->E()); - dau2.SetPxPyPzE(decay2->Px(), decay2->Py(), decay2->Pz(), decay2->E()); - - // create dielectron before resolution effects: - ee = dau1 + dau2; - - // get index for histograms - hindex[0] = nInputParticles - 1; - hindex[1] = -1; - hindex[2] = -1; - - // Fill tree words before resolution/acceptance - treeWords.fd1origpt = dau1.Pt(); - treeWords.fd1origp = dau1.P(); - treeWords.fd1origeta = dau1.Eta(); - treeWords.fd1origphi = dau1.Phi(); - treeWords.fd2origpt = dau2.Pt(); - treeWords.fd2origp = dau2.P(); - treeWords.fd2origeta = dau2.Eta(); - treeWords.fd2origphi = dau2.Phi(); - treeWords.feeorigpt = ee.Pt(); - treeWords.feeorigp = ee.P(); - treeWords.feeorigm = ee.M(); - treeWords.feeorigeta = ee.Eta(); - treeWords.feeorigrap = ee.Rapidity(); - treeWords.feeorigphi = ee.Phi(); + // Fill tree words before resolution/acceptance + treeWords.fd1origpt = dau1.Pt(); + treeWords.fd1origp = dau1.P(); + treeWords.fd1origeta = dau1.Eta(); + treeWords.fd1origphi = dau1.Phi(); + treeWords.fd2origpt = dau2.Pt(); + treeWords.fd2origp = dau2.P(); + treeWords.fd2origeta = dau2.Eta(); + treeWords.fd2origphi = dau2.Phi(); + treeWords.feeorigpt = ee.Pt(); + treeWords.feeorigp = ee.P(); + treeWords.feeorigm = ee.M(); + treeWords.feeorigeta = ee.Eta(); + treeWords.feeorigrap = ee.Rapidity(); + treeWords.feeorigphi = ee.Phi(); + if (mctrack.GetPdgCode() > 0) { treeWords.feeorigphiv = PhiV(dau1, dau2); + } else { + treeWords.feeorigphiv = PhiV(dau2, dau1); + } - // get the efficiency weight - Int_t effbin = fhwEffpT->FindBin(treeWords.fd1origpt); - treeWords.fwEffpT = fhwEffpT->GetBinContent(effbin); - effbin = fhwEffpT->FindBin(treeWords.fd2origpt); - treeWords.fwEffpT = treeWords.fwEffpT * fhwEffpT->GetBinContent(effbin); + // get the efficiency weight + Int_t effbin = fhwEffpT->FindBin(treeWords.fd1origpt); + treeWords.fwEffpT = fhwEffpT->GetBinContent(effbin); + effbin = fhwEffpT->FindBin(treeWords.fd2origpt); + treeWords.fwEffpT = treeWords.fwEffpT * fhwEffpT->GetBinContent(effbin); - // Resolution and acceptance - //------------------------- - dau1 = applySmearingPxPyPzE(1, dau1); - dau2 = applySmearingPxPyPzE(-1, dau2); - treeWords.fpass = true; - if (dau1.Pt() < fConfigMinPt || dau2.Pt() < fConfigMinPt) - treeWords.fpass = false; // leg pT cut - if (dau1.Pt() > fConfigMaxPt || dau2.Pt() > fConfigMaxPt) - treeWords.fpass = false; // leg pT cut - if (dau1.Vect().Unit().Dot(dau2.Vect().Unit()) > TMath::Cos(fConfigMinOpAng)) - treeWords.fpass = false; // opening angle cut - if (TMath::Abs(dau1.Eta()) > fConfigMaxEta || TMath::Abs(dau2.Eta()) > fConfigMaxEta) - treeWords.fpass = false; - - treeWords.fpairDCA = 10000.; // ?? - - // Fill tree words after resolution/acceptance - ee = dau1 + dau2; - treeWords.fd1pt = dau1.Pt(); - treeWords.fd1p = dau1.P(); - treeWords.fd1eta = dau1.Eta(); - treeWords.fd1phi = dau1.Phi(); - treeWords.fd2pt = dau2.Pt(); - treeWords.fd2p = dau2.P(); - treeWords.fd2eta = dau2.Eta(); - treeWords.fd2phi = dau2.Phi(); - treeWords.feept = ee.Pt(); - treeWords.feemt = ee.Mt(); - treeWords.feep = ee.P(); - treeWords.feem = ee.M(); - treeWords.feeeta = ee.Eta(); - treeWords.feerap = ee.Rapidity(); - treeWords.feephi = ee.Phi(); - treeWords.feephiv = PhiV(dau1, dau2); - treeWords.fmotherpt = beam.Pt(); - treeWords.fmothermt = sqrt(pow(beam.M(), 2) + pow(beam.Pt(), 2)); - treeWords.fmotherp = beam.P(); - treeWords.fmotherm = beam.M(); - treeWords.fmothereta = beam.Eta(); - treeWords.fmotherphi = beam.Phi(); - treeWords.fID = 0; // set ID to Zero for VPH - treeWords.fweight = VPHweight; - // get multiplicity based weight: - treeWords.fwMultmT = 1; // no weight for photons so far - - // Fill the tree - if (fConfigWriteTTree) { // many parameters not set for photons: d1DCA,fd2DCA, fdectyp,fdau3pdg,fwMultpT,fwMultpT2,fwMultmT2 - tree->Fill(); + // Resolution and acceptance + //------------------------- + int ch1 = 1; + int ch2 = 1; + if (mctrack.GetPdgCode() > 0) { + ch1 = -1; + } + if (mctrack2.GetPdgCode() > 0) { + ch2 = -1; + } + dau1 = applySmearingPxPyPzE(ch1, dau1); + dau2 = applySmearingPxPyPzE(ch2, dau2); + + treeWords.fd1pt = dau1.Pt(); + treeWords.fd1eta = dau1.Eta(); + treeWords.fd2pt = dau2.Pt(); + treeWords.fd2eta = dau2.Eta(); + treeWords.fpass = true; + if (treeWords.fd1pt < fConfigMinPt || treeWords.fd2pt < fConfigMinPt) + treeWords.fpass = false; // leg pT cut + if (treeWords.fd1pt > fConfigMaxPt || treeWords.fd2pt > fConfigMaxPt) + treeWords.fpass = false; // leg pT cut + if (dau1.Vect().Unit().Dot(dau2.Vect().Unit()) > TMath::Cos(fConfigMinOpAng)) + treeWords.fpass = false; // opening angle cut + if (TMath::Abs(treeWords.fd1eta) > fConfigMaxEta || TMath::Abs(treeWords.fd2eta) > fConfigMaxEta) + treeWords.fpass = false; + + // get the pair DCA (based in smeared pT) + for (int jj = 0; jj < nbDCAtemplate; jj++) { // loop over DCA templates + if (dau1.Pt() >= DCATemplateEdges[jj] && dau1.Pt() < DCATemplateEdges[jj + 1]) { + treeWords.fd1DCA = fh_DCAtemplates[jj]->GetRandom(); + } + if (dau2.Pt() >= DCATemplateEdges[jj] && dau2.Pt() < DCATemplateEdges[jj + 1]) { + treeWords.fd2DCA = fh_DCAtemplates[jj]->GetRandom(); } + } + treeWords.fpairDCA = sqrt((pow(treeWords.fd1DCA, 2) + pow(treeWords.fd2DCA, 2)) / 2); + + // Fill tree words after resolution/acceptance + ee = dau1 + dau2; + treeWords.fd1p = dau1.P(); + treeWords.fd1phi = dau1.Phi(); + treeWords.fd2p = dau2.P(); + treeWords.fd2phi = dau2.Phi(); + treeWords.feept = ee.Pt(); + treeWords.feemt = ee.Mt(); + treeWords.feep = ee.P(); + treeWords.feem = ee.M(); + treeWords.feeeta = ee.Eta(); + treeWords.feerap = ee.Rapidity(); + treeWords.feephi = ee.Phi(); + if (mctrack.GetPdgCode() > 0) { + treeWords.feephiv = PhiV(dau1, dau2); + } else { + treeWords.feephiv = PhiV(dau2, dau1); + } + treeWords.fmotherpt = mother.GetPt(); + treeWords.fmotherm = sqrt(pow(mother.GetEnergy(), 2) + pow(mother.GetP(), 2)); + treeWords.fmothermt = sqrt(pow(treeWords.fmotherm, 2) + pow(treeWords.fmotherpt, 2)); + treeWords.fmotherp = mother.GetP(); + treeWords.fmothereta = mother.GetEta(); + treeWords.fmotherphi = mother.GetPhi(); + treeWords.fID = mother.GetPdgCode(); + treeWords.fweight = mctrack.getWeight(); // get particle weight from generator + + // get multiplicity based weight: + int iwbin = fhwMultpT->FindBin(treeWords.fmotherpt); + treeWords.fwMultpT = fhwMultpT->GetBinContent(iwbin); // pT weight + treeWords.fwMultpT2 = fhwMultpT2->GetBinContent(iwbin); // pT weight + double min_mT = fhwMultmT->GetBinLowEdge(1); // consider as minimum valid mT value the edge of the weight histo. + if (treeWords.fmothermt > min_mT) { + iwbin = fhwMultmT->FindBin(treeWords.fmothermt); + treeWords.fwMultmT = fhwMultmT->GetBinContent(iwbin); // mT weight + treeWords.fwMultmT2 = fhwMultmT2->GetBinContent(iwbin); // mT weight + } else { + LOGP(error, "Generated particle with mT < Pion mass cannot be weighted"); + treeWords.fwMultmT = 0.; + treeWords.fwMultmT2 = 0.; + } - // Fill the histograms + // Which ALT weight to use?: + Double_t fwALT = treeWords.fwEffpT; // by default use pt efficiency weight + if (fConfigALTweight == 1) + fwALT = treeWords.fwMultmT; // mT multiplicity weight + if (fConfigALTweight == 11) + fwALT = treeWords.fwMultmT2; // mT multiplicity weight, higher mult + if (fConfigALTweight == 2) + fwALT = treeWords.fwMultpT; // pT multiplicity weight + if (fConfigALTweight == 22) + fwALT = treeWords.fwMultpT2; // pT multiplicity weight, higher mult + + // fill the tree + if (fConfigWriteTTree) { + tree->Fill(); + } + + // fill the histograms + if (treeWords.fdectyp < 4) { // why here <4 and before <5 ??? for (Int_t jj = 0; jj < 3; jj++) { // fill the different hindex -> particles if (hindex[jj] > -1) { - fmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, VPHweight); - fpteevsmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, VPHweight); - fphi_orig[hindex[jj]]->Fill(treeWords.feeorigphi, VPHweight); - frap_orig[hindex[jj]]->Fill(treeWords.feeorigrap, VPHweight); - fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight); + fmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.fweight); + if (fConfigALTweight == 1 || fConfigALTweight == 11) { + fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmothermt, treeWords.fweight); + } else if (fConfigALTweight == 2 || fConfigALTweight == 22 || fConfigALTweight == 0) { + fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight); + } + fpteevsmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, treeWords.fweight); + fphi_orig[hindex[jj]]->Fill(treeWords.feeorigphi, treeWords.fweight); + frap_orig[hindex[jj]]->Fill(treeWords.feeorigrap, treeWords.fweight); + fmee_orig_wALT[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.fweight * fwALT); + fpteevsmee_orig_wALT[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, treeWords.fweight * fwALT); + if (fConfigALTweight == 1 || fConfigALTweight == 11) { + fmotherpT_orig_wALT[hindex[jj]]->Fill(treeWords.fmothermt, treeWords.fweight * fwALT); + } else if (fConfigALTweight == 2 || fConfigALTweight == 22 || fConfigALTweight == 0) { + fmotherpT_orig_wALT[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight * fwALT); + } if (treeWords.fpass) { - fmee[hindex[jj]]->Fill(treeWords.feem, VPHweight); - fpteevsmee[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, VPHweight); - fphi[hindex[jj]]->Fill(treeWords.feephi, VPHweight); - frap[hindex[jj]]->Fill(treeWords.feerap, VPHweight); + fmee[hindex[jj]]->Fill(treeWords.feem, treeWords.fweight); + fpteevsmee[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, treeWords.fweight); + fphi[hindex[jj]]->Fill(treeWords.feephi, treeWords.fweight); + frap[hindex[jj]]->Fill(treeWords.feerap, treeWords.fweight); + registry.fill(HIST("DCAeevsmee"), treeWords.feem, treeWords.fpairDCA, treeWords.fweight); + registry.fill(HIST("DCAeevsptee"), treeWords.feept, treeWords.fpairDCA, treeWords.fweight); + fmee_wALT[hindex[jj]]->Fill(treeWords.feem, treeWords.fweight * fwALT); + fpteevsmee_wALT[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, treeWords.fweight * fwALT); } } } + } - } // mother.pdgCode()==111 - } // fConfigDoVirtPh + if (fConfigDoVirtPh) { + // Virtual photon generation + //------------------------- + // We will generate one virtual photon per histogrammed pion + if (mother.GetPdgCode() == 111) { + // get mass and pt from histos and flat eta and phi + Double_t VPHpT = ffVPHpT->GetRandom(); + Double_t VPHmass = fhKW->GetRandom(); + Double_t VPHeta = -1. + gRandom->Rndm() * 2.; + Double_t VPHphi = 2.0 * TMath::ACos(-1.) * gRandom->Rndm(); + TLorentzVector beam; + beam.SetPtEtaPhiM(VPHpT, VPHeta, VPHphi, VPHmass); + Double_t decaymasses[2] = {(TDatabasePDG::Instance()->GetParticle(11))->Mass(), (TDatabasePDG::Instance()->GetParticle(11))->Mass()}; + TGenPhaseSpace VPHgen; + Bool_t SetDecay; + SetDecay = VPHgen.SetDecay(beam, 2, decaymasses); + if (SetDecay == 0) + LOGP(error, "Decay not permitted by kinematics"); + Double_t VPHweight = VPHgen.Generate(); + // get electrons from the decay + TLorentzVector *decay1, *decay2; + decay1 = VPHgen.GetDecay(0); + decay2 = VPHgen.GetDecay(1); + dau1.SetPxPyPzE(decay1->Px(), decay1->Py(), decay1->Pz(), decay1->E()); + dau2.SetPxPyPzE(decay2->Px(), decay2->Py(), decay2->Pz(), decay2->E()); + + // create dielectron before resolution effects: + ee = dau1 + dau2; + + // get index for histograms + hindex[0] = nInputParticles - 1; + hindex[1] = -1; + hindex[2] = -1; + + // Fill tree words before resolution/acceptance + treeWords.fd1origpt = dau1.Pt(); + treeWords.fd1origp = dau1.P(); + treeWords.fd1origeta = dau1.Eta(); + treeWords.fd1origphi = dau1.Phi(); + treeWords.fd2origpt = dau2.Pt(); + treeWords.fd2origp = dau2.P(); + treeWords.fd2origeta = dau2.Eta(); + treeWords.fd2origphi = dau2.Phi(); + treeWords.feeorigpt = ee.Pt(); + treeWords.feeorigp = ee.P(); + treeWords.feeorigm = ee.M(); + treeWords.feeorigeta = ee.Eta(); + treeWords.feeorigrap = ee.Rapidity(); + treeWords.feeorigphi = ee.Phi(); + treeWords.feeorigphiv = PhiV(dau1, dau2); + + // get the efficiency weight + Int_t effbin = fhwEffpT->FindBin(treeWords.fd1origpt); + treeWords.fwEffpT = fhwEffpT->GetBinContent(effbin); + effbin = fhwEffpT->FindBin(treeWords.fd2origpt); + treeWords.fwEffpT = treeWords.fwEffpT * fhwEffpT->GetBinContent(effbin); + + // Resolution and acceptance + //------------------------- + dau1 = applySmearingPxPyPzE(1, dau1); + dau2 = applySmearingPxPyPzE(-1, dau2); + treeWords.fpass = true; + if (dau1.Pt() < fConfigMinPt || dau2.Pt() < fConfigMinPt) + treeWords.fpass = false; // leg pT cut + if (dau1.Pt() > fConfigMaxPt || dau2.Pt() > fConfigMaxPt) + treeWords.fpass = false; // leg pT cut + if (dau1.Vect().Unit().Dot(dau2.Vect().Unit()) > TMath::Cos(fConfigMinOpAng)) + treeWords.fpass = false; // opening angle cut + if (TMath::Abs(dau1.Eta()) > fConfigMaxEta || TMath::Abs(dau2.Eta()) > fConfigMaxEta) + treeWords.fpass = false; + + treeWords.fpairDCA = 10000.; // ?? + + // Fill tree words after resolution/acceptance + ee = dau1 + dau2; + treeWords.fd1pt = dau1.Pt(); + treeWords.fd1p = dau1.P(); + treeWords.fd1eta = dau1.Eta(); + treeWords.fd1phi = dau1.Phi(); + treeWords.fd2pt = dau2.Pt(); + treeWords.fd2p = dau2.P(); + treeWords.fd2eta = dau2.Eta(); + treeWords.fd2phi = dau2.Phi(); + treeWords.feept = ee.Pt(); + treeWords.feemt = ee.Mt(); + treeWords.feep = ee.P(); + treeWords.feem = ee.M(); + treeWords.feeeta = ee.Eta(); + treeWords.feerap = ee.Rapidity(); + treeWords.feephi = ee.Phi(); + treeWords.feephiv = PhiV(dau1, dau2); + treeWords.fmotherpt = beam.Pt(); + treeWords.fmothermt = sqrt(pow(beam.M(), 2) + pow(beam.Pt(), 2)); + treeWords.fmotherp = beam.P(); + treeWords.fmotherm = beam.M(); + treeWords.fmothereta = beam.Eta(); + treeWords.fmotherphi = beam.Phi(); + treeWords.fID = 0; // set ID to Zero for VPH + treeWords.fweight = VPHweight; + // get multiplicity based weight: + treeWords.fwMultmT = 1; // no weight for photons so far + + // Fill the tree + if (fConfigWriteTTree) { // many parameters not set for photons: d1DCA,fd2DCA, fdectyp,fdau3pdg,fwMultpT,fwMultpT2,fwMultmT2 + tree->Fill(); + } - } // abs(pdgCode())==11 + // Fill the histograms + for (Int_t jj = 0; jj < 3; jj++) { // fill the different hindex -> particles + if (hindex[jj] > -1) { + fmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, VPHweight); + fpteevsmee_orig[hindex[jj]]->Fill(treeWords.feeorigm, treeWords.feept, VPHweight); + fphi_orig[hindex[jj]]->Fill(treeWords.feeorigphi, VPHweight); + frap_orig[hindex[jj]]->Fill(treeWords.feeorigrap, VPHweight); + fmotherpT_orig[hindex[jj]]->Fill(treeWords.fmotherpt, treeWords.fweight); + if (treeWords.fpass) { + fmee[hindex[jj]]->Fill(treeWords.feem, VPHweight); + fpteevsmee[hindex[jj]]->Fill(treeWords.feem, treeWords.feept, VPHweight); + fphi[hindex[jj]]->Fill(treeWords.feephi, VPHweight); + frap[hindex[jj]]->Fill(treeWords.feerap, VPHweight); + } + } + } + + } // mother.pdgCode()==111 + } // fConfigDoVirtPh - } // loop over mctracks + } // abs(pdgCode())==11 - // Clear buffers - eBuff.clear(); - echBuff.clear(); - eweightBuff.clear(); + } // loop over mctracks + + // Clear buffers + eBuff.clear(); + echBuff.clear(); + eweightBuff.clear(); + } } Double_t PhiV(PxPyPzEVector e1, PxPyPzEVector e2) @@ -736,8 +728,8 @@ struct lmeelfcocktail { AxisSpec ptAxis = {fConfigNBinsPtee, fConfigMinPtee, fConfigMaxPtee, "#it{p}_{T,ee} (GeV/c)"}; AxisSpec mAxis = {fConfigNBinsMee, fConfigMinMee, fConfigMaxMee, "#it{m}_{ee} (GeV/c^{2})"}; - AxisSpec phiAxis = {fConfigNBinsPhi, fConfigMinPhi, fConfigMaxPhi, "#it{phi}_{ee}"}; - AxisSpec rapAxis = {fConfigNBinsRap, fConfigMinRap, fConfigMaxRap, "#it{y}_{ee}"}; + AxisSpec phiAxis = {fConfigNBinsPhi, -TMath::TwoPi() / 2, TMath::TwoPi() / 2, "#it{phi}_{ee}"}; + AxisSpec rapAxis = {fConfigNBinsRap, -fConfigMaxAbsRap, fConfigMaxAbsRap, "#it{y}_{ee}"}; registry.add("NEvents", "NEvents", HistType::kTH1F, {{1, 0, 1}}, false); @@ -751,15 +743,8 @@ struct lmeelfcocktail { registry.add("LSmm_orig", "LSmm_orig", HistType::kTH2F, {mAxis, ptAxis}, true); } - // configurable axes crashed the task. Take them out for the moment - // registry.add("DCAeevsmee", "DCAeevsmee", HistType::kTH2F, {{fConfigMBins, "#it{m}_{ee} (GeV/c^{2})"}, {fConfigDCABins, "DCA_{xy}^{ee} (cm)"}}, true); - // registry.add("DCAeevsptee", "DCAeevsptee", HistType::kTH2F, {{fConfigPtBins, "#it{p}_{T,ee} (GeV/c)"}, {fConfigDCABins, "DCA_{xy}^{ee} (cm)"}}, true); - // replace them with hard coded axes - AxisSpec configPtBins = {{0., 0.5, 1, 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., 6.5, 7., 7.5, 8.}, "#it{p}_{T,ee} (GeV/c)"}; - AxisSpec configMBins = {{0., 0.08, 0.14, 0.2, 1.1, 2.7, 2.8, 3.2, 5.0}, "#it{m}_{ee} (GeV/c^{2})"}; - AxisSpec configDcaBins = {{0., 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 3., 4., 5., 7., 10.}, "DCA_{xy}^{ee} (cm)"}; - registry.add("DCAeevsmee", "DCAeevsmee", HistType::kTH2F, {configMBins, configDcaBins}, true); - registry.add("DCAeevsptee", "DCAeevsptee", HistType::kTH2F, {configPtBins, configDcaBins}, true); + registry.add("DCAeevsmee", "DCAeevsmee", HistType::kTH2F, {{fConfigMBins, "#it{m}_{ee} (GeV/c^{2})"}, {fConfigDCABins, "DCA_{xy}^{ee} (cm)"}}, true); + registry.add("DCAeevsptee", "DCAeevsptee", HistType::kTH2F, {{fConfigPtBins, "#it{p}_{T,ee} (GeV/c)"}, {fConfigDCABins, "DCA_{xy}^{ee} (cm)"}}, true); for (auto& particle : fParticleListNames) { fmee.push_back(registry.add(Form("mee_%s", particle.Data()), Form("mee_%s", particle.Data()), HistType::kTH1F, {mAxis}, true)); @@ -987,12 +972,11 @@ struct lmeelfcocktail { { // Build Kroll-wada for virtual photon mass parametrization: Double_t KWmass = 0.; - // Int_t KWnbins = 10000; + Int_t KWnbins = 10000; Float_t KWmin = 2. * eMass; - // Float_t KWmax = 1.1; - Double_t KWbinwidth = (fConfigKWMax - KWmin) / (Double_t)fConfigKWNBins; - fhKW = new TH1F("fhKW", "fhKW", fConfigKWNBins, KWmin, fConfigKWMax); - for (Int_t ibin = 1; ibin <= fConfigKWNBins; ibin++) { + Double_t KWbinwidth = (fConfigKWMax - KWmin) / (Double_t)KWnbins; + fhKW = new TH1F("fhKW", "fhKW", KWnbins, KWmin, fConfigKWMax); + for (Int_t ibin = 1; ibin <= KWnbins; ibin++) { KWmass = KWmin + (Double_t)(ibin - 1) * KWbinwidth + KWbinwidth / 2.0; fhKW->AddBinContent(ibin, 2. * (1. / 137.03599911) / 3. / 3.14159265359 / KWmass * sqrt(1. - 4. * eMass * eMass / KWmass / KWmass) * (1. + 2. * eMass * eMass / KWmass / KWmass)); } diff --git a/PWGEM/PhotonMeson/Core/CMakeLists.txt b/PWGEM/PhotonMeson/Core/CMakeLists.txt index c48b665b86e..a24ef31ed5d 100644 --- a/PWGEM/PhotonMeson/Core/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Core/CMakeLists.txt @@ -12,6 +12,7 @@ o2physics_add_library(PWGEMPhotonMesonCore SOURCES V0PhotonCut.cxx PHOSPhotonCut.cxx + DalitzEECut.cxx EMCPhotonCut.cxx PairCut.cxx CutsLibrary.cxx @@ -20,6 +21,7 @@ o2physics_add_library(PWGEMPhotonMesonCore o2physics_target_root_dictionary(PWGEMPhotonMesonCore HEADERS V0PhotonCut.h + DalitzEECut.h PHOSPhotonCut.h EMCPhotonCut.h PairCut.h diff --git a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx index d1a2d58a114..7bb2b726206 100644 --- a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx @@ -23,192 +23,199 @@ V0PhotonCut* o2::aod::pcmcuts::GetCut(const char* cutName) cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); - cut->SetMinCosPA(0.998); + cut->SetMinCosPA(0.995); cut->SetMaxPCA(0.5); cut->SetRxyRange(1, 90); - cut->SetMaxMeePsiPairDep([](float psipair) { return psipair < 0.4 ? 0.06 : 0.015; }); return cut; } - if (!nameStr.compare("analysis_eta12")) { + if (!nameStr.compare("qc")) { // for track cut->SetTrackPtRange(0.01f, 1e10f); - cut->SetTrackEtaRange(-1.2, +1.2); + cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); - cut->SetV0EtaRange(-1.2, +1.2); - cut->SetMinCosPA(0.998); - cut->SetMaxPCA(0.5); - cut->SetRxyRange(1, 90); - cut->SetMaxMeePsiPairDep([](float psipair) { return psipair < 0.4 ? 0.06 : 0.015; }); + cut->SetV0PtRange(0.05f, 1e10f); + cut->SetV0EtaRange(-0.9, +0.9); + cut->SetMinCosPA(0.99); + cut->SetMaxPCA(1.5); + cut->SetRxyRange(1, 180); return cut; } - if (!nameStr.compare("analysis_wo_mee")) { + if (!nameStr.compare("qc_ITSTPC")) { // for track cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(true); + cut->SetRequireITSTPC(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); - cut->SetMinCosPA(0.998); + cut->SetMinCosPA(0.99); cut->SetMaxPCA(0.5); - cut->SetRxyRange(1, 90); + cut->SetRxyRange(1, 180); + cut->SetAPRange(0.95, 0.02); return cut; } - if (!nameStr.compare("analysis_wo_mee_eta12")) { + if (!nameStr.compare("qc_ITSonly")) { // for track cut->SetTrackPtRange(0.01f, 1e10f); - cut->SetTrackEtaRange(-1.2, +1.2); - cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); - cut->SetTPCNsigmaElRange(-3, +3); + cut->SetTrackEtaRange(-0.9, +0.9); cut->SetIsWithinBeamPipe(true); + cut->SetRequireITSonly(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); - cut->SetV0EtaRange(-1.2, +1.2); - cut->SetMinCosPA(0.998); - cut->SetMaxPCA(0.5); - cut->SetRxyRange(1, 90); + cut->SetV0PtRange(0.05f, 1e10f); + cut->SetV0EtaRange(-0.9, +0.9); + cut->SetMinCosPA(0.99); + cut->SetMaxPCA(1.5); + cut->SetRxyRange(1, 180); + cut->SetAPRange(0.95, 0.02); return cut; } - if (!nameStr.compare("qc_w_mee")) { + if (!nameStr.compare("qc_TPConly")) { // for track cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(true); + cut->SetRequireTPConly(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); cut->SetMinCosPA(0.99); cut->SetMaxPCA(1.5); cut->SetRxyRange(1, 180); - cut->SetMaxMeePsiPairDep([](float psipair) { return psipair < 0.4 ? 0.06 : 0.015; }); return cut; } - if (!nameStr.compare("qc")) { + if (!nameStr.compare("qc_TPCTRD")) { // for track cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(true); + cut->SetRequireTPCTRD(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); cut->SetMinCosPA(0.99); cut->SetMaxPCA(1.5); cut->SetRxyRange(1, 180); return cut; } - if (!nameStr.compare("qc_eta12")) { + if (!nameStr.compare("qc_TPCTOF")) { // for track cut->SetTrackPtRange(0.01f, 1e10f); - cut->SetTrackEtaRange(-1.2, +1.2); + cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(true); + cut->SetRequireTPCTOF(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); - cut->SetV0EtaRange(-1.2, +1.2); + cut->SetV0PtRange(0.05f, 1e10f); + cut->SetV0EtaRange(-0.9, +0.9); cut->SetMinCosPA(0.99); cut->SetMaxPCA(1.5); cut->SetRxyRange(1, 180); return cut; } - if (!nameStr.compare("qc_ITS")) { + if (!nameStr.compare("qc_TPCTRDTOF")) { // for track cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(true); - cut->SetRequireITS(true); + cut->SetRequireTPCTRDTOF(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); cut->SetMinCosPA(0.99); cut->SetMaxPCA(1.5); cut->SetRxyRange(1, 180); return cut; } - if (!nameStr.compare("qc_TPConly")) { + if (!nameStr.compare("wwire")) { // conversion only on tungstate wire // for track cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); - cut->SetTPCNsigmaElRange(-3, +3); - cut->SetIsWithinBeamPipe(true); - cut->SetRequireTPConly(true); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetTPCNsigmaElRange(-4, +4); + cut->SetNClustersITS(2, 4); + // cut->SetIsWithinBeamPipe(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); - cut->SetMinCosPA(0.99); - cut->SetMaxPCA(1.5); - cut->SetRxyRange(1, 180); + cut->SetMinCosPA(0.995); + cut->SetMaxPCA(0.5); + cut->SetOnWwireIB(true); + cut->SetOnWwireOB(true); + cut->SetAPRange(0.95, 0.02); return cut; } - if (!nameStr.compare("qc_AntiTPConly")) { + if (!nameStr.compare("wwire_ib")) { // conversion only on tungstate wire outside of ITSib // for track cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); - cut->SetIsWithinBeamPipe(true); - cut->SetRequireAntiTPConly(true); + cut->SetNClustersITS(2, 4); + // cut->SetIsWithinBeamPipe(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); - cut->SetMinCosPA(0.99); - cut->SetMaxPCA(1.5); - cut->SetRxyRange(1, 180); + cut->SetMinCosPA(0.995); + cut->SetMaxPCA(0.5); + cut->SetOnWwireIB(true); + cut->SetOnWwireOB(false); + cut->SetAPRange(0.95, 0.02); return cut; } - if (!nameStr.compare("wwire")) { // conversion only on tungstate wire + if (!nameStr.compare("wwire_ob")) { // conversion only on tungstate wire outside of ITSob (middle layer) // for track cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); - cut->SetIsWithinBeamPipe(true); + cut->SetNClustersITS(0, 2); + // cut->SetIsWithinBeamPipe(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); - cut->SetMinCosPA(0.99); - cut->SetMaxPCA(1.5); - cut->SetOnWwireIB(true); + cut->SetMinCosPA(0.995); + cut->SetMaxPCA(0.5); + cut->SetOnWwireIB(false); + cut->SetOnWwireOB(true); + cut->SetAPRange(0.95, 0.02); return cut; } if (!nameStr.compare("nopid")) { @@ -216,11 +223,11 @@ V0PhotonCut* o2::aod::pcmcuts::GetCut(const char* cutName) cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetIsWithinBeamPipe(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); cut->SetMinCosPA(0.99); cut->SetMaxPCA(1.5); @@ -232,12 +239,12 @@ V0PhotonCut* o2::aod::pcmcuts::GetCut(const char* cutName) cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(false); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); cut->SetMinCosPA(0.99); cut->SetMaxPCA(1.5); @@ -249,15 +256,15 @@ V0PhotonCut* o2::aod::pcmcuts::GetCut(const char* cutName) cut->SetTrackPtRange(0.01f, 1e10f); cut->SetTrackEtaRange(-0.9, +0.9); cut->SetMinNCrossedRowsTPC(20); - cut->SetMinNCrossedRowsOverFindableClustersTPC(0.6); - cut->SetMaxChi2PerClusterTPC(4.0); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); cut->SetTPCNsigmaElRange(-3, +3); cut->SetIsWithinBeamPipe(true); - cut->SetRequireITS(true); + cut->SetRequireITSTPC(true); // for v0 - cut->SetV0PtRange(0.01f, 1e10f); + cut->SetV0PtRange(0.05f, 1e10f); cut->SetV0EtaRange(-0.9, +0.9); - cut->SetMinCosPA(0.998); + cut->SetMinCosPA(0.995); cut->SetMaxPCA(0.5); cut->SetRxyRange(1, 90); return cut; @@ -268,6 +275,514 @@ V0PhotonCut* o2::aod::pcmcuts::GetCut(const char* cutName) return nullptr; } +DalitzEECut* o2::aod::dalitzeecuts::GetCut(const char* cutName) +{ + DalitzEECut* cut = new DalitzEECut(cutName, cutName); + std::string nameStr = cutName; + + if (!nameStr.compare("mee_all_tpchadrejortofreq_lowB")) { + // for pair + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTOFNsigmaElRange(-3, +3); + cut->SetTPCNsigmaMuRange(-2, +2); + cut->SetTPCNsigmaPiRange(-3, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetMuonExclusionTPC(true); + return cut; + } + + if (!nameStr.compare("mee_all_tpchadrej_lowB")) { + // for pair + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrej); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaMuRange(-2, +2); + cut->SetTPCNsigmaPiRange(-3, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetMuonExclusionTPC(true); + cut->SetTOFbetaRange(true, 0.0, 0.95); + return cut; + } + + if (!nameStr.compare("mee_all_tofreq_lowB")) { + // for pair + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTOFNsigmaElRange(-3, +3); + cut->SetTPCNsigmaPiRange(-3, +3); + return cut; + } + if (!nameStr.compare("mee_all_nopid_lowB")) { + // for pair + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kUnDef); + return cut; + } + if (!nameStr.compare("mee_0_120_tpconly")) { + // for pair + cut->SetMeeRange(0., 0.12); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.2f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-1e+10, +3); + return cut; + } + if (!nameStr.compare("mee_120_500_tpconly")) { + // for pair + cut->SetMeeRange(0.12, 0.5); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.2f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-1e+10, +3); + return cut; + } + if (!nameStr.compare("mee_0_500_tpconly")) { + // for pair + cut->SetMeeRange(0., 0.5); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.2f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-1e+10, +3); + return cut; + } + if (!nameStr.compare("mee_0_120_tpconly_lowB")) { + // for pair + cut->SetMeeRange(0., 0.12); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-3, +3); + return cut; + } + if (!nameStr.compare("mee_120_500_tpconly_lowB")) { + // for pair + cut->SetMeeRange(0.12, 0.5); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-3, +3); + return cut; + } + if (!nameStr.compare("mee_0_500_tpconly_lowB")) { + // for pair + cut->SetMeeRange(0., 0.5); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPConly); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-3, +3); + return cut; + } + if (!nameStr.compare("mee_0_120_tpchadrejortofreq_lowB")) { + // for pair + cut->SetMeeRange(0., 0.12); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTOFNsigmaElRange(-3, +3); + cut->SetTPCNsigmaMuRange(-2, +2); + cut->SetTPCNsigmaPiRange(-3, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetMuonExclusionTPC(true); + return cut; + } + if (!nameStr.compare("mee_120_500_tpchadrejortofreq_lowB")) { + // for pair + cut->SetMeeRange(0.12, 0.5); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTOFNsigmaElRange(-3, +3); + cut->SetTPCNsigmaMuRange(-2, +2); + cut->SetTPCNsigmaPiRange(-3, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetMuonExclusionTPC(true); + return cut; + } + if (!nameStr.compare("mee_0_500_tpchadrejortofreq_lowB")) { + // for pair + cut->SetMeeRange(0., 0.5); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.05f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTOFNsigmaElRange(-3, +3); + cut->SetTPCNsigmaMuRange(-2, +2); + cut->SetTPCNsigmaPiRange(-3, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetMuonExclusionTPC(true); + return cut; + } + + if (!nameStr.compare("mee_all_tpchadrejortofreq")) { + // for pair + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.2f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-1e+10, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetTOFNsigmaElRange(-3, +3); + return cut; + } + if (!nameStr.compare("mee_0_120_tpchadrejortofreq")) { + // for pair + cut->SetMeeRange(0, 0.12); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.2f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-1e+10, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetTOFNsigmaElRange(-3, +3); + return cut; + } + if (!nameStr.compare("mee_0_120_tpchadrejortofreq_wo_phiv")) { + // for pair + cut->SetMeeRange(0, 0.12); + + // for track + cut->SetTrackPtRange(0.2f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-1e+10, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetTOFNsigmaElRange(-3, +3); + return cut; + } + if (!nameStr.compare("mee_120_500_tpchadrejortofreq")) { + // for pair + cut->SetMeeRange(0.12, 0.5); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.2f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-1e+10, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetTOFNsigmaElRange(-3, +3); + return cut; + } + if (!nameStr.compare("mee_0_500_tpchadrejortofreq")) { + // for pair + cut->SetMeeRange(0., 0.5); + cut->SetMaxPhivPairMeeDep([](float mee) { + return mee < 0.01 ? 1.5 : (mee < 0.02 ? 2.0 : (mee < 0.03 ? 2.5 : 3.2)); + }); + + // for track + cut->SetTrackPtRange(0.2f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + + // for PID + cut->SetPIDScheme(DalitzEECut::PIDSchemes::kTPChadrejORTOFreq); + cut->SetTOFbetaRange(true, 0.0, 0.95); + cut->SetTPCNsigmaElRange(-2, +3); + cut->SetTPCNsigmaPiRange(-1e+10, +3); + cut->SetTPCNsigmaKaRange(-3, +3); + cut->SetTPCNsigmaPrRange(-3, +3); + cut->SetTOFNsigmaElRange(-3, +3); + return cut; + } + + if (!nameStr.compare("nocut")) { + // for track + cut->SetTrackPtRange(0.01f, 1e10f); + cut->SetTrackEtaRange(-0.9, +0.9); + cut->SetMinNCrossedRowsTPC(80); + cut->SetMinNCrossedRowsOverFindableClustersTPC(0.8); + cut->SetChi2PerClusterTPC(0.0, 4.0); + cut->SetChi2PerClusterITS(0.0, 5.0); + cut->SetNClustersITS(4, 7); + cut->SetMaxDcaXY(1.0); + cut->SetMaxDcaZ(1.0); + return cut; + } + + delete cut; + LOGF(info, Form("Did not find cut %s", cutName)); + return nullptr; +} + PHOSPhotonCut* o2::aod::phoscuts::GetCut(const char* cutName) { PHOSPhotonCut* cut = new PHOSPhotonCut(cutName, cutName); diff --git a/PWGEM/PhotonMeson/Core/CutsLibrary.h b/PWGEM/PhotonMeson/Core/CutsLibrary.h index 656cc10f84a..2fe25725ded 100644 --- a/PWGEM/PhotonMeson/Core/CutsLibrary.h +++ b/PWGEM/PhotonMeson/Core/CutsLibrary.h @@ -17,6 +17,7 @@ #include #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" @@ -27,6 +28,10 @@ namespace pcmcuts { V0PhotonCut* GetCut(const char* cutName); } // namespace pcmcuts +namespace dalitzeecuts +{ +DalitzEECut* GetCut(const char* cutName); +} // namespace dalitzeecuts namespace phoscuts { diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx new file mode 100644 index 00000000000..ce61281159a --- /dev/null +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx @@ -0,0 +1,230 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// +// Class for track selection +// + +#include "Framework/Logger.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" + +ClassImp(DalitzEECut); + +const char* DalitzEECut::mCutNames[static_cast(DalitzEECut::DalitzEECuts::kNCuts)] = {"Mee", "PairPtRange", "PairEtaRange", "PhivPair", "TrackPtRange", "TrackEtaRange", "TPCNCls", "TPCCrossedRows", "TPCCrossedRowsOverNCls", "TPCChi2NDF", "TPCNsigmaEl", "TPCNsigmaMu", "TPCNsigmaPi", "TPCNsigmaKa", "TPCNsigmaPr", "TOFNsigmaEl", "TOFNsigmaMu", "TOFNsigmaPi", "TOFNsigmaKa", "TOFNsigmaPr", "DCAxy", "DCAz", "ITSNCls", "ITSChi2NDF"}; + +void DalitzEECut::SetPairPtRange(float minPt, float maxPt) +{ + mMinPairPt = minPt; + mMaxPairPt = maxPt; + LOG(info) << "DalitzEE Cut, set pair pt range: " << mMinPairPt << " - " << mMaxPairPt; +} +void DalitzEECut::SetPairEtaRange(float minEta, float maxEta) +{ + mMinPairEta = minEta; + mMaxPairEta = maxEta; + LOG(info) << "DalitzEE Cut, set pair eta range: " << mMinPairEta << " - " << mMaxPairEta; +} +void DalitzEECut::SetMeeRange(float min, float max) +{ + mMinMee = min; + mMaxMee = max; + LOG(info) << "DalitzEE selection, set mee range: " << mMinMee << " - " << mMaxMee; +} +void DalitzEECut::SetMaxPhivPairMeeDep(std::function meeDepCut) +{ + mMaxPhivPairMeeDep = meeDepCut; + LOG(info) << "DalitzEE Cut, set max phiv pair mee dep: " << mMaxPhivPairMeeDep(0.02); +} +void DalitzEECut::SetTrackPtRange(float minPt, float maxPt) +{ + mMinTrackPt = minPt; + mMaxTrackPt = maxPt; + LOG(info) << "DalitzEE Cut, set track pt range: " << mMinTrackPt << " - " << mMaxTrackPt; +} +void DalitzEECut::SetTrackEtaRange(float minEta, float maxEta) +{ + mMinTrackEta = minEta; + mMaxTrackEta = maxEta; + LOG(info) << "DalitzEE Cut, set track eta range: " << mMinTrackEta << " - " << mMaxTrackEta; +} +void DalitzEECut::SetMinNClustersTPC(int minNClustersTPC) +{ + mMinNClustersTPC = minNClustersTPC; + LOG(info) << "DalitzEE Cut, set min N clusters TPC: " << mMinNClustersTPC; +} +void DalitzEECut::SetMinNCrossedRowsTPC(int minNCrossedRowsTPC) +{ + mMinNCrossedRowsTPC = minNCrossedRowsTPC; + LOG(info) << "DalitzEE Cut, set min N crossed rows TPC: " << mMinNCrossedRowsTPC; +} +void DalitzEECut::SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC) +{ + mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; + LOG(info) << "DalitzEE Cut, set min N crossed rows over findable clusters TPC: " << mMinNCrossedRowsOverFindableClustersTPC; +} +void DalitzEECut::SetChi2PerClusterTPC(float min, float max) +{ + mMinChi2PerClusterTPC = min; + mMaxChi2PerClusterTPC = max; + LOG(info) << "DalitzEE Cut, set chi2 per cluster TPC range: " << mMinChi2PerClusterTPC << " - " << mMaxChi2PerClusterTPC; +} + +void DalitzEECut::SetNClustersITS(int min, int max) +{ + mMinNClustersITS = min; + mMaxNClustersITS = max; + LOG(info) << "DalitzEE Cut, set N clusters ITS range: " << mMinNClustersITS << " - " << mMaxNClustersITS; +} +void DalitzEECut::SetChi2PerClusterITS(float min, float max) +{ + mMinChi2PerClusterITS = min; + mMaxChi2PerClusterITS = max; + LOG(info) << "DalitzEE Cut, set chi2 per cluster ITS range: " << mMinChi2PerClusterITS << " - " << mMaxChi2PerClusterITS; +} + +void DalitzEECut::SetMaxDcaXY(float maxDcaXY) +{ + mMaxDcaXY = maxDcaXY; + LOG(info) << "DalitzEE Cut, set max DCA xy: " << mMaxDcaXY; +} +void DalitzEECut::SetMaxDcaZ(float maxDcaZ) +{ + mMaxDcaZ = maxDcaZ; + LOG(info) << "DalitzEE Cut, set max DCA z: " << mMaxDcaZ; +} + +void DalitzEECut::SetMaxDcaXYPtDep(std::function ptDepCut) +{ + mMaxDcaXYPtDep = ptDepCut; + LOG(info) << "DalitzEE Cut, set max DCA xy pt dep: " << mMaxDcaXYPtDep(1.0); +} + +void DalitzEECut::SetPIDScheme(PIDSchemes scheme) +{ + mPIDScheme = scheme; + LOG(info) << "DalitzEE Cut, PID scheme: " << static_cast(mPIDScheme); +} +void DalitzEECut::SetMinPinTOF(float min) +{ + mMinPinTOF = min; + LOG(info) << "DalitzEE Cut, set min pin for TOF: " << mMinPinTOF; +} + +void DalitzEECut::SetMuonExclusionTPC(bool flag) +{ + mMuonExclusionTPC = flag; + LOG(info) << "DalitzEE Cut, set flag for muon exclusion in TPC: " << mMuonExclusionTPC; +} + +void DalitzEECut::SetTOFbetaRange(bool flag, float min, float max) +{ + mApplyTOFbeta = flag; + mMinTOFbeta = min; + mMaxTOFbeta = max; + LOG(info) << "DalitzEE selection, set TOF beta rejection range: " << mMinTOFbeta << " - " << mMaxTOFbeta; +} + +void DalitzEECut::SetTPCNsigmaElRange(float min, float max) +{ + mMinTPCNsigmaEl = min; + mMaxTPCNsigmaEl = max; + LOG(info) << "DalitzEE selection, set TPC n sigma El range: " << mMinTPCNsigmaEl << " - " << mMaxTPCNsigmaEl; +} +void DalitzEECut::SetTPCNsigmaMuRange(float min, float max) +{ + mMinTPCNsigmaMu = min; + mMaxTPCNsigmaMu = max; + LOG(info) << "DalitzEE selection, set TPC n sigma Mu range: " << mMinTPCNsigmaMu << " - " << mMaxTPCNsigmaMu; +} +void DalitzEECut::SetTPCNsigmaPiRange(float min, float max) +{ + mMinTPCNsigmaPi = min; + mMaxTPCNsigmaPi = max; + LOG(info) << "DalitzEE selection, set TPC n sigma Pi range: " << mMinTPCNsigmaPi << " - " << mMaxTPCNsigmaPi; +} +void DalitzEECut::SetTPCNsigmaKaRange(float min, float max) +{ + mMinTPCNsigmaKa = min; + mMaxTPCNsigmaKa = max; + LOG(info) << "DalitzEE selection, set TPC n sigma Ka range: " << mMinTPCNsigmaKa << " - " << mMaxTPCNsigmaKa; +} +void DalitzEECut::SetTPCNsigmaPrRange(float min, float max) +{ + mMinTPCNsigmaPr = min; + mMaxTPCNsigmaPr = max; + LOG(info) << "DalitzEE selection, set TPC n sigma Pr range: " << mMinTPCNsigmaPr << " - " << mMaxTPCNsigmaPr; +} + +void DalitzEECut::SetTOFNsigmaElRange(float min, float max) +{ + mMinTOFNsigmaEl = min; + mMaxTOFNsigmaEl = max; + LOG(info) << "DalitzEE selection, set TOF n sigma El range: " << mMinTOFNsigmaEl << " - " << mMaxTOFNsigmaEl; +} +void DalitzEECut::SetTOFNsigmaMuRange(float min, float max) +{ + mMinTOFNsigmaMu = min; + mMaxTOFNsigmaMu = max; + LOG(info) << "DalitzEE selection, set TOF n sigma Mu range: " << mMinTOFNsigmaMu << " - " << mMaxTOFNsigmaMu; +} +void DalitzEECut::SetTOFNsigmaPiRange(float min, float max) +{ + mMinTOFNsigmaPi = min; + mMaxTOFNsigmaPi = max; + LOG(info) << "DalitzEE selection, set TOF n sigma Pi range: " << mMinTOFNsigmaPi << " - " << mMaxTOFNsigmaPi; +} +void DalitzEECut::SetTOFNsigmaKaRange(float min, float max) +{ + mMinTOFNsigmaKa = min; + mMaxTOFNsigmaKa = max; + LOG(info) << "DalitzEE selection, set TOF n sigma Ka range: " << mMinTOFNsigmaKa << " - " << mMaxTOFNsigmaKa; +} +void DalitzEECut::SetTOFNsigmaPrRange(float min, float max) +{ + mMinTOFNsigmaPr = min; + mMaxTOFNsigmaPr = max; + LOG(info) << "DalitzEE selection, set TOF n sigma Pr range: " << mMinTOFNsigmaPr << " - " << mMaxTOFNsigmaPr; +} + +void DalitzEECut::print() const +{ + LOG(info) << "Dalitz EE Cut:"; + for (int i = 0; i < static_cast(DalitzEECuts::kNCuts); i++) { + switch (static_cast(i)) { + case DalitzEECuts::kTrackPtRange: + LOG(info) << mCutNames[i] << " in [" << mMinTrackPt << ", " << mMaxTrackPt << "]"; + break; + case DalitzEECuts::kTrackEtaRange: + LOG(info) << mCutNames[i] << " in [" << mMinTrackEta << ", " << mMaxTrackEta << "]"; + break; + case DalitzEECuts::kTPCNCls: + LOG(info) << mCutNames[i] << " > " << mMinNClustersTPC; + break; + case DalitzEECuts::kTPCCrossedRows: + LOG(info) << mCutNames[i] << " > " << mMinNCrossedRowsTPC; + break; + case DalitzEECuts::kTPCCrossedRowsOverNCls: + LOG(info) << mCutNames[i] << " > " << mMinNCrossedRowsOverFindableClustersTPC; + break; + case DalitzEECuts::kTPCChi2NDF: + LOG(info) << mCutNames[i] << " < " << mMaxChi2PerClusterTPC; + break; + case DalitzEECuts::kDCAxy: + LOG(info) << mCutNames[i] << " < " << mMaxDcaXY; + break; + case DalitzEECuts::kDCAz: + LOG(info) << mCutNames[i] << " < " << mMaxDcaZ; + break; + default: + LOG(fatal) << "Cut unknown!"; + } + } +} diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.h b/PWGEM/PhotonMeson/Core/DalitzEECut.h new file mode 100644 index 00000000000..0bb3855f450 --- /dev/null +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.h @@ -0,0 +1,354 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// +// Class for dalitz ee selection +// + +#ifndef PWGEM_PHOTONMESON_CORE_DALITZEECUT_H_ +#define PWGEM_PHOTONMESON_CORE_DALITZEECUT_H_ + +#include +#include +#include +#include +#include +#include "Framework/Logger.h" +#include "Framework/DataTypes.h" +#include "Rtypes.h" +#include "TNamed.h" +#include "TMath.h" + +class DalitzEECut : public TNamed +{ + public: + DalitzEECut() = default; + DalitzEECut(const char* name, const char* title) : TNamed(name, title) {} + + enum class DalitzEECuts : int { + // pair cut + kMee = 0, + kPairPtRange, + kPairEtaRange, + kPhiV, + // track cut + kTrackPtRange, + kTrackEtaRange, + kTPCNCls, + kTPCCrossedRows, + kTPCCrossedRowsOverNCls, + kTPCChi2NDF, + kTPCNsigmaEl, + kTPCNsigmaMu, + kTPCNsigmaPi, + kTPCNsigmaKa, + kTPCNsigmaPr, + kTOFNsigmaEl, + kTOFNsigmaMu, + kTOFNsigmaPi, + kTOFNsigmaKa, + kTOFNsigmaPr, + kDCAxy, + kDCAz, + kITSNCls, + kITSChi2NDF, + kNCuts + }; + static const char* mCutNames[static_cast(DalitzEECuts::kNCuts)]; + + enum class PIDSchemes : int { + kUnDef = -1, + // for nominal B analysis + kTOFreq = 0, + kTOFif = 1, + kTPChadrej = 2, + kTPChadrejORTOFreq = 3, + kTPConly = 4, + }; + + template + bool IsSelected(TPair const& pair) const + { + if (!IsSelectedPair(pair, DalitzEECuts::kPairPtRange)) { + return false; + } + if (!IsSelectedPair(pair, DalitzEECuts::kPairEtaRange)) { + return false; + } + if (!IsSelectedPair(pair, DalitzEECuts::kMee)) { + return false; + } + if (!IsSelectedPair(pair, DalitzEECuts::kPhiV)) { + return false; + } + + auto pos = pair.template posTrack_as(); + auto ele = pair.template negTrack_as(); + + for (auto& track : {pos, ele}) { + if (!track.hasITS() || !track.hasTPC()) { // track has to be ITS-TPC matched track + return false; + } + + if (!IsSelectedTrack(track, DalitzEECuts::kTrackPtRange)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTrackEtaRange)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kDCAxy)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kDCAz)) { + return false; + } + + // ITS cuts + if (!IsSelectedTrack(track, DalitzEECuts::kITSNCls)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kITSChi2NDF)) { + return false; + } + + // TPC cuts + if (!IsSelectedTrack(track, DalitzEECuts::kTPCNCls)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRows)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCChi2NDF)) { + return false; + } + + // PID cuts here. + if (!PassPID(track)) { + return false; + } + + if (mApplyTOFbeta && (mMinTOFbeta < track.beta() && track.beta() < mMaxTOFbeta)) { + return false; + } + } + return true; + } + + template + bool PassPID(T const& track) const + { + switch (mPIDScheme) { + case PIDSchemes::kTOFreq: + return PassTOFreq(track); + + case PIDSchemes::kTOFif: + return PassTOFif(track); + + case PIDSchemes::kTPChadrej: + return PassTPChadrej(track); + + case PIDSchemes::kTPChadrejORTOFreq: + return PassTPChadrej(track) || PassTOFreq(track); + + case PIDSchemes::kTPConly: + return PassTPConly(track); + + case PIDSchemes::kUnDef: + return true; + + default: + return true; + } + } + + template + bool PassTOFreq(T const& track) const + { + bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; + bool is_pi_excluded_TPC = track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi(); + bool is_el_included_TOF = mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl; + return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; + } + + template + bool PassTOFif(T const& track) const + { + bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; + bool is_pi_excluded_TPC = track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi(); + bool is_el_included_TOF = (track.tpcInnerParam() < mMinPinTOF || track.beta() < 0.0) ? true : mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl; + return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; + } + + template + bool PassTPChadrej(T const& track) const + { + bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; + bool is_mu_excluded_TPC = mMuonExclusionTPC ? track.tpcNSigmaMu() < mMinTPCNsigmaMu || mMaxTPCNsigmaMu < track.tpcNSigmaMu() : true; + bool is_pi_excluded_TPC = track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi(); + bool is_ka_excluded_TPC = track.tpcNSigmaKa() < mMinTPCNsigmaKa || mMaxTPCNsigmaKa < track.tpcNSigmaKa(); + bool is_pr_excluded_TPC = track.tpcNSigmaPr() < mMinTPCNsigmaPr || mMaxTPCNsigmaPr < track.tpcNSigmaPr(); + return is_el_included_TPC && is_mu_excluded_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC; + } + + template + bool PassTPConly(T const& track) const + { + bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; + bool is_pi_excluded_TPC = track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi(); + return is_el_included_TPC && is_pi_excluded_TPC; + } + + template + bool IsSelectedPair(T const& pair, const DalitzEECuts& cut) const + { + switch (cut) { + case DalitzEECuts::kPairPtRange: + return pair.pt() >= mMinPairPt && pair.pt() <= mMaxPairPt; + + case DalitzEECuts::kPairEtaRange: + return pair.eta() >= mMinPairEta && pair.eta() <= mMaxPairEta; + + case DalitzEECuts::kMee: + return mMinMee <= pair.mee() && pair.mee() <= mMaxMee; + + case DalitzEECuts::kPhiV: + return mMinPhivPair <= pair.phiv() && pair.phiv() <= (mMaxPhivPairMeeDep ? mMaxPhivPairMeeDep(pair.mee()) : mMaxPhivPair); + + default: + return false; + } + } + + template + bool IsSelectedTrack(T const& track, const DalitzEECuts& cut) const + { + switch (cut) { + case DalitzEECuts::kTrackPtRange: + return track.pt() >= mMinTrackPt && track.pt() <= mMaxTrackPt; + + case DalitzEECuts::kTrackEtaRange: + return track.eta() >= mMinTrackEta && track.eta() <= mMaxTrackEta; + + case DalitzEECuts::kTPCNCls: + return track.tpcNClsFound() >= mMinNClustersTPC; + + case DalitzEECuts::kTPCCrossedRows: + return track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC; + + case DalitzEECuts::kTPCCrossedRowsOverNCls: + return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; + + case DalitzEECuts::kTPCChi2NDF: + return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; + + case DalitzEECuts::kDCAxy: + return abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + + case DalitzEECuts::kDCAz: + return abs(track.dcaZ()) <= mMaxDcaZ; + + case DalitzEECuts::kITSNCls: + return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; + + case DalitzEECuts::kITSChi2NDF: + return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; + + default: + return false; + } + } + + // Setters + void SetPairPtRange(float minPt = 0.f, float maxPt = 1e10f); + void SetPairEtaRange(float minEta = -1e10f, float maxEta = 1e10f); + void SetMeeRange(float min = 0.f, float max = 0.5); + void SetMaxPhivPairMeeDep(std::function meeDepCut); + + void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f); + void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f); + void SetMinNClustersTPC(int minNClustersTPC); + void SetMinNCrossedRowsTPC(int minNCrossedRowsTPC); + void SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC); + void SetChi2PerClusterTPC(float min, float max); + void SetNClustersITS(int min, int max); + void SetChi2PerClusterITS(float min, float max); + + void SetPIDScheme(PIDSchemes scheme); + void SetMinPinTOF(float min); + void SetMuonExclusionTPC(bool flag); + void SetTOFbetaRange(bool flag, float min, float max); + void SetTPCNsigmaElRange(float min = -1e+10, float max = 1e+10); + void SetTPCNsigmaMuRange(float min = -1e+10, float max = 1e+10); + void SetTPCNsigmaPiRange(float min = -1e+10, float max = 1e+10); + void SetTPCNsigmaKaRange(float min = -1e+10, float max = 1e+10); + void SetTPCNsigmaPrRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaElRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaMuRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaPiRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaKaRange(float min = -1e+10, float max = 1e+10); + void SetTOFNsigmaPrRange(float min = -1e+10, float max = 1e+10); + + void SetMaxDcaXY(float maxDcaXY); + void SetMaxDcaZ(float maxDcaZ); + void SetMaxDcaXYPtDep(std::function ptDepCut); + + /// @brief Print the track selection + void print() const; + + private: + // pair cuts + float mMinMee{0.f}, mMaxMee{1e10f}; + float mMinPairPt{0.f}, mMaxPairPt{1e10f}; // range in pT + float mMinPairEta{-1e10f}, mMaxPairEta{1e10f}; // range in eta + float mMinPhivPair{0.f}, mMaxPhivPair{+3.2}; + std::function mMaxPhivPairMeeDep{}; // max phiv as a function of mee + + // kinematic cuts + float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT + float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta + + // track quality cuts + int mMinNClustersTPC{0}; // min number of TPC clusters + int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC + float mMinChi2PerClusterTPC{-1e10f}, mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster + float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters + int mMinNClustersITS{0}, mMaxNClustersITS{7}; // range in number of ITS clusters + float mMinChi2PerClusterITS{-1e10f}, mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster + + float mMaxDcaXY{1.0f}; // max dca in xy plane + float mMaxDcaZ{1.0f}; // max dca in z direction + std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT + + // pid cuts + PIDSchemes mPIDScheme{PIDSchemes::kUnDef}; + float mMinPinTOF{0.0f}; // min pin cut for TOF. + bool mMuonExclusionTPC{false}; // flag to reject muon in TPC for low B + bool mApplyTOFbeta{false}; // flag to reject hadron contamination with TOF + float mMinTOFbeta{0.0}, mMaxTOFbeta{0.95}; + float mMinTPCNsigmaEl{-1e+10}, mMaxTPCNsigmaEl{+1e+10}; + float mMinTPCNsigmaMu{-1e+10}, mMaxTPCNsigmaMu{+1e+10}; + float mMinTPCNsigmaPi{-1e+10}, mMaxTPCNsigmaPi{+1e+10}; + float mMinTPCNsigmaKa{-1e+10}, mMaxTPCNsigmaKa{+1e+10}; + float mMinTPCNsigmaPr{-1e+10}, mMaxTPCNsigmaPr{+1e+10}; + + float mMinTOFNsigmaEl{-1e+10}, mMaxTOFNsigmaEl{+1e+10}; + float mMinTOFNsigmaMu{-1e+10}, mMaxTOFNsigmaMu{+1e+10}; + float mMinTOFNsigmaPi{-1e+10}, mMaxTOFNsigmaPi{+1e+10}; + float mMinTOFNsigmaKa{-1e+10}, mMaxTOFNsigmaKa{+1e+10}; + float mMinTOFNsigmaPr{-1e+10}, mMaxTOFNsigmaPr{+1e+10}; + + ClassDef(DalitzEECut, 1); +}; + +#endif // PWGEM_PHOTONMESON_CORE_DALITZEECUT_H_ diff --git a/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx b/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx index f8c8d3792c6..e2f32c5be50 100644 --- a/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx @@ -46,9 +46,9 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* } if (TString(histClass) == "V0Leg") { list->Add(new TH1F("hPt", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); - list->Add(new TH1F("hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", 1000, -50, 50)); + list->Add(new TH1F("hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", 400, -20, 20)); list->Add(new TH2F("hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", 180, 0, TMath::TwoPi(), 40, -2.0f, 2.0f)); - list->Add(new TH2F("hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", 1000, -50.0f, 50.0f, 1000, -50.0f, 50.0f)); + list->Add(new TH2F("hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", 200, -50.0f, 50.0f, 200, -50.0f, 50.0f)); list->Add(new TH1F("hNclsTPC", "number of TPC clusters", 161, -0.5, 160.5)); list->Add(new TH1F("hNcrTPC", "number of TPC crossed rows", 161, -0.5, 160.5)); list->Add(new TH1F("hChi2TPC", "chi2/number of TPC clusters", 100, 0, 10)); @@ -59,46 +59,35 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* list->Add(new TH1F("hTPCNcls2Nf", "TPC Ncls/Nfindable", 200, 0, 2)); list->Add(new TH1F("hNclsITS", "number of ITS clusters", 8, -0.5, 7.5)); list->Add(new TH1F("hChi2ITS", "chi2/number of ITS clusters", 360, 0, 36)); - list->Add(new TH2F("hXY", "X vs. Y;X;Y", 100, 0, 100, 100, -50, 50)); - list->Add(new TH2F("hZX", "Z vs. X;Z;X", 200, -100, 100, 100, 0, 100)); + list->Add(new TH1F("hITSClusterMap", "ITS cluster map", 128, -0.5, 127.5)); + list->Add(new TH2F("hXY", "X vs. Y;X;Y", 200, 0, 200, 100, -50, 50)); + list->Add(new TH2F("hZX", "Z vs. X;Z;X", 200, -100, 100, 200, 0, 200)); list->Add(new TH2F("hZY", "Z vs. Y;Z;Y", 200, -100, 100, 100, -50, 50)); - list->Add(new TH2F("hDCAxyEta", "DCAxy vs. #eta;#eta;DCA_{xy} (cm)", 400, -2, +2, 100, -50, 50)); list->Add(new TH2F("hDCAxyZ", "DCAxy vs. Z;Z (cm);DCA_{xy} (cm)", 200, -100, +100, 100, -50, 50)); } if (TString(histClass) == "V0") { list->Add(new TH1F("hPt", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); list->Add(new TH2F("hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", 180, 0, TMath::TwoPi(), 40, -2.0f, 2.0f)); - list->Add(new TH2F("hRadius", "V0Radius; radius in Z (cm);radius in XY (cm)", 500, -250, 250, 500, 0.0f, 250.0f)); - list->Add(new TH2F("hRadius_recalc", "V0Radius; radius in Z (cm);radius in XY (cm)", 500, -250, 250, 500, 0.0f, 250.0f)); + list->Add(new TH2F("hRadius", "V0Radius; radius in Z (cm);radius in XY (cm)", 200, -100, 100, 200, 0.0f, 100.0f)); + list->Add(new TH2F("hRadius_recalc", "V0Radius; radius in Z (cm);radius in XY (cm)", 200, -100, 100, 200, 0.0f, 100.0f)); list->Add(new TH1F("hCosPA", "V0CosPA;cosine pointing angle", 100, 0.9f, 1.0f)); - list->Add(new TH1F("hPCA", "distance between 2 legs; PCA (cm)", 100, 0.0f, 10.0f)); + list->Add(new TH1F("hPCA", "distance between 2 legs; PCA (cm)", 50, 0.0f, 5.0f)); list->Add(new TH2F("hAPplot", "AP plot;#alpha;q_{T} (GeV/c)", 200, -1.0f, +1.0f, 250, 0.0f, 0.25f)); - list->Add(new TH2F("hGammaPsiPair", "#psi_{pair} for photon conversion;#psi_{pair} (rad.);m_{ee} (GeV/c^{2})", 150, 0, TMath::PiOver2(), 100, 0.0f, 0.1f)); list->Add(new TH2F("hMassGamma", "hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", 200, 0.0f, 100.0f, 100, 0.0f, 0.1f)); list->Add(new TH2F("hMassGamma_recalc", "recalc. hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", 200, 0.0f, 100.0f, 100, 0.0f, 0.1f)); + list->Add(new TH2F("hMassGammaKF_SV_Rxy", "recalc. hMassGamma KF SV;R_{xy} (cm);m_{ee} (GeV/c^{2})", 400, 0.0f, 200.0f, 300, 0.0f, 0.3f)); + list->Add(new TH2F("hMassGammaKF_PV_SV", "hMassGamma;m_{ee} at PV (GeV/c^{2});m_{ee} at SV (GeV/c^{2})", 300, 0.0f, 0.3f, 300, 0.0f, 0.3f)); + list->Add(new TH2F("hMassGammaKF_SV_PsiPair", "#psi_{pair} for photon conversion;#psi_{pair} (rad.);m_{ee} at SV (GeV/c^{2})", 150, 0, TMath::PiOver2(), 300, 0.0f, 0.3f)); + list->Add(new TH2F("hMassGammaKF_SV_PhiV", "#varphi_{V} for photon conversion;#varphi_{V} (rad.);m_{ee} at SV (GeV/c^{2})", 100, 0, TMath::Pi(), 300, 0.0f, 0.3f)); list->Add(new TH2F("hGammaRxy", "conversion point in XY;V_{x} (cm);V_{y} (cm)", 400, -100.0f, 100.0f, 400, -100.0f, 100.0f)); list->Add(new TH2F("hGammaRxy_recalc", "recalc. conversion point in XY;V_{x} (cm);V_{y} (cm)", 400, -100.0f, 100.0f, 400, -100.0f, 100.0f)); list->Add(new TH2F("hKFChi2vsR", "KF chi2 vs. recalc. conversion point in XY;R_{xy} (cm);KF chi2/NDF", 200, 0.0f, 200.0f, 100, 0.f, 100.0f)); - list->Add(new TH2F("hKFChi2vsZ", "KF chi2 vs. recalc. conversion point in Z;Z (cm);KF chi2/NDF", 500, -250.0f, 250.0f, 100, 0.f, 100.0f)); + list->Add(new TH2F("hKFChi2vsX", "KF chi2 vs. recalc. conversion point in X;X (cm);KF chi2/NDF", 200, -100.0f, 100.0f, 100, 0.f, 100.0f)); + list->Add(new TH2F("hKFChi2vsY", "KF chi2 vs. recalc. conversion point in Y;Y (cm);KF chi2/NDF", 200, -100.0f, 100.0f, 100, 0.f, 100.0f)); + list->Add(new TH2F("hKFChi2vsZ", "KF chi2 vs. recalc. conversion point in Z;Z (cm);KF chi2/NDF", 200, -100.0f, 100.0f, 100, 0.f, 100.0f)); list->Add(new TH1F("hNgamma", "Number of #gamma candidates per collision", 101, -0.5f, 100.5f)); - - const int nrxy = 102; - double rxy[nrxy] = {0.f}; - for (int i = 0; i < 90; i++) { - rxy[i] = 1.0 * i; - } - for (int i = 90; i < nrxy; i++) { - rxy[i] = 10.0 * (i - 90) + 90.0; - } - - const int ndim = 3; // r, phi, eta - const int nbins[ndim] = {nrxy - 1, 72, 40}; - const double xmin[ndim] = {0.0, 0.0, -2.0}; - const double xmax[ndim] = {200.0, TMath::TwoPi(), +2.0}; - - THnSparseF* hs_conv_point = new THnSparseF("hs_conv_point", "hs_conv_point;R_{xy} (cm);#varphi (rad.);#eta;", ndim, nbins, xmin, xmax); - hs_conv_point->SetBinEdges(0, rxy); - list->Add(hs_conv_point); + list->Add(new TH2F("hCorrTgl", "correlation of track tgl between e^{+} and e^{-};e^{-} track tgl;e^{+} track tgl", 300, -1.5f, 1.5f, 300, -1.5f, 1.5f)); + list->Add(new TH2F("hCorrZ", "correlation of track iu z between e^{+} and e^{-};e^{-} track iu Z (cm);e^{+} track iu Z (cm)", 400, -100.f, 100.f, 400, -100.f, 100.f)); if (TString(subGroup) == "mc") { list->Add(new TH1F("hPt_Photon_Primary", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); // for MC efficiency @@ -106,10 +95,10 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* list->Add(new TH1F("hPt_Photon_FromWD", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); // for MC feed down correction list->Add(new TH2F("hEtaPhi_Photon_FromWD", "#eta vs. #varphi;#varphi (rad.);#eta", 180, 0, TMath::TwoPi(), 40, -2.0f, 2.0f)); // for MC feed down correction - list->Add(new TH2F("hRZ_Photon_test", "R vs. Z;Z (cm);R_{xy} (cm)", 500, -250.0f, +250, 200, 0, 200)); - list->Add(new TH1F("hPt_Photon_test", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); - list->Add(new TH1F("hEta_Photon_test", "rapidity;y", 40, -2.0f, 2.0f)); - list->Add(new TH1F("hPhi_Photon_test", "#varphi;#varphi (rad.);", 180, 0, TMath::TwoPi())); + list->Add(new TH2F("hRZ_Photon_hs", "R vs. Z of photon from hadronic shower in materials;Z (cm);R_{xy} (cm)", 500, -250.0f, +250, 200, 0, 200)); + list->Add(new TH1F("hPt_Photon_hs", "pT of photon from hadronic shower in materials;p_{T} (GeV/c)", 1000, 0.0f, 10)); + list->Add(new TH1F("hEta_Photon_hs", "rapidity of photon from hadronic shower in materials;y", 40, -2.0f, 2.0f)); + list->Add(new TH1F("hPhi_Photon_hs", "#varphi of photon from hadronic shower in materials;#varphi (rad.);", 180, 0, TMath::TwoPi())); list->Add(new TH2F("hConvPoint_diffX", "conversion point diff X MC;X_{MC} (cm);X_{rec} - X_{MC} (cm)", 500, -250, +250, 100, -50.0f, 50.0f)); list->Add(new TH2F("hConvPoint_diffY", "conversion point diff Y MC;Y_{MC} (cm);Y_{rec} - Y_{MC} (cm)", 500, -250, +250, 100, -50.0f, 50.0f)); @@ -122,7 +111,99 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* list->Add(new TH2F("hPtGen_DeltaPtOverPtGen", "photon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", 1000, 0, 10, 1000, -1.0f, 1.0f)); list->Add(new TH2F("hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", 1000, 0, 10, 1000, -1.0f, 1.0f)); list->Add(new TH2F("hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", 1000, 0, 10, 1000, -1.0f, 1.0f)); + } // end of mc + } // end of V0 + + if (TString(histClass) == "DalitzEE") { + const int nm = 150; + double mee[nm] = {0.f}; + for (int i = 0; i < 110; i++) { + mee[i] = 0.01 * i; + } + for (int i = 110; i < nm; i++) { + mee[i] = 0.1 * (i - 110) + 1.1; + } + + const int npt = 61; + double pt[npt] = {0.f}; + for (int i = 0; i < 50; i++) { + pt[i] = 0.1 * i; + } + for (int i = 50; i < npt; i++) { + pt[i] = 0.5 * (i - 50) + 5.0; + } + + const int ndca = 66; + double dca[ndca] = {0.f}; + for (int i = 0; i < 50; i++) { + dca[i] = 0.1 * i; } + for (int i = 50; i < ndca; i++) { + dca[i] = 1.0 * (i - 50) + 5.0; + } + + const int ndim = 4; // m, pt, dca, phiv + const int nbins[ndim] = {nm - 1, npt - 1, ndca - 1, 32}; + const double xmin[ndim] = {0.0, 0.0, 0.0, 0.0}; + const double xmax[ndim] = {5.0, 10.0, 20.0, 3.2}; + + THnSparseF* hs_dilepton_uls = new THnSparseF("hs_dilepton_uls", "hs_dilepton_uls;m_{ee} (GeV/c);p_{T,ee} (GeV/c);DCA_{xy,ee} (#sigma);#varphi_{V} (rad.);", ndim, nbins, xmin, xmax); + hs_dilepton_uls->SetBinEdges(0, mee); + hs_dilepton_uls->SetBinEdges(1, pt); + hs_dilepton_uls->SetBinEdges(2, dca); + hs_dilepton_uls->Sumw2(); + list->Add(hs_dilepton_uls); + + THnSparseF* hs_dilepton_lspp = new THnSparseF("hs_dilepton_lspp", "hs_dilepton_lspp;m_{ee} (GeV/c);p_{T,ee} (GeV/c);DCA_{xy,ee} (#sigma);#varphi_{V} (rad.);", ndim, nbins, xmin, xmax); + hs_dilepton_lspp->SetBinEdges(0, mee); + hs_dilepton_lspp->SetBinEdges(1, pt); + hs_dilepton_lspp->SetBinEdges(2, dca); + hs_dilepton_lspp->Sumw2(); + list->Add(hs_dilepton_lspp); + + THnSparseF* hs_dilepton_lsmm = new THnSparseF("hs_dilepton_lsmm", "hs_dilepton_lsmm;m_{ee} (GeV/c);p_{T,ee} (GeV/c);DCA_{xy,ee} (#sigma);#varphi_{V} (rad.);", ndim, nbins, xmin, xmax); + hs_dilepton_lsmm->SetBinEdges(0, mee); + hs_dilepton_lsmm->SetBinEdges(1, pt); + hs_dilepton_lsmm->SetBinEdges(2, dca); + hs_dilepton_lsmm->Sumw2(); + list->Add(hs_dilepton_lsmm); + + list->Add(new TH1F("hNpair_uls", "Number of ULS pairs per collision", 101, -0.5f, 100.5f)); + list->Add(new TH1F("hNpair_lspp", "Number of LS++ pairs per collision", 101, -0.5f, 100.5f)); + list->Add(new TH1F("hNpair_lsmm", "Number of LS-- pairs per collision", 101, -0.5f, 100.5f)); + + if (TString(subGroup) == "mc") { + list->Add(new TH1F("hPt_Photon_Primary", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); // for MC efficiency + list->Add(new TH2F("hEtaPhi_Photon_Primary", "#eta vs. #varphi;#varphi (rad.);#eta", 180, 0, TMath::TwoPi(), 40, -2.0f, 2.0f)); // for MC efficiency + } // end of mc + } // end of DalitzEE + if (TString(histClass) == "Track") { + list->Add(new TH1F("hPt", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); + list->Add(new TH1F("hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", 400, -20, 20)); + list->Add(new TH2F("hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", 180, 0, TMath::TwoPi(), 40, -2.0f, 2.0f)); + list->Add(new TH2F("hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", 200, -1.0f, 1.0f, 200, -1.0f, 1.0f)); + list->Add(new TH2F("hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", 1000, 0, 10, 100, 0., 1000)); + list->Add(new TH2F("hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", 1000, 0, 10, 100, 0., 1000)); + list->Add(new TH1F("hNclsTPC", "number of TPC clusters", 161, -0.5, 160.5)); + list->Add(new TH1F("hNcrTPC", "number of TPC crossed rows", 161, -0.5, 160.5)); + list->Add(new TH1F("hChi2TPC", "chi2/number of TPC clusters", 100, 0, 10)); + list->Add(new TH2F("hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", 1000, 0, 10, 200, 0, 200)); + list->Add(new TH2F("hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTOFbeta", "TOF beta;p_{in} (GeV/c);TOF #beta", 1000, 0, 10, 600, 0, 1.2)); + list->Add(new TH2F("hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH2F("hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", 1000, 0, 10, 100, -5, +5)); + list->Add(new TH1F("hTPCNcr2Nf", "TPC Ncr/Nfindable", 200, 0, 2)); + list->Add(new TH1F("hTPCNcls2Nf", "TPC Ncls/Nfindable", 200, 0, 2)); + list->Add(new TH1F("hNclsITS", "number of ITS clusters", 8, -0.5, 7.5)); + list->Add(new TH1F("hChi2ITS", "chi2/number of ITS clusters", 360, 0, 36)); + list->Add(new TH1F("hITSClusterMap", "ITS cluster map", 128, -0.5, 127.5)); } if (TString(histClass) == "Cluster") { @@ -144,9 +225,9 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* } if (TString(histClass) == "singlephoton") { - list->Add(new TH1F("hPt", "pT of photon;p_{T} (GeV/c)", 1000, 0.0f, 10)); - list->Add(new TH1F("hY", "rapidity of photon;y", 40, -2.0f, 2.0f)); - list->Add(new TH1F("hPhi", "azimuthal angle of photon;#varphi (rad.)", 180, 0, TMath::TwoPi())); + list->Add(new TH1F("hPt", "pT of photon candidates;p_{T} (GeV/c)", 1000, 0.0f, 10)); + list->Add(new TH1F("hY", "rapidity of photon candidates;y", 40, -2.0f, 2.0f)); + list->Add(new TH1F("hPhi", "azimuthal angle of photon candidates;#varphi (rad.)", 180, 0, TMath::TwoPi())); if (TString(subGroup) == "mc") { list->Add(new TH1F("hPt_Photon_Primary", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); // for MC efficiency list->Add(new TH1F("hY_Photon_Primary", "rapidity;y", 40, -2.0f, 2.0f)); // for MC efficiency @@ -154,6 +235,9 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* list->Add(new TH1F("hPt_Photon_FromWD", "pT;p_{T} (GeV/c)", 1000, 0.0f, 10)); // for MC efficiency list->Add(new TH1F("hY_Photon_FromWD", "rapidity;y", 40, -2.0f, 2.0f)); // for MC efficiency list->Add(new TH1F("hPhi_Photon_FromWD", "#varphi;#varphi (rad.);", 180, 0, TMath::TwoPi())); // for MC efficiency + list->Add(new TH1F("hPt_Photon_hs", "pT of photon from hadronic shower in materials;p_{T} (GeV/c)", 1000, 0.0f, 10)); + list->Add(new TH1F("hY_Photon_hs", "rapidity from hadronic shower in materials;y", 40, -2.0f, 2.0f)); + list->Add(new TH1F("hPhi_Photon_hs", "#varphi from hadronic shower in materials;#varphi (rad.);", 180, 0, TMath::TwoPi())); } } @@ -198,6 +282,61 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* reinterpret_cast(list->FindObject("hMggPt_Eta_Primary"))->Sumw2(); } + if (TString(histClass) == "material_budget_study") { + const int nrxy = 102; + double rxy[nrxy] = {0.f}; + for (int i = 0; i < 90; i++) { + rxy[i] = 1.0 * i; + } + for (int i = 90; i < nrxy; i++) { + rxy[i] = 10.0 * (i - 90) + 90.0; + } + + const int npt = 71; + double pt[npt] = {0.f}; + for (int i = 0; i < 10; i++) { + pt[i] = 0.01 * i; + } + for (int i = 10; i < 60; i++) { + pt[i] = 0.1 * (i - 10) + 0.1; + } + for (int i = 60; i < npt; i++) { + pt[i] = 0.5 * (i - 60) + 5.0; + } + if (TString(subGroup) == "V0") { + const int ndim = 4; // pt, r, phi, eta + const int nbins[ndim] = {npt - 1, nrxy - 1, 72, 40}; + const double xmin[ndim] = {0.0, 0.0, 0.0, -2.0}; + const double xmax[ndim] = {10.0, 200.0, TMath::TwoPi(), +2.0}; + THnSparseF* hs_conv_point = new THnSparseF("hs_conv_point", "hs_conv_point;p_{T,#gamma} (GeV/c);R_{xy} (cm);#varphi (rad.);#eta;", ndim, nbins, xmin, xmax); + hs_conv_point->SetBinEdges(0, pt); + hs_conv_point->SetBinEdges(1, rxy); + hs_conv_point->Sumw2(); + list->Add(hs_conv_point); + } else if (TString(subGroup) == "Pair") { + const int ndim = 9; // mgg, pT1, rxy1, eta1, phi1, pT2, rxy2, eta2, phi2 + const int nbins[ndim] = {200, npt - 1, nrxy - 1, 72, 40, npt - 1, nrxy - 1, 72, 40}; + const double xmin[ndim] = {0.0, 0.0, 0, 0, -2, 0.0, 0, 0, -2}; + const double xmax[ndim] = {0.4, 10.0, 200, TMath::TwoPi(), +2, 10.0, 200, TMath::TwoPi(), +2}; + + THnSparseF* hs_conv_point_same = new THnSparseF("hs_conv_point_same", "hs_conv_point;m_{#gamma#gamma} (GeV/c^{2});p_{T,#gamma}^{tag} (GeV/c);R_{xy}^{tag} (cm);#varphi^{tag} (rad.);#eta^{tag};p_{T,#gamma}^{probe} (GeV/c);R_{xy}^{probe} (cm);#varphi^{probe} (rad.);#eta^{probe};", ndim, nbins, xmin, xmax); + hs_conv_point_same->SetBinEdges(1, pt); + hs_conv_point_same->SetBinEdges(2, rxy); + hs_conv_point_same->SetBinEdges(5, pt); + hs_conv_point_same->SetBinEdges(6, rxy); + hs_conv_point_same->Sumw2(); + list->Add(hs_conv_point_same); + + THnSparseF* hs_conv_point_mix = new THnSparseF("hs_conv_point_mix", "hs_conv_point;m_{#gamma#gamma} (GeV/c^{2});p_{T,#gamma}^{tag} (GeV/c);R_{xy}^{tag} (cm);#varphi^{tag} (rad.);#eta^{tag};p_{T,#gamma}^{probe} (GeV/c);R_{xy}^{probe} (cm);#varphi^{probe} (rad.);#eta^{probe};", ndim, nbins, xmin, xmax); + hs_conv_point_mix->SetBinEdges(1, pt); + hs_conv_point_mix->SetBinEdges(2, rxy); + hs_conv_point_mix->SetBinEdges(5, pt); + hs_conv_point_mix->SetBinEdges(6, rxy); + hs_conv_point_mix->Sumw2(); + list->Add(hs_conv_point_mix); + } // end of pair + } // end of material budget study + if (TString(histClass) == "Generated") { list->Add(new TH1F("hCollisionCounter", "hCollisionCounter", 5, 0.5f, 5.5f)); list->Add(new TH1F("hZvtx_before", "vertex z; Zvtx (cm)", 100, -50, +50)); @@ -247,10 +386,21 @@ void o2::aod::emphotonhistograms::DefineHistograms(THashList* list, const char* reinterpret_cast(list->FindObject("hMggPt_Mixed"))->Sumw2(); } if (TString(histClass) == "tagging_pi0_mc") { - list->Add(new TH1F("hPt_v0photon_Pi0", "reconstructed v0 photon from pi0;p_{T,ee} (GeV/c);N_{ee}^{#pi^{0}}", npTgg10 - 1, pTgg10)); // denominator for conditional probability - list->Add(new TH2F("hMggPt_Pi0", "reconstructed m_{ee#gamma} vs. p_{T,ee} from pi0;m_{ee#gamma} (GeV/c^{2});p_{T,ee} (GeV/c);N_{ee}^{tagged #pi^{0}}", nmgg04 - 1, mgg04, npTgg10 - 1, pTgg10)); // numerator for conditional probability - reinterpret_cast(list->FindObject("hPt_v0photon_Pi0"))->Sumw2(); - reinterpret_cast(list->FindObject("hMggPt_Pi0"))->Sumw2(); + if (TString(subGroup) == "pcm") { + list->Add(new TH1F("hPt_v0photon_Pi0_Primary", "reconstcuted v0 photon from primary #pi^{0};p_{T,ee} (GeV/c);N_{ee}^{#pi^{0}}", npTgg10 - 1, pTgg10)); // denominator for conditional probability + reinterpret_cast(list->FindObject("hPt_v0photon_Pi0_Primary"))->Sumw2(); + list->Add(new TH1F("hPt_v0photon_Pi0_FromWD", "reconstcuted v0 photon from #pi^{0} from WD;p_{T,ee} (GeV/c);N_{ee}^{#pi^{0}}", npTgg10 - 1, pTgg10)); // denominator for conditional probability + reinterpret_cast(list->FindObject("hPt_v0photon_Pi0_FromWD"))->Sumw2(); + list->Add(new TH1F("hPt_v0photon_Pi0_hs", "reconstcuted v0 photon from #pi^{0} from hadronic shower in materials;p_{T,ee} (GeV/c);N_{ee}^{#pi^{0}}", npTgg10 - 1, pTgg10)); // denominator for conditional probability + reinterpret_cast(list->FindObject("hPt_v0photon_Pi0_hs"))->Sumw2(); + } else if (TString(subGroup) == "pair") { + list->Add(new TH2F("hMggPt_Pi0_Primary", "reconstructed m_{ee#gamma} vs. p_{T,ee} from primary #pi^{0};m_{ee#gamma} (GeV/c^{2});p_{T,ee} (GeV/c);N_{ee}^{tagged #pi^{0}}", nmgg04 - 1, mgg04, npTgg10 - 1, pTgg10)); // numerator for conditional probability + reinterpret_cast(list->FindObject("hMggPt_Pi0_Primary"))->Sumw2(); + list->Add(new TH2F("hMggPt_Pi0_FromWD", "reconstructed m_{ee#gamma} vs. p_{T,ee} from #pi^{0} from WD;m_{ee#gamma} (GeV/c^{2});p_{T,ee} (GeV/c);N_{ee}^{tagged #pi^{0}}", nmgg04 - 1, mgg04, npTgg10 - 1, pTgg10)); // numerator for conditional probability + reinterpret_cast(list->FindObject("hMggPt_Pi0_FromWD"))->Sumw2(); + list->Add(new TH2F("hMggPt_Pi0_hs", "reconstructed m_{ee#gamma} vs. p_{T,ee} from #pi^{0} from hadronic shower in material;m_{ee#gamma} (GeV/c^{2});p_{T,ee} (GeV/c);N_{ee}^{tagged #pi^{0}}", nmgg04 - 1, mgg04, npTgg10 - 1, pTgg10)); // numerator for conditional probability + reinterpret_cast(list->FindObject("hMggPt_Pi0_hs"))->Sumw2(); + } } if (TString(histClass) == "tag_and_probe") { diff --git a/PWGEM/PhotonMeson/Core/HistogramsLibrary.h b/PWGEM/PhotonMeson/Core/HistogramsLibrary.h index 03d239a9cf8..73ee3eabd38 100644 --- a/PWGEM/PhotonMeson/Core/HistogramsLibrary.h +++ b/PWGEM/PhotonMeson/Core/HistogramsLibrary.h @@ -17,7 +17,6 @@ #include #include -using namespace std; #include #include #include @@ -35,13 +34,15 @@ using namespace std; #include #include -enum EMHistType { +enum class EMHistType : int { kEvent = 0, kV0 = 1, kV0Leg = 2, - kPHOSCluster = 3, - kEMCCluster = 4, - kPhoton = 5, // photon candidates + kDalitzEE = 3, + kTrack = 4, + kPHOSCluster = 5, + kEMCCluster = 6, + kPhoton = 7, // photon candidates }; namespace o2::aod @@ -69,44 +70,68 @@ void FillHistClass(THashList* list, const char* subGroup, T const& obj) reinterpret_cast(list->FindObject("hEtaPhi"))->Fill(obj.phi(), obj.eta()); reinterpret_cast(list->FindObject("hRadius"))->Fill(obj.vz(), obj.v0radius()); reinterpret_cast(list->FindObject("hRadius_recalc"))->Fill(obj.recalculatedVtxZ(), obj.recalculatedVtxR()); - reinterpret_cast(list->FindObject("hCosPA"))->Fill(abs(obj.cospa())); + reinterpret_cast(list->FindObject("hCosPA"))->Fill(obj.cospa()); reinterpret_cast(list->FindObject("hPCA"))->Fill(obj.pca()); reinterpret_cast(list->FindObject("hAPplot"))->Fill(obj.alpha(), obj.qtarm()); reinterpret_cast(list->FindObject("hMassGamma"))->Fill(obj.v0radius(), obj.mGamma()); reinterpret_cast(list->FindObject("hMassGamma_recalc"))->Fill(obj.recalculatedVtxR(), obj.mGamma()); - reinterpret_cast(list->FindObject("hGammaPsiPair"))->Fill(obj.psipair(), obj.mGamma()); + reinterpret_cast(list->FindObject("hMassGammaKF_SV_Rxy"))->Fill(obj.recalculatedVtxR(), obj.mGammaKFSV()); reinterpret_cast(list->FindObject("hGammaRxy"))->Fill(obj.vx(), obj.vy()); reinterpret_cast(list->FindObject("hGammaRxy_recalc"))->Fill(obj.recalculatedVtxX(), obj.recalculatedVtxY()); reinterpret_cast(list->FindObject("hKFChi2vsR"))->Fill(obj.recalculatedVtxR(), obj.chiSquareNDF()); + reinterpret_cast(list->FindObject("hKFChi2vsX"))->Fill(obj.recalculatedVtxX(), obj.chiSquareNDF()); + reinterpret_cast(list->FindObject("hKFChi2vsY"))->Fill(obj.recalculatedVtxY(), obj.chiSquareNDF()); reinterpret_cast(list->FindObject("hKFChi2vsZ"))->Fill(obj.recalculatedVtxZ(), obj.chiSquareNDF()); - - float phi_recalc = atan2(obj.recalculatedVtxY(), obj.recalculatedVtxX()); - float r3d = sqrt(pow(obj.recalculatedVtxX(), 2) + pow(obj.recalculatedVtxY(), 2) + pow(obj.recalculatedVtxZ(), 2)); - float eta_cp = std::atanh(obj.recalculatedVtxZ() / r3d); - double value_cp[3] = {obj.recalculatedVtxR(), phi_recalc < 0 ? phi_recalc + TMath::TwoPi() : phi_recalc, eta_cp}; // r, phi, eta - reinterpret_cast(list->FindObject("hs_conv_point"))->Fill(value_cp); + reinterpret_cast(list->FindObject("hMassGammaKF_PV_SV"))->Fill(obj.mGammaKFPV(), obj.mGammaKFSV()); + reinterpret_cast(list->FindObject("hMassGammaKF_SV_PsiPair"))->Fill(abs(obj.psipair()), obj.mGammaKFSV()); + reinterpret_cast(list->FindObject("hMassGammaKF_SV_PhiV"))->Fill(obj.phiv(), obj.mGammaKFSV()); } else if constexpr (htype == EMHistType::kV0Leg) { - reinterpret_cast(list->FindObject("hPt"))->Fill(obj.pt()); reinterpret_cast(list->FindObject("hQoverPt"))->Fill(obj.sign() / obj.pt()); reinterpret_cast(list->FindObject("hEtaPhi"))->Fill(obj.phi(), obj.eta()); reinterpret_cast(list->FindObject("hDCAxyz"))->Fill(obj.dcaXY(), obj.dcaZ()); - reinterpret_cast(list->FindObject("hNclsTPC"))->Fill(obj.tpcNClsFound()); reinterpret_cast(list->FindObject("hNclsITS"))->Fill(obj.itsNCls()); + reinterpret_cast(list->FindObject("hNclsTPC"))->Fill(obj.tpcNClsFound()); reinterpret_cast(list->FindObject("hNcrTPC"))->Fill(obj.tpcNClsCrossedRows()); reinterpret_cast(list->FindObject("hTPCNcr2Nf"))->Fill(obj.tpcCrossedRowsOverFindableCls()); reinterpret_cast(list->FindObject("hTPCNcls2Nf"))->Fill(obj.tpcFoundOverFindableCls()); reinterpret_cast(list->FindObject("hChi2TPC"))->Fill(obj.tpcChi2NCl()); reinterpret_cast(list->FindObject("hChi2ITS"))->Fill(obj.itsChi2NCl()); + reinterpret_cast(list->FindObject("hITSClusterMap"))->Fill(obj.itsClusterMap()); reinterpret_cast(list->FindObject("hTPCdEdx"))->Fill(obj.tpcInnerParam(), obj.tpcSignal()); reinterpret_cast(list->FindObject("hTPCNsigmaEl"))->Fill(obj.tpcInnerParam(), obj.tpcNSigmaEl()); reinterpret_cast(list->FindObject("hTPCNsigmaPi"))->Fill(obj.tpcInnerParam(), obj.tpcNSigmaPi()); reinterpret_cast(list->FindObject("hXY"))->Fill(obj.x(), obj.y()); reinterpret_cast(list->FindObject("hZX"))->Fill(obj.z(), obj.x()); reinterpret_cast(list->FindObject("hZY"))->Fill(obj.z(), obj.y()); - reinterpret_cast(list->FindObject("hDCAxyEta"))->Fill(obj.eta(), obj.dcaXY()); reinterpret_cast(list->FindObject("hDCAxyZ"))->Fill(obj.z(), obj.dcaXY()); - + } else if constexpr (htype == EMHistType::kTrack) { + reinterpret_cast(list->FindObject("hPt"))->Fill(obj.pt()); + reinterpret_cast(list->FindObject("hQoverPt"))->Fill(obj.sign() / obj.pt()); + reinterpret_cast(list->FindObject("hEtaPhi"))->Fill(obj.phi(), obj.eta()); + reinterpret_cast(list->FindObject("hDCAxyz"))->Fill(obj.dcaXY(), obj.dcaZ()); + reinterpret_cast(list->FindObject("hDCAxyRes_Pt"))->Fill(obj.pt(), sqrt(obj.cYY()) * 1e+4); // convert cm to um + reinterpret_cast(list->FindObject("hDCAzRes_Pt"))->Fill(obj.pt(), sqrt(obj.cZZ()) * 1e+4); // convert cm to um + reinterpret_cast(list->FindObject("hNclsITS"))->Fill(obj.itsNCls()); + reinterpret_cast(list->FindObject("hNclsTPC"))->Fill(obj.tpcNClsFound()); + reinterpret_cast(list->FindObject("hNcrTPC"))->Fill(obj.tpcNClsCrossedRows()); + reinterpret_cast(list->FindObject("hTPCNcr2Nf"))->Fill(obj.tpcCrossedRowsOverFindableCls()); + reinterpret_cast(list->FindObject("hTPCNcls2Nf"))->Fill(obj.tpcFoundOverFindableCls()); + reinterpret_cast(list->FindObject("hChi2TPC"))->Fill(obj.tpcChi2NCl()); + reinterpret_cast(list->FindObject("hChi2ITS"))->Fill(obj.itsChi2NCl()); + reinterpret_cast(list->FindObject("hITSClusterMap"))->Fill(obj.itsClusterMap()); + reinterpret_cast(list->FindObject("hTPCdEdx"))->Fill(obj.tpcInnerParam(), obj.tpcSignal()); + reinterpret_cast(list->FindObject("hTPCNsigmaEl"))->Fill(obj.tpcInnerParam(), obj.tpcNSigmaEl()); + reinterpret_cast(list->FindObject("hTPCNsigmaMu"))->Fill(obj.tpcInnerParam(), obj.tpcNSigmaMu()); + reinterpret_cast(list->FindObject("hTPCNsigmaPi"))->Fill(obj.tpcInnerParam(), obj.tpcNSigmaPi()); + reinterpret_cast(list->FindObject("hTPCNsigmaKa"))->Fill(obj.tpcInnerParam(), obj.tpcNSigmaKa()); + reinterpret_cast(list->FindObject("hTPCNsigmaPr"))->Fill(obj.tpcInnerParam(), obj.tpcNSigmaPr()); + reinterpret_cast(list->FindObject("hTOFbeta"))->Fill(obj.tpcInnerParam(), obj.beta()); + reinterpret_cast(list->FindObject("hTOFNsigmaEl"))->Fill(obj.tpcInnerParam(), obj.tofNSigmaEl()); + reinterpret_cast(list->FindObject("hTOFNsigmaMu"))->Fill(obj.tpcInnerParam(), obj.tofNSigmaMu()); + reinterpret_cast(list->FindObject("hTOFNsigmaPi"))->Fill(obj.tpcInnerParam(), obj.tofNSigmaPi()); + reinterpret_cast(list->FindObject("hTOFNsigmaKa"))->Fill(obj.tpcInnerParam(), obj.tofNSigmaKa()); + reinterpret_cast(list->FindObject("hTOFNsigmaPr"))->Fill(obj.tpcInnerParam(), obj.tofNSigmaPr()); } else if constexpr (htype == EMHistType::kPHOSCluster) { reinterpret_cast(list->FindObject("hPt"))->Fill(obj.pt()); reinterpret_cast(list->FindObject("hEtaPhi"))->Fill(obj.phi(), obj.eta()); diff --git a/PWGEM/PhotonMeson/Core/PWGEMPhotonMesonCoreLinkDef.h b/PWGEM/PhotonMeson/Core/PWGEMPhotonMesonCoreLinkDef.h index 0bbe073b16c..963229d1d24 100644 --- a/PWGEM/PhotonMeson/Core/PWGEMPhotonMesonCoreLinkDef.h +++ b/PWGEM/PhotonMeson/Core/PWGEMPhotonMesonCoreLinkDef.h @@ -17,6 +17,7 @@ #pragma link off all functions; #pragma link C++ class V0PhotonCut + ; +#pragma link C++ class DalitzEECut + ; #pragma link C++ class PHOSPhotonCut + ; #pragma link C++ class EMCPhotonCut + ; #pragma link C++ class PairCut + ; diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx index 1490ca5dd19..5c45ba35f00 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx @@ -18,7 +18,11 @@ ClassImp(V0PhotonCut); -const char* V0PhotonCut::mCutNames[static_cast(V0PhotonCut::V0PhotonCuts::kNCuts)] = {"Mee", "V0PtRange", "V0EtaRange", "PsiPair", "Rxy", "CosPA", "PCA", "RZLine", "OnWwireIB", "OnWwireOB", "TrackPtRange", "TrackEtaRange", "TPCNCls", "TPCCrossedRows", "TPCCrossedRowsOverNCls", "TPCChi2NDF", "TPCNsigmaEl", "TPCNsigmaPi", "DCAxy", "DCAz", "IsWithinBeamPipe", "RequireITS", "TPConly", "AntiTPConly"}; +const char* V0PhotonCut::mCutNames[static_cast(V0PhotonCut::V0PhotonCuts::kNCuts)] = {"Mee", "V0PtRange", "V0EtaRange", "AP", " PsiPair", "PhivPair", "Rxy", "CosPA", "PCA", "RZLine", "OnWwireIB", "OnWwireOB", "TrackPtRange", "TrackEtaRange", "TPCNCls", "TPCCrossedRows", "TPCCrossedRowsOverNCls", "TPCChi2NDF", "TPCNsigmaEl", "TPCNsigmaPi", "DCAxy", "DCAz", "ITSNCls", "ITSChi2NDF", "IsWithinBeamPipe", "RequireITSTPC", "RequireITSonly", "RequireTPConly", "RequireTPCTRD", "RequireTPCTOF", "RequireTPCTRDTOF"}; + +const std::pair> V0PhotonCut::its_ib_Requirement = {0, {0, 1, 2}}; // no hit on 3 ITS ib layers. +const std::pair> V0PhotonCut::its_ob_Requirement = {4, {3, 4, 5, 6}}; // all hits on 4 ITS ob layers. +const std::pair> V0PhotonCut::its_ob_Requirement_ITSTPC = {2, {3, 4, 5, 6}}; // at least 2 hits on 4 ITS ob layers. void V0PhotonCut::SetV0PtRange(float minPt, float maxPt) { @@ -44,6 +48,18 @@ void V0PhotonCut::SetPsiPairRange(float min, float max) mMaxPsiPair = max; LOG(info) << "V0 Photon selection, set psi pair range: " << mMinPsiPair << " - " << mMaxPsiPair; } +void V0PhotonCut::SetPhivPairRange(float min, float max) +{ + mMinPhivPair = min; + mMaxPhivPair = max; + LOG(info) << "V0 Photon selection, set phiv pair range: " << mMinPhivPair << " - " << mMaxPhivPair; +} +void V0PhotonCut::SetAPRange(float max_alpha, float max_qt) +{ + mMaxAlpha = max_alpha; + mMaxQt = max_qt; + LOG(info) << "V0 Photon selection, set Armenteroz-Podolanski range: " << mMaxAlpha << " - " << mMaxQt; +} void V0PhotonCut::SetMaxMeePsiPairDep(std::function psiDepCut) { mMaxMeePsiPairDep = psiDepCut; @@ -73,12 +89,12 @@ void V0PhotonCut::SetMaxMarginZ(float max) void V0PhotonCut::SetOnWwireIB(bool flag) { mIsOnWwireIB = flag; - LOG(info) << "V0 Photon Cut, select photon on Tungstate wire IB: " << mIsOnWwireIB; + LOG(info) << "V0 Photon Cut, select photon on Tungsten wire IB: " << mIsOnWwireIB; } void V0PhotonCut::SetOnWwireOB(bool flag) { mIsOnWwireOB = flag; - LOG(info) << "V0 Photon Cut, select photon on Tungstate wire OB: " << mIsOnWwireOB; + LOG(info) << "V0 Photon Cut, select photon on Tungsten wire OB: " << mIsOnWwireOB; } void V0PhotonCut::SetTPCNsigmaElRange(float min, float max) { @@ -119,10 +135,11 @@ void V0PhotonCut::SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRow mMinNCrossedRowsOverFindableClustersTPC = minNCrossedRowsOverFindableClustersTPC; LOG(info) << "V0 Photon Cut, set min N crossed rows over findable clusters TPC: " << mMinNCrossedRowsOverFindableClustersTPC; } -void V0PhotonCut::SetMaxChi2PerClusterTPC(float maxChi2PerClusterTPC) +void V0PhotonCut::SetChi2PerClusterTPC(float min, float max) { - mMaxChi2PerClusterTPC = maxChi2PerClusterTPC; - LOG(info) << "V0 Photon Cut, set max chi2 per cluster TPC: " << mMaxChi2PerClusterTPC; + mMinChi2PerClusterTPC = min; + mMaxChi2PerClusterTPC = max; + LOG(info) << "V0 Photon Cut, set chi2 per cluster TPC range: " << mMinChi2PerClusterTPC << " - " << mMaxChi2PerClusterTPC; } void V0PhotonCut::SetMaxDcaXY(float maxDcaXY) { @@ -141,28 +158,59 @@ void V0PhotonCut::SetMaxDcaXYPtDep(std::function ptDepCut) LOG(info) << "V0 Photon Cut, set max DCA xy pt dep: " << mMaxDcaXYPtDep(1.0); } +void V0PhotonCut::SetNClustersITS(int min, int max) +{ + mMinNClustersITS = min; + mMaxNClustersITS = max; + LOG(info) << "V0 Photon Cut, set N clusters ITS range: " << mMinNClustersITS << " - " << mMaxNClustersITS; +} +void V0PhotonCut::SetChi2PerClusterITS(float min, float max) +{ + mMinChi2PerClusterITS = min; + mMaxChi2PerClusterITS = max; + LOG(info) << "V0 Photon Cut, set chi2 per cluster ITS range: " << mMinChi2PerClusterITS << " - " << mMaxChi2PerClusterITS; +} + void V0PhotonCut::SetIsWithinBeamPipe(bool flag) { mIsWithinBP = flag; LOG(info) << "V0 Photon Cut, propagated to within beam pipe: " << mIsWithinBP; } -void V0PhotonCut::SetRequireITS(bool flag) +void V0PhotonCut::SetRequireITSTPC(bool flag) { - mRequireITS = flag; - LOG(info) << "V0 Photon Cut, require ITS hit: " << mRequireITS; + mRequireITSTPC = flag; + LOG(info) << "V0 Photon Cut, require ITS-TPC matched track: " << mRequireITSTPC; +} + +void V0PhotonCut::SetRequireITSonly(bool flag) +{ + mRequireITSonly = flag; + LOG(info) << "V0 Photon Cut, require ITS only track: " << mRequireITSonly; } void V0PhotonCut::SetRequireTPConly(bool flag) { mRequireTPConly = flag; - LOG(info) << "V0 Photon Cut, require TPConly: " << mRequireTPConly; + LOG(info) << "V0 Photon Cut, require TPConly track: " << mRequireTPConly; +} + +void V0PhotonCut::SetRequireTPCTRD(bool flag) +{ + mRequireTPCTRD = flag; + LOG(info) << "V0 Photon Cut, require TPC-TRD track: " << mRequireTPCTRD; +} + +void V0PhotonCut::SetRequireTPCTOF(bool flag) +{ + mRequireTPCTOF = flag; + LOG(info) << "V0 Photon Cut, require TPC-TOF track: " << mRequireTPCTOF; } -void V0PhotonCut::SetRequireAntiTPConly(bool flag) +void V0PhotonCut::SetRequireTPCTRDTOF(bool flag) { - mRequireAntiTPConly = flag; - LOG(info) << "V0 Photon Cut, require AntiTPConly: " << mRequireAntiTPConly; + mRequireTPCTRDTOF = flag; + LOG(info) << "V0 Photon Cut, require TPC-TOF track: " << mRequireTPCTRDTOF; } void V0PhotonCut::print() const diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index 95571b47628..e0b9ad9407f 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -16,16 +16,18 @@ #ifndef PWGEM_PHOTONMESON_CORE_V0PHOTONCUT_H_ #define PWGEM_PHOTONMESON_CORE_V0PHOTONCUT_H_ +#include #include #include #include #include -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" #include "Rtypes.h" #include "TNamed.h" #include "TMath.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" +using namespace o2::pwgem::photonmeson; + class V0PhotonCut : public TNamed { public: @@ -37,7 +39,9 @@ class V0PhotonCut : public TNamed kMee = 0, kV0PtRange, kV0EtaRange, + kAP, kPsiPair, + kPhiV, kRxy, kCosPA, kPCA, @@ -55,10 +59,15 @@ class V0PhotonCut : public TNamed kTPCNsigmaPi, kDCAxy, kDCAz, + kITSNCls, + kITSChi2NDF, kIsWithinBeamPipe, - kRequireITS, - kTPConly, - kAntiTPConly, + kRequireITSTPC, + kRequireITSonly, + kRequireTPConly, + kRequireTPCTRD, + kRequireTPCTOF, + kRequireTPCTRDTOF, kNCuts }; @@ -76,9 +85,15 @@ class V0PhotonCut : public TNamed if (!IsSelectedV0(v0, V0PhotonCuts::kMee)) { return false; } + if (!IsSelectedV0(v0, V0PhotonCuts::kAP)) { + return false; + } if (!IsSelectedV0(v0, V0PhotonCuts::kPsiPair)) { return false; } + if (!IsSelectedV0(v0, V0PhotonCuts::kPhiV)) { + return false; + } if (!IsSelectedV0(v0, V0PhotonCuts::kRxy)) { return false; } @@ -91,21 +106,37 @@ class V0PhotonCut : public TNamed if (!IsSelectedV0(v0, V0PhotonCuts::kRZLine)) { return false; } - if (mIsOnWwireIB && !IsSelectedV0(v0, V0PhotonCuts::kOnWwireIB)) { - return false; - } - if (mIsOnWwireOB && !IsSelectedV0(v0, V0PhotonCuts::kOnWwireOB)) { - return false; + + if (mIsOnWwireIB && mIsOnWwireOB) { + if (!IsSelectedV0(v0, V0PhotonCuts::kOnWwireIB) && !IsSelectedV0(v0, V0PhotonCuts::kOnWwireOB)) { + return false; + } + } else if (mIsOnWwireIB) { + if (!IsSelectedV0(v0, V0PhotonCuts::kOnWwireIB)) { + return false; + } + } else if (mIsOnWwireOB) { + if (!IsSelectedV0(v0, V0PhotonCuts::kOnWwireOB)) { + return false; + } } auto pos = v0.template posTrack_as(); auto ele = v0.template negTrack_as(); - // float pos_rxy = sqrt(pos.x() * pos.x() + pos.y()*pos.y()); - // float ele_rxy = sqrt(ele.x() * ele.x() + ele.y()*ele.y()); - // if (v0.recalculatedVtxR() > std::min(pos_rxy, ele_rxy)) { - // return false; - // } + if (pos.hasITS() && ele.hasITS()) { + if (v0.mGammaKFSV() > 0.06 && v0.recalculatedVtxR() < 12.f) { + return false; + } + } + + bool isTPConly_pos = isTPConlyTrack(pos); + bool isTPConly_ele = isTPConlyTrack(ele); + if (isTPConly_pos && isTPConly_ele) { + if (v0.mGammaKFSV() > v0.mGammaKFPV()) { + return false; + } + } for (auto& track : {pos, ele}) { if (!IsSelectedTrack(track, V0PhotonCuts::kTrackPtRange)) { @@ -114,42 +145,104 @@ class V0PhotonCut : public TNamed if (!IsSelectedTrack(track, V0PhotonCuts::kTrackEtaRange)) { return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNCls)) { + if (!IsSelectedTrack(track, V0PhotonCuts::kDCAxy)) { return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kTPCCrossedRows)) { + if (!IsSelectedTrack(track, V0PhotonCuts::kDCAz)) { return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kTPCCrossedRowsOverNCls)) { + if (mIsWithinBP && !IsSelectedTrack(track, V0PhotonCuts::kIsWithinBeamPipe)) { return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kTPCChi2NDF)) { + if (!track.hasITS() && !track.hasTPC()) { // track has to be ITSonly or TPConly or ITS-TPC return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNsigmaEl)) { + + bool isITSonly = isITSonlyTrack(track); + auto hits_ib = std::count_if(its_ib_Requirement.second.begin(), its_ib_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + auto hits_ob = std::count_if(its_ob_Requirement.second.begin(), its_ob_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + bool its_ob_only = (hits_ib <= its_ib_Requirement.first) && (hits_ob >= its_ob_Requirement.first); + if (isITSonly && !its_ob_only) { // ITSonly tracks should not have any ITSib hits. return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNsigmaPi)) { + + bool isITSTPC = isITSTPCTrack(track); + auto hits_ob_itstpc = std::count_if(its_ob_Requirement_ITSTPC.second.begin(), its_ob_Requirement_ITSTPC.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + bool its_ob_only_itstpc = (hits_ib <= its_ib_Requirement.first) && (hits_ob_itstpc >= its_ob_Requirement_ITSTPC.first); + if (isITSTPC && !its_ob_only_itstpc) { // ITSonly tracks should not have any ITSib hits. return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kDCAxy)) { + + if (isITSonly) { + if (!CheckITSCuts(track)) { + return false; + } + } else if (track.hasTPC()) { + if (!CheckTPCCuts(track)) { + return false; + } + } else { // remove ITS-TRD, ITS-TOF, ITS-TRD-TOF that are unrealistic tracks. return false; } - if (!IsSelectedTrack(track, V0PhotonCuts::kDCAz)) { + + if (mIsOnWwireIB && !CheckITSCuts(track)) { // photon conversion on ibw requires ITS hits. return false; } - if (mIsWithinBP && !IsSelectedTrack(track, V0PhotonCuts::kIsWithinBeamPipe)) { + + if (mRequireITSonly && !IsSelectedTrack(track, V0PhotonCuts::kRequireITSonly)) { + return false; + } + if (mRequireITSTPC && !IsSelectedTrack(track, V0PhotonCuts::kRequireITSTPC)) { return false; } - if (mRequireITS && !IsSelectedTrack(track, V0PhotonCuts::kRequireITS)) { + if (mRequireTPConly && !IsSelectedTrack(track, V0PhotonCuts::kRequireTPConly)) { return false; } - if (mRequireTPConly && !IsSelectedTrack(track, V0PhotonCuts::kTPConly)) { + if (mRequireTPCTRD && !IsSelectedTrack(track, V0PhotonCuts::kRequireTPCTRD)) { return false; } - if (mRequireAntiTPConly && !IsSelectedTrack(track, V0PhotonCuts::kAntiTPConly)) { + if (mRequireTPCTOF && !IsSelectedTrack(track, V0PhotonCuts::kRequireTPCTOF)) { return false; } + if (mRequireTPCTRDTOF && !IsSelectedTrack(track, V0PhotonCuts::kRequireTPCTRDTOF)) { + return false; + } + } + return true; + } + + template + bool CheckITSCuts(T const& track) const + { + if (!IsSelectedTrack(track, V0PhotonCuts::kITSNCls)) { + return false; + } + if (!IsSelectedTrack(track, V0PhotonCuts::kITSChi2NDF)) { + return false; + } + return true; + } + + template + bool CheckTPCCuts(T const& track) const + { + if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNCls)) { + return false; + } + if (!IsSelectedTrack(track, V0PhotonCuts::kTPCCrossedRows)) { + return false; + } + if (!IsSelectedTrack(track, V0PhotonCuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, V0PhotonCuts::kTPCChi2NDF)) { + return false; + } + if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNsigmaEl)) { + return false; + } + if (!IsSelectedTrack(track, V0PhotonCuts::kTPCNsigmaPi)) { + return false; } return true; } @@ -182,7 +275,6 @@ class V0PhotonCut : public TNamed template bool IsSelectedV0(T const& v0, const V0PhotonCuts& cut) const { - const float margin = 1.0; // cm switch (cut) { case V0PhotonCuts::kV0PtRange: return v0.pt() >= mMinV0Pt && v0.pt() <= mMaxV0Pt; @@ -193,9 +285,15 @@ class V0PhotonCut : public TNamed case V0PhotonCuts::kMee: return v0.mGamma() <= ((mMaxMeePsiPairDep) ? mMaxMeePsiPairDep(abs(v0.psipair())) : mMaxMee); + case V0PhotonCuts::kAP: + return pow(v0.alpha() / mMaxAlpha, 2) + pow(v0.qtarm() / mMaxQt, 2) < 1.0; + case V0PhotonCuts::kPsiPair: return v0.psipair() >= mMinPsiPair && v0.psipair() <= mMaxPsiPair; + case V0PhotonCuts::kPhiV: + return v0.phiv() >= mMinPhivPair && v0.phiv() <= mMaxPhivPair; + case V0PhotonCuts::kRxy: return v0.recalculatedVtxR() >= mMinRxy && v0.recalculatedVtxR() <= mMaxRxy; @@ -209,40 +307,48 @@ class V0PhotonCut : public TNamed return v0.recalculatedVtxR() > abs(v0.recalculatedVtxZ()) * TMath::Tan(2 * TMath::ATan(TMath::Exp(-mMaxV0Eta))) - mMaxMarginZ; // as long as z recalculation is not fixed use this case V0PhotonCuts::kOnWwireIB: { - const float rxy_min = 5.506; // cm - const float rxy_max = 14.846; // cm - const float z_min = -17.56; // cm - const float z_max = +31.15; // cm + const float margin_xy = 1.0; // cm + // const float margin_z = 20.0; // cm + // const float rxy_min = 5.506; // cm + // const float rxy_max = 14.846; // cm + // const float z_min = -17.56; // cm + // const float z_max = +31.15; // cm float x = abs(v0.recalculatedVtxX()); // cm, measured secondary vertex of gamma->ee float y = v0.recalculatedVtxY(); // cm, measured secondary vertex of gamma->ee - float z = v0.recalculatedVtxZ(); // cm, measured secondary vertex of gamma->ee + // float z = v0.recalculatedVtxZ(); // cm, measured secondary vertex of gamma->ee + float rxy = sqrt(x * x + y * y); - if ((rxy < rxy_min || rxy_max < rxy) || (z < z_min || z_max < z)) { - return false; - } - float x_exp = abs(rxy * TMath::Cos(-8.52 * TMath::DegToRad())); // cm, expected position x of W wire - float y_exp = rxy * TMath::Sin(-8.52 * TMath::DegToRad()); // cm, expected position y of W wire - float z_exp = z_min + (rxy - rxy_min) / TMath::Tan(10.86 * TMath::DegToRad()); // cm, expected position rxy of W wire as a function of z - if (abs(x - x_exp) > margin || abs(y - y_exp) > margin || abs(z - z_exp) > margin) { + if (rxy < 7.5 || 15.0 < rxy) { return false; } - return true; + + // float z_exp = z_min + (rxy - rxy_min) / TMath::Tan(10.86 * TMath::DegToRad()); // cm, expected position rxy of W wire as a function of z + // if (abs(z - z_exp) > margin_z) { + // return false; + // } + + float dxy = abs(1.0 * y - x * TMath::Tan(-8.52 * TMath::DegToRad())) / sqrt(pow(1.0, 2) + pow(TMath::Tan(-8.52 * TMath::DegToRad()), 2)); + return !(dxy > margin_xy); } case V0PhotonCuts::kOnWwireOB: { - const float rxy_min = 30.8 - margin; // cm - const float rxy_max = 30.8 + margin; // cm - const float z_min = -47.0; // cm - const float z_max = +47.0; // cm - float x = abs(v0.recalculatedVtxX()); // cm, measured secondary vertex of gamma->ee - float y = v0.recalculatedVtxY(); // cm, measured secondary vertex of gamma->ee - float z = v0.recalculatedVtxZ(); // cm, measured secondary vertex of gamma->ee - float rxy = sqrt(x * x + y * y); - if ((rxy < rxy_min || rxy_max < rxy) || (z < z_min || z_max < z)) { + const float margin_x = 2.0; // cm + const float margin_y = 0.5; // cm + const float margin_z = 5.0; // cm + const float rxy_exp = 30.8; // cm + const float x_exp = rxy_exp * TMath::Cos(-1.3 * TMath::DegToRad()); // cm, expected position x of W wire + const float y_exp = rxy_exp * TMath::Sin(-1.3 * TMath::DegToRad()); // cm, expected position y of W wire + const float z_min = -47.0; // cm + const float z_max = +47.0; // cm + float x = v0.recalculatedVtxX(); // cm, measured secondary vertex of gamma->ee + float y = v0.recalculatedVtxY(); // cm, measured secondary vertex of gamma->ee + float z = v0.recalculatedVtxZ(); // cm, measured secondary vertex of gamma->ee + if (z + margin_z < z_min || z_max < z - margin_z) { + return false; + } + if (abs(x - x_exp) > margin_x) { return false; } - float x_exp = abs(rxy * TMath::Cos(-1.3 * TMath::DegToRad())); // cm, expected position x of W wire - float y_exp = rxy * TMath::Sin(-1.3 * TMath::DegToRad()); // cm, expected position y of W wire - if (abs(x - x_exp) > margin || abs(y - y_exp) > margin) { + if (abs(y - y_exp) > margin_y) { return false; } return true; @@ -273,7 +379,7 @@ class V0PhotonCut : public TNamed return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; case V0PhotonCuts::kTPCChi2NDF: - return track.tpcChi2NCl() <= mMaxChi2PerClusterTPC; + return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; case V0PhotonCuts::kTPCNsigmaEl: return track.tpcNSigmaEl() >= mMinTPCNsigmaEl && track.tpcNSigmaEl() <= mMaxTPCNsigmaEl; @@ -287,24 +393,42 @@ class V0PhotonCut : public TNamed case V0PhotonCuts::kDCAz: return abs(track.dcaZ()) <= mMaxDcaZ; + case V0PhotonCuts::kITSNCls: + return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; + + case V0PhotonCuts::kITSChi2NDF: + return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; + case V0PhotonCuts::kIsWithinBeamPipe: { // return track.isWithinBeamPipe(); - if (15.f < abs(track.dcaXY()) && abs(track.dcaXY()) < 100.f) { + if (abs(track.y()) > abs(track.x() * TMath::Tan(10.f * TMath::DegToRad())) + 15.f) { return false; } - if (abs(abs(track.z()) - 44.f) < 2.f && 15.f < abs(track.dcaXY())) { + + if (track.x() > 82.9 && abs(track.y()) > abs(track.x() * TMath::Tan(10.f * TMath::DegToRad())) + 5.f) { return false; } - return true; + + const float slope = TMath::Tan(2 * TMath::ATan(TMath::Exp(-0.5))); + return !(track.x() > 82.9 && abs(track.y()) < 40.f && abs(abs(track.z()) - track.x() / slope) < 3.5f && 15.f < abs(track.dcaXY())); } - case V0PhotonCuts::kRequireITS: - return track.hasITS(); + case V0PhotonCuts::kRequireITSTPC: + return isITSTPCTrack(track); + + case V0PhotonCuts::kRequireITSonly: + return isITSonlyTrack(track); + + case V0PhotonCuts::kRequireTPConly: + return isTPConlyTrack(track); + + case V0PhotonCuts::kRequireTPCTRD: + return isTPCTRDTrack(track); - case V0PhotonCuts::kTPConly: - return track.hasTPC() & (!track.hasITS() & !track.hasTOF() & !track.hasTRD()); + case V0PhotonCuts::kRequireTPCTOF: + return isTPCTOFTrack(track); - case V0PhotonCuts::kAntiTPConly: - return track.hasTPC() & (track.hasITS() | track.hasTOF() | track.hasTRD()); + case V0PhotonCuts::kRequireTPCTRDTOF: + return isTPCTRDTOFTrack(track); default: return false; @@ -316,6 +440,8 @@ class V0PhotonCut : public TNamed void SetV0EtaRange(float minEta = -1e10f, float maxEta = 1e10f); void SetMeeRange(float min = 0.f, float max = 0.1); void SetPsiPairRange(float min = -3.15, float max = +3.15); + void SetPhivPairRange(float min = 0.f, float max = +3.15); + void SetAPRange(float max_alpha = 0.95, float max_qt = 0.05); // Armenteros Podolanski void SetRxyRange(float min = 0.f, float max = 180.f); void SetMinCosPA(float min = 0.95); void SetMaxPCA(float max = 2.f); @@ -329,7 +455,9 @@ class V0PhotonCut : public TNamed void SetMinNClustersTPC(int minNClustersTPC); void SetMinNCrossedRowsTPC(int minNCrossedRowsTPC); void SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC); - void SetMaxChi2PerClusterTPC(float maxChi2PerClusterTPC); + void SetChi2PerClusterTPC(float min, float max); + void SetNClustersITS(int min, int max); + void SetChi2PerClusterITS(float min, float max); void SetTPCNsigmaElRange(float min = -3, float max = +3); void SetTPCNsigmaPiRange(float min = -1e+10, float max = 1e+10); @@ -338,19 +466,27 @@ class V0PhotonCut : public TNamed void SetMaxDcaZ(float maxDcaZ); void SetMaxDcaXYPtDep(std::function ptDepCut); void SetIsWithinBeamPipe(bool flag); - void SetRequireITS(bool flag); + void SetRequireITSTPC(bool flag); + void SetRequireITSonly(bool flag); void SetRequireTPConly(bool flag); - void SetRequireAntiTPConly(bool flag); + void SetRequireTPCTRD(bool flag); + void SetRequireTPCTOF(bool flag); + void SetRequireTPCTRDTOF(bool flag); /// @brief Print the track selection void print() const; private: + static const std::pair> its_ib_Requirement; + static const std::pair> its_ob_Requirement; + static const std::pair> its_ob_Requirement_ITSTPC; // v0 cuts float mMinMee{0.f}, mMaxMee{0.1f}; float mMinV0Pt{0.f}, mMaxV0Pt{1e10f}; // range in pT float mMinV0Eta{-1e10f}, mMaxV0Eta{1e10f}; // range in eta + float mMaxAlpha{0.95}, mMaxQt{0.05}; float mMinPsiPair{-3.15}, mMaxPsiPair{+3.15}; + float mMinPhivPair{0.f}, mMaxPhivPair{+3.15}; float mMinRxy{0.f}, mMaxRxy{180.f}; float mMinCosPA{0.95}; float mMaxPCA{2.f}; @@ -368,18 +504,23 @@ class V0PhotonCut : public TNamed float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta // track quality cuts - int mMinNClustersTPC{0}; // min number of TPC clusters - int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC - float mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster - float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters + int mMinNClustersTPC{0}; // min number of TPC clusters + int mMinNCrossedRowsTPC{0}; // min number of crossed rows in TPC + float mMinChi2PerClusterTPC{-1e10f}, mMaxChi2PerClusterTPC{1e10f}; // max tpc fit chi2 per TPC cluster + float mMinNCrossedRowsOverFindableClustersTPC{0.f}; // min ratio crossed rows / findable clusters + int mMinNClustersITS{0}, mMaxNClustersITS{7}; // range in number of ITS clusters + float mMinChi2PerClusterITS{-1e10f}, mMaxChi2PerClusterITS{1e10f}; // max its fit chi2 per ITS cluster float mMaxDcaXY{1e10f}; // max dca in xy plane float mMaxDcaZ{1e10f}; // max dca in z direction std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT bool mIsWithinBP{false}; - bool mRequireITS{false}; + bool mRequireITSTPC{false}; + bool mRequireITSonly{false}; bool mRequireTPConly{false}; - bool mRequireAntiTPConly{false}; + bool mRequireTPCTRD{false}; + bool mRequireTPCTOF{false}; + bool mRequireTPCTRDTOF{false}; ClassDef(V0PhotonCut, 1); }; diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index a1a8e20ede8..b7d940a69e6 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -47,7 +47,7 @@ DECLARE_SOA_TABLE(EMReducedEvents, "AOD", "EMREDUCEDEVENT", //! Main event inf collision::NumContrib, collision::CollisionTime, collision::CollisionTimeRes, mult::MultTPC, mult::MultFV0A, mult::MultFV0C, mult::MultFT0A, mult::MultFT0C, mult::MultFDDA, mult::MultFDDC, mult::MultZNA, mult::MultZNC, mult::MultTracklets, mult::MultNTracksPV, mult::MultNTracksPVeta1, - cent::CentFV0A, cent::CentFT0M, cent::CentFT0A, cent::CentFT0C, cent::CentFDDM, cent::CentNTPV, + cent::CentFT0M, cent::CentFT0A, cent::CentFT0C, cent::CentNTPV, emreducedevent::NgammaPCM, emreducedevent::NgammaPHOS, emreducedevent::NgammaEMC); using EMReducedEvent = EMReducedEvents::iterator; @@ -124,17 +124,27 @@ DECLARE_SOA_TABLE_FULL(EMMCParticles, "EMMCParticles", "AOD", "EMMCPARTICLE", // using EMMCParticle = EMMCParticles::iterator; -namespace emmcparticlelabel +namespace v0legmclabel { DECLARE_SOA_INDEX_COLUMN(EMMCParticle, emmcparticle); //! DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); -} // namespace emmcparticlelabel +} // namespace v0legmclabel -// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with the track tables) -DECLARE_SOA_TABLE(EMMCParticleLabels, "AOD", "EMMCPARLABEL", //! - emmcparticlelabel::EMMCParticleId, emmcparticlelabel::McMask); +// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with v0leg table) +DECLARE_SOA_TABLE(V0LegMCLabels, "AOD", "V0LEGMCLABEL", //! + v0legmclabel::EMMCParticleId, v0legmclabel::McMask); +using V0LegMCLabel = V0LegMCLabels::iterator; -using EMMCParticleLabel = EMMCParticleLabels::iterator; +namespace emprimarytrackmclabel +{ +DECLARE_SOA_INDEX_COLUMN(EMMCParticle, emmcparticle); //! +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); +} // namespace emprimarytrackmclabel + +// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with emprimarytrack table) +DECLARE_SOA_TABLE(EMPrimaryTrackMCLabels, "AOD", "EMPRMTRKMCLABEL", //! + emprimarytrackmclabel::EMMCParticleId, emprimarytrackmclabel::McMask); +using EMPrimaryTrackMCLabel = EMPrimaryTrackMCLabels::iterator; namespace v0leg { @@ -144,7 +154,6 @@ DECLARE_SOA_COLUMN(Sign, sign, int); //! DECLARE_SOA_COLUMN(IsAmbTrack, isAmbTrack, bool); //! } // namespace v0leg -// reconstructed v0 information DECLARE_SOA_TABLE(V0Legs, "AOD", "V0LEG", //! o2::soa::Index<>, v0leg::CollisionId, v0leg::TrackId, v0leg::Sign, v0leg::IsAmbTrack, @@ -171,6 +180,7 @@ using V0Leg = V0Legs::iterator; namespace v0photon { +DECLARE_SOA_INDEX_COLUMN(EMReducedEvent, emreducedevent); //! DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, V0Legs, "_Pos"); //! DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, V0Legs, "_Neg"); //! @@ -191,7 +201,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pypos, float pyneg) -> float { retur DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pzpos, float pzneg) -> float { return pzpos + pzneg; }); DECLARE_SOA_DYNAMIC_COLUMN(E, e, [](float pxpos, float pxneg, float pypos, float pyneg, float pzpos, float pzneg, float m = 0) -> float { return RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg, m); }); //! energy of v0 photn, mass to be given as argument when getter is called! DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float pxpos, float pypos, float pxneg, float pyneg) -> float { return RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg); }); -DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::eta(array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::eta(std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}); }); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float pxpos, float pypos, float pxneg, float pyneg) -> float { return RecoDecay::phi(pxpos + pxneg, pypos + pyneg); }); DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); }); DECLARE_SOA_DYNAMIC_COLUMN(PPos, ppos, [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); @@ -227,8 +237,13 @@ DECLARE_SOA_TABLE(V0Photons, "AOD", "V0PHOTON", //! // iterators using V0Photon = V0Photons::iterator; +DECLARE_SOA_TABLE(V0EMReducedEventIds, "AOD", "V0EMEVENTID", v0photon::EMReducedEventId); // To be joined with V0Photons table at analysis level. +// iterators +using V0EMReducedEventId = V0EMReducedEventIds::iterator; + namespace v0photonkf { +DECLARE_SOA_INDEX_COLUMN(EMReducedEvent, emreducedevent); //! DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! DECLARE_SOA_INDEX_COLUMN(V0Photon, v0photon); //! DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, V0Legs, "_Pos"); //! @@ -240,17 +255,20 @@ DECLARE_SOA_COLUMN(Px, px, float); DECLARE_SOA_COLUMN(Py, py, float); DECLARE_SOA_COLUMN(Pz, pz, float); DECLARE_SOA_COLUMN(MGamma, mGamma, float); +DECLARE_SOA_COLUMN(MGammaKFPV, mGammaKFPV, float); +DECLARE_SOA_COLUMN(MGammaKFSV, mGammaKFSV, float); DECLARE_SOA_COLUMN(CosPA, cospa, float); //! DECLARE_SOA_COLUMN(PCA, pca, float); //! DECLARE_SOA_COLUMN(Alpha, alpha, float); DECLARE_SOA_COLUMN(QtArm, qtarm, float); DECLARE_SOA_COLUMN(PsiPair, psipair, float); +DECLARE_SOA_COLUMN(PhiV, phiv, float); DECLARE_SOA_COLUMN(ChiSquareNDF, chiSquareNDF, float); // Chi2 / NDF of the reconstructed V0 DECLARE_SOA_DYNAMIC_COLUMN(E, e, [](float px, float py, float pz, float m = 0) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz, m); }); //! energy of v0 photn, mass to be given as argument when getter is called! DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); -DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) -> float { return RecoDecay::eta(array{px, py, pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float px, float py) -> float { return RecoDecay::phi(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0radius, [](float vx, float vy) -> float { return RecoDecay::sqrtSumOfSquares(vx, vy); }); @@ -260,8 +278,9 @@ DECLARE_SOA_TABLE(V0PhotonsKF, "AOD", "V0PHOTONKF", //! o2::soa::Index<>, v0photonkf::CollisionId, v0photonkf::V0PhotonId, v0photon::PosTrackId, v0photon::NegTrackId, v0photonkf::Vx, v0photonkf::Vy, v0photonkf::Vz, v0photonkf::Px, v0photonkf::Py, v0photonkf::Pz, - v0photonkf::MGamma, v0photonkf::CosPA, v0photonkf::PCA, - v0photonkf::Alpha, v0photonkf::QtArm, v0photonkf::PsiPair, + v0photonkf::MGamma, v0photonkf::MGammaKFPV, v0photonkf::MGammaKFSV, + v0photonkf::CosPA, v0photonkf::PCA, + v0photonkf::Alpha, v0photonkf::QtArm, v0photonkf::PsiPair, v0photonkf::PhiV, v0photonkf::ChiSquareNDF, // dynamic column v0photonkf::E, @@ -273,6 +292,65 @@ DECLARE_SOA_TABLE(V0PhotonsKF, "AOD", "V0PHOTONKF", //! // iterators using V0PhotonKF = V0PhotonsKF::iterator; +DECLARE_SOA_TABLE(V0KFEMReducedEventIds, "AOD", "V0KFEMEVENTID", v0photonkf::EMReducedEventId); // To be joined with V0PhotonsKF table at analysis level. +// iterators +using V0KFEMReducedEventId = V0KFEMReducedEventIds::iterator; + +namespace emprimarytrack +{ +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(TrackId, trackId, int); //! +DECLARE_SOA_COLUMN(Sign, sign, int); //! +} // namespace emprimarytrack +DECLARE_SOA_TABLE(EMPrimaryTracks, "AOD", "EMPRIMARYTRACK", //! + o2::soa::Index<>, emprimarytrack::CollisionId, + emprimarytrack::TrackId, emprimarytrack::Sign, + track::Pt, track::Eta, track::Phi, track::DcaXY, track::DcaZ, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, + track::TPCChi2NCl, track::TPCInnerParam, + track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtofbeta::Beta, pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, + track::ITSClusterMap, track::ITSChi2NCl, track::DetectorMap, track::Signed1Pt, track::CYY, track::CZZ, + + // dynamic column + track::TPCNClsFound, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls, + track::ITSNCls, + track::HasITS, track::HasTPC, + track::HasTRD, track::HasTOF); + +// iterators +using EMPrimaryTrack = EMPrimaryTracks::iterator; + +namespace dalitzee +{ +DECLARE_SOA_INDEX_COLUMN(EMReducedEvent, emreducedevent); //! +DECLARE_SOA_INDEX_COLUMN_FULL(PosTrack, posTrack, int, EMPrimaryTracks, "_Pos"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(NegTrack, negTrack, int, EMPrimaryTracks, "_Neg"); //! +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Mee, mee, float); +DECLARE_SOA_COLUMN(PhiV, phiv, float); +DECLARE_SOA_COLUMN(DCAeeXY, dcaeeXY, float); +DECLARE_SOA_COLUMN(DCAeeZ, dcaeeZ, float); +DECLARE_SOA_COLUMN(Sign, sign, int); //! +DECLARE_SOA_DYNAMIC_COLUMN(Energy, e, [](float pt, float eta, float m) { return RecoDecay::sqrtSumOfSquares(pt * std::cosh(eta), m); }); // e = sqrt(p*p + m*m) +} // namespace dalitzee +DECLARE_SOA_TABLE(DalitzEEs, "AOD", "DALITZEE", //! + o2::soa::Index<>, dalitzee::CollisionId, dalitzee::PosTrackId, dalitzee::NegTrackId, + dalitzee::Pt, dalitzee::Eta, dalitzee::Phi, dalitzee::Mee, dalitzee::PhiV, dalitzee::DCAeeXY, dalitzee::DCAeeZ, dalitzee::Sign, + dalitzee::Energy); +// iterators +using DalitzEE = DalitzEEs::iterator; + +DECLARE_SOA_TABLE(DalitzEEEMReducedEventIds, "AOD", "EEEMEVENTID", dalitzee::EMReducedEventId); // To be joined with DalitzEEs table at analysis level. +// iterators +using DalitzEEEMReducedEventId = DalitzEEEMReducedEventIds::iterator; + namespace MCTracksTrue { DECLARE_SOA_COLUMN(SameMother, sameMother, bool); // Do the tracks have the same mother particle? @@ -303,18 +381,11 @@ DECLARE_SOA_COLUMN(RecalculatedVtxZ, recalculatedVtxZ, float); //! Recalculated DECLARE_SOA_DYNAMIC_COLUMN(RecalculatedVtxR, recalculatedVtxR, [](float x, float y) { return sqrt(x * x + y * y); }); } // namespace v0Recalculations -// namespace v0KFParticle -//{ -// DECLARE_SOA_COLUMN(ChiSquareNDF, chiSquareNDF, float); // Chi2 / NDF of the reconstructed V0 -// } // namespace v0KFParticle - DECLARE_SOA_TABLE(V0Recalculation, "AOD", "V0RECALC", v0Recalculations::RecalculatedVtxX, v0Recalculations::RecalculatedVtxY, v0Recalculations::RecalculatedVtxZ, - v0Recalculations::RecalculatedVtxR - // v0KFParticle::ChiSquareNDF -); + v0Recalculations::RecalculatedVtxR); namespace gammamctrue { @@ -387,6 +458,7 @@ DECLARE_SOA_COLUMN(NLM, nlm, int); //! numbe namespace emccluster { +DECLARE_SOA_INDEX_COLUMN(EMReducedEvent, emreducedevent); //! DECLARE_SOA_COLUMN(CoreEnergy, coreEnergy, float); //! cluster core energy (GeV) DECLARE_SOA_COLUMN(Time, time, float); //! cluster time (ns) DECLARE_SOA_COLUMN(IsExotic, isExotic, bool); //! flag to mark cluster as exotic @@ -406,8 +478,14 @@ DECLARE_SOA_TABLE(SkimEMCClusters, "AOD", "SKIMEMCCLUSTERS", //! table of skimme // dynamic column emccluster::Pt); using SkimEMCCluster = SkimEMCClusters::iterator; + +DECLARE_SOA_TABLE(EMCEMReducedEventIds, "AOD", "EMCEMEVENTID", emccluster::EMReducedEventId); // To be joined with SkimEMCClusters table at analysis level. +// iterators +using EMCEMReducedEventId = EMCEMReducedEventIds::iterator; + namespace phoscluster { +DECLARE_SOA_INDEX_COLUMN(EMReducedEvent, emreducedevent); //! DECLARE_SOA_INDEX_COLUMN_FULL(MatchedTrack, matchedTrack, int, Tracks, "_Matched"); //! matched track index DECLARE_SOA_COLUMN(X, x, float); //! cluster hit position in ALICE global coordinate DECLARE_SOA_COLUMN(Y, y, float); //! cluster hit position in ALICE global coordinate @@ -422,7 +500,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float e, float x, float y, float z, float DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float e, float x, float y, float z, float m = 0) -> float { return y / RecoDecay::sqrtSumOfSquares(x, y, z) * sqrt(e * e - m * m); }); DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float e, float x, float y, float z, float m = 0) -> float { return z / RecoDecay::sqrtSumOfSquares(x, y, z) * sqrt(e * e - m * m); }); DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float e, float x, float y, float z, float m = 0) -> float { return RecoDecay::sqrtSumOfSquares(x, y) / RecoDecay::sqrtSumOfSquares(x, y, z) * sqrt(e * e - m * m); }); -DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float x, float y, float z) -> float { return RecoDecay::eta(array{x, y, z}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float x, float y, float z) -> float { return RecoDecay::eta(std::array{x, y, z}); }); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float x, float y) -> float { return RecoDecay::phi(x, y); }); } // namespace phoscluster @@ -442,6 +520,10 @@ DECLARE_SOA_TABLE(PHOSClusters, "AOD", "PHOSCLUSTERS", //! phoscluster::Phi); using PHOSCluster = PHOSClusters::iterator; +DECLARE_SOA_TABLE(PHOSEMReducedEventIds, "AOD", "PHOSEMEVENTID", phoscluster::EMReducedEventId); // To be joined with PHOSClusters table at analysis level. +// iterators +using PHOSEMReducedEventId = PHOSEMReducedEventIds::iterator; + namespace caloextra { DECLARE_SOA_INDEX_COLUMN_FULL(Cluster, cluster, int, SkimEMCClusters, ""); //! reference to the gamma in the skimmed EMCal table diff --git a/PWGEM/PhotonMeson/DataModel/mcV0Tables.h b/PWGEM/PhotonMeson/DataModel/mcV0Tables.h new file mode 100644 index 00000000000..0d8f156434d --- /dev/null +++ b/PWGEM/PhotonMeson/DataModel/mcV0Tables.h @@ -0,0 +1,134 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \brief Tables for investigating the MC V0 phase-space +/// \author felix.schlepper@cern.ch + +#ifndef PWGEM_PHOTONMESON_DATAMODEL_MCV0TABLES_H_ +#define PWGEM_PHOTONMESON_DATAMODEL_MCV0TABLES_H_ + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ + +namespace mcV0 +{ +enum TrackTypes : uint8_t { + ITSTPC_ITSTPC = 0, + TPConly_TPConly, + ITSonly_ITSonly, + ITSTPC_TPConly, + ITSTPC_ITSonly, + TPConly_ITSonly, +}; + +// Track Pos +DECLARE_SOA_COLUMN(RecoPosPt, recoPosPt, float); //! Reconstructed pt of pos track +DECLARE_SOA_COLUMN(RecoPosEta, recoPosEta, float); //! Reconstructed eta of pos track +DECLARE_SOA_COLUMN(RecoPosTgl, recoPosTgl, float); //! Reconstructed tgl of pos track +DECLARE_SOA_COLUMN(RecoPosX, recoPosX, float); //! Reconstructed X of pos track +DECLARE_SOA_COLUMN(RecoPosY, recoPosY, float); //! Reconstructed X of pos track +DECLARE_SOA_COLUMN(RecoPosZ, recoPosZ, float); //! Reconstructed X of pos track +DECLARE_SOA_COLUMN(RecoPosT, recoPosT, float); //! Estimated time of the pos track in ns wrt collision() +DECLARE_SOA_COLUMN(RecoPosSign, recoPosSign, int16_t); //! Sign of pos track +DECLARE_SOA_COLUMN(RecoPosHasITS, recoPosHasITS, bool); //! if pos track has ITS +DECLARE_SOA_COLUMN(RecoPosHasTPC, recoPosHasTPC, bool); //! if pos track has TPC +DECLARE_SOA_COLUMN(RecoPosHasTRD, recoPosHasTRD, bool); //! if pos track has TRD +DECLARE_SOA_COLUMN(RecoPosHasTOF, recoPosHasTOF, bool); //! if pos track has TOF +// Track Ele +DECLARE_SOA_COLUMN(RecoElePt, recoElePt, float); //! Reconstructed pt of ele track +DECLARE_SOA_COLUMN(RecoEleTgl, recoEleTgl, float); //! Reconstructed tgl of ele track +DECLARE_SOA_COLUMN(RecoEleEta, recoEleEta, float); //! Reconstructed eta of ele track +DECLARE_SOA_COLUMN(RecoEleX, recoEleX, float); //! Reconstructed X of ele track +DECLARE_SOA_COLUMN(RecoEleY, recoEleY, float); //! Reconstructed X of ele track +DECLARE_SOA_COLUMN(RecoEleZ, recoEleZ, float); //! Reconstructed X of ele track +DECLARE_SOA_COLUMN(RecoEleT, recoEleT, float); //! Estimated time of the ele track in ns wrt collision() +DECLARE_SOA_COLUMN(RecoEleSign, recoEleSign, int16_t); //! Sign of ele track +DECLARE_SOA_COLUMN(RecoEleHasITS, recoEleHasITS, bool); //! If ele track has ITS +DECLARE_SOA_COLUMN(RecoEleHasTPC, recoEleHasTPC, bool); //! If ele track has TPC +DECLARE_SOA_COLUMN(RecoEleHasTRD, recoEleHasTRD, bool); //! If ele track has TRD +DECLARE_SOA_COLUMN(RecoEleHasTOF, recoEleHasTOF, bool); //! If ele track has TOF +// MC particle pos +DECLARE_SOA_COLUMN(MCPosPt, mcPosPt, float); //! Generated pt of pos particle +DECLARE_SOA_COLUMN(MCPosEta, mcPosEta, float); //! Generated eta of pos particle +DECLARE_SOA_COLUMN(MCPosX, mcPosX, float); //! Generated x of pos particle +DECLARE_SOA_COLUMN(MCPosY, mcPosY, float); //! Generated y of pos particle +DECLARE_SOA_COLUMN(MCPosZ, mcPosZ, float); //! Generated z of pos particle +// MC particle ele +DECLARE_SOA_COLUMN(MCElePt, mcElePt, float); //! Generated pt of ele particle +DECLARE_SOA_COLUMN(MCEleEta, mcEleEta, float); //! Generated eta of ele particle +DECLARE_SOA_COLUMN(MCEleX, mcEleX, float); //! Generated x of ele particle +DECLARE_SOA_COLUMN(MCEleY, mcEleY, float); //! Generated y of ele particle +DECLARE_SOA_COLUMN(MCEleZ, mcEleZ, float); //! Generated z of ele particle +// Propagated MC pos +DECLARE_SOA_COLUMN(MCPosPropX, mcPosPropX, float); //! Propagated generated x of pos particle +DECLARE_SOA_COLUMN(MCPosPropY, mcPosPropY, float); //! Propagated generated y of pos particle +DECLARE_SOA_COLUMN(MCPosPropZ, mcPosPropZ, float); //! Propagated generated z of pos particle +DECLARE_SOA_COLUMN(MCPosPropEta, mcPosPropEta, float); //! Propagated generated eta of pos particle +DECLARE_SOA_COLUMN(MCPosPropTgl, mcPosPropTgl, float); //! Propagated generated tgl of pos particle +DECLARE_SOA_COLUMN(MCPosPropPt, mcPosPropPt, float); //! Propagated generated Pt of pos particle +// Propagated MC ele +DECLARE_SOA_COLUMN(MCElePropX, mcElePropX, float); //! Propagated generated x of ele particle +DECLARE_SOA_COLUMN(MCElePropY, mcElePropY, float); //! Propagated generated y of ele particle +DECLARE_SOA_COLUMN(MCElePropZ, mcElePropZ, float); //! Propagated generated z of ele particle +DECLARE_SOA_COLUMN(MCElePropEta, mcElePropEta, float); //! Propagated generated eta of ele particle +DECLARE_SOA_COLUMN(MCElePropTgl, mcElePropTgl, float); //! Propagated generated tgl of ele particle +DECLARE_SOA_COLUMN(MCElePropPt, mcElePropPt, float); //! Propagated generated Pt of ele particle +// MC mother particle +DECLARE_SOA_COLUMN(MCMotherIsPrimary, mcMotherIsPrimary, bool); //! If MC mother is primary +DECLARE_SOA_COLUMN(MCMotherIsGenerator, mcMotherIsGenerator, bool); //! If MC mother is generated +DECLARE_SOA_COLUMN(MCMotherPt, mcMotherPt, float); //! Mother particle Pt +DECLARE_SOA_COLUMN(MCMotherEta, mcMotherEta, float); //! Mother particle eta +DECLARE_SOA_COLUMN(MCMotherX, mcMotherX, float); //! Mother particle vertex x +DECLARE_SOA_COLUMN(MCMotherY, mcMotherY, float); //! Mother particle vertex y +DECLARE_SOA_COLUMN(MCMotherZ, mcMotherZ, float); //! Mother particle vertex z +// MC Primary Vertex +DECLARE_SOA_COLUMN(MCPVtxX, mcPVtxX, float); //! MC Primary vertex X +DECLARE_SOA_COLUMN(MCPVtxY, mcPVtxY, float); //! MC Primary vertex Y +DECLARE_SOA_COLUMN(MCPVtxZ, mcPVtxZ, float); //! MC Primary vertex Z +// TrackType +DECLARE_SOA_COLUMN(TrackType, trackType, uint8_t); //! Track type, see enum TrackTypes +} // namespace mcV0 + +DECLARE_SOA_TABLE(MCV0, "AOD", "MCV0", o2::soa::Index<>, + // Track Pos + mcV0::RecoPosPt, mcV0::RecoPosEta, mcV0::RecoPosTgl, + mcV0::RecoPosX, mcV0::RecoPosY, mcV0::RecoPosZ, + mcV0::RecoPosT, mcV0::RecoPosSign, + mcV0::RecoPosHasITS, mcV0::RecoPosHasTPC, mcV0::RecoPosHasTRD, mcV0::RecoPosHasTOF, + // Track Ele + mcV0::RecoElePt, mcV0::RecoEleEta, mcV0::RecoEleTgl, + mcV0::RecoEleX, mcV0::RecoEleY, mcV0::RecoEleZ, + mcV0::RecoEleT, mcV0::RecoEleSign, + mcV0::RecoEleHasITS, mcV0::RecoEleHasTPC, mcV0::RecoEleHasTRD, mcV0::RecoEleHasTOF, + // MC particle pos + mcV0::MCPosPt, mcV0::MCPosEta, + mcV0::MCPosX, mcV0::MCPosY, mcV0::MCPosZ, + // MC particle ele + mcV0::MCElePt, mcV0::MCEleEta, + mcV0::MCEleX, mcV0::MCEleY, mcV0::MCEleZ, + // Propagated MC pos + mcV0::MCPosPropX, mcV0::MCPosPropY, mcV0::MCPosPropZ, + mcV0::MCPosPropEta, mcV0::MCPosPropTgl, mcV0::MCPosPropPt, + // Propagated MC pos + mcV0::MCElePropX, mcV0::MCElePropY, mcV0::MCElePropZ, + mcV0::MCElePropEta, mcV0::MCElePropTgl, mcV0::MCElePropPt, + // MC mother particle + mcV0::MCMotherIsPrimary, mcV0::MCMotherIsGenerator, mcV0::MCMotherPt, mcV0::MCMotherEta, + mcV0::MCMotherX, mcV0::MCMotherY, mcV0::MCMotherZ, + // Primary Vertex + mcV0::MCPVtxX, mcV0::MCPVtxY, mcV0::MCPVtxZ, + // Track type + mcV0::TrackType); +} // namespace o2::aod + +#endif // PWGEM_PHOTONMESON_DATAMODEL_MCV0TABLES_H_ diff --git a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt index d6f8e937231..d41f96a1c21 100644 --- a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt +++ b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt @@ -9,13 +9,13 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2physics_add_dpl_workflow(skimmergammaconversions - SOURCES skimmerGammaConversions.cxx +o2physics_add_dpl_workflow(skimmer-gamma-conversion + SOURCES skimmerGammaConversion.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(skimmergammaconversionstruthonlymc - SOURCES skimmerGammaConversionsTruthOnlyMc.cxx +o2physics_add_dpl_workflow(skimmer-gamma-conversion-truthonlymc + SOURCES skimmerGammaConversionTruthOnlyMc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -34,7 +34,7 @@ o2physics_add_dpl_workflow(create-emreduced-mc-event PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(skimmergammacalo +o2physics_add_dpl_workflow(skimmer-gamma-calo SOURCES skimmerGammaCalo.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -44,6 +44,11 @@ o2physics_add_dpl_workflow(skimmer-phos PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::PHOSBase COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(skimmer-dalitz-ee + SOURCES skimmerDalitzEE.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(gamma-table-producer SOURCES gammaSelection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/PhotonMeson/TableProducer/createEMReducedEvent.cxx b/PWGEM/PhotonMeson/TableProducer/createEMReducedEvent.cxx index 52624c541ff..fd77b77e221 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMReducedEvent.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMReducedEvent.cxx @@ -31,11 +31,16 @@ using namespace o2::soa; struct createEMReducedEvent { Produces event; + Produces v0kfeventid; + Produces dalitzeventid; + Produces phoseventid; + Produces emceventid; enum SubSystem { kPCM = 0x1, kPHOS = 0x2, kEMC = 0x4, + kDalitzEE = 0x8, kUndef = -1, }; @@ -46,28 +51,31 @@ struct createEMReducedEvent { HistogramRegistry registry{"registry"}; - Preslice perCollision_pcm = aod::v0photon::collisionId; + Preslice perCollision_pcm = aod::v0photonkf::collisionId; + Preslice perCollision_dalitz = aod::dalitzee::collisionId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; void init(o2::framework::InitContext&) { - auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{6, 0.5f, 6.5f}}); + auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{7, 0.5f, 7.5f}}); hEventCounter->GetXaxis()->SetBinLabel(1, "all"); hEventCounter->GetXaxis()->SetBinLabel(2, "has > minN_PCM"); hEventCounter->GetXaxis()->SetBinLabel(3, "has > minN_PHOS"); hEventCounter->GetXaxis()->SetBinLabel(4, "has > minN_EMC"); hEventCounter->GetXaxis()->SetBinLabel(5, "has > minN_any"); hEventCounter->GetXaxis()->SetBinLabel(6, "sel8"); + hEventCounter->GetXaxis()->SetBinLabel(7, "sel8 & minN"); registry.add("hNGammas_PCM", ";#it{N}_{#gamma,PCM};#it{count}", kTH1I, {{21, -0.5, 20.5}}); + registry.add("hNGammas_DalitzEE", ";#it{N}_{#gamma*};#it{count}", kTH1I, {{21, -0.5, 20.5}}); registry.add("hNGammas_PHOS", ";#it{N}_{#gamma,PHOS};#it{count}", kTH1I, {{21, -0.5, 20.5}}); registry.add("hNGammas_EMC", ";#it{N}_{#gamma,EMC};#it{count}", kTH1I, {{21, -0.5, 20.5}}); } - using MyCollisions = soa::Join; + using MyCollisions = soa::Join; - template - void process(MyCollisions const& collisions, aod::BCs const&, TPCMs const& v0photons, TPHOSs const& phosclusters, TEMCs const& emcclusters) + template + void processEvent(MyCollisions const& collisions, aod::BCs const&, TPCMs const& v0photons, TPHOSs const& phosclusters, TEMCs const& emcclusters, TDielectorns const& dielectrons) { for (auto& collision : collisions) { registry.fill(HIST("hEventCounter"), 1); @@ -79,23 +87,42 @@ struct createEMReducedEvent { int ng_pcm = 0; int ng_phos = 0; int ng_emc = 0; + int ng_dilepton = 0; bool minN_any = false; if constexpr (static_cast(system & kPCM)) { auto v0photons_coll = v0photons.sliceBy(perCollision_pcm, collision.globalIndex()); ng_pcm = v0photons_coll.size(); registry.fill(HIST("hNGammas_PCM"), ng_pcm); + for (int iv0 = 0; iv0 < v0photons_coll.size(); iv0++) { + v0kfeventid(event.lastIndex() + 1); + } } if constexpr (static_cast(system & kPHOS)) { auto phos_coll = phosclusters.sliceBy(perCollision_phos, collision.globalIndex()); ng_phos = phos_coll.size(); registry.fill(HIST("hNGammas_PHOS"), ng_phos); + for (int iphos = 0; iphos < phos_coll.size(); iphos++) { + phoseventid(event.lastIndex() + 1); + } } if constexpr (static_cast(system & kEMC)) { auto emc_coll = emcclusters.sliceBy(perCollision_emc, collision.globalIndex()); ng_emc = emc_coll.size(); registry.fill(HIST("hNGammas_EMC"), ng_emc); + for (int iemc = 0; iemc < emc_coll.size(); iemc++) { + emceventid(event.lastIndex() + 1); + } } + if constexpr (static_cast(system & kDalitzEE)) { + auto dielectrons_coll = dielectrons.sliceBy(perCollision_dalitz, collision.globalIndex()); + ng_dilepton = dielectrons_coll.size(); + registry.fill(HIST("hNGammas_DalitzEE"), ng_dilepton); + for (int iee = 0; iee < dielectrons_coll.size(); iee++) { + dalitzeventid(event.lastIndex() + 1); + } + } + if (ng_pcm >= minN_PCM) { minN_any = true; registry.fill(HIST("hEventCounter"), 2); @@ -114,6 +141,9 @@ struct createEMReducedEvent { if (collision.sel8()) { registry.fill(HIST("hEventCounter"), 6); } + if (collision.sel8() && ng_emc >= minN_EMC && ng_phos >= minN_PHOS && ng_pcm >= minN_PCM) { + registry.fill(HIST("hEventCounter"), 7); + } // store event selection decisions uint64_t tag = collision.selection_raw(); @@ -123,55 +153,78 @@ struct createEMReducedEvent { collision.numContrib(), collision.collisionTime(), collision.collisionTimeRes(), collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), collision.multNTracksPVeta1(), - collision.centFV0A(), collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centFDDM(), collision.centNTPV(), + collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), ng_pcm, ng_phos, ng_emc); // ng is needed for event mixing to filter events that contain at least 1 photon. } // end of collision loop + } // end of processEvent - } // end of process - - void process_PCM(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0Photons const& v0photons) + void process_PCM(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0PhotonsKF const& v0photons) + { + processEvent(collisions, bcs, v0photons, nullptr, nullptr, nullptr); + } + void process_PCM_DalitzEE(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0PhotonsKF const& v0photons, aod::DalitzEEs const& dielectrons) { - process(collisions, bcs, v0photons, nullptr, nullptr); + const uint8_t sysflag = kPCM | kDalitzEE; + processEvent(collisions, bcs, v0photons, nullptr, nullptr, dielectrons); } void process_PHOS(MyCollisions const& collisions, aod::BCs const& bcs, aod::PHOSClusters const& phosclusters) { - process(collisions, bcs, nullptr, phosclusters, nullptr); + processEvent(collisions, bcs, nullptr, phosclusters, nullptr, nullptr); } void process_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::SkimEMCClusters const& emcclusters) { - process(collisions, bcs, nullptr, nullptr, emcclusters); + processEvent(collisions, bcs, nullptr, nullptr, emcclusters, nullptr); } - void process_PCM_PHOS(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0Photons const& v0photons, aod::PHOSClusters const& phosclusters) + void process_PCM_PHOS(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0PhotonsKF const& v0photons, aod::PHOSClusters const& phosclusters) { const uint8_t sysflag = kPCM | kPHOS; - process(collisions, bcs, v0photons, phosclusters, nullptr); + processEvent(collisions, bcs, v0photons, phosclusters, nullptr, nullptr); } - void process_PCM_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0Photons const& v0photons, aod::SkimEMCClusters const& emcclusters) + void process_PCM_PHOS_DalitzEE(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0PhotonsKF const& v0photons, aod::PHOSClusters const& phosclusters, aod::DalitzEEs const& dielectrons) + { + const uint8_t sysflag = kPCM | kPHOS | kDalitzEE; + processEvent(collisions, bcs, v0photons, phosclusters, nullptr, dielectrons); + } + void process_PCM_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0PhotonsKF const& v0photons, aod::SkimEMCClusters const& emcclusters) { const uint8_t sysflag = kPCM | kEMC; - process(collisions, bcs, v0photons, nullptr, emcclusters); + processEvent(collisions, bcs, v0photons, nullptr, emcclusters, nullptr); + } + void process_PCM_EMC_DalitzEE(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0PhotonsKF const& v0photons, aod::SkimEMCClusters const& emcclusters, aod::DalitzEEs const& dielectrons) + { + const uint8_t sysflag = kPCM | kEMC | kDalitzEE; + processEvent(collisions, bcs, v0photons, nullptr, emcclusters, dielectrons); } void process_PHOS_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters) { const uint8_t sysflag = kPHOS | kEMC; - process(collisions, bcs, nullptr, phosclusters, emcclusters); + processEvent(collisions, bcs, nullptr, phosclusters, emcclusters, nullptr); } - void process_PCM_PHOS_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0Photons const& v0photons, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters) + void process_PCM_PHOS_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0PhotonsKF const& v0photons, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters) { const uint8_t sysflag = kPCM | kPHOS | kEMC; - process(collisions, bcs, v0photons, phosclusters, emcclusters); + processEvent(collisions, bcs, v0photons, phosclusters, emcclusters, nullptr); + } + void process_PCM_PHOS_EMC_DalitzEE(MyCollisions const& collisions, aod::BCs const& bcs, aod::V0PhotonsKF const& v0photons, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters, aod::DalitzEEs const& dielectrons) + { + const uint8_t sysflag = kPCM | kPHOS | kEMC | kDalitzEE; + processEvent(collisions, bcs, v0photons, phosclusters, emcclusters, dielectrons); } void processDummy(MyCollisions const& collisions) {} PROCESS_SWITCH(createEMReducedEvent, process_PCM, "create em event table for PCM", false); + PROCESS_SWITCH(createEMReducedEvent, process_PCM_DalitzEE, "create em event table for PCM, DalitzEE", false); PROCESS_SWITCH(createEMReducedEvent, process_PHOS, "create em event table for PHOS", false); PROCESS_SWITCH(createEMReducedEvent, process_EMC, "create em event table for EMCal", false); PROCESS_SWITCH(createEMReducedEvent, process_PCM_PHOS, "create em event table for PCM, PHOS", false); + PROCESS_SWITCH(createEMReducedEvent, process_PCM_PHOS_DalitzEE, "create em event table for PCM, PHOS, DalitzEE", false); PROCESS_SWITCH(createEMReducedEvent, process_PCM_EMC, "create em event table for PCM, EMCal", false); + PROCESS_SWITCH(createEMReducedEvent, process_PCM_EMC_DalitzEE, "create em event table for PCM, EMCal, DalitzEE", false); PROCESS_SWITCH(createEMReducedEvent, process_PHOS_EMC, "create em event table for PHOS, EMCal", false); PROCESS_SWITCH(createEMReducedEvent, process_PCM_PHOS_EMC, "create em event table for PCM, PHOS, EMCal", false); + PROCESS_SWITCH(createEMReducedEvent, process_PCM_PHOS_EMC_DalitzEE, "create em event table for PCM, PHOS, EMCal, DalitzEE", false); PROCESS_SWITCH(createEMReducedEvent, processDummy, "processDummy", true); }; diff --git a/PWGEM/PhotonMeson/TableProducer/createEMReducedMCEvent.cxx b/PWGEM/PhotonMeson/TableProducer/createEMReducedMCEvent.cxx index 4824252d941..8003957b0ac 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMReducedMCEvent.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMReducedMCEvent.cxx @@ -38,13 +38,19 @@ struct createEMReducedMCEvent { kPCM = 0x1, kPHOS = 0x2, kEMC = 0x4, + kDalitzEE = 0x8, kUndef = -1, }; Produces events; Produces mcevents; Produces mceventlabels; Produces emmcparticles; - Produces emmcparticlelabels; + Produces v0legmclabels; + Produces emprimarytrackmclabels; + Produces v0kfeventid; + Produces dalitzeventid; + Produces phoseventid; + Produces emceventid; HistogramRegistry registry{"EMMCEvent"}; @@ -56,13 +62,15 @@ struct createEMReducedMCEvent { Preslice perMcCollision = aod::mcparticle::mcCollisionId; Preslice perCollision_pcm = aod::v0photon::collisionId; + Preslice perCollision_dalitz = aod::dalitzee::collisionId; + Preslice perCollision_emprmtrk = aod::emprimarytrack::collisionId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; - using MyCollisions = soa::Join; + using MyCollisions = soa::Join; - template - void skimmingMC(MyCollisions const& collisions, aod::BCs const&, aod::McCollisions const&, aod::McParticles const& mcTracks, TTracks const&, TPCMs const& v0photons, TPCMLegs const& v0legs, TPHOSs const& phosclusters, TEMCs const& emcclusters) + template + void skimmingMC(MyCollisions const& collisions, aod::BCs const&, aod::McCollisions const&, aod::McParticles const& mcTracks, TTracks const& o2tracks, TPCMs const& v0photons, TPCMLegs const& v0legs, TPHOSs const& phosclusters, TEMCs const& emcclusters, TDielectorns const& dielectrons, TEMPrimaryTracks const& emprimarytracks) { // temporary variables used for the indexing of the skimmed MC stack std::map fNewLabels; @@ -77,6 +85,7 @@ struct createEMReducedMCEvent { int ng_pcm = 0; int ng_phos = 0; int ng_emc = 0; + int ng_dilepton = 0; // TODO: investigate the collisions without corresponding mcCollision if (!collision.has_mcCollision()) { @@ -92,14 +101,30 @@ struct createEMReducedMCEvent { if constexpr (static_cast(system & kPCM)) { auto v0photons_coll = v0photons.sliceBy(perCollision_pcm, collision.globalIndex()); ng_pcm = v0photons_coll.size(); + for (int iv0 = 0; iv0 < v0photons_coll.size(); iv0++) { + v0kfeventid(events.lastIndex() + 1); + } } if constexpr (static_cast(system & kPHOS)) { auto phos_coll = phosclusters.sliceBy(perCollision_phos, collision.globalIndex()); ng_phos = phos_coll.size(); + for (int iphos = 0; iphos < phos_coll.size(); iphos++) { + phoseventid(events.lastIndex() + 1); + } } if constexpr (static_cast(system & kEMC)) { auto emc_coll = emcclusters.sliceBy(perCollision_emc, collision.globalIndex()); ng_emc = emc_coll.size(); + for (int iemc = 0; iemc < emc_coll.size(); iemc++) { + emceventid(events.lastIndex() + 1); + } + } + if constexpr (static_cast(system & kDalitzEE)) { + auto dielectrons_coll = dielectrons.sliceBy(perCollision_dalitz, collision.globalIndex()); + ng_dilepton = dielectrons_coll.size(); + for (int iee = 0; iee < dielectrons_coll.size(); iee++) { + dalitzeventid(events.lastIndex() + 1); + } } // store event selection decisions @@ -111,7 +136,7 @@ struct createEMReducedMCEvent { collision.numContrib(), collision.collisionTime(), collision.collisionTimeRes(), collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), collision.multNTracksPVeta1(), - collision.centFV0A(), collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centFDDM(), collision.centNTPV(), + collision.centFT0M(), collision.centFT0A(), collision.centFT0C(), collision.centNTPV(), ng_pcm, ng_phos, ng_emc); // make an entry for this MC event only if it was not already added to the table @@ -171,11 +196,14 @@ struct createEMReducedMCEvent { auto ele = v0.template negTrack_as(); auto pos = v0.template posTrack_as(); + auto o2track_ele = ele.template track_as(); + auto o2track_pos = pos.template track_as(); + if (!o2track_ele.has_mcParticle() || !o2track_pos.has_mcParticle()) { + continue; // If no MC particle is found, skip the v0 + } + for (auto& leg : {pos, ele}) { // be carefull of order {pos, ele}! auto o2track = leg.template track_as(); - if (!o2track.has_mcParticle()) { - continue; // If no MC particle is found, skip the track - } auto mctrack = o2track.template mcParticle_as(); // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack @@ -186,11 +214,31 @@ struct createEMReducedMCEvent { fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; fCounters[0]++; } - emmcparticlelabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + v0legmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); } // end of leg loop } // end of v0 loop } - + if constexpr (static_cast(system & kDalitzEE)) { + // for dalitz ee + auto emprimarytracks_coll = emprimarytracks.sliceBy(perCollision_emprmtrk, collision.globalIndex()); + for (auto& emprimarytrack : emprimarytracks_coll) { + auto o2track = o2tracks.iteratorAt(emprimarytrack.trackId()); + if (!o2track.has_mcParticle()) { + continue; // If no MC particle is found, skip the dilepton + } + auto mctrack = o2track.template mcParticle_as(); + + // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack + if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mctrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); + // fMCFlags[mctrack.globalIndex()] = mcflags; + fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision.globalIndex())->second; + fCounters[0]++; + } + emprimarytrackmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); + } // end of em primary track loop + } } // end of collision loop // Loop over the label map, create the mother/daughter relationships if these exist and write the skimmed MC stack @@ -200,28 +248,6 @@ struct createEMReducedMCEvent { std::vector mothers; if (mctrack.has_mothers()) { - ////auto mp = mctrack.template mothers_first_as(); - // int motherid = mctrack.mothersIds()[0];//first mother index - // while(motherid > -1) { - // if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? - // auto mp = mcTracks.iteratorAt(motherid); - - // if (fNewLabels.find(mp.globalIndex()) != fNewLabels.end()) { - // mothers.push_back(fNewLabels.find(mp.globalIndex())->second); - // } - - // if(mp.has_mothers()){ - // motherid = mp.mothersIds()[0];//first mother index - // } else { - // motherid = -999; - // } - // } - // else{ - // std::cout << "Mother label (" << motherid << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; - // std::cout << " Check the MC generator" << std::endl; - // } - //} - for (auto& m : mctrack.mothersIds()) { if (m < mcTracks.size()) { // protect against bad mother indices if (fNewLabels.find(m) != fNewLabels.end()) { @@ -271,48 +297,72 @@ struct createEMReducedMCEvent { fCounters[1] = 0; } // end of skimmingMC - void processMC_PCM(soa::SmallGroups const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs) + void processMC_PCM(soa::SmallGroups const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs) { - skimmingMC(collisions, bcs, mccollisions, mcTracks, tracks, v0photons, v0legs, nullptr, nullptr); + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, nullptr, nullptr, nullptr); + } + void processMC_PCM_DalitzEE(soa::SmallGroups const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::DalitzEEs const& dielectrons, aod::EMPrimaryTracks const& emprimarytracks) + { + const uint8_t sysflag = kPCM | kDalitzEE; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, nullptr, dielectrons, emprimarytracks); } void processMC_PHOS(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, aod::PHOSClusters const& phosclusters) { - skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, phosclusters, nullptr); + skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, phosclusters, nullptr, nullptr, nullptr); } void processMC_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, aod::SkimEMCClusters const& emcclusters) { - skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, nullptr, emcclusters); + skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, nullptr, emcclusters, nullptr, nullptr); } - void processMC_PCM_PHOS(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters) + void processMC_PCM_PHOS(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters) { const uint8_t sysflag = kPCM | kPHOS; - skimmingMC(collisions, bcs, mccollisions, mcTracks, tracks, v0photons, v0legs, phosclusters, nullptr); + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, phosclusters, nullptr, nullptr, nullptr); + } + void processMC_PCM_PHOS_DalitzEE(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, aod::DalitzEEs const& dielectrons, aod::EMPrimaryTracks const& emprimarytracks) + { + const uint8_t sysflag = kPCM | kPHOS | kDalitzEE; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, phosclusters, nullptr, dielectrons, emprimarytracks); } - void processMC_PCM_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::SkimEMCClusters const& emcclusters) + void processMC_PCM_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::SkimEMCClusters const& emcclusters) { const uint8_t sysflag = kPCM | kEMC; - skimmingMC(collisions, bcs, mccollisions, mcTracks, tracks, v0photons, v0legs, nullptr, emcclusters); + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, emcclusters, nullptr, nullptr); + } + void processMC_PCM_EMC_DalitzEE(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::SkimEMCClusters const& emcclusters, aod::DalitzEEs const& dielectrons, aod::EMPrimaryTracks const& emprimarytracks) + { + const uint8_t sysflag = kPCM | kEMC | kDalitzEE; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, nullptr, emcclusters, dielectrons, emprimarytracks); } void processMC_PHOS_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters) { const uint8_t sysflag = kPHOS | kEMC; - skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, phosclusters, emcclusters); + skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, nullptr, nullptr, phosclusters, emcclusters, nullptr, nullptr); } - void processMC_PCM_PHOS_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters) + void processMC_PCM_PHOS_EMC(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters) { const uint8_t sysflag = kPCM | kPHOS | kEMC; - skimmingMC(collisions, bcs, mccollisions, mcTracks, tracks, v0photons, v0legs, phosclusters, emcclusters); + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, phosclusters, emcclusters, nullptr, nullptr); + } + void processMC_PCM_PHOS_EMC_DalitzEE(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters, aod::DalitzEEs const& dielectrons, aod::EMPrimaryTracks const& emprimarytracks) + { + const uint8_t sysflag = kPCM | kPHOS | kEMC | kDalitzEE; + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, v0photons, v0legs, phosclusters, emcclusters, dielectrons, emprimarytracks); } - void processDummy(MyCollisions const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, aod::V0Photons const& v0photons, aod::V0Legs const& v0legs) {} + void processDummy(MyCollisions const& collisions) {} PROCESS_SWITCH(createEMReducedMCEvent, processMC_PCM, "create em mc event table for PCM", false); + PROCESS_SWITCH(createEMReducedMCEvent, processMC_PCM_DalitzEE, "create em mc event table for PCM, DalitzEE", false); PROCESS_SWITCH(createEMReducedMCEvent, processMC_PHOS, "create em mc event table for PHOS", false); PROCESS_SWITCH(createEMReducedMCEvent, processMC_EMC, "create em mc event table for EMCal", false); PROCESS_SWITCH(createEMReducedMCEvent, processMC_PCM_PHOS, "create em mc event table for PCM, PHOS", false); + PROCESS_SWITCH(createEMReducedMCEvent, processMC_PCM_PHOS_DalitzEE, "create em mc event table for PCM, PHOS, DalitzEE", false); PROCESS_SWITCH(createEMReducedMCEvent, processMC_PCM_EMC, "create em mc event table for PCM, EMCal", false); + PROCESS_SWITCH(createEMReducedMCEvent, processMC_PCM_EMC_DalitzEE, "create em mc event table for PCM, EMCal, DalitzEE", false); PROCESS_SWITCH(createEMReducedMCEvent, processMC_PHOS_EMC, "create em mc event table for PHOS, EMCal", false); PROCESS_SWITCH(createEMReducedMCEvent, processMC_PCM_PHOS_EMC, "create em mc event table for PCM, PHOS, EMCal", false); + PROCESS_SWITCH(createEMReducedMCEvent, processMC_PCM_PHOS_EMC_DalitzEE, "create em mc event table for PCM, PHOS, EMCal, DalitzEE", false); PROCESS_SWITCH(createEMReducedMCEvent, processDummy, "processDummy", true); }; diff --git a/PWGEM/PhotonMeson/TableProducer/createPCM.cxx b/PWGEM/PhotonMeson/TableProducer/createPCM.cxx index 159c429d64d..0e8693cc7c2 100644 --- a/PWGEM/PhotonMeson/TableProducer/createPCM.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createPCM.cxx @@ -15,11 +15,12 @@ // Please write to: daiki.sekihata@cern.ch #include +#include +#include #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" #include "Common/Core/trackUtilities.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/CollisionAssociationTables.h" @@ -31,12 +32,14 @@ #include "CCDB/BasicCCDBManager.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" using namespace o2; +using namespace o2::soa; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::soa; -using std::array; +using namespace o2::pwgem::photonmeson; using FullTracksExtIU = soa::Join; // using FullTracksExt = soa::Join; @@ -67,21 +70,31 @@ struct createPCM { Configurable d_UseWeightedPCA{"d_UseWeightedPCA", false, "Vertices use cov matrices"}; Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; - Configurable minv0cospa{"minv0cospa", 0.95, "minimum V0 CosPA"}; - Configurable maxdcav0dau{"maxdcav0dau", 1.5, "max DCA between V0 Daughters"}; + Configurable minv0cospa{"minv0cospa", 0.90, "minimum V0 CosPA"}; + Configurable maxdcav0dau{"maxdcav0dau", 2.0, "max DCA between V0 Daughters"}; Configurable v0Rmin{"v0Rmin", 0.0, "v0Rmin"}; Configurable v0Rmax{"v0Rmax", 180.0, "v0Rmax"}; Configurable dcamin{"dcamin", 0.1, "dcamin"}; Configurable dcamax{"dcamax", 1e+10, "dcamax"}; - Configurable maxX{"maxX", 100.0, "maximum X (starting point of track X)"}; // maxX is equal to or smaller than minPropagationDistance in trackPropagation.cxx for DCA + Configurable nsw{"nsw", 1, "number of searching window in collisions"}; + Configurable maxX{"maxX", 83.1, "maximum X (starting point X of track iu)"}; + Configurable maxY{"maxY", 20.0, "maximum Y (starting point Y of track iu)"}; Configurable minpt{"minpt", 0.01, "min pT for single track in GeV/c"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance for single track"}; Configurable mincrossedrows{"mincrossedrows", 10, "min crossed rows"}; Configurable maxchi2tpc{"maxchi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 5.0, "max chi2/NclsITS"}; + Configurable maxpt_itsonly{"maxpt_itsonly", 0.5, "max pT for ITSonly tracks"}; Configurable min_tpcdEdx{"min_tpcdEdx", 30.0, "min TPC dE/dx"}; Configurable max_tpcdEdx{"max_tpcdEdx", 110.0, "max TPC dE/dx"}; - Configurable useTPConly{"useTPConly", false, "Use truly TPC only tracks for V0 finder"}; - Configurable rejectTPConly{"rejectTPConly", false, "Reject truly TPC only tracks for V0 finder"}; + Configurable margin_r{"margin_r", 7.0, "margin for r cut"}; + Configurable max_qt_arm{"max_qt_arm", 0.03, "max qt for AP cut in GeV/c"}; + Configurable max_r_req_its{"max_r_req_its", 16.0, "min Rxy for V0 with ITS hits"}; + Configurable min_r_tpconly{"min_r_tpconly", 32.0, "min Rxy for V0 with TPConly tracks"}; + Configurable max_diff_tgl{"max_diff_tgl", 999.0, "max difference in track iu tgl between ele and pos"}; + Configurable max_diff_z_itstpc{"max_diff_z_itstpc", 999.0, "max difference in track iu z between ele and pos for ITS-TPC tracks"}; + Configurable max_diff_z_itsonly{"max_diff_z_itsonly", 999.0, "max difference in track iu z between ele and pos for ITSonly tracks"}; + Configurable max_diff_z_tpconly{"max_diff_z_tpconly", 999.0, "max difference in track iu z between ele and pos for TPConly tracks"}; int mRunNumber; float d_bz; @@ -121,10 +134,12 @@ struct createPCM { // Material correction in the DCA fitter o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - if (useMatCorrType == 1) + if (useMatCorrType == 1) { matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - if (useMatCorrType == 2) + } + if (useMatCorrType == 2) { matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + } fitter.setMatCorrType(matCorr); } @@ -148,16 +163,16 @@ struct createPCM { } auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - o2::parameters::GRPMagField* grpmag = 0x0; - if (grpo) { + auto* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + o2::parameters::GRPMagField* grpmag = nullptr; + if (grpo != nullptr) { o2::base::Propagator::initFieldFromGRP(grpo); // Fetch magnetic field from ccdb for current collision d_bz = grpo->getNominalL3Field(); LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; } else { grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { + if (grpmag == nullptr) { LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; } o2::base::Propagator::initFieldFromGRP(grpmag); @@ -176,23 +191,109 @@ struct createPCM { } } + static float v0_alpha(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) + { + float momTot = RecoDecay::p(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + float lQlNeg = RecoDecay::dotProd(std::array{pxneg, pyneg, pzneg}, std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}) / momTot; + float lQlPos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}) / momTot; + return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); + } + static float v0_qt(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) + { + float momTot = RecoDecay::p2(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + float dp = RecoDecay::dotProd(std::array{pxneg, pyneg, pzneg}, std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}); + return std::sqrt(RecoDecay::p2(pxneg, pyneg, pzneg) - dp * dp / momTot); + } + template - bool IsTPConlyTrack(TTrack const& track) + bool reconstructV0(TTrack const& ele, TTrack const& pos) { - if (track.hasTPC() && (!track.hasITS() && !track.hasTOF() && !track.hasTRD())) { - return true; + bool isITSonly_pos = pos.hasITS() && !pos.hasTPC(); + bool isITSonly_ele = ele.hasITS() && !ele.hasTPC(); + bool isTPConly_pos = !pos.hasITS() && pos.hasTPC(); + bool isTPConly_ele = !ele.hasITS() && ele.hasTPC(); + bool isITSTPC_pos = pos.hasITS() && pos.hasTPC(); + bool isITSTPC_ele = ele.hasITS() && ele.hasTPC(); + + if ((isITSonly_pos && isTPConly_ele) || (isITSonly_ele && isTPConly_pos)) { + return false; + } + + if (abs(ele.tgl() - pos.tgl()) > max_diff_tgl) { + return false; + } + + if (isITSTPC_pos && isITSTPC_ele) { + if (abs(ele.z() - pos.z()) > max_diff_z_itstpc) { + return false; + } + } else if (isTPConly_pos && isTPConly_ele) { + if (abs(ele.z() - pos.z()) > max_diff_z_tpconly) { + return false; + } + } else if (isITSonly_pos && isITSonly_ele) { + if (abs(ele.z() - pos.z()) > max_diff_z_itsonly) { + return false; + } + } + + // fitter is memeber variable. + auto pTrack = getTrackParCov(pos); // positive + auto nTrack = getTrackParCov(ele); // negative + std::array svpos = {0.}; // secondary vertex position + std::array pvec0 = {0.}; + std::array pvec1 = {0.}; + + int nCand = fitter.process(pTrack, nTrack); + if (nCand != 0) { + fitter.propagateTracksToVertex(); + const auto& vtx = fitter.getPCACandidate(); + for (int i = 0; i < 3; i++) { + svpos[i] = vtx[i]; + } + fitter.getTrack(0).getPxPyPzGlo(pvec0); // positive + fitter.getTrack(1).getPxPyPzGlo(pvec1); // negative } else { return false; } + + float v0dca = fitter.getChi2AtPCACandidate(); // distance between 2 legs. + if (v0dca > maxdcav0dau) { + return false; + } + + if (!checkAP(v0_alpha(pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2]), v0_qt(pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2]), 0.95, max_qt_arm)) { // store only photon conversions + return false; + } + if (ele.hasITS() && pos.hasITS() && !checkAP(v0_alpha(pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2]), v0_qt(pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2]), 0.95, 0.02)) { // store only photon conversions + return false; + } + + float xyz[3] = {0.f, 0.f, 0.f}; + Vtx_recalculation(o2::base::Propagator::Instance(), pos, ele, xyz); + float recalculatedVtxR = std::sqrt(pow(xyz[0], 2) + pow(xyz[1], 2)); + // LOGF(info, "recalculated vtx : x = %f , y = %f , z = %f", xyz[0], xyz[1], xyz[2]); + if (recalculatedVtxR > std::min(pos.x(), ele.x()) + margin_r && (pos.x() > 1.f && ele.x() > 1.f)) { + return false; + } + + if (recalculatedVtxR < max_r_req_its && (!pos.hasITS() || !ele.hasITS())) { + return false; + } + if (recalculatedVtxR < min_r_tpconly && (!pos.hasITS() && !ele.hasITS())) { + return false; + } + + return true; } template - void fillV0Table(TCollision const& collision, TTrack const& ele, TTrack const& pos) + void fillV0Table(TCollision const& collision, TTrack const& ele, TTrack const& pos, const bool filltable) { - array pVtx = {collision.posX(), collision.posY(), collision.posZ()}; - array svpos = {0.}; // secondary vertex position - array pvec0 = {0.}; - array pvec1 = {0.}; + std::array pVtx = {collision.posX(), collision.posY(), collision.posZ()}; + std::array svpos = {0.}; // secondary vertex position + std::array pvec0 = {0.}; + std::array pvec1 = {0.}; auto pTrack = getTrackParCov(pos); // positive auto nTrack = getTrackParCov(ele); // negative @@ -210,67 +311,221 @@ struct createPCM { return; } - float px = pvec0[0] + pvec1[0]; - float py = pvec0[1] + pvec1[1]; - float pz = pvec0[2] + pvec1[2]; + std::array pvxyz{pvec0[0] + pvec1[0], pvec0[1] + pvec1[1], pvec0[2] + pvec1[2]}; float v0dca = fitter.getChi2AtPCACandidate(); // distance between 2 legs. - float v0CosinePA = RecoDecay::cpa(pVtx, array{svpos[0], svpos[1], svpos[2]}, array{px, py, pz}); + float v0CosinePA = RecoDecay::cpa(pVtx, svpos, pvxyz); float v0radius = RecoDecay::sqrtSumOfSquares(svpos[0], svpos[1]); if (v0dca > maxdcav0dau) { return; } - if (v0radius < v0Rmin || v0Rmax < v0radius) { + if (v0CosinePA < minv0cospa) { return; } - if (v0CosinePA < minv0cospa) { + + if (!checkAP(v0_alpha(pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2]), v0_qt(pvec0[0], pvec0[1], pvec0[2], pvec1[0], pvec1[1], pvec1[2]), 0.95, max_qt_arm)) { // store only photon conversions return; } - v0data(pos.globalIndex(), ele.globalIndex(), collision.globalIndex(), -1, - fitter.getTrack(0).getX(), fitter.getTrack(1).getX(), - svpos[0], svpos[1], svpos[2], - pvec0[0], pvec0[1], pvec0[2], - pvec1[0], pvec1[1], pvec1[2], - v0dca, pos.dcaXY(), ele.dcaXY()); + if (filltable) { + if (v0radius < v0Rmin || v0Rmax < v0radius) { + return; + } + v0data(pos.globalIndex(), ele.globalIndex(), collision.globalIndex(), -1, + fitter.getTrack(0).getX(), fitter.getTrack(1).getX(), + svpos[0], svpos[1], svpos[2], + pvec0[0], pvec0[1], pvec0[2], + pvec1[0], pvec1[1], pvec1[2], + v0dca, pos.dcaXY(), ele.dcaXY()); + + } else { + // LOGF(info, "storing: collision.globalIndex() = %d , pos.globalIndex() = %d , ele.globalIndex() = %d, cospa = %f", collision.globalIndex(), pos.globalIndex(), ele.globalIndex(), v0CosinePA); + pca_map[std::make_tuple(pos.globalIndex(), ele.globalIndex(), collision.globalIndex())] = v0dca; + cospa_map[std::make_tuple(pos.globalIndex(), ele.globalIndex(), collision.globalIndex())] = v0CosinePA; + } // store indices + } + + template + bool isSelected(TTrack const& track) + { + if (track.pt() < minpt || abs(track.eta()) > maxeta) { + return false; + } + if (abs(track.dcaXY()) < dcamin || dcamax < abs(track.dcaXY())) { + return false; + } + if (!track.hasITS() && !track.hasTPC()) { + return false; + } + + if (track.hasITS() && !track.hasTPC() && (track.hasTRD() || track.hasTOF())) { // remove unrealistic track. this should not happen. + return false; + } + + if (track.hasTPC()) { + if (track.tpcNClsCrossedRows() < mincrossedrows || track.tpcChi2NCl() > maxchi2tpc) { + return false; + } + if (track.tpcSignal() < min_tpcdEdx || max_tpcdEdx < track.tpcSignal()) { + return false; + } + } + + if (track.hasITS()) { + if (track.itsChi2NCl() > maxchi2its) { + return false; + } + bool isITSonly = isITSonlyTrack(track); + if (isITSonly) { + if (track.pt() > maxpt_itsonly) { + return false; + } + } + } + + return true; } - Filter trackFilter = o2::aod::track::x < maxX && o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& dcamin < nabs(o2::aod::track::dcaXY) && nabs(o2::aod::track::dcaXY) < dcamax&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& min_tpcdEdx < o2::aod::track::tpcSignal&& o2::aod::track::tpcSignal < max_tpcdEdx; + Filter trackFilter = o2::aod::track::x < maxX && nabs(o2::aod::track::y) < maxY && o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& dcamin < nabs(o2::aod::track::dcaXY) && nabs(o2::aod::track::dcaXY) < dcamax && ((min_tpcdEdx < o2::aod::track::tpcSignal && o2::aod::track::tpcSignal < max_tpcdEdx) || o2::aod::track::tpcSignal < -10.f); using MyFilteredTracks = soa::Filtered; + + std::map, float> pca_map; + std::map, float> cospa_map; + + // Partition orphan_posTracks = o2::aod::track::signed1Pt > 0.f && o2::aod::track::collisionId < int32_t(0); + // Partition orphan_negTracks = o2::aod::track::signed1Pt < 0.f && o2::aod::track::collisionId < int32_t(0); Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; + std::vectorsliceByCached(o2::aod::track::collisionId, 0, cache))> negTracks_sw; + std::vectorsliceByCached(o2::aod::track::collisionId, 0, cache))> posTracks_sw; void processSA(MyFilteredTracks const& tracks, aod::Collisions const& collisions, aod::BCsWithTimestamps const&) { - for (auto& collision : collisions) { - registry.fill(HIST("hEventCounter"), 1); + // LOGF(info, "collisions.size() = %d, tracks.size() = %d", collisions.size(), tracks.size()); + for (int64_t icoll = 0; icoll < collisions.size(); icoll += nsw) { // don't repeat the same collision + auto collision = collisions.rawIteratorAt(icoll); + // LOGF(info, "collision.globalIndex() = %d", collision.globalIndex()); auto bc = collision.bc_as(); initCCDB(bc); + // registry.fill(HIST("hEventCounter"), 1); + + int32_t min_sw = std::max(int64_t(0), collision.globalIndex()); + int32_t max_sw = std::min(int64_t(min_sw + nsw), int64_t(collisions.size())); + + // LOGF(info, "orphan_posTracks.size() = %d, orphan_negTracks.size() = %d", orphan_posTracks.size(), orphan_negTracks.size()); + negTracks_sw.reserve(max_sw - min_sw); + posTracks_sw.reserve(max_sw - min_sw); + + // int npos = 0, nneg = 0; + for (int32_t isw = min_sw; isw < max_sw; isw++) { + negTracks_sw.emplace_back(negTracks->sliceByCached(o2::aod::track::collisionId, isw, cache)); + posTracks_sw.emplace_back(posTracks->sliceByCached(o2::aod::track::collisionId, isw, cache)); + // npos += posTracks_sw.back().size(); + // nneg += negTracks_sw.back().size(); + // LOGF(info, "collision.globalIndex() = %d , posTracks_sw.back().size() = %d , negTracks_sw.back().size() = %d", collision.globalIndex(), posTracks_sw.back().size(), negTracks_sw.back().size()); + } + // LOGF(info, "min_sw = %d , max_sw = %d , collision.globalIndex() = %d , n posTracks_sw = %d , n negTracks_sw = %d", min_sw, max_sw, collision.globalIndex(), npos, nneg); + + for (auto& negTracks_coll : negTracks_sw) { + for (auto& posTracks_coll : posTracks_sw) { + for (auto& [ele, pos] : combinations(CombinationsFullIndexPolicy(negTracks_coll, posTracks_coll))) { + if (!isSelected(ele) || !isSelected(pos)) { + continue; + } + if (!reconstructV0(ele, pos)) { // this is needed for speed-up. + continue; + } + + for (int32_t isw = min_sw; isw < max_sw; isw++) { + auto collision_in_sw = collisions.rawIteratorAt(isw); + + if (ele.isPVContributor() && isw != ele.collisionId()) { + continue; + } + if (pos.isPVContributor() && isw != pos.collisionId()) { + continue; + } + + // LOGF(info, "pairing: collision_in_sw.globalIndex() = %d , ele.collisionId() = %d , pos.collisionId() = %d ele.globalIndex() = %d , pos.globalIndex() = %d", + // collision_in_sw.globalIndex(), ele.collisionId(), pos.collisionId(), ele.globalIndex(), pos.globalIndex()); + fillV0Table(collision_in_sw, ele, pos, false); + } // end of searching window loop + } // end of pairing loop + } // end of pos track loop in sw + } // end of pos track loop in sw + + // LOGF(info, "possible number of V0 = %d", cospa_map.size()); + std::map, bool> used_pair_map; + + for (const auto& [key, value] : cospa_map) { + auto pos = tracks.rawIteratorAt(std::get<0>(key)); + auto ele = tracks.rawIteratorAt(std::get<1>(key)); + + // LOGF(info, "candidate : pos.globalIndex() = %d , ele.globalIndex() = %d , collision.globalIndex() = %d , cospa = %f , pca = %f", std::get<0>(key), std::get<1>(key), std::get<2>(key), value, pca_map[key]); + + std::vector vec_cospa; // vector for each searching window + vec_cospa.reserve(max_sw - min_sw); + for (int32_t isw = min_sw; isw < max_sw; isw++) { + auto collision_in_sw = collisions.rawIteratorAt(isw); + if (cospa_map.find(std::make_tuple(pos.globalIndex(), ele.globalIndex(), collision_in_sw.globalIndex())) != cospa_map.end()) { + vec_cospa.emplace_back(cospa_map[std::make_tuple(pos.globalIndex(), ele.globalIndex(), collision_in_sw.globalIndex())]); + } else { + vec_cospa.emplace_back(-999.f); + } + } // end of searching window loop + + // search for the most probable collision where V0 belongs by maximal cospa. + int32_t collision_id_most_prob = std::distance(vec_cospa.begin(), std::max_element(vec_cospa.begin(), vec_cospa.end())) + min_sw; + auto collision_most_prob = collisions.rawIteratorAt(collision_id_most_prob); + // float max_cospa = *std::max_element(vec_cospa.begin(), vec_cospa.end()); + // LOGF(info, "max cospa is found! collision_most_prob.globalIndex() = %d , pos.collisionId() = %d , ele.collisionId() = %d, max_cospa = %f", collision_most_prob.globalIndex(), pos.collisionId(), ele.collisionId(), max_cospa); + vec_cospa.clear(); + vec_cospa.shrink_to_fit(); + + // next, check pca between 2 legs in this searching window and select V0s that have the smallest pca to avoid double counting of legs. + float v0pca = pca_map[std::make_tuple(pos.globalIndex(), ele.globalIndex(), collision_most_prob.globalIndex())]; + bool is_closest_v0 = true; + for (const auto& [key_tmp, value_tmp] : pca_map) { + auto pos_tmp = tracks.rawIteratorAt(std::get<0>(key_tmp)); + auto ele_tmp = tracks.rawIteratorAt(std::get<1>(key_tmp)); + + float v0pca_tmp = value_tmp; + // float v0pca_tmp = 999.f; + // if(pca_map.find(std::make_tuple(pos_tmp.globalIndex(), ele_tmp.globalIndex(), collision_most_prob.globalIndex())) != pca_map.end()){ + // v0pca_tmp = pca_map[std::make_tuple(pos_tmp.globalIndex(), ele_tmp.globalIndex(), collision_most_prob.globalIndex())]; + // } + + if (ele.globalIndex() == ele_tmp.globalIndex() && pos.globalIndex() == pos_tmp.globalIndex()) { // skip exactly the same V0 + continue; + } + if ((ele.globalIndex() == ele_tmp.globalIndex() || pos.globalIndex() == pos_tmp.globalIndex()) && v0pca > v0pca_tmp) { + // LOGF(info, "!reject! | collision id = %d | posid1 = %d , eleid1 = %d , posid2 = %d , eleid2 = %d , pca1 = %f , pca2 = %f", + // collision.globalIndex(), pos.globalIndex(), ele.globalIndex(), pos_tmp.globalIndex(), ele_tmp.globalIndex(), v0pca, v0pca_tmp); + is_closest_v0 = false; + break; + } + } // end of pca_map loop + + if (is_closest_v0 && used_pair_map.find(std::make_pair(pos.globalIndex(), ele.globalIndex())) == used_pair_map.end()) { + // LOGF(info, "store : pos.globalIndex() = %d , ele.globalIndex() = %d , collision.globalIndex() = %d , cospa = %f , pca = %f", std::get<0>(key), std::get<1>(key), std::get<2>(key), value, pca_map[key]); + fillV0Table(collision_most_prob, ele, pos, true); + used_pair_map[std::make_pair(pos.globalIndex(), ele.globalIndex())] = true; + } + } // end of pca_map loop + used_pair_map.clear(); - auto negTracks_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto posTracks_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - - // LOGF(info, "collision.globalIndex() = %d , negTracks_coll.size() = %d , posTracks_coll.size() = %d", collision.globalIndex(), negTracks_coll.size(), posTracks_coll.size()); + pca_map.clear(); + cospa_map.clear(); - for (auto& [ele, pos] : combinations(CombinationsFullIndexPolicy(negTracks_coll, posTracks_coll))) { - if (!ele.hasTPC() || !pos.hasTPC()) { - continue; - } - if (ele.tpcNClsCrossedRows() < mincrossedrows || pos.tpcNClsCrossedRows() < mincrossedrows) { - continue; - } - if (useTPConly && (!IsTPConlyTrack(ele) || !IsTPConlyTrack(pos))) { - continue; - } - if (rejectTPConly && (IsTPConlyTrack(ele) || IsTPConlyTrack(pos))) { - continue; - } - fillV0Table(collision, ele, pos); - } + negTracks_sw.clear(); + posTracks_sw.clear(); + negTracks_sw.shrink_to_fit(); + posTracks_sw.shrink_to_fit(); } // end of collision loop - } // end of process + + } // end of process PROCESS_SWITCH(createPCM, processSA, "create V0s with stand-alone way", true); Preslice trackIndicesPerCollision = aod::track_association::collisionId; @@ -292,42 +547,15 @@ struct createPCM { if (ele.sign() * pos.sign() > 0) { // reject same sign combination continue; } - if ((abs(ele.dcaXY()) < dcamin || dcamax < abs(ele.dcaXY())) || (abs(pos.dcaXY()) < dcamin || dcamax < abs(pos.dcaXY()))) { - continue; - } - if (!ele.hasTPC() || !pos.hasTPC()) { - continue; - } - if (ele.tpcNClsCrossedRows() < mincrossedrows || pos.tpcNClsCrossedRows() < mincrossedrows) { - continue; - } - if (ele.tpcChi2NCl() > maxchi2tpc || pos.tpcChi2NCl() > maxchi2tpc) { - continue; - } - if (abs(ele.eta()) > maxeta || abs(pos.eta()) > maxeta) { - continue; - } - if (ele.pt() < minpt || pos.pt() < minpt) { - continue; - } - if (ele.tpcSignal() < min_tpcdEdx || max_tpcdEdx < ele.tpcSignal()) { - continue; - } - if (pos.tpcSignal() < min_tpcdEdx || max_tpcdEdx < pos.tpcSignal()) { - continue; - } - if (useTPConly && (!IsTPConlyTrack(ele) || !IsTPConlyTrack(pos))) { - continue; - } - if (rejectTPConly && (IsTPConlyTrack(ele) || IsTPConlyTrack(pos))) { + if (!isSelected(ele) || !isSelected(pos)) { continue; } if (ele.sign() < 0) { - fillV0Table(collision, ele, pos); + fillV0Table(collision, ele, pos, true); } else { - fillV0Table(collision, pos, ele); + fillV0Table(collision, pos, ele, true); } } } // end of collision loop diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx new file mode 100644 index 00000000000..16d3edba63a --- /dev/null +++ b/PWGEM/PhotonMeson/TableProducer/skimmerDalitzEE.cxx @@ -0,0 +1,337 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \brief write relevant information for dalitz ee analysis to an AO2D.root file. This file is then the only necessary input to perform pcm analysis. +/// \author daiki.sekihata@cern.ch + +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/trackUtilities.h" +#include "CommonConstants/PhysicsConstants.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +using MyTracks = soa::Join; +using MyTracksMC = soa::Join; + +struct skimmerDalitzEE { + enum class EM_EEPairType : int { + kULS = 0, + kLSpp = +1, + kLSnn = -1, + }; + + SliceCache cache; + Preslice perCol = o2::aod::track::collisionId; + Produces dalitzees; + Produces emprimarytracks; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + Configurable minitsncls{"minitsncls", 4, "min. number of ITS clusters"}; + Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; + Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; + Configurable minpt{"minpt", 0.05, "min pt for track"}; + Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; + Configurable dca_xy_max{"dca_xy_max", 1.0f, "max DCAxy in cm"}; + Configurable dca_z_max{"dca_z_max", 1.0f, "max DCAz in cm"}; + Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 4.0, "max. TPC n sigma for electron inclusion"}; + Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 2.0, "max. TPC n sigma for pion exclusion"}; + + HistogramRegistry fRegistry{ + "fRegistry", + { + {"hNpairs", "hNpairs;pair type;Number of Pairs", {HistType::kTH1F, {{3, -1.5f, +1.5f}}}}, + }, + }; + + std::pair> itsRequirement = {1, {0, 1, 2}}; // any hits on 3 ITS ib layers. + + int mRunNumber; + float d_bz; + Service ccdb; + void init(InitContext const&) + { + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + o2::parameters::GRPMagField* grpmag = 0x0; + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = bc.runNumber(); + } + + template + bool checkTrack(TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + if (track.itsNCls() < minitsncls) { + return false; + } + + auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); + if (hits < itsRequirement.first) { + return false; + } + + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + if (abs(track.tpcNSigmaEl()) > maxTPCNsigmaEl) { + return false; + } + if (abs(track.tpcNSigmaPi()) < maxTPCNsigmaPi) { + return false; + } + return true; + } + + template + void fillPairTable(TCollision const& collision, TTracks1 const& tracks1, TTracks2 const& tracks2) + { + if constexpr (pairtype == EM_EEPairType::kULS) { // ULS + for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (!checkTrack(t1) || !checkTrack(t2)) { + continue; + } + fRegistry.fill(HIST("hNpairs"), static_cast(pairtype)); + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + float dcaxy1 = t1.dcaXY() / sqrt(t1.cYY()); + float dcaxy2 = t2.dcaXY() / sqrt(t2.cYY()); + float dcaeexy = sqrt((pow(dcaxy1, 2) + pow(dcaxy2, 2)) / 2.); + float dcaz1 = t1.dcaZ() / sqrt(t1.cZZ()); + float dcaz2 = t2.dcaZ() / sqrt(t2.cZZ()); + float dcaeez = sqrt((pow(dcaz1, 2) + pow(dcaz2, 2)) / 2.); + + dalitzees(collision.globalIndex(), fNewLabels[t1.globalIndex()], fNewLabels[t2.globalIndex()], v12.Pt(), v12.Eta(), v12.Phi() > 0 ? v12.Phi() : v12.Phi() + TMath::TwoPi(), v12.M(), phiv, dcaeexy, dcaeez, static_cast(pairtype)); + // LOGF(info, "ULS: collision.globalIndex() = %d, fNewLabels[t1.globalIndex()] = %d, fNewLabels[t2.globalIndex()] = %d", collision.globalIndex(), fNewLabels[t1.globalIndex()], fNewLabels[t2.globalIndex()]); + } // end of pairing loop + } else { // LS + for (auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(tracks1, tracks2))) { + if (!checkTrack(t1) || !checkTrack(t2)) { + continue; + } + fRegistry.fill(HIST("hNpairs"), static_cast(pairtype)); + ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + float phiv = getPhivPair(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz(), t1.sign(), t2.sign(), d_bz); + float dcaxy1 = t1.dcaXY() / sqrt(t1.cYY()); + float dcaxy2 = t2.dcaXY() / sqrt(t2.cYY()); + float dcaeexy = sqrt((pow(dcaxy1, 2) + pow(dcaxy2, 2)) / 2.); + float dcaz1 = t1.dcaZ() / sqrt(t1.cZZ()); + float dcaz2 = t2.dcaZ() / sqrt(t2.cZZ()); + float dcaeez = sqrt((pow(dcaz1, 2) + pow(dcaz2, 2)) / 2.); + dalitzees(collision.globalIndex(), fNewLabels[t1.globalIndex()], fNewLabels[t2.globalIndex()], v12.Pt(), v12.Eta(), v12.Phi() > 0 ? v12.Phi() : v12.Phi() + TMath::TwoPi(), v12.M(), phiv, dcaeexy, dcaeez, static_cast(pairtype)); + // LOGF(info, "LS: collision.globalIndex() = %d, fNewLabels[t1.globalIndex()] = %d, fNewLabels[t2.globalIndex()] = %d", collision.globalIndex(), fNewLabels[t1.globalIndex()], fNewLabels[t2.globalIndex()]); + } // end of pairing loop + } + } + + template + void fillTrackTable(TTracks const& tracks) + { + for (auto& track : tracks) { + if (!checkTrack(track)) { + continue; + } + + if (!(fNewLabels.find(track.globalIndex()) != fNewLabels.end())) { + fNewLabels[track.globalIndex()] = fCounter; + + emprimarytracks(track.collisionId(), track.globalIndex(), track.sign(), + track.pt(), track.eta(), track.phi(), track.dcaXY(), track.dcaZ(), + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.itsClusterMap(), track.itsChi2NCl(), track.detectorMap(), track.signed1Pt(), track.cYY(), track.cZZ()); + + fCounter++; + } + } // end of track loop + } + + // ============================ FUNCTION DEFINITIONS ==================================================== + + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its; + using MyFilteredTracks = soa::Filtered; + Partition posTracks = o2::aod::track::signed1Pt > 0.f; + Partition negTracks = o2::aod::track::signed1Pt < 0.f; + + std::map fNewLabels; + int fCounter = 0; + void processRec(aod::Collisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + { + for (auto& collision : collisions) { + auto bc = collision.bc_as(); + initCCDB(bc); + + auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + + // store track info which belongs to pairs. (i.e. only 1 track per event does not enter pair analysis.) + int npos = 0, nneg = 0; + for (auto& ptrack : posTracks_per_coll) { + if (!checkTrack(ptrack)) { + continue; + } + npos++; + } + for (auto& ntrack : negTracks_per_coll) { + if (!checkTrack(ntrack)) { + continue; + } + nneg++; + } + + if (npos + nneg < 2) { + continue; + } + + fillTrackTable(posTracks_per_coll); + fillTrackTable(negTracks_per_coll); + + fillPairTable(collision, posTracks_per_coll, negTracks_per_coll); // ULS + fillPairTable(collision, posTracks_per_coll, posTracks_per_coll); // LS++ + fillPairTable(collision, negTracks_per_coll, negTracks_per_coll); // LS-- + + } // end of collision loop + fNewLabels.clear(); + fCounter = 0; + } + PROCESS_SWITCH(skimmerDalitzEE, processRec, "process reconstructed info only", true); + + using MyFilteredTracksMC = soa::Filtered; + Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; + Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; + void processMC(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) + { + for (auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + // auto mcCollision = collision.mcCollision(); + auto bc = collision.bc_as(); + initCCDB(bc); + auto posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + + // store track info which belongs to pairs. (i.e. only 1 track per event does not enter pair analysis.) + int npos = 0, nneg = 0; + for (auto& ptrack : posTracks_per_coll) { + if (!checkTrack(ptrack)) { + continue; + } + npos++; + } + for (auto& ntrack : negTracks_per_coll) { + if (!checkTrack(ntrack)) { + continue; + } + nneg++; + } + + if (npos + nneg < 2) { + continue; + } + + fillTrackTable(posTracks_per_coll); + fillTrackTable(negTracks_per_coll); + + fillPairTable(collision, posTracks_per_coll, negTracks_per_coll); // ULS + fillPairTable(collision, posTracks_per_coll, posTracks_per_coll); // LS++ + fillPairTable(collision, negTracks_per_coll, negTracks_per_coll); // LS-- + } // end of collision loop + fNewLabels.clear(); + fCounter = 0; + } + PROCESS_SWITCH(skimmerDalitzEE, processMC, "process reconstructed and MC info ", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"skimmer-dalitz-ee"})}; +} diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx index 868d3411d99..a696474d52a 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx @@ -144,6 +144,6 @@ struct skimmerGammaCalo { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + WorkflowSpec workflow{adaptAnalysisTask(cfgc, TaskName{"skimmer-gamma-calo"})}; return workflow; } diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversions.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx similarity index 65% rename from PWGEM/PhotonMeson/TableProducer/skimmerGammaConversions.cxx rename to PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx index ee5bcacb27a..7f94d97fd71 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversions.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx @@ -42,21 +42,24 @@ #include "DCAFitter/HelixHelper.h" #include "ReconstructionDataFormats/TrackFwd.h" #include "Common/Core/trackUtilities.h" +#include "CommonConstants/PhysicsConstants.h" #include #include +#include "Math/Vector4D.h" #include "Tools/KFparticle/KFUtilities.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; // using tracksAndTPCInfo = soa::Join; using tracksAndTPCInfo = soa::Join; using tracksAndTPCInfoMC = soa::Join; -struct skimmerGammaConversions { +struct skimmerGammaConversion { // configurables for CCDB access Configurable ccdbPath{"ccdb-path", "GLO/GRP/GRP", "path to the ccdb object"}; @@ -67,6 +70,7 @@ struct skimmerGammaConversions { Configurable mincrossedrows{"mincrossedrows", 10, "min. crossed rows"}; Configurable maxchi2tpc{"maxchi2tpc", 4.0, "max. chi2/NclsTPC"}; + Configurable minpt{"minpt", 0.01, "min pt for track"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 5.0, "max. TPC n sigma for electron"}; Configurable dcamin{"dcamin", 0.1, "dcamin"}; @@ -210,26 +214,26 @@ struct skimmerGammaConversions { sameMother); } - template - bool checkV0leg(TLeg const& leg) + template + bool checkV0leg(TTrack const& track) { - if (abs(leg.eta()) > maxeta) { + if (track.pt() < minpt || abs(track.eta()) > maxeta) { return false; } - if (abs(leg.tpcNSigmaEl()) > maxTPCNsigmaEl) { + if (abs(track.dcaXY()) < dcamin || dcamax < abs(track.dcaXY())) { return false; } - if (leg.tpcChi2NCl() > maxchi2tpc) { + if (!track.hasITS() && !track.hasTPC()) { return false; } - if (leg.tpcNClsCrossedRows() < mincrossedrows) { - return false; - } - if (abs(leg.dcaXY()) < dcamin) { - return false; - } - if (dcamax < abs(leg.dcaXY())) { - return false; + + if (track.hasTPC()) { + if (track.tpcNClsCrossedRows() < mincrossedrows || track.tpcChi2NCl() > maxchi2tpc) { + return false; + } + if (abs(track.tpcNSigmaEl()) > maxTPCNsigmaEl) { + return false; + } } return true; } @@ -255,35 +259,73 @@ struct skimmerGammaConversions { KFParticle KFPV(kfpVertex); float xyz[3] = {recalculatedVertex.recalculatedConversionPoint[0], recalculatedVertex.recalculatedConversionPoint[1], recalculatedVertex.recalculatedConversionPoint[2]}; + // LOGF(info, "recalculated vtx : x = %f , y = %f , z = %f", xyz[0], xyz[1], xyz[2]); + // LOGF(info, "primary vtx : x = %f , y = %f , z = %f", collision.posX(), collision.posY(), collision.posZ()); - /// Transport the gamma to the recalculated decay vertex - KFParticle gammaKF_DecayVtx = gammaKF; + // Transport the gamma to the recalculated decay vertex + KFParticle gammaKF_DecayVtx = gammaKF; // with respect to (0,0,0) gammaKF_DecayVtx.TransportToPoint(xyz); - /// Apply a topological constraint of the gamma to the PV. - /// Parameters will be given at the primary vertex. + // Apply a topological constraint of the gamma to the PV. Parameters will be given at the primary vertex. KFParticle gammaKF_PV = gammaKF_DecayVtx; gammaKF_PV.SetProductionVertex(KFPV); + KFParticle gammaKF_DecayVtx2 = gammaKF_PV; // with respect to the PV + gammaKF_DecayVtx2.TransportToPoint(xyz); + // LOGF(info, "px = %f (KF at SV1) , %f (KF at PV) , %f (KF at SV2)", gammaKF_DecayVtx.GetPx(), gammaKF_PV.GetPx(), gammaKF_DecayVtx2.GetPx()); + // LOGF(info, "py = %f (KF at SV1) , %f (KF at PV) , %f (KF at SV2)", gammaKF_DecayVtx.GetPy(), gammaKF_PV.GetPy(), gammaKF_DecayVtx2.GetPy()); + // LOGF(info, "pz = %f (KF at SV1) , %f (KF at PV) , %f (KF at SV2)", gammaKF_DecayVtx.GetPz(), gammaKF_PV.GetPz(), gammaKF_DecayVtx2.GetPz()); + + // LOGF(info, "cpaFromKF(gammaKF_DecayVtx, KFPV) = %f", cpaFromKF(gammaKF_DecayVtx, KFPV)); + // LOGF(info, "cpaFromKF(gammaKF_DecayVtx2, KFPV) = %f", cpaFromKF(gammaKF_DecayVtx2, KFPV)); + // LOGF(info, "gammaKF_DecayVtx.GetMass() = %f" , gammaKF_DecayVtx.GetMass()); + // LOGF(info, "gammaKF_DecayVtx2.GetMass() = %f", gammaKF_DecayVtx2.GetMass()); + float chi2kf = -1.f; if (gammaKF_DecayVtx.GetNDF() > 0) { chi2kf = gammaKF_DecayVtx.GetChi2() / gammaKF_DecayVtx.GetNDF(); } - // LOGF(info, "mee = %f (DCAFitter) , %f (KF)", v0.mGamma(), gammaKF_DecayVtx.GetMass()); + KFParticle kfp_pos_PV = kfp_pos; + KFParticle kfp_ele_PV = kfp_ele; + kfp_pos_PV.SetProductionVertex(KFPV); + kfp_ele_PV.SetProductionVertex(KFPV); + + KFParticle kfp_pos_DecayVtx = kfp_pos_PV; + KFParticle kfp_ele_DecayVtx = kfp_ele_PV; + kfp_pos_DecayVtx.TransportToPoint(xyz); + kfp_ele_DecayVtx.TransportToPoint(xyz); + // LOGF(info, "ele px = %f (original) , %f (KF at init) , %f (KF at PV) , %f (KF at SV)", ele.px(), kfp_ele.GetPx(), kfp_ele_PV.GetPx(), kfp_ele_DecayVtx.GetPx()); + // LOGF(info, "pos px = %f (original) , %f (KF at init) , %f (KF at PV) , %f (KF at SV)", pos.px(), kfp_pos.GetPx(), kfp_pos_PV.GetPx(), kfp_pos_DecayVtx.GetPx()); + + ROOT::Math::PxPyPzMVector vpos_pv(kfp_pos_PV.GetPx(), kfp_pos_PV.GetPy(), kfp_pos_PV.GetPz(), o2::constants::physics::MassElectron); + ROOT::Math::PxPyPzMVector vele_pv(kfp_ele_PV.GetPx(), kfp_ele_PV.GetPy(), kfp_ele_PV.GetPz(), o2::constants::physics::MassElectron); + ROOT::Math::PxPyPzMVector v0_pv = vpos_pv + vele_pv; + + ROOT::Math::PxPyPzMVector vpos_sv(kfp_pos_DecayVtx.GetPx(), kfp_pos_DecayVtx.GetPy(), kfp_pos_DecayVtx.GetPz(), o2::constants::physics::MassElectron); + ROOT::Math::PxPyPzMVector vele_sv(kfp_ele_DecayVtx.GetPx(), kfp_ele_DecayVtx.GetPy(), kfp_ele_DecayVtx.GetPz(), o2::constants::physics::MassElectron); + ROOT::Math::PxPyPzMVector v0_sv = vpos_sv + vele_sv; + // LOGF(info, "mee = %f (KF at PV) , %f (KF at SV)", v0_pv.M(), v0_sv.M()); + + // calculate psipair, phiv at the decay vertex + float phiv = getPhivPair(kfp_pos_DecayVtx.GetPx(), kfp_pos_DecayVtx.GetPy(), kfp_pos_DecayVtx.GetPz(), kfp_ele_DecayVtx.GetPx(), kfp_ele_DecayVtx.GetPy(), kfp_ele_DecayVtx.GetPz(), kfp_pos_DecayVtx.GetQ(), kfp_ele_DecayVtx.GetQ(), o2::base::Propagator::Instance()->getNominalBz()); + float psipair = getPsiPair(kfp_pos_DecayVtx.GetPx(), kfp_pos_DecayVtx.GetPy(), kfp_pos_DecayVtx.GetPz(), kfp_ele_DecayVtx.GetPx(), kfp_ele_DecayVtx.GetPy(), kfp_ele_DecayVtx.GetPz()); + // LOGF(info, "bz = %f , phiv = %f , psipair = %f", bz, phiv, psipair); // float pca_kf = kfp_pos.GetDistanceFromParticle(kfp_ele); + // LOGF(info, "pca = %f (DCAFitter) , %f (KF at SV)", v0.dcaV0daughters(), pca_kf); v0photonskf(collision.globalIndex(), v0photons.lastIndex(), v0legs.lastIndex() + 1, v0legs.lastIndex() + 2, gammaKF_DecayVtx.GetX(), gammaKF_DecayVtx.GetY(), gammaKF_DecayVtx.GetZ(), gammaKF_PV.GetPx(), gammaKF_PV.GetPy(), gammaKF_PV.GetPz(), - v0.mGamma(), cpaFromKF(gammaKF_DecayVtx, KFPV), v0.dcaV0daughters(), - v0.alpha(), v0.qtarm(), v0.psipair(), chi2kf); + v0.mGamma(), v0_pv.M(), v0_sv.M(), + cpaFromKF(gammaKF_DecayVtx, KFPV), v0.dcaV0daughters(), + v0.alpha(), v0.qtarm(), psipair, phiv, chi2kf); } // ============================ FUNCTION DEFINITIONS ==================================================== - Preslice perCollision = aod::v0data::collisionId; + PresliceUnsorted perCollision = aod::v0data::collisionId; void processRec(aod::Collisions const& collisions, aod::BCsWithTimestamps const& bcs, @@ -306,35 +348,13 @@ struct skimmerGammaConversions { continue; } - bool flag_closer = true; - for (auto& v0tmp : groupedV0s) { - if (!checkAP(v0tmp.alpha(), v0tmp.qtarm())) { // store only photon conversions - continue; - } - auto pos_tmp = v0tmp.template posTrack_as(); // positive daughter - auto ele_tmp = v0tmp.template negTrack_as(); // negative daughter - if (!checkV0leg(pos_tmp) || !checkV0leg(ele_tmp)) { - continue; - } - - if (v0.index() == v0tmp.index()) { // don't check onviously, exactly the same v0. - // LOGF(info, "don't check the exactly the same 2 V0s"); - continue; - } - if ((ele.globalIndex() == ele_tmp.globalIndex() || pos.globalIndex() == pos_tmp.globalIndex()) && v0.dcaV0daughters() > v0tmp.dcaV0daughters()) { - // LOGF(info, "!reject! | collision id = %d | g1 id = %d , g2 id = %d , posid1 = %d , eleid1 = %d , posid2 = %d , eleid2 = %d , pca1 = %f , pca2 = %f", - // collision.globalIndex(), v0.index(), v0tmp.index(), pos.globalIndex(), ele.globalIndex(), pos_tmp.globalIndex(), ele_tmp.globalIndex(), v0.dcaV0daughters(), v0tmp.dcaV0daughters()); - flag_closer = false; - break; - } - } // end of v0tmp loop - - if (!flag_closer) { - continue; - } - + float xyz[3] = {0.f, 0.f, 0.f}; + Vtx_recalculation(o2::base::Propagator::Instance(), pos, ele, xyz); recalculatedVertexParameters recalculatedVertex; - Vtx_recalculation(pos, ele, &recalculatedVertex); + recalculatedVertex.recalculatedConversionPoint[0] = xyz[0]; + recalculatedVertex.recalculatedConversionPoint[1] = xyz[1]; + recalculatedVertex.recalculatedConversionPoint[2] = xyz[2]; + v0photons(collision.globalIndex(), v0legs.lastIndex() + 1, v0legs.lastIndex() + 2, v0.x(), v0.y(), v0.z(), v0.pxpos(), v0.pypos(), v0.pzpos(), @@ -349,7 +369,7 @@ struct skimmerGammaConversions { } // end of v0 loop } // end of collision loop } - PROCESS_SWITCH(skimmerGammaConversions, processRec, "process reconstructed info only", true); + PROCESS_SWITCH(skimmerGammaConversion, processRec, "process reconstructed info only", true); Preslice perMcCollision = aod::mcparticle::mcCollisionId; void processMc(soa::Join const& collisions, @@ -386,39 +406,19 @@ struct skimmerGammaConversions { continue; } - bool flag_closer = true; - for (auto& v0tmp : lGroupedV0s) { - if (!checkAP(v0tmp.alpha(), v0tmp.qtarm())) { // store only photon conversions - continue; - } - auto pos_tmp = v0tmp.template posTrack_as(); // positive daughter - auto ele_tmp = v0tmp.template negTrack_as(); // negative daughter - if (!checkV0leg(pos_tmp) || !checkV0leg(ele_tmp)) { - continue; - } - - if (v0.index() == v0tmp.index()) { // don't check onviously, exactly the same v0. - // LOGF(info, "don't check the exactly the same 2 V0s"); - continue; - } - if ((ele.globalIndex() == ele_tmp.globalIndex() || pos.globalIndex() == pos_tmp.globalIndex()) && v0.dcaV0daughters() > v0tmp.dcaV0daughters()) { - // LOGF(info, "!reject! | collision id = %d | g1 id = %d , g2 id = %d , posid1 = %d , eleid1 = %d , posid2 = %d , eleid2 = %d , pca1 = %f , pca2 = %f", - // collision.globalIndex(), v0.index(), v0tmp.index(), pos.globalIndex(), ele.globalIndex(), pos_tmp.globalIndex(), ele_tmp.globalIndex(), v0.dcaV0daughters(), v0tmp.dcaV0daughters()); - flag_closer = false; - break; - } - } // end of v0tmp loop - - if (!flag_closer) { - continue; + if (!ele.has_mcParticle() || !pos.has_mcParticle()) { + continue; // If no MC particle is found, skip the v0 } eV0Confirmation v0Status = isTrueV0(v0, pos, ele); - fRegistry.get(HIST("hV0Confirmation"))->Fill(v0Status); + float xyz[3] = {0.f, 0.f, 0.f}; + Vtx_recalculation(o2::base::Propagator::Instance(), pos, ele, xyz); recalculatedVertexParameters recalculatedVertex; - Vtx_recalculation(pos, ele, &recalculatedVertex); + recalculatedVertex.recalculatedConversionPoint[0] = xyz[0]; + recalculatedVertex.recalculatedConversionPoint[1] = xyz[1]; + recalculatedVertex.recalculatedConversionPoint[2] = xyz[2]; v0photons(collision.globalIndex(), v0legs.lastIndex() + 1, v0legs.lastIndex() + 2, v0.x(), v0.y(), v0.z(), @@ -434,7 +434,7 @@ struct skimmerGammaConversions { } } } - PROCESS_SWITCH(skimmerGammaConversions, processMc, "process reconstructed and mc info ", false); + PROCESS_SWITCH(skimmerGammaConversion, processMc, "process reconstructed and mc info ", false); template eV0Confirmation isTrueV0(TV0 const& theV0, @@ -543,87 +543,9 @@ struct skimmerGammaConversions { } return kGoodMcMother; } - - template - void Vtx_recalculation(T lTrackPos, T lTrackNeg, recalculatedVertexParameters* recalculatedVertex) - { - o2::base::Propagator* prop = o2::base::Propagator::Instance(); // This singleton propagator requires some initialisation of the CCDB object. - float bz = prop->getNominalBz(); - - //******************************************************* - - // o2::track::TrackParametrizationWithError = TrackParCov, I use the full version to have control over the data type - o2::track::TrackParametrizationWithError trackPosInformation = getTrackParCov(lTrackPos); // first get an object that stores Track information (positive) - o2::track::TrackParametrizationWithError trackNegInformation = getTrackParCov(lTrackNeg); // first get an object that stores Track information (negative) - - o2::track::TrackAuxPar helixPos(trackPosInformation, bz); // This object is a descendant of a CircleXY and stores cirlce information with respect to the magnetic field. This object uses functions and information of the o2::track::TrackParametrizationWithError object (positive) - o2::track::TrackAuxPar helixNeg(trackNegInformation, bz); // This object is a descendant of a CircleXY and stores cirlce information with respect to the magnetic field. This object uses functions and information of the o2::track::TrackParametrizationWithError object (negative) - - recalculatedVertex->recalculatedConversionPoint[0] = (helixPos.xC * helixNeg.rC + helixNeg.xC * helixPos.rC) / (helixPos.rC + helixNeg.rC); // This calculates the coordinates of the conversion point as an weighted average of the two helix centers. xC and yC should be the global coordinates for the helix center as far as I understand. But you can double check the code of trackPosInformation.getCircleParamsLoc - recalculatedVertex->recalculatedConversionPoint[1] = (helixPos.yC * helixNeg.rC + helixNeg.yC * helixPos.rC) / (helixPos.rC + helixNeg.rC); // If this calculation doesn't work check if the rotateZ function, because the "documentation" says I get global coordinates but maybe i don't. - - // I am unsure about the Z calculation but this is how it is done in AliPhysics as far as I understand - o2::track::TrackParametrizationWithError trackPosInformationCopy = o2::track::TrackParametrizationWithError(trackPosInformation); - o2::track::TrackParametrizationWithError trackNegInformationCopy = o2::track::TrackParametrizationWithError(trackNegInformation); - - // I think this calculation gets the closest point on the track to the conversion point - // This alpha is a different alpha than the usual alpha and I think it is the angle between X axis and conversion point - Double_t alphaPos = TMath::Pi() + TMath::ATan2(-(recalculatedVertex->recalculatedConversionPoint[1] - helixPos.yC), (recalculatedVertex->recalculatedConversionPoint[0] - helixPos.xC)); - Double_t alphaNeg = TMath::Pi() + TMath::ATan2(-(recalculatedVertex->recalculatedConversionPoint[1] - helixNeg.yC), (recalculatedVertex->recalculatedConversionPoint[0] - helixNeg.xC)); - - Double_t vertexXPos = helixPos.xC + helixPos.rC * TMath::Cos(alphaPos); - Double_t vertexYPos = helixPos.yC + helixPos.rC * TMath::Sin(alphaPos); - Double_t vertexXNeg = helixNeg.xC + helixNeg.rC * TMath::Cos(alphaNeg); - Double_t vertexYNeg = helixNeg.yC + helixNeg.rC * TMath::Sin(alphaNeg); - - TVector2 vertexPos(vertexXPos, vertexYPos); - TVector2 vertexNeg(vertexXNeg, vertexYNeg); - - // Convert to local coordinate system - TVector2 vertexPosRot = vertexPos.Rotate(-trackPosInformationCopy.getAlpha()); - TVector2 vertexNegRot = vertexNeg.Rotate(-trackNegInformationCopy.getAlpha()); - - prop->propagateToX(trackPosInformationCopy, - vertexPosRot.X(), - bz, - o2::base::PropagatorImpl::MAX_SIN_PHI, - o2::base::PropagatorImpl::MAX_STEP, - o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE); - // o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); - prop->propagateToX(trackNegInformationCopy, - vertexNegRot.X(), - bz, - o2::base::PropagatorImpl::MAX_SIN_PHI, - o2::base::PropagatorImpl::MAX_STEP, - o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE); - // o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); - - // TODO: This is still off and needs to be checked... - recalculatedVertex->recalculatedConversionPoint[2] = (trackPosInformationCopy.getZ() * helixNeg.rC + trackNegInformationCopy.getZ() * helixPos.rC) / (helixPos.rC + helixNeg.rC); - - KFPTrack kFTrackPos = createKFPTrackFromTrackParCov(trackPosInformationCopy, lTrackPos.sign(), lTrackPos.tpcNClsFound(), lTrackPos.tpcChi2NCl()); - int pdg_ePlus = -11; // e+ - KFParticle kFParticleEPlus(kFTrackPos, pdg_ePlus); - - KFPTrack kFTrackNeg = createKFPTrackFromTrackParCov(trackNegInformationCopy, lTrackNeg.sign(), lTrackNeg.tpcNClsFound(), lTrackNeg.tpcChi2NCl()); - int pdg_eMinus = 11; // e- - KFParticle kFParticleEMinus(kFTrackNeg, pdg_eMinus); - - KFParticle gammaKF; - gammaKF.SetConstructMethod(2); - gammaKF.AddDaughter(kFParticleEPlus); - gammaKF.AddDaughter(kFParticleEMinus); - gammaKF.SetNonlinearMassConstraint(kfMassConstrain); - - if (gammaKF.GetNDF() == 0) { - recalculatedVertex->KFParticleChi2DividedByNDF = -1.f; - } else { - recalculatedVertex->KFParticleChi2DividedByNDF = gammaKF.GetChi2() / gammaKF.GetNDF(); - } - } }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"skimmer-gamma-conversion"})}; } diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionsTruthOnlyMc.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionTruthOnlyMc.cxx similarity index 96% rename from PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionsTruthOnlyMc.cxx rename to PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionTruthOnlyMc.cxx index 9f9b186f2c2..509a949b0dd 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionsTruthOnlyMc.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversionTruthOnlyMc.cxx @@ -30,7 +30,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct skimmerGammaConversionsTruthOnlyMc { +struct skimmerGammaConversionTruthOnlyMc { Produces fFuncTableMcGammas; Produces fFuncTableMcDaughter; @@ -109,5 +109,5 @@ struct skimmerGammaConversionsTruthOnlyMc { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} \ No newline at end of file + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"skimmer-gamma-conversion-truthonlymc"})}; +} diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index 8e6b13405a5..bcba27bd6a6 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -34,6 +34,16 @@ o2physics_add_dpl_workflow(pcm-qc-mc PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(dalitz-ee-qc + SOURCES dalitzEEQC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(dalitz-ee-qc-mc + SOURCES dalitzEEQCMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phos-qc SOURCES phosQC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore @@ -78,3 +88,19 @@ o2physics_add_dpl_workflow(tag-and-probe SOURCES TagAndProbe.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(material-budget + SOURCES MaterialBudget.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(material-budget-mc + SOURCES MaterialBudgetMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(check-mc-v0 + SOURCES CheckMCV0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + diff --git a/PWGEM/PhotonMeson/Tasks/CheckMCV0.cxx b/PWGEM/PhotonMeson/Tasks/CheckMCV0.cxx new file mode 100644 index 00000000000..4d0702784d8 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/CheckMCV0.cxx @@ -0,0 +1,462 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \brief check the v0 phase-space +/// \dependencies: o2-analysis-lf-lambdakzeromcfinder +/// \author daiki.sekihata@cern.ch felix.schlepper@cern.ch + +#include "TDatabasePDG.h" +#include "TMath.h" + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StaticFor.h" +#include "ReconstructionDataFormats/Track.h" +#include "DetectorsBase/Propagator.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" +#include "PWGEM/PhotonMeson/DataModel/mcV0Tables.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/LHCConstants.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using namespace o2::pwgem::photonmeson; + +struct CheckMCV0 { + // Output Objects + Produces mcV0Table; + HistogramRegistry registry{"output", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Track selection + Configurable ptLogAxis{"ptLogAxis", false, "Flag to use a log momentum axis"}; + Configurable minpt{"minpt", 0.001, "min pt for track in GeV/c"}; + Configurable maxpt{"maxpt", 20.0, "max pt for track in GeV/c"}; + Configurable maxeta{"maxeta", 999.0, "eta acceptance"}; + Configurable dcamin{"dcamin", 0.1, "dcamin"}; + Configurable dcamax{"dcamax", 1e+10, "dcamax"}; + Configurable maxZ{"maxZ", 200.0, "max z for track"}; + Configurable maxX{"maxX", 200.0, "maximum X (starting point of track X)"}; + Configurable maxY{"maxY", 200.0, "maximum Y (starting point of track Y)"}; + Configurable maxChi2TPC{"maxChi2TPC", 100.0, "max chi2/NclsTPC"}; + Configurable minCrossedRowsTPC{"minCrossedRowsTPC", 10, "min crossed rows tpc"}; + Configurable cutSign{"cutSign", false, "wrong sign cut"}; + Configurable cutSameSign{"cutSameSign", false, "reject same sign"}; + + // Filters + Filter trackPt = aod::track::pt > minpt&& aod::track::pt < maxpt; + Filter trackZ = nabs(aod::track::z) < maxZ; + Filter trackX = aod::track::x < maxX; + Filter trackY = nabs(aod::track::y) < maxY; + Filter trackEta = nabs(aod::track::eta) < maxeta; + Filter trackDCA = nabs(aod::track::dcaXY) > dcamin&& nabs(aod::track::dcaXY) < dcamax; + using TracksMC = soa::Join; + using FilteredTracksMC = soa::Filtered; + using CollisionsMC = soa::Join; + + // Histogram Parameters + Configurable tglNBins{"tglNBins", 500, "nBins for tgl"}; + Configurable zNBins{"zNBins", 2 * static_cast(maxZ), "nBins for z"}; + Configurable xNBins{"xNBins", static_cast(maxX), "nBins for x"}; + Configurable yNBins{"yNBins", static_cast(maxY), "nBins for y"}; + Configurable ptNBins{"ptNBins", 200, "nBins for pt"}; + Configurable ptLowCut{"ptLowCut", 0.1, "low pt cut"}; + // Axes + AxisSpec axisTgl{tglNBins, -3.f, +3.f, "tan(#lambda)"}; + AxisSpec axisTglEle{tglNBins, -3.f, +3.f, "tan(#lambda) of e^{#minus}"}; + AxisSpec axisTglPos{tglNBins, -3.f, +3.f, "tan(#lambda) of e^{#plus}"}; + AxisSpec axisEta{300, -1.6, +1.6, "#eta"}; + AxisSpec axisX{xNBins, 0.0, maxX, "reco. x"}; + AxisSpec axisXMC{xNBins, 0.0, maxX, "MC prop. x"}; + AxisSpec axisXEle{xNBins, 0.0, maxX, "reco. x of e^{#minus}"}; + AxisSpec axisXPos{xNBins, 0.0, maxX, "reco. x of e^{#plus}"}; + AxisSpec axisXMCEle{xNBins, 0.0, maxX, "MC prop. x of e^{#minus}"}; + AxisSpec axisXMCPos{xNBins, 0.0, maxX, "MC prop. x of e^{#plus}"}; + AxisSpec axisY{yNBins, -maxY, maxY, "reco. y"}; + AxisSpec axisYMC{yNBins, -maxY, maxY, "MC prop. y"}; + AxisSpec axisYEle{yNBins, -maxY, maxY, "reco. y of e^{#minus}"}; + AxisSpec axisYPos{yNBins, -maxY, maxY, "reco. y of e^{#plus}"}; + AxisSpec axisYMCEle{yNBins, -maxY, maxY, "MC prop. y of e^{#minus}"}; + AxisSpec axisYMCPos{yNBins, -maxY, maxY, "MC prop. y of e^{#plus}"}; + AxisSpec axisZ{zNBins, -maxZ, maxZ, "reco. z"}; + AxisSpec axisZMC{zNBins, -maxZ, maxZ, "MC prop.z"}; + AxisSpec axisZEle{zNBins, -maxZ, maxZ, "reco. z of e^{#minus}"}; + AxisSpec axisZPos{zNBins, -maxZ, maxZ, "reco. z of e^{#plus}"}; + AxisSpec axisZMCEle{zNBins, -maxZ, maxZ, "MC prop. z of e^{#minus}"}; + AxisSpec axisZMCPos{zNBins, -maxZ, maxZ, "MC prop. z of e^{#plus}"}; + AxisSpec axisYDiff{yNBins, -maxY, maxY, "reco. y of e^{#plus} - reco. y of e^{#minus}"}; + AxisSpec axisZDiff{zNBins, -maxZ, maxZ, "reco. z of e^{#plus} - reco. z of e^{#minus}"}; + AxisSpec axisPt{ptNBins, minpt, maxpt, "#it{p}_{T} GeV/#it{c}"}; + AxisSpec axisPtPos{ptNBins, minpt, maxpt, "#it{p}_{T} GeV/#it{c} of e^{#plus}"}; + AxisSpec axisPtEle{ptNBins, minpt, maxpt, "#it{p}_{T} GeV/#it{c} of e^{#minus}"}; + AxisSpec axisTPos{1000, -50'000, +50'000, "timeStamp ns of e^{#plus}"}; + AxisSpec axisTEle{1000, -50'000, +50'000, "timeStamp ns of e^{#minus}"}; + + static constexpr std::array cutsBinLabels{"Pre", "checkV0leg", "sign", "sameSign", "photon", "propagationFailed", "lowPt", "highPt", "survived"}; + enum cutsBinEnum : uint8_t { + PRE = 1, + CHECKV0LEG, + SIGN, + SAMESIGN, + PHOTON, + PROPFAIL, + LOWPT, + HIGHPT, + SURVIVED, + }; + static_assert(cutsBinLabels.size() == cutsBinEnum::SURVIVED); + + static constexpr std::array checkV0legLabels{"PtmaxPt", "dcadcamax", "tpcChi2NCl>maxchi2tpc", "no ITS||TPC", "eta>maxEta", "tpcCrossedRows mCCDBPath{"ccdb-path", "GLO/GRP/GRP", "path to the ccdb object"}; + Configurable mGRPMagPath{"grpmagPath", "GLO/Config/GRPMagField", "path to the GRPMagField object"}; + Configurable mLUTPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + Configurable mCCDBUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service mCCDB; + int mRunNumber{-1}; + o2::base::MatLayerCylSet* mLUT{nullptr}; + o2::parameters::GRPMagField* mGRPMagField{nullptr}; + + // params + std::array mcPosXYZEtaTglPtProp{}; + std::array mcEleXYZEtaTglPtProp{}; + std::array mcMotherXYZEtaTglPtProp{}; + + // Track Types + static constexpr std::array v0Types{"ITSTPC_ITSTPC/", "TPConly_TPConly/", "ITSonly_ITSonly/", "ITSTPC_TPConly/", "ITSTPC_ITSonly/", "TPConly_ITSonly/"}; + std::array v0TypesPassed{}; + static constexpr std::array cuts{"lowPt/", "highPt/", "zReco43/", "all/"}; + + void init(InitContext const& /*unused*/) + { + // setup CCDB + mCCDB->setURL(mCCDBUrl); + mCCDB->setCaching(true); + mCCDB->setLocalObjectValidityChecking(); + mLUT = o2::base::MatLayerCylSet::rectifyPtrFromFile(mCCDB->get(mLUTPath)); + + // maybe logarithmic + if (ptLogAxis) { + axisPt.makeLogarithmic(); + axisPtPos.makeLogarithmic(); + axisPtEle.makeLogarithmic(); + } + + // Create histograms + for (const auto& v0type : v0Types) { + for (const auto& cut : cuts) { + const auto path = Form("%s%s", v0type.data(), cut.data()); + registry.add(Form("%sTglTgl", path), "tan(#lambda) vs. tan(#lambda)", HistType::kTH2F, {axisTglPos, axisTglEle}); + registry.add(Form("%sPtPt", path), "p_{T} vs. p_{T}", HistType::kTH2F, {axisPtPos, axisPtEle}); + registry.add(Form("%sXX", path), "x vs. x", HistType::kTH2F, {axisXPos, axisXEle}); + registry.add(Form("%sYY", path), "y vs. y", HistType::kTH2F, {axisYPos, axisYEle}); + registry.add(Form("%sZZ", path), "z vs. z", HistType::kTH2F, {axisZPos, axisZEle}); + registry.add(Form("%sZPt", path), "z vs. p_{T}", HistType::kTH2F, {axisZ, axisPt}); + registry.add(Form("%sZTgl", path), "z vs. tan(#lambda)", HistType::kTH2F, {axisZ, axisTgl}); + registry.add(Form("%sPtTgl", path), "p_{T} vs. tan(#lambda)", HistType::kTH2F, {axisPt, axisTgl}); + registry.add(Form("%sTT", path), "est. Time vs. Time", HistType::kTH2F, {axisTPos, axisTEle}); + registry.add(Form("%sMC/XX", path), Form("MC x vs. reconstructed x (ptLowCut=%.2f)", ptLowCut.value), HistType::kTH2F, {axisXMC, axisX}); + registry.add(Form("%sMC/YY", path), Form("MC y vs. rconstructed y (ptLowCut=%.2f)", ptLowCut.value), HistType::kTH2F, {axisYMC, axisY}); + registry.add(Form("%sMC/ZZ", path), Form("MC z vs. reconstructed z (ptLowCut=%.2f)", ptLowCut.value), HistType::kTH2F, {axisZMC, axisZ}); + registry.add(Form("%sMC/VertexPropagationX", path), Form("MC vertex X propagated to track (ptLowCut=%.2f)", ptLowCut.value), HistType::kTH2F, {{axisXMCPos, axisXMCEle}}); + registry.add(Form("%sMC/VertexPropagationY", path), Form("MC vertex Y propagated to track (ptLowCut=%.2f)", ptLowCut.value), HistType::kTH2F, {{axisYMCPos, axisYMCEle}}); + registry.add(Form("%sMC/VertexPropagationZ", path), Form("MC vertex Z propagated to track (ptLowCut=%.2f)", ptLowCut.value), HistType::kTH2F, {{axisZMCPos, axisZMCEle}}); + } + } + + registry.add("V0Counter", "V0 counter", HistType::kTH1F, {{cutsBinLabels.size(), 0.5, 0.5 + cutsBinLabels.size()}}); + for (int iBin = 0; iBin < cutsBinLabels.size(); ++iBin) { + registry.get(HIST("V0Counter"))->GetXaxis()->SetBinLabel(iBin + 1, cutsBinLabels[iBin].data()); + } + + registry.add("V0TypeCounter", "V0 Type counter", HistType::kTH1F, {{v0Types.size(), 0.5, 0.5 + v0Types.size()}}); + for (int iBin = 0; iBin < v0Types.size(); ++iBin) { + registry.get(HIST("V0TypeCounter"))->GetXaxis()->SetBinLabel(iBin + 1, v0Types[iBin].data()); + } + + registry.add("CheckV0Leg", "CheckV0Leg", HistType::kTH1F, {{checkV0legLabels.size(), 0.5, 0.5 + checkV0legLabels.size()}}); + for (int iBin = 0; iBin < checkV0legLabels.size(); ++iBin) { + registry.get(HIST("CheckV0Leg"))->GetXaxis()->SetBinLabel(iBin + 1, checkV0legLabels[iBin].data()); + } + } + + void processMCV0(CollisionsMC const& collisions, aod::V0s const& v0s, FilteredTracksMC const& /*unused*/, aod::McParticles const& /*unused*/, aod::McCollisions const& /*unused*/, aod::BCsWithTimestamps const& /*unused*/) + { + // Check for new ccdb parameters + const auto bc = collisions.begin().bc_as(); + initCCDB(bc); + + // loop over all true photon pairs + for (const auto& v0 : v0s) { + registry.fill(HIST("V0Counter"), cutsBinEnum::PRE); + + // tracks + const auto& pos = v0.template posTrack_as(); // positive daughter + const auto& ele = v0.template negTrack_as(); // negative daughter + if (!checkV0leg(pos) || !checkV0leg(ele)) { + registry.fill(HIST("V0Counter"), cutsBinEnum::CHECKV0LEG); + continue; + } + + // set correct track types + checkPassed(pos, ele); + + if (cutSign && (std::signbit(pos.sign()) || !std::signbit(ele.sign()))) { // wrong sign and same sign reject (e.g. loopers) + registry.fill(HIST("V0Counter"), cutsBinEnum::SIGN); + continue; + } + if (cutSameSign && (pos.sign() * ele.sign() > 0)) { + registry.fill(HIST("V0Counter"), cutsBinEnum::SAMESIGN); + continue; + } + const auto& posMC = pos.template mcParticle_as(); + const auto& eleMC = ele.template mcParticle_as(); + if (!checkMCParticles(posMC, eleMC)) { + registry.fill(HIST("V0Counter"), cutsBinEnum::PHOTON); + continue; + } + const auto& mother = posMC.mothers_first_as(); + + // Propagate the vertex position of the MC track to the reconstructed vertex position of the track + if (!recacluateMCVertex(ele, eleMC, mcEleXYZEtaTglPtProp) || !recacluateMCVertex(pos, posMC, mcPosXYZEtaTglPtProp)) { + registry.fill(HIST("V0Counter"), cutsBinEnum::PROPFAIL); + continue; + } + registry.fill(HIST("V0Counter"), SURVIVED); + + static_for<0, v0Types.size() - 1>([&](auto i) { + static_for<0, cuts.size() - 1>([&](auto j) { + fillHistograms(pos, ele); + }); + }); + + mcV0Table( + // Track Pos + pos.pt(), pos.eta(), pos.tgl(), pos.x(), pos.y(), pos.z(), pos.trackTime(), pos.sign(), + pos.hasITS(), pos.hasTPC(), pos.hasTRD(), pos.hasTOF(), + // Track Ele + ele.pt(), ele.eta(), ele.tgl(), ele.x(), ele.y(), ele.z(), ele.trackTime(), ele.sign(), + ele.hasITS(), ele.hasTPC(), ele.hasTRD(), ele.hasTOF(), + // MC particle Pos + posMC.pt(), posMC.eta(), posMC.vx(), posMC.vy(), posMC.vz(), + // MC particle Ele + eleMC.pt(), eleMC.eta(), eleMC.vx(), eleMC.vy(), eleMC.vz(), + // Propagated MC pos + mcPosXYZEtaTglPtProp[0], mcPosXYZEtaTglPtProp[1], mcPosXYZEtaTglPtProp[2], + mcPosXYZEtaTglPtProp[3], mcPosXYZEtaTglPtProp[4], mcPosXYZEtaTglPtProp[5], + // Propagated MC ele + mcEleXYZEtaTglPtProp[0], mcEleXYZEtaTglPtProp[1], mcEleXYZEtaTglPtProp[2], + mcEleXYZEtaTglPtProp[3], mcEleXYZEtaTglPtProp[4], mcEleXYZEtaTglPtProp[5], + // MC mother particle + mother.isPhysicalPrimary(), mother.producedByGenerator(), mother.pt(), mother.eta(), + mother.vx(), mother.vy(), mother.vz(), + // MC Primary Vertex + mother.vx(), mother.vy(), mother.vz(), + // TrackType + std::distance(v0TypesPassed.cbegin(), std::find(v0TypesPassed.cbegin(), v0TypesPassed.cend(), true))); + } + } + PROCESS_SWITCH(CheckMCV0, processMCV0, "process reconstructed MC V0 info", true); + + template + inline void fillHistograms(TTrack const& pos, TTrack const& ele) + { + constexpr auto hist = HIST(v0Types[idxV0Type]) + HIST(cuts[idxCut]); + + if (!v0TypesPassed[idxV0Type]) { + return; + } + + if constexpr (idxCut == 0) { // lowPt + if (pos.pt() > ptLowCut && ele.pt() > ptLowCut) { + return; + } + } else if constexpr (idxCut == 1) { // highPt + if (pos.pt() < ptLowCut && ele.pt() < ptLowCut) { + return; + } + } else if constexpr (idxCut == 2) { + if (!(abs(pos.z()) > 38.f && abs(pos.z()) < 46.f) && !(abs(ele.z()) > 38.f && abs(ele.z()) < 46.f)) { + return; + } + } + + registry.fill(hist + HIST("TglTgl"), pos.tgl(), ele.tgl()); + registry.fill(hist + HIST("PtPt"), pos.pt(), ele.pt()); + registry.fill(hist + HIST("XX"), pos.x(), ele.x()); + registry.fill(hist + HIST("YY"), pos.y(), ele.y()); + registry.fill(hist + HIST("ZZ"), pos.z(), ele.z()); + registry.fill(hist + HIST("ZPt"), pos.z(), pos.pt()); + registry.fill(hist + HIST("ZPt"), ele.z(), ele.pt()); + registry.fill(hist + HIST("ZTgl"), pos.z(), pos.tgl()); + registry.fill(hist + HIST("ZTgl"), ele.z(), ele.tgl()); + registry.fill(hist + HIST("PtTgl"), pos.pt(), pos.tgl()); + registry.fill(hist + HIST("PtTgl"), ele.pt(), ele.tgl()); + registry.fill(hist + HIST("TT"), pos.trackTime(), ele.trackTime()); + if constexpr (idxCut == 0) { + if (pos.pt() < ptLowCut || ele.pt() < ptLowCut) { + registry.fill(HIST("V0Counter"), cutsBinEnum::LOWPT); + } + if (pos.pt() < ptLowCut) { + registry.fill(hist + HIST("MC/") + HIST("XX"), mcPosXYZEtaTglPtProp[0], pos.x()); + registry.fill(hist + HIST("MC/") + HIST("YY"), mcPosXYZEtaTglPtProp[1], pos.y()); + registry.fill(hist + HIST("MC/") + HIST("ZZ"), mcPosXYZEtaTglPtProp[2], pos.z()); + } + if (ele.pt() < ptLowCut) { + registry.fill(hist + HIST("MC/") + HIST("XX"), mcEleXYZEtaTglPtProp[0], ele.x()); + registry.fill(hist + HIST("MC/") + HIST("YY"), mcEleXYZEtaTglPtProp[1], ele.y()); + registry.fill(hist + HIST("MC/") + HIST("ZZ"), mcEleXYZEtaTglPtProp[2], ele.z()); + } + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationX"), mcPosXYZEtaTglPtProp[0], mcEleXYZEtaTglPtProp[0]); + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationY"), mcPosXYZEtaTglPtProp[1], mcEleXYZEtaTglPtProp[1]); + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationZ"), mcPosXYZEtaTglPtProp[2], mcEleXYZEtaTglPtProp[2]); + } else if constexpr (idxCut == 1) { + if (pos.pt() > ptLowCut || ele.pt() > ptLowCut) { + registry.fill(HIST("V0Counter"), cutsBinEnum::HIGHPT); + } + if (pos.pt() > ptLowCut) { + registry.fill(hist + HIST("MC/") + HIST("XX"), mcPosXYZEtaTglPtProp[0], pos.x()); + registry.fill(hist + HIST("MC/") + HIST("YY"), mcPosXYZEtaTglPtProp[1], pos.y()); + registry.fill(hist + HIST("MC/") + HIST("ZZ"), mcPosXYZEtaTglPtProp[2], pos.z()); + } + if (ele.pt() > ptLowCut) { + registry.fill(hist + HIST("MC/") + HIST("XX"), mcEleXYZEtaTglPtProp[0], ele.x()); + registry.fill(hist + HIST("MC/") + HIST("YY"), mcEleXYZEtaTglPtProp[1], ele.y()); + registry.fill(hist + HIST("MC/") + HIST("ZZ"), mcEleXYZEtaTglPtProp[2], ele.z()); + } + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationX"), mcPosXYZEtaTglPtProp[0], mcEleXYZEtaTglPtProp[0]); + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationY"), mcPosXYZEtaTglPtProp[1], mcEleXYZEtaTglPtProp[1]); + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationZ"), mcPosXYZEtaTglPtProp[2], mcEleXYZEtaTglPtProp[2]); + } else { + registry.fill(hist + HIST("MC/") + HIST("XX"), mcPosXYZEtaTglPtProp[0], pos.x()); + registry.fill(hist + HIST("MC/") + HIST("YY"), mcPosXYZEtaTglPtProp[1], pos.y()); + registry.fill(hist + HIST("MC/") + HIST("ZZ"), mcPosXYZEtaTglPtProp[2], pos.z()); + registry.fill(hist + HIST("MC/") + HIST("XX"), mcEleXYZEtaTglPtProp[0], ele.x()); + registry.fill(hist + HIST("MC/") + HIST("YY"), mcEleXYZEtaTglPtProp[1], ele.y()); + registry.fill(hist + HIST("MC/") + HIST("ZZ"), mcEleXYZEtaTglPtProp[2], ele.z()); + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationX"), mcPosXYZEtaTglPtProp[0], mcEleXYZEtaTglPtProp[0]); + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationY"), mcPosXYZEtaTglPtProp[1], mcEleXYZEtaTglPtProp[1]); + registry.fill(hist + HIST("MC/") + HIST("VertexPropagationZ"), mcPosXYZEtaTglPtProp[2], mcEleXYZEtaTglPtProp[2]); + } + } + + // Templates + template + inline bool checkV0leg(TTrack const& track) + { + if (track.pt() < minpt) { + registry.fill(HIST("CheckV0Leg"), checkV0legEnum::PTMIN); + return false; + } + if (track.pt() > maxpt) { + registry.fill(HIST("CheckV0Leg"), checkV0legEnum::PTMAX); + return false; + } + if (!track.hasITS() && !track.hasTPC()) { + registry.fill(HIST("CheckV0Leg"), checkV0legEnum::NOITSTPC); + return false; + } + if (abs(track.eta()) > maxeta) { + registry.fill(HIST("CheckV0Leg"), checkV0legEnum::MAXETA); + return false; + } + if (abs(track.dcaXY()) < dcamin) { + registry.fill(HIST("CheckV0Leg"), checkV0legEnum::DCAMIN); + return false; + } + if (abs(track.dcaXY()) > dcamax) { + registry.fill(HIST("CheckV0Leg"), checkV0legEnum::DCAMAX); + return false; + } + if (track.tpcChi2NCl() > maxChi2TPC) { + registry.fill(HIST("CheckV0Leg"), checkV0legEnum::TPCCHI2NCL); + return false; + } + if (track.tpcNClsCrossedRows() < minCrossedRowsTPC) { + registry.fill(HIST("CheckV0Leg"), checkV0legEnum::MINCROSSEDROWSTPC); + return false; + } + if (track.trackTimeRes() <= o2::constants::lhc::LHCBunchSpacingNS) { + return false; + } + return true; + } + + template + inline void checkPassed(TTrack const& track0, TTrack const& track1) + { + v0TypesPassed.fill(false); // reset + v0TypesPassed[0] = isITSTPC_ITSTPC(track0, track1); + v0TypesPassed[1] = isTPConly_TPConly(track0, track1); + v0TypesPassed[2] = isITSonly_ITSonly(track0, track1); + v0TypesPassed[3] = isITSTPC_TPConly(track0, track1); + v0TypesPassed[4] = isITSTPC_ITSonly(track0, track1); + v0TypesPassed[5] = isTPConly_ITSonly(track0, track1); + for (int i = 0; i < v0TypesPassed.size(); ++i) { + if (v0TypesPassed[i]) { + registry.fill(HIST("V0TypeCounter"), i + 1); + } + } + } + + template + inline bool recacluateMCVertex(TTrack const& track, MCTrack const& mcTrack, std::array& xyzEtaTglPt) + { + std::array xyzMC{mcTrack.vx(), mcTrack.vy(), mcTrack.vz()}; + std::array pxyzMC{mcTrack.px(), mcTrack.py(), mcTrack.pz()}; + auto pPDG = TDatabasePDG::Instance()->GetParticle(mcTrack.pdgCode()); + if (!pPDG) { + return false; + } + o2::track::TrackPar mctrO2(xyzMC, pxyzMC, TMath::Nint(pPDG->Charge() / 3), false); + // rotate track into padplane of detector and then propagate to corresponding x of track + if (!mctrO2.rotate(track.alpha()) || !o2::base::Propagator::Instance()->PropagateToXBxByBz(mctrO2, track.x())) { + return false; + } + xyzEtaTglPt = {mctrO2.getX(), mctrO2.getY(), mctrO2.getZ(), mctrO2.getEta(), mctrO2.getTgl(), mctrO2.getPt()}; + return true; + } + + template + inline void initCCDB(BC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mGRPMagField = mCCDB->getForTimeStamp(mGRPMagPath, bc.timestamp()); + o2::base::Propagator::initFieldFromGRP(mGRPMagField); + o2::base::Propagator::Instance()->setMatLUT(mLUT); + mRunNumber = bc.runNumber(); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"check-mc-v0"})}; +} diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx new file mode 100644 index 00000000000..937f59fbc82 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx @@ -0,0 +1,419 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code loops over v0 photons for studying material budget. +// Please write to: daiki.sekihata@cern.ch + +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/RecoDecay.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/Core/PairCut.h" +#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::photonpair; + +using MyV0Photons = soa::Join; +using MyV0Photon = MyV0Photons::iterator; + +struct MaterialBudget { + + Configurable CentMin{"CentMin", -1, "min. centrality"}; + Configurable CentMax{"CentMax", 999, "max. centrality"}; + Configurable CentEstimator{"CentEstimator", "FT0M", "centrality estimator"}; + + Configurable fConfigTagPCMCuts{"cfgTagPCMCuts", "qc_ITSTPC", "Comma separated list of V0 photon cuts for tag"}; + Configurable fConfigProbePCMCuts{"cfgProbePCMCuts", "qc_ITSTPC,qc_TPConly,qc_ITSonly", "Comma separated list of V0 photon cuts for probe"}; + Configurable fConfigPairCuts{"cfgPairCuts", "nocut", "Comma separated list of pair cuts"}; + Configurable fDoMixing{"DoMixing", false, "do event mixing"}; + + OutputObj fOutputEvent{"Event"}; + OutputObj fOutputV0{"V0"}; + OutputObj fOutputPair{"Pair"}; // 2-photon pair + THashList* fMainList = new THashList(); + + std::vector fTagPCMCuts; + std::vector fProbePCMCuts; + std::vector fPairCuts; + + std::vector fPairNames; + void init(InitContext& context) + { + if (context.mOptions.get("processMB")) { + fPairNames.push_back("PCMPCM"); + } + + DefineTagPCMCuts(); + DefineProbePCMCuts(); + DefinePairCuts(); + addhistograms(); + + fOutputEvent.setObject(reinterpret_cast(fMainList->FindObject("Event"))); + fOutputV0.setObject(reinterpret_cast(fMainList->FindObject("V0"))); + fOutputPair.setObject(reinterpret_cast(fMainList->FindObject("Pair"))); + } + + template + void add_pair_histograms(THashList* list_pair, const std::string pairname, TCuts1 const& cuts1, TCuts2 const& cuts2, TCuts3 const& cuts3) + { + for (auto& cut1 : cuts1) { + for (auto& cut2 : cuts2) { + std::string cutname1 = cut1.GetName(); + std::string cutname2 = cut2.GetName(); + + // if (cutname1 == cutname2) { + // continue; + // } + + THashList* list_pair_subsys = reinterpret_cast(list_pair->FindObject(pairname.data())); + std::string photon_cut_name = cutname1 + "_" + cutname2; + o2::aod::emphotonhistograms::AddHistClass(list_pair_subsys, photon_cut_name.data()); + THashList* list_pair_subsys_photoncut = reinterpret_cast(list_pair_subsys->FindObject(photon_cut_name.data())); + + for (auto& cut3 : cuts3) { + std::string pair_cut_name = cut3.GetName(); + o2::aod::emphotonhistograms::AddHistClass(list_pair_subsys_photoncut, pair_cut_name.data()); + THashList* list_pair_subsys_paircut = reinterpret_cast(list_pair_subsys_photoncut->FindObject(pair_cut_name.data())); + o2::aod::emphotonhistograms::DefineHistograms(list_pair_subsys_paircut, "material_budget_study", "Pair"); + } // end of cut3 loop pair cut + } // end of cut2 loop + } // end of cut1 loop + } + + static constexpr std::string_view pairnames[6] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PHOSEMC"}; + void addhistograms() + { + fMainList->SetOwner(true); + fMainList->SetName("fMainList"); + + // create sub lists first. + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Event"); + THashList* list_ev = reinterpret_cast(fMainList->FindObject("Event")); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Pair"); + THashList* list_pair = reinterpret_cast(fMainList->FindObject("Pair")); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "V0"); + THashList* list_v0 = reinterpret_cast(fMainList->FindObject("V0")); + + // for V0s + for (const auto& cut : fProbePCMCuts) { + const char* cutname = cut.GetName(); + THashList* list_v0_cut = o2::aod::emphotonhistograms::AddHistClass(list_v0, cutname); + o2::aod::emphotonhistograms::DefineHistograms(list_v0_cut, "material_budget_study", "V0"); + } + + for (auto& pairname : fPairNames) { + LOGF(info, "Enabled pairs = %s", pairname.data()); + + o2::aod::emphotonhistograms::AddHistClass(list_ev, pairname.data()); + THashList* list_ev_pair = reinterpret_cast(list_ev->FindObject(pairname.data())); + o2::aod::emphotonhistograms::DefineHistograms(list_ev_pair, "Event"); + + o2::aod::emphotonhistograms::AddHistClass(list_pair, pairname.data()); + + if (pairname == "PCMPCM") { + add_pair_histograms(list_pair, pairname, fTagPCMCuts, fProbePCMCuts, fPairCuts); + } + + } // end of pair name loop + } + + void DefineTagPCMCuts() + { + TString cutNamesStr = fConfigTagPCMCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fTagPCMCuts.push_back(*pcmcuts::GetCut(cutname)); + } + } + LOGF(info, "Number of Tag PCM cuts = %d", fTagPCMCuts.size()); + } + + void DefineProbePCMCuts() + { + TString cutNamesStr = fConfigProbePCMCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fProbePCMCuts.push_back(*pcmcuts::GetCut(cutname)); + } + } + LOGF(info, "Number of Probe PCM cuts = %d", fProbePCMCuts.size()); + } + + void DefinePairCuts() + { + TString cutNamesStr = fConfigPairCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fPairCuts.push_back(*paircuts::GetCut(cutname)); + } + } + LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); + } + + Preslice perCollision_pcm = aod::v0photonkf::emreducedeventId; + + template + bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2) + { + // bool is_selected_pair = false; + // return is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + return o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + } + + template + void fillsinglephoton(TEvents const& collisions, TPhotons const& photons, TPreslice const& perCollision, TCuts const& cuts, TLegs const& legs) + { + THashList* list_v0 = static_cast(fMainList->FindObject("V0")); + double value[4] = {0.f}; + for (auto& collision : collisions) { + if (!collision.sel8()) { + continue; + } + if (collision.numContrib() < 0.5) { + continue; + } + if (abs(collision.posZ()) > 10.0) { + continue; + } + + auto photons_coll = photons.sliceBy(perCollision, collision.collisionId()); + for (auto& cut : cuts) { + for (auto& photon : photons_coll) { + + if (!cut.template IsSelected(photon)) { + continue; + } + + float phi_cp = atan2(photon.recalculatedVtxY(), photon.recalculatedVtxX()); + float eta_cp = std::atanh(photon.recalculatedVtxZ() / sqrt(pow(photon.recalculatedVtxX(), 2) + pow(photon.recalculatedVtxY(), 2) + pow(photon.recalculatedVtxZ(), 2))); + value[0] = photon.pt(); + value[1] = photon.recalculatedVtxR(); + value[2] = phi_cp > 0 ? phi_cp : phi_cp + TMath::TwoPi(); + value[3] = eta_cp; + reinterpret_cast(list_v0->FindObject(cut.GetName())->FindObject("hs_conv_point"))->Fill(value); + + } // end of photon loop + } // end of cut loop + + } // end of collision loop + } + + template + void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs) + { + THashList* list_ev_pair = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())); + THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); + + for (auto& collision : collisions) { + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hZvtx_before"))->Fill(collision.posZ()); + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(1.0); // all + if (!collision.sel8()) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(2.0); // FT0VX i.e. FT0and + + if (collision.numContrib() < 0.5) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(3.0); // Ncontrib > 0 + + if (abs(collision.posZ()) > 10.0) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hZvtx_after"))->Fill(collision.posZ()); + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(4.0); // |Zvtx| < 10 cm + + o2::aod::emphotonhistograms::FillHistClass(list_ev_pair, "", collision); + + auto photons1_coll = photons1.sliceBy(perCollision1, collision.collisionId()); + auto photons2_coll = photons2.sliceBy(perCollision2, collision.collisionId()); + + double value[9] = {0.f}; + float phi_cp1 = 0.f, eta_cp1 = 0.f; + float phi_cp2 = 0.f, eta_cp2 = 0.f; + for (auto& cut1 : cuts1) { + for (auto& cut2 : cuts2) { + // if (std::string(cut1.GetName()) == std::string(cut2.GetName())) { + // continue; + // } + for (auto& g1 : photons1_coll) { + for (auto& g2 : photons2_coll) { + if (g1.globalIndex() == g2.globalIndex()) { + continue; + } + if (!IsSelectedPair(g1, g2, cut1, cut2)) { + continue; + } + for (auto& paircut : paircuts) { + + if (!paircut.IsSelected(g1, g2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // tag + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // probe + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + phi_cp1 = atan2(g1.recalculatedVtxY(), g1.recalculatedVtxX()); + eta_cp1 = std::atanh(g1.recalculatedVtxZ() / sqrt(pow(g1.recalculatedVtxX(), 2) + pow(g1.recalculatedVtxY(), 2) + pow(g1.recalculatedVtxZ(), 2))); + phi_cp2 = atan2(g2.recalculatedVtxY(), g2.recalculatedVtxX()); + eta_cp2 = std::atanh(g2.recalculatedVtxZ() / sqrt(pow(g2.recalculatedVtxX(), 2) + pow(g2.recalculatedVtxY(), 2) + pow(g2.recalculatedVtxZ(), 2))); + value[0] = v12.M(); + value[1] = g1.pt(); + value[2] = g1.recalculatedVtxR(); + value[3] = phi_cp1 > 0.f ? phi_cp1 : phi_cp1 + TMath::TwoPi(); + value[4] = eta_cp1; + value[5] = g2.pt(); + value[6] = g2.recalculatedVtxR(); + value[7] = phi_cp2 > 0.f ? phi_cp2 : phi_cp2 + TMath::TwoPi(); + value[8] = eta_cp2; + + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hs_conv_point_same"))->Fill(value); + + } // end of pair cut loop + } // end of g2 loop + } // end of g1 loop + } // end of cut2 loop + } // end of cut1 loop + } // end of collision loop + } + + Configurable ndepth{"ndepth", 5, "depth for event mixing"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis ConfMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 1e+10f}, "Mixing bins - multiplicity"}; + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{ConfVtxBins, ConfMultBins}, true}; + + template + void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs) + { + THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); + // LOGF(info, "Number of collisions after filtering: %d", collisions.size()); + for (auto& [collision1, collision2] : soa::selfCombinations(colBinning, ndepth, -1, collisions, collisions)) { // internally, CombinationsStrictlyUpperIndexPolicy(collisions, collisions) is called. + + // LOGF(info, "Mixed event collisionId: (%d, %d) , ngpcm: (%d, %d), ngphos: (%d, %d), ngemc: (%d, %d)", + // collision1.collisionId(), collision2.collisionId(), collision1.ngpcm(), collision2.ngpcm(), collision1.ngphos(), collision2.ngphos(), collision1.ngemc(), collision2.ngemc()); + + auto photons_coll1 = photons1.sliceBy(perCollision1, collision1.collisionId()); + auto photons_coll2 = photons2.sliceBy(perCollision2, collision2.collisionId()); + // LOGF(info, "collision1: posZ = %f, numContrib = %d , sel8 = %d | collision2: posZ = %f, numContrib = %d , sel8 = %d", + // collision1.posZ(), collision1.numContrib(), collision1.sel8(), collision2.posZ(), collision2.numContrib(), collision2.sel8()); + + double value[9] = {0.f}; + float phi_cp1 = 0.f, eta_cp1 = 0.f; + float phi_cp2 = 0.f, eta_cp2 = 0.f; + for (auto& cut1 : cuts1) { + for (auto& cut2 : cuts2) { + // if (std::string(cut1.GetName()) == std::string(cut2.GetName())) { + // continue; + // } + for (auto& g1 : photons_coll1) { + for (auto& g2 : photons_coll2) { + if (g1.globalIndex() == g2.globalIndex()) { + continue; + } + if (!IsSelectedPair(g1, g2, cut1, cut2)) { + continue; + } + // LOGF(info, "Mixed event photon pair: (%d, %d) from events (%d, %d), photon event: (%d, %d)", g1.index(), g2.index(), collision1.index(), collision2.index(), g1.collisionId(), g2.collisionId()); + + for (auto& paircut : paircuts) { + + if (!paircut.IsSelected(g1, g2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // tag + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // probe + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + phi_cp1 = atan2(g1.recalculatedVtxY(), g1.recalculatedVtxX()); + eta_cp1 = std::atanh(g1.recalculatedVtxZ() / sqrt(pow(g1.recalculatedVtxX(), 2) + pow(g1.recalculatedVtxY(), 2) + pow(g1.recalculatedVtxZ(), 2))); + phi_cp2 = atan2(g2.recalculatedVtxY(), g2.recalculatedVtxX()); + eta_cp2 = std::atanh(g2.recalculatedVtxZ() / sqrt(pow(g2.recalculatedVtxX(), 2) + pow(g2.recalculatedVtxY(), 2) + pow(g2.recalculatedVtxZ(), 2))); + value[0] = v12.M(); + value[1] = g1.pt(); + value[2] = g1.recalculatedVtxR(); + value[3] = phi_cp1 > 0.f ? phi_cp1 : phi_cp1 + TMath::TwoPi(); + value[4] = eta_cp1; + value[5] = g2.pt(); + value[6] = g2.recalculatedVtxR(); + value[7] = phi_cp2 > 0.f ? phi_cp2 : phi_cp2 + TMath::TwoPi(); + value[8] = eta_cp2; + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hs_conv_point_mix"))->Fill(value); + + } // end of pair cut loop + } // end of g2 loop + } // end of g1 loop + } // end of cut2 loop + } // end of cut1 loop + } // end of different collision combinations + } + + Partition grouped_collisions = CentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < CentMax; // this goes to same event. + Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true && CentMin < o2::aod::cent::centFT0M&& o2::aod::cent::centFT0M < CentMax; + Filter collisionFilter_subsys = o2::aod::emreducedevent::ngpcm >= 1; + using MyFilteredCollisions = soa::Filtered; // this goes to mixed event. + + void processMB(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) + { + fillsinglephoton(grouped_collisions, v0photons, perCollision_pcm, fProbePCMCuts, legs); + SameEventPairing(grouped_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fTagPCMCuts, fProbePCMCuts, fPairCuts, legs); + if (fDoMixing) { + MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fTagPCMCuts, fProbePCMCuts, fPairCuts, legs); + } + } + + void processDummy(aod::EMReducedEvents::iterator const& collision) + { + // do nothing + } + + PROCESS_SWITCH(MaterialBudget, processMB, "process material budget", false); + PROCESS_SWITCH(MaterialBudget, processDummy, "Dummy function", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"material-budget"})}; +} diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx new file mode 100644 index 00000000000..58e3fa6135d --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx @@ -0,0 +1,462 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code loops over v0 photons for studying material budget. +// Please write to: daiki.sekihata@cern.ch + +#include +#include + +#include "TString.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/RecoDecay.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/Core/PairCut.h" +#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::photonpair; + +using MyV0Photons = soa::Join; +using MyV0Photon = MyV0Photons::iterator; + +struct MaterialBudgetMC { + using MyMCV0Legs = soa::Join; + + Configurable CentMin{"CentMin", -1, "min. centrality"}; + Configurable CentMax{"CentMax", 999, "max. centrality"}; + Configurable CentEstimator{"CentEstimator", "FT0M", "centrality estimator"}; + + Configurable maxY{"maxY", 999.f, "maximum rapidity for generated particles"}; + Configurable fConfigTagPCMCuts{"cfgTagPCMCuts", "qc_ITSTPC", "Comma separated list of V0 photon cuts for tag"}; + Configurable fConfigProbePCMCuts{"cfgProbePCMCuts", "qc_ITSTPC,qc_TPConly,qc_ITSonly", "Comma separated list of V0 photon cuts for probe"}; + Configurable fConfigPairCuts{"cfgPairCuts", "nocut", "Comma separated list of pair cuts"}; + + OutputObj fOutputEvent{"Event"}; + OutputObj fOutputV0{"V0"}; + OutputObj fOutputPair{"Pair"}; // 2-photon pair + OutputObj fOutputGen{"Generated"}; + THashList* fMainList = new THashList(); + + std::vector fTagPCMCuts; + std::vector fProbePCMCuts; + std::vector fPairCuts; + + std::vector fPairNames; + void init(InitContext& context) + { + if (context.mOptions.get("processMBMC")) { + fPairNames.push_back("PCMPCM"); + } + + DefineTagPCMCuts(); + DefineProbePCMCuts(); + DefinePairCuts(); + addhistograms(); + + fOutputEvent.setObject(reinterpret_cast(fMainList->FindObject("Event"))); + fOutputV0.setObject(reinterpret_cast(fMainList->FindObject("V0"))); + fOutputPair.setObject(reinterpret_cast(fMainList->FindObject("Pair"))); + fOutputGen.setObject(reinterpret_cast(fMainList->FindObject("Generated"))); + } + + template + void add_pair_histograms(THashList* list_pair, const std::string pairname, TCuts1 const& cuts1, TCuts2 const& cuts2, TCuts3 const& cuts3) + { + for (auto& cut1 : cuts1) { + for (auto& cut2 : cuts2) { + std::string cutname1 = cut1.GetName(); + std::string cutname2 = cut2.GetName(); + + // if (cutname1 == cutname2) { + // continue; + // } + + THashList* list_pair_subsys = reinterpret_cast(list_pair->FindObject(pairname.data())); + std::string photon_cut_name = cutname1 + "_" + cutname2; + o2::aod::emphotonhistograms::AddHistClass(list_pair_subsys, photon_cut_name.data()); + THashList* list_pair_subsys_photoncut = reinterpret_cast(list_pair_subsys->FindObject(photon_cut_name.data())); + + for (auto& cut3 : cuts3) { + std::string pair_cut_name = cut3.GetName(); + o2::aod::emphotonhistograms::AddHistClass(list_pair_subsys_photoncut, pair_cut_name.data()); + THashList* list_pair_subsys_paircut = reinterpret_cast(list_pair_subsys_photoncut->FindObject(pair_cut_name.data())); + o2::aod::emphotonhistograms::DefineHistograms(list_pair_subsys_paircut, "material_budget_study", "Pair"); + } // end of cut3 loop pair cut + } // end of cut2 loop + } // end of cut1 loop + } + + static constexpr std::string_view pairnames[6] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PHOSEMC"}; + void addhistograms() + { + fMainList->SetOwner(true); + fMainList->SetName("fMainList"); + + // create sub lists first. + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Event"); + THashList* list_ev = reinterpret_cast(fMainList->FindObject("Event")); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Pair"); + THashList* list_pair = reinterpret_cast(fMainList->FindObject("Pair")); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "V0"); + THashList* list_v0 = reinterpret_cast(fMainList->FindObject("V0")); + + // for V0s + for (const auto& cut : fProbePCMCuts) { + const char* cutname = cut.GetName(); + THashList* list_v0_cut = o2::aod::emphotonhistograms::AddHistClass(list_v0, cutname); + o2::aod::emphotonhistograms::DefineHistograms(list_v0_cut, "material_budget_study", "V0"); + } + + for (auto& pairname : fPairNames) { + LOGF(info, "Enabled pairs = %s", pairname.data()); + + o2::aod::emphotonhistograms::AddHistClass(list_ev, pairname.data()); + THashList* list_ev_pair = reinterpret_cast(list_ev->FindObject(pairname.data())); + o2::aod::emphotonhistograms::DefineHistograms(list_ev_pair, "Event"); + + o2::aod::emphotonhistograms::AddHistClass(list_pair, pairname.data()); + + if (pairname == "PCMPCM") { + add_pair_histograms(list_pair, pairname, fTagPCMCuts, fProbePCMCuts, fPairCuts); + } + + } // end of pair name loop + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Generated"); + THashList* list_gen = reinterpret_cast(fMainList->FindObject("Generated")); + o2::aod::emphotonhistograms::DefineHistograms(list_gen, "Generated", "Photon"); + o2::aod::emphotonhistograms::DefineHistograms(list_gen, "Generated", "ConversionStudy"); + } + + void DefineTagPCMCuts() + { + TString cutNamesStr = fConfigTagPCMCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fTagPCMCuts.push_back(*pcmcuts::GetCut(cutname)); + } + } + LOGF(info, "Number of Tag PCM cuts = %d", fTagPCMCuts.size()); + } + + void DefineProbePCMCuts() + { + TString cutNamesStr = fConfigProbePCMCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fProbePCMCuts.push_back(*pcmcuts::GetCut(cutname)); + } + } + LOGF(info, "Number of Probe PCM cuts = %d", fProbePCMCuts.size()); + } + + void DefinePairCuts() + { + TString cutNamesStr = fConfigPairCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fPairCuts.push_back(*paircuts::GetCut(cutname)); + } + } + LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); + } + + Preslice perCollision_pcm = aod::v0photonkf::emreducedeventId; + + template + bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2) + { + return o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + } + + template + void fillsinglephoton(TEvents const& collisions, TPhotons const& photons, TPreslice const& perCollision, TCuts const& cuts, TLegs const& legs, TMCParticles const& mcparticles, TMCEvents const&) + { + THashList* list_v0 = static_cast(fMainList->FindObject("V0")); + double value[4] = {0.f}; + for (auto& collision : collisions) { + if (!collision.sel8()) { + continue; + } + if (collision.numContrib() < 0.5) { + continue; + } + if (abs(collision.posZ()) > 10.0) { + continue; + } + + auto photons_coll = photons.sliceBy(perCollision, collision.collisionId()); + for (auto& cut : cuts) { + for (auto& photon : photons_coll) { + + if (!cut.template IsSelected(photon)) { + continue; + } + + auto pos = photon.template posTrack_as(); + auto ele = photon.template negTrack_as(); + auto posmc = pos.template emmcparticle_as(); + auto elemc = ele.template emmcparticle_as(); + + int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); + if (photonid < 0) { // check swap, true electron is reconstructed as positron and vice versa. + photonid = FindCommonMotherFrom2Prongs(posmc, elemc, 11, -11, 22, mcparticles); + } + + bool is_photon_physical_primary = false; + if (photonid > 0) { + auto mcphoton = mcparticles.iteratorAt(photonid); + is_photon_physical_primary = IsPhysicalPrimary(mcphoton.emreducedmcevent(), mcphoton, mcparticles); + } + if (!is_photon_physical_primary) { + continue; + } + + float phi_cp = atan2(photon.recalculatedVtxY(), photon.recalculatedVtxX()); + float eta_cp = std::atanh(photon.recalculatedVtxZ() / sqrt(pow(photon.recalculatedVtxX(), 2) + pow(photon.recalculatedVtxY(), 2) + pow(photon.recalculatedVtxZ(), 2))); + value[0] = photon.pt(); + value[1] = photon.recalculatedVtxR(); + value[2] = phi_cp > 0 ? phi_cp : phi_cp + TMath::TwoPi(); + value[3] = eta_cp; + reinterpret_cast(list_v0->FindObject(cut.GetName())->FindObject("hs_conv_point"))->Fill(value); + + } // end of photon loop + } // end of cut loop + + } // end of collision loop + } + + template + void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs, TMCParticles const& mcparticles, TMCEvents const&) + { + THashList* list_ev_pair = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())); + THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); + + for (auto& collision : collisions) { + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hZvtx_before"))->Fill(collision.posZ()); + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(1.0); // all + if (!collision.sel8()) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(2.0); // FT0VX i.e. FT0and + + if (collision.numContrib() < 0.5) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(3.0); // Ncontrib > 0 + + if (abs(collision.posZ()) > 10.0) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hZvtx_after"))->Fill(collision.posZ()); + reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(4.0); // |Zvtx| < 10 cm + + o2::aod::emphotonhistograms::FillHistClass(list_ev_pair, "", collision); + + auto photons1_coll = photons1.sliceBy(perCollision1, collision.collisionId()); + auto photons2_coll = photons2.sliceBy(perCollision2, collision.collisionId()); + + double value[9] = {0.f}; + float phi_cp1 = 0.f, eta_cp1 = 0.f; + float phi_cp2 = 0.f, eta_cp2 = 0.f; + for (auto& cut1 : cuts1) { + for (auto& cut2 : cuts2) { + // if (std::string(cut1.GetName()) == std::string(cut2.GetName())) { + // continue; + // } + for (auto& g1 : photons1_coll) { + for (auto& g2 : photons2_coll) { + if (g1.globalIndex() == g2.globalIndex()) { + continue; + } + if (!IsSelectedPair(g1, g2, cut1, cut2)) { + continue; + } + + for (auto& paircut : paircuts) { + if (!paircut.IsSelected(g1, g2)) { + continue; + } + + auto pos1 = g1.template posTrack_as(); + auto ele1 = g1.template negTrack_as(); + auto pos2 = g2.template posTrack_as(); + auto ele2 = g2.template negTrack_as(); + + auto pos1mc = pos1.template emmcparticle_as(); + auto ele1mc = ele1.template emmcparticle_as(); + auto pos2mc = pos2.template emmcparticle_as(); + auto ele2mc = ele2.template emmcparticle_as(); + // LOGF(info,"pos1mc.globalIndex() = %d , ele1mc.globalIndex() = %d , pos2mc.globalIndex() = %d , ele2mc.globalIndex() = %d", pos1mc.globalIndex(), ele1mc.globalIndex(), pos2mc.globalIndex(), ele2mc.globalIndex()); + + int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); + int photonid2 = FindCommonMotherFrom2Prongs(pos2mc, ele2mc, -11, 11, 22, mcparticles); + + if (photonid1 < 0) { // check swap, true electron is reconstructed as positron and vice versa. + photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, 11, -11, 22, mcparticles); + } + if (photonid2 < 0) { // check swap, true electron is reconstructed as positron and vice versa. + photonid2 = FindCommonMotherFrom2Prongs(pos2mc, ele2mc, 11, -11, 22, mcparticles); + } + + // LOGF(info,"photonid1 = %d , photonid2 = %d", photonid1, photonid2); + if (photonid1 < 0 || photonid2 < 0) { + continue; + } + + auto g1mc = mcparticles.iteratorAt(photonid1); + auto g2mc = mcparticles.iteratorAt(photonid2); + int pi0id = FindCommonMotherFrom2Prongs(g1mc, g2mc, 22, 22, 111, mcparticles); + + bool is_pi0_physical_primary = false; + if (pi0id > 0) { + auto pi0mc = mcparticles.iteratorAt(pi0id); + is_pi0_physical_primary = IsPhysicalPrimary(pi0mc.emreducedmcevent(), pi0mc, mcparticles); + } + if (!is_pi0_physical_primary) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // tag + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // probe + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + phi_cp1 = atan2(g1.recalculatedVtxY(), g1.recalculatedVtxX()); + eta_cp1 = std::atanh(g1.recalculatedVtxZ() / sqrt(pow(g1.recalculatedVtxX(), 2) + pow(g1.recalculatedVtxY(), 2) + pow(g1.recalculatedVtxZ(), 2))); + phi_cp2 = atan2(g2.recalculatedVtxY(), g2.recalculatedVtxX()); + eta_cp2 = std::atanh(g2.recalculatedVtxZ() / sqrt(pow(g2.recalculatedVtxX(), 2) + pow(g2.recalculatedVtxY(), 2) + pow(g2.recalculatedVtxZ(), 2))); + value[0] = v12.M(); + value[1] = g1.pt(); + value[2] = g1.recalculatedVtxR(); + value[3] = phi_cp1 > 0.f ? phi_cp1 : phi_cp1 + TMath::TwoPi(); + value[4] = eta_cp1; + value[5] = g2.pt(); + value[6] = g2.recalculatedVtxR(); + value[7] = phi_cp2 > 0.f ? phi_cp2 : phi_cp2 + TMath::TwoPi(); + value[8] = eta_cp2; + + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hs_conv_point_same"))->Fill(value); + + } // end of pair cut loop + } // end of g2 loop + } // end of g1 loop + } // end of cut2 loop + } // end of cut1 loop + } // end of collision loop + } + + Partition grouped_collisions = CentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < CentMax; // this goes to same event. + + void processMBMC(aod::EMReducedEvents const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const& legs, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const& mccollisions) + { + fillsinglephoton(grouped_collisions, v0photons, perCollision_pcm, fProbePCMCuts, legs, mcparticles, mccollisions); + SameEventPairing(grouped_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fTagPCMCuts, fProbePCMCuts, fPairCuts, legs, mcparticles, mccollisions); + } + + PresliceUnsorted perMcCollision = aod::emmcparticle::emreducedmceventId; + void processGen(soa::Join const& collisions, aod::EMReducedMCEvents const&, aod::EMMCParticles const& mcparticles) + { + // loop over mc stack and fill histograms for pure MC truth signals + // all MC tracks which belong to the MC event corresponding to the current reconstructed event + + for (auto& collision : collisions) { + auto mccollision = collision.emreducedmcevent(); + // LOGF(info, "mccollision.globalIndex() = %d", mccollision.globalIndex()); + + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(1.0); + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hZvtx_before"))->Fill(mccollision.posZ()); + if (!collision.sel8()) { + continue; + } + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(2.0); + + if (collision.numContrib() < 0.5) { + continue; + } + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(3.0); + + if (abs(collision.posZ()) > 10.0) { + continue; + } + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(4.0); + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hZvtx_after"))->Fill(mccollision.posZ()); + + auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); + for (auto& mctrack : mctracks_coll) { + if (abs(mctrack.y()) > maxY) { + continue; + } + if (abs(mctrack.pdgCode()) == 22 && IsPhysicalPrimary(mctrack.emreducedmcevent(), mctrack, mcparticles)) { + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPt_Photon"))->Fill(mctrack.pt()); + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hY_Photon"))->Fill(mctrack.y()); + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPhi_Photon"))->Fill(mctrack.phi()); + } + + int photonid = IsEleFromPC(mctrack, mcparticles); + if (photonid > 0) { + auto mcphoton = mcparticles.iteratorAt(photonid); + if (!IsPhysicalPrimary(mcphoton.emreducedmcevent(), mcphoton, mcparticles)) { + continue; + } + float rxy = sqrt(pow(mctrack.vx(), 2) + pow(mctrack.vy(), 2)); + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPhotonRZ"))->Fill(mctrack.vz(), rxy); + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPhotonRxy"))->Fill(mctrack.vx(), mctrack.vy()); + reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPhotonPhivsRxy"))->Fill(mctrack.phi(), rxy); + } + } + } + } + + void processDummy(aod::EMReducedEvents::iterator const& collision) + { + // do nothing + } + + PROCESS_SWITCH(MaterialBudgetMC, processMBMC, "process material budget", false); + PROCESS_SWITCH(MaterialBudgetMC, processGen, "process generated information", false); + PROCESS_SWITCH(MaterialBudgetMC, processDummy, "Dummy function", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"material-budget-mc"})}; +} diff --git a/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx b/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx index 899d0464a13..8cb23c59be7 100644 --- a/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx +++ b/PWGEM/PhotonMeson/Tasks/PhotonHBT.cxx @@ -48,6 +48,7 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::aod::photonpair; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx index 95b91dfdfef..17f5930b092 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGamma.cxx @@ -11,7 +11,7 @@ // // ======================== // -// This code loops over v0 photons and makes pairs for neutral mesons analyses. +// This code loops over photons and makes pairs for neutral mesons analyses. // Please write to: daiki.sekihata@cern.ch #include @@ -27,17 +27,12 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" + #include "Common/Core/RecoDecay.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" @@ -49,25 +44,28 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::aod::photonpair; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; +using MyDalitzEEs = soa::Join; +using MyDalitzEE = MyDalitzEEs::iterator; + struct Pi0EtaToGammaGamma { - // HistogramRegistry registry{"Pi0EtaToGammaGamma"}; Configurable CentMin{"CentMin", -1, "min. centrality"}; Configurable CentMax{"CentMax", 999, "max. centrality"}; Configurable CentEstimator{"CentEstimator", "FT0M", "centrality estimator"}; Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,qc,nocut", "Comma separated list of V0 photon cuts"}; + Configurable fConfigDalitzEECuts{"cfgDalitzEECuts", "mee_0_120_tpchadrejortofreq_lowB,mee_120_500_tpchadrejortofreq_lowB,mee_0_500_tpchadrejortofreq_lowB", "Comma separated list of Dalitz ee cuts"}; Configurable fConfigPHOSCuts{"cfgPHOSCuts", "test02,test03", "Comma separated list of PHOS photon cuts"}; Configurable fConfigPairCuts{"cfgPairCuts", "nocut,asym08", "Comma separated list of pair cuts"}; - Configurable useRotation{"useRotation", 0, "use rotation method for EMC-EMC background estimation"}; Configurable minOpenAngle{"minOpenAngle", 0.0202, "apply min opening angle"}; - Configurable fConfigEMCCuts{"fConfigEMCCuts", "custom,standard,nocut", "Comma separated list of EMCal photon cuts"}; + Configurable fConfigEMCCuts{"cfgEMCCuts", "custom,standard,nocut", "Comma separated list of EMCal photon cuts"}; // Configurable for EMCal cuts Configurable EMC_minTime{"EMC_minTime", -20., "Minimum cluster time for EMCal time cut"}; @@ -86,6 +84,7 @@ struct Pi0EtaToGammaGamma { THashList* fMainList = new THashList(); std::vector fPCMCuts; + std::vector fDalitzEECuts; std::vector fPHOSCuts; std::vector fEMCCuts; std::vector fPairCuts; @@ -108,11 +107,15 @@ struct Pi0EtaToGammaGamma { if (context.mOptions.get("processPCMEMC")) { fPairNames.push_back("PCMEMC"); } + if (context.mOptions.get("processPCMDalitz")) { + fPairNames.push_back("PCMDalitz"); + } if (context.mOptions.get("processPHOSEMC")) { fPairNames.push_back("PHOSEMC"); } DefinePCMCuts(); + DefineDalitzEECuts(); DefinePHOSCuts(); DefineEMCCuts(); DefinePairCuts(); @@ -148,7 +151,7 @@ struct Pi0EtaToGammaGamma { } // end of cut1 loop } - static constexpr std::string_view pairnames[6] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PHOSEMC"}; + static constexpr std::string_view pairnames[7] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PCMDalitz", "PHOSEMC"}; void addhistograms() { fMainList->SetOwner(true); @@ -185,6 +188,9 @@ struct Pi0EtaToGammaGamma { if (pairname == "PCMEMC") { add_pair_histograms(list_pair, pairname, fPCMCuts, fEMCCuts, fPairCuts); } + if (pairname == "PCMDalitz") { + add_pair_histograms(list_pair, pairname, fPCMCuts, fDalitzEECuts, fPairCuts); + } if (pairname == "PHOSEMC") { add_pair_histograms(list_pair, pairname, fPHOSCuts, fEMCCuts, fPairCuts); } @@ -205,6 +211,21 @@ struct Pi0EtaToGammaGamma { } LOGF(info, "Number of PCM cuts = %d", fPCMCuts.size()); } + + void DefineDalitzEECuts() + { + TString cutNamesStr = fConfigDalitzEECuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fDalitzEECuts.push_back(*dalitzeecuts::GetCut(cutname)); + } + } + LOGF(info, "Number of DalitzEE cuts = %d", fDalitzEECuts.size()); + } + void DefinePHOSCuts() { TString cutNamesStr = fConfigPHOSCuts.value; @@ -275,7 +296,8 @@ struct Pi0EtaToGammaGamma { LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); } - Preslice perCollision = aod::v0photon::collisionId; + Preslice perCollision = aod::v0photonkf::emreducedeventId; + Preslice perCollision_dalitz = aod::dalitzee::emreducedeventId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; @@ -293,6 +315,8 @@ struct Pi0EtaToGammaGamma { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPCMEMC) { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + } else if constexpr (pairtype == PairType::kPCMDalitz) { + is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPHOSEMC) { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else { @@ -301,8 +325,8 @@ struct Pi0EtaToGammaGamma { return is_selected_pair; } - template - void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs, TEMCMTs const& emcmatchedtracks) + template + void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs, TPrimaryTracks const& primarytracks, TEMCMTs const& emcmatchedtracks) { THashList* list_ev_pair = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())); THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); @@ -335,8 +359,8 @@ struct Pi0EtaToGammaGamma { o2::aod::emphotonhistograms::FillHistClass(list_ev_pair, "", collision); - auto photons1_coll = photons1.sliceBy(perCollision1, collision.collisionId()); - auto photons2_coll = photons2.sliceBy(perCollision2, collision.collisionId()); + auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); if constexpr (pairtype == PairType::kPCMPCM || pairtype == PairType::kPHOSPHOS || pairtype == PairType::kEMCEMC) { for (auto& cut : cuts1) { @@ -406,11 +430,13 @@ struct Pi0EtaToGammaGamma { ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + if constexpr (pairtype == PairType::kPCMDalitz) { + v2.SetM(g2.mee()); + } ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; if (abs(v12.Rapidity()) > maxY) { continue; } - // reinterpret_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject("hMggPt_Same"))->Fill(v12.M(), v12.Pt()); reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Same"))->Fill(v12.M(), v12.Pt()); } // end of combination } // end of pair cut loop @@ -426,8 +452,8 @@ struct Pi0EtaToGammaGamma { using BinningType = ColumnBinningPolicy; BinningType colBinning{{ConfVtxBins, ConfMultBins}, true}; - template - void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs, TEMCMTs const& emcmatchedtracks) + template + void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs, TPrimaryTracks const& primarytracks, TEMCMTs const& emcmatchedtracks) { THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); // LOGF(info, "Number of collisions after filtering: %d", collisions.size()); @@ -436,8 +462,8 @@ struct Pi0EtaToGammaGamma { // LOGF(info, "Mixed event collisionId: (%d, %d) , ngpcm: (%d, %d), ngphos: (%d, %d), ngemc: (%d, %d)", // collision1.collisionId(), collision2.collisionId(), collision1.ngpcm(), collision2.ngpcm(), collision1.ngphos(), collision2.ngphos(), collision1.ngemc(), collision2.ngemc()); - auto photons_coll1 = photons1.sliceBy(perCollision1, collision1.collisionId()); - auto photons_coll2 = photons2.sliceBy(perCollision2, collision2.collisionId()); + auto photons_coll1 = photons1.sliceBy(perCollision1, collision1.globalIndex()); + auto photons_coll2 = photons2.sliceBy(perCollision2, collision2.globalIndex()); // LOGF(info, "collision1: posZ = %f, numContrib = %d , sel8 = %d | collision2: posZ = %f, numContrib = %d , sel8 = %d", // collision1.posZ(), collision1.numContrib(), collision1.sel8(), collision2.posZ(), collision2.numContrib(), collision2.sel8()); @@ -459,11 +485,13 @@ struct Pi0EtaToGammaGamma { ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + if constexpr (pairtype == PairType::kPCMDalitz) { + v2.SetM(g2.mee()); + } ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; if (abs(v12.Rapidity()) > maxY) { continue; } - // reinterpret_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject("hMggPt_Mixed"))->Fill(v12.M(), v12.Pt()); reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Mixed"))->Fill(v12.M(), v12.Pt()); } // end of different photon combinations @@ -535,6 +563,9 @@ struct Pi0EtaToGammaGamma { } } + Filter DalitzEEFilter = o2::aod::dalitzee::sign == 0; // analyze only uls + using MyFilteredDalitzEEs = soa::Filtered; + Partition grouped_collisions = CentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < CentMax; // this goes to same event. Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true && CentMin < o2::aod::cent::centFT0M&& o2::aod::cent::centFT0M < CentMax; Filter collisionFilter_subsys = (o2::aod::emreducedevent::ngpcm >= 1) || (o2::aod::emreducedevent::ngphos >= 1) || (o2::aod::emreducedevent::ngemc >= 1); @@ -542,38 +573,44 @@ struct Pi0EtaToGammaGamma { void processPCMPCM(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) { - SameEventPairing(grouped_collisions, v0photons, v0photons, perCollision, perCollision, fPCMCuts, fPCMCuts, fPairCuts, legs, nullptr); - MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision, perCollision, fPCMCuts, fPCMCuts, fPairCuts, legs, nullptr); + SameEventPairing(grouped_collisions, v0photons, v0photons, perCollision, perCollision, fPCMCuts, fPCMCuts, fPairCuts, legs, nullptr, nullptr); + MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision, perCollision, fPCMCuts, fPCMCuts, fPairCuts, legs, nullptr, nullptr); } void processPHOSPHOS(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, aod::PHOSClusters const& phosclusters) { - SameEventPairing(grouped_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fPHOSCuts, fPHOSCuts, fPairCuts, nullptr, nullptr); - MixedEventPairing(filtered_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fPHOSCuts, fPHOSCuts, fPairCuts, nullptr, nullptr); + SameEventPairing(grouped_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fPHOSCuts, fPHOSCuts, fPairCuts, nullptr, nullptr, nullptr); + MixedEventPairing(filtered_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fPHOSCuts, fPHOSCuts, fPairCuts, nullptr, nullptr, nullptr); } void processEMCEMC(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, aod::SkimEMCClusters const& emcclusters, aod::SkimEMCMTs const& emcmatchedtracks) { - SameEventPairing(grouped_collisions, emcclusters, emcclusters, perCollision_emc, perCollision_emc, fEMCCuts, fEMCCuts, fPairCuts, nullptr, emcmatchedtracks); - MixedEventPairing(filtered_collisions, emcclusters, emcclusters, perCollision_emc, perCollision_emc, fEMCCuts, fEMCCuts, fPairCuts, nullptr, emcmatchedtracks); + SameEventPairing(grouped_collisions, emcclusters, emcclusters, perCollision_emc, perCollision_emc, fEMCCuts, fEMCCuts, fPairCuts, nullptr, nullptr, emcmatchedtracks); + MixedEventPairing(filtered_collisions, emcclusters, emcclusters, perCollision_emc, perCollision_emc, fEMCCuts, fEMCCuts, fPairCuts, nullptr, nullptr, emcmatchedtracks); + } + + void processPCMDalitz(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs, MyFilteredDalitzEEs const& dileptons, aod::EMPrimaryTracks const& emprimarytracks) + { + SameEventPairing(grouped_collisions, v0photons, dileptons, perCollision, perCollision_dalitz, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimarytracks, nullptr); + MixedEventPairing(filtered_collisions, v0photons, dileptons, perCollision, perCollision_dalitz, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimarytracks, nullptr); } void processPCMPHOS(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::PHOSClusters const& phosclusters, aod::V0Legs const& legs) { - SameEventPairing(grouped_collisions, v0photons, phosclusters, perCollision, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr); - MixedEventPairing(filtered_collisions, v0photons, phosclusters, perCollision, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr); + SameEventPairing(grouped_collisions, v0photons, phosclusters, perCollision, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr, nullptr); + MixedEventPairing(filtered_collisions, v0photons, phosclusters, perCollision, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr, nullptr); } void processPCMEMC(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::SkimEMCClusters const& emcclusters, aod::V0Legs const& legs, aod::SkimEMCMTs const& emcmatchedtracks) { - SameEventPairing(grouped_collisions, v0photons, emcclusters, perCollision, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs, emcmatchedtracks); - MixedEventPairing(filtered_collisions, v0photons, emcclusters, perCollision, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs, emcmatchedtracks); + SameEventPairing(grouped_collisions, v0photons, emcclusters, perCollision, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs, nullptr, emcmatchedtracks); + MixedEventPairing(filtered_collisions, v0photons, emcclusters, perCollision, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs, nullptr, emcmatchedtracks); } void processPHOSEMC(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, aod::PHOSClusters const& phosclusters, aod::SkimEMCClusters const& emcclusters, aod::SkimEMCMTs const& emcmatchedtracks) { - SameEventPairing(grouped_collisions, phosclusters, emcclusters, perCollision_phos, perCollision_emc, fPHOSCuts, fEMCCuts, fPairCuts, nullptr, emcmatchedtracks); - MixedEventPairing(filtered_collisions, phosclusters, emcclusters, perCollision_phos, perCollision_emc, fPHOSCuts, fEMCCuts, fPairCuts, nullptr, emcmatchedtracks); + SameEventPairing(grouped_collisions, phosclusters, emcclusters, perCollision_phos, perCollision_emc, fPHOSCuts, fEMCCuts, fPairCuts, nullptr, nullptr, emcmatchedtracks); + MixedEventPairing(filtered_collisions, phosclusters, emcclusters, perCollision_phos, perCollision_emc, fPHOSCuts, fEMCCuts, fPairCuts, nullptr, nullptr, emcmatchedtracks); } void processDummy(aod::EMReducedEvents::iterator const& collision) @@ -586,6 +623,7 @@ struct Pi0EtaToGammaGamma { PROCESS_SWITCH(Pi0EtaToGammaGamma, processEMCEMC, "pairing EMCal-EMCal", false); PROCESS_SWITCH(Pi0EtaToGammaGamma, processPCMPHOS, "pairing PCM-PHOS", false); PROCESS_SWITCH(Pi0EtaToGammaGamma, processPCMEMC, "pairing PCM-EMCal", false); + PROCESS_SWITCH(Pi0EtaToGammaGamma, processPCMDalitz, "pairing PCM-Dalitz", false); PROCESS_SWITCH(Pi0EtaToGammaGamma, processPHOSEMC, "pairing PHOS-EMCal", false); PROCESS_SWITCH(Pi0EtaToGammaGamma, processDummy, "Dummy function", true); }; diff --git a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx index 0760a0e4462..980fa32a399 100644 --- a/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/Pi0EtaToGammaGammaMC.cxx @@ -20,18 +20,13 @@ #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" + #include "Common/Core/RecoDecay.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" @@ -43,16 +38,21 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::aod::photonpair; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; +using MyDalitzEEs = soa::Join; +using MyDalitzEE = MyDalitzEEs::iterator; + struct Pi0EtaToGammaGammaMC { - using MyMCV0Legs = soa::Join; + using MyMCV0Legs = soa::Join; + using MyMCTracks = soa::Join; - // HistogramRegistry registry{"Pi0EtaToGammaGammaMC"}; Configurable maxY{"maxY", 0.9, "maximum rapidity for generated particles"}; Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,qc,nocut", "Comma separated list of V0 photon cuts"}; + Configurable fConfigDalitzEECuts{"cfgDalitzEECuts", "mee_0_120_tpchadrejortofreq_lowB,mee_120_500_tpchadrejortofreq_lowB,mee_0_500_tpchadrejortofreq_lowB", "Comma separated list of Dalitz ee cuts"}; Configurable fConfigPairCuts{"cfgPairCuts", "nocut,asym08", "Comma separated list of pair cuts"}; OutputObj fOutputEvent{"Event"}; @@ -61,6 +61,7 @@ struct Pi0EtaToGammaGammaMC { THashList* fMainList = new THashList(); std::vector fPCMCuts; + std::vector fDalitzEECuts; std::vector fPHOSCuts; std::vector fEMCCuts; std::vector fPairCuts; @@ -83,11 +84,15 @@ struct Pi0EtaToGammaGammaMC { if (context.mOptions.get("processPCMEMC")) { fPairNames.push_back("PCMEMC"); } + if (context.mOptions.get("processPCMDalitz")) { + fPairNames.push_back("PCMDalitz"); + } if (context.mOptions.get("processPHOSEMC")) { fPairNames.push_back("PHOSEMC"); } DefinePCMCuts(); + DefineDalitzEECuts(); DefinePairCuts(); addhistograms(); @@ -122,7 +127,7 @@ struct Pi0EtaToGammaGammaMC { } // end of cut1 loop } - static constexpr std::string_view pairnames[6] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PHOSEMC"}; + static constexpr std::string_view pairnames[7] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PCMDalitz", "PHOSEMC"}; static constexpr std::string_view parnames[3] = {"Gamma", "Pi0", "Eta"}; void addhistograms() { @@ -164,6 +169,9 @@ struct Pi0EtaToGammaGammaMC { if (pairname == "PCMEMC") { add_pair_histograms(list_pair, pairname, fPCMCuts, fEMCCuts, fPairCuts); } + if (pairname == "PCMDalitz") { + add_pair_histograms(list_pair, pairname, fPCMCuts, fDalitzEECuts, fPairCuts); + } if (pairname == "PHOSEMC") { add_pair_histograms(list_pair, pairname, fPHOSCuts, fEMCCuts, fPairCuts); } @@ -185,6 +193,20 @@ struct Pi0EtaToGammaGammaMC { LOGF(info, "Number of PCM cuts = %d", fPCMCuts.size()); } + void DefineDalitzEECuts() + { + TString cutNamesStr = fConfigDalitzEECuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fDalitzEECuts.push_back(*dalitzeecuts::GetCut(cutname)); + } + } + LOGF(info, "Number of DalitzEE cuts = %d", fDalitzEECuts.size()); + } + void DefinePairCuts() { TString cutNamesStr = fConfigPairCuts.value; @@ -213,6 +235,8 @@ struct Pi0EtaToGammaGammaMC { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPCMEMC) { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + } else if constexpr (pairtype == PairType::kPCMDalitz) { + is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPHOSEMC) { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else { @@ -221,10 +245,11 @@ struct Pi0EtaToGammaGammaMC { return is_selected_pair; } - Preslice perCollision_pcm = aod::v0photon::collisionId; + Preslice perCollision_pcm = aod::v0photonkf::emreducedeventId; + Preslice perCollision_dalitz = aod::dalitzee::emreducedeventId; - template - void TruePairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TV0Legs const& v0legs, TMCParticles const& mcparticles, TMCEvents const& mcevents) + template + void TruePairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TV0Legs const& v0legs, TEMTracks const& emprimarytracks, TMCParticles const& mcparticles, TMCEvents const& mcevents) { THashList* list_ev_pair = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())); THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); @@ -258,12 +283,12 @@ struct Pi0EtaToGammaGammaMC { reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(4.0); // |Zvtx| < 10 cm o2::aod::emphotonhistograms::FillHistClass(list_ev_pair, "", collision); - auto photons1_coll = photons1.sliceBy(perCollision1, collision.collisionId()); - auto photons2_coll = photons2.sliceBy(perCollision2, collision.collisionId()); + auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); int pi0id = -1; int etaid = -1; - if (pairtype == PairType::kPCMPCM || pairtype == PairType::kPHOSPHOS || pairtype == PairType::kEMCEMC) { + if constexpr (pairtype == PairType::kPCMPCM || pairtype == PairType::kPHOSPHOS || pairtype == PairType::kEMCEMC) { for (auto& cut : cuts1) { for (auto& paircut : paircuts) { for (auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photons1_coll, photons2_coll))) { @@ -306,6 +331,9 @@ struct Pi0EtaToGammaGammaMC { pi0id = FindCommonMotherFrom2Prongs(g1mc, g2mc, 22, 22, 111, mcparticles); etaid = FindCommonMotherFrom2Prongs(g1mc, g2mc, 22, 22, 221, mcparticles); } + if (pi0id < 0 && etaid < 0) { + continue; + } ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); @@ -321,8 +349,7 @@ struct Pi0EtaToGammaGammaMC { } else if (IsFromWD(pi0mc.emreducedmcevent(), pi0mc, mcparticles)) { reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut.GetName(), cut.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_FromWD"))->Fill(v12.M(), v12.Pt()); } - } - if (etaid > 0) { + } else if (etaid > 0) { reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut.GetName(), cut.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Eta_Primary"))->Fill(v12.M(), v12.Pt()); } } // end of combination @@ -353,16 +380,49 @@ struct Pi0EtaToGammaGammaMC { continue; } } + } else if constexpr (pairtype == PairType::kPCMDalitz) { // check 4 legs + auto pos1 = g1.template posTrack_as(); + auto ele1 = g1.template negTrack_as(); + auto pos2 = g2.template posTrack_as(); + auto ele2 = g2.template negTrack_as(); + + auto pos1mc = pos1.template emmcparticle_as(); + auto ele1mc = ele1.template emmcparticle_as(); + auto pos2mc = pos2.template emmcparticle_as(); + auto ele2mc = ele2.template emmcparticle_as(); + // LOGF(info,"pos1mc.globalIndex() = %d , ele1mc.globalIndex() = %d , pos2mc.globalIndex() = %d , ele2mc.globalIndex() = %d", pos1mc.globalIndex(), ele1mc.globalIndex(), pos2mc.globalIndex(), ele2mc.globalIndex()); + + int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); // real photon + if (photonid1 < 0) { + continue; + } + auto g1mc = mcparticles.iteratorAt(photonid1); + pi0id = FindCommonMotherFrom3Prongs(g1mc, pos2mc, ele2mc, 22, -11, 11, 111, mcparticles); + etaid = FindCommonMotherFrom3Prongs(g1mc, pos2mc, ele2mc, 22, -11, 11, 221, mcparticles); + } + if (pi0id < 0 && etaid < 0) { + continue; } ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + if constexpr (pairtype == PairType::kPCMDalitz) { + v2.SetM(g2.mee()); + } ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; if (abs(v12.Rapidity()) > maxY) { continue; } - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_Primary"))->Fill(v12.M(), v12.Pt()); - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Eta_Primary"))->Fill(v12.M(), v12.Pt()); + if (pi0id > 0) { + auto pi0mc = mcparticles.iteratorAt(pi0id); + if (IsPhysicalPrimary(pi0mc.emreducedmcevent(), pi0mc, mcparticles)) { + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_Primary"))->Fill(v12.M(), v12.Pt()); + } else if (IsFromWD(pi0mc.emreducedmcevent(), pi0mc, mcparticles)) { + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_FromWD"))->Fill(v12.M(), v12.Pt()); + } + } else if (etaid > 0) { + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Eta_Primary"))->Fill(v12.M(), v12.Pt()); + } } // end of combination } // end of paircutloop @@ -377,12 +437,18 @@ struct Pi0EtaToGammaGammaMC { void processPCMPCM(MyCollisions const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const& v0legs, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const& mccollisions) { - TruePairing(collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMCuts, fPairCuts, v0legs, mcparticles, mccollisions); + TruePairing(collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMCuts, fPairCuts, v0legs, nullptr, mcparticles, mccollisions); } void processPHOSPHOS(MyCollisions const& collisions) {} void processEMCEMC(MyCollisions const& collisions) {} void processPCMPHOS(MyCollisions const& collisions) {} void processPCMEMC(MyCollisions const& collisions) {} + + void processPCMDalitz(MyCollisions const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const& v0legs, MyDalitzEEs const& dileptons, MyMCTracks const& emprimarytracks, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const& mccollisions) + { + TruePairing(collisions, v0photons, dileptons, perCollision_pcm, perCollision_dalitz, fPCMCuts, fDalitzEECuts, fPairCuts, v0legs, emprimarytracks, mcparticles, mccollisions); + } + void processPHOSEMC(MyCollisions const& collisions) {} PresliceUnsorted perMcCollision = aod::emmcparticle::emreducedmceventId; @@ -447,6 +513,7 @@ struct Pi0EtaToGammaGammaMC { PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processEMCEMC, "true pairing EMC-EMC", false); PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processPCMPHOS, "true pairing PCM-PHOS", false); PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processPCMEMC, "true pairing PCM-EMC", false); + PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processPCMDalitz, "true pairing PCM-Dalitz", false); PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processPHOSEMC, "true pairing PHOS-EMC", false); PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processGen, "process generated information", false); PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processDummy, "Dummy function", true); diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx index 0b943f508ad..04f5c887081 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx @@ -60,7 +60,7 @@ struct SinglePhoton { Configurable CentEstimator{"CentEstimator", "FT0M", "centrality estimator"}; Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,qc,nocut", "Comma separated list of V0 photon cuts"}; + Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,wwire_ib,qc,qc_ITSTPC,qc_ITSonly,qc_TPConly", "Comma separated list of V0 photon cuts"}; Configurable fConfigPHOSCuts{"cfgPHOSCuts", "test02,test03", "Comma separated list of PHOS photon cuts"}; Configurable fConfigEMCCuts{"fConfigEMCCuts", "custom,standard,nocut", "Comma separated list of EMCal photon cuts"}; diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx index c7ec141e384..ddf4ccff2db 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx @@ -48,7 +48,7 @@ using namespace o2::soa; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyMCV0Legs = soa::Join; +using MyMCV0Legs = soa::Join; struct SinglePhotonMC { enum EMDetType { @@ -324,6 +324,10 @@ struct SinglePhotonMC { reinterpret_cast(fMainList->FindObject("Photon")->FindObject(detnames[photontype].data())->FindObject(cut.GetName())->FindObject("hPt_Photon_FromWD"))->Fill(v1.Pt()); reinterpret_cast(fMainList->FindObject("Photon")->FindObject(detnames[photontype].data())->FindObject(cut.GetName())->FindObject("hY_Photon_FromWD"))->Fill(v1.Rapidity()); reinterpret_cast(fMainList->FindObject("Photon")->FindObject(detnames[photontype].data())->FindObject(cut.GetName())->FindObject("hPhi_Photon_FromWD"))->Fill(v1.Phi() < 0.0 ? v1.Phi() + TMath::TwoPi() : v1.Phi()); + } else { + reinterpret_cast(fMainList->FindObject("Photon")->FindObject(detnames[photontype].data())->FindObject(cut.GetName())->FindObject("hPt_Photon_hs"))->Fill(v1.Pt()); + reinterpret_cast(fMainList->FindObject("Photon")->FindObject(detnames[photontype].data())->FindObject(cut.GetName())->FindObject("hY_Photon_hs"))->Fill(v1.Rapidity()); + reinterpret_cast(fMainList->FindObject("Photon")->FindObject(detnames[photontype].data())->FindObject(cut.GetName())->FindObject("hPhi_Photon_hs"))->Fill(v1.Phi() < 0.0 ? v1.Phi() + TMath::TwoPi() : v1.Phi()); } } // end of photon loop diff --git a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx index a4080d9ab34..cb8d0e39e28 100644 --- a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx +++ b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx @@ -42,6 +42,7 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::aod::photonpair; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx index 9112ed99f3c..d8d6dbe8e08 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0.cxx @@ -19,25 +19,15 @@ #include "TString.h" #include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/LorentzRotation.h" -#include "Math/Rotation3D.h" -#include "Math/AxisAngle.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/Core/RecoDecay.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" @@ -49,16 +39,22 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::aod::photonpair; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; +using MyDalitzEEs = soa::Join; +using MyDalitzEE = MyDalitzEEs::iterator; + struct TaggingPi0 { - Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,qc,nocut", "Comma separated list of V0 photon cuts"}; + // Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; + Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis", "Comma separated list of V0 photon cuts"}; + Configurable fConfigDalitzEECuts{"cfgDalitzEECuts", "mee_0_120_tpchadrejortofreq,mee_0_120_tpchadrejortofreq_lowB", "Comma separated list of Dalitz ee cuts"}; + Configurable fConfigPCMibwCuts{"cfgPCMibwCuts", "wwire_ib", "Comma separated list of V0 photon cuts"}; Configurable fConfigPHOSCuts{"cfgPHOSCuts", "test02,test03", "Comma separated list of PHOS photon cuts"}; - Configurable fConfigEMCCuts{"fConfigEMCCuts", "custom,standard,nocut", "Comma separated list of EMCal photon cuts"}; + Configurable fConfigEMCCuts{"cfgEMCCuts", "standard", "Comma separated list of EMCal photon cuts"}; Configurable fConfigPairCuts{"cfgPairCuts", "nocut", "Comma separated list of pair cuts"}; // Configurable for EMCal cuts @@ -78,6 +74,8 @@ struct TaggingPi0 { THashList* fMainList = new THashList(); std::vector fPCMCuts; + std::vector fDalitzEECuts; + std::vector fPCMibwCuts; std::vector fPHOSCuts; std::vector fEMCCuts; std::vector fPairCuts; @@ -85,6 +83,12 @@ struct TaggingPi0 { std::vector fPairNames; void init(InitContext& context) { + if (context.mOptions.get("processPCMPCMibw")) { + fPairNames.push_back("PCMPCMibw"); + } + if (context.mOptions.get("processPCMDalitz")) { + fPairNames.push_back("PCMDalitz"); + } if (context.mOptions.get("processPCMPHOS")) { fPairNames.push_back("PCMPHOS"); } @@ -93,6 +97,8 @@ struct TaggingPi0 { } DefinePCMCuts(); + DefineDalitzEECuts(); + DefinePCMibwCuts(); DefinePHOSCuts(); DefineEMCCuts(); DefinePairCuts(); @@ -128,7 +134,7 @@ struct TaggingPi0 { } // end of cut1 loop } - static constexpr std::string_view pairnames[6] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PHOSEMC"}; + static constexpr std::string_view pairnames[8] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PCMDalitz", "PHOSEMC", "PCMPCMibw"}; void addhistograms() { fMainList->SetOwner(true); @@ -150,12 +156,18 @@ struct TaggingPi0 { o2::aod::emphotonhistograms::AddHistClass(list_pair, pairname.data()); + if (pairname == "PCMPCMibw") { + add_pair_histograms(list_pair, pairname, fPCMCuts, fPCMibwCuts, fPairCuts); + } if (pairname == "PCMPHOS") { add_pair_histograms(list_pair, pairname, fPCMCuts, fPHOSCuts, fPairCuts); } if (pairname == "PCMEMC") { add_pair_histograms(list_pair, pairname, fPCMCuts, fEMCCuts, fPairCuts); } + if (pairname == "PCMDalitz") { + add_pair_histograms(list_pair, pairname, fPCMCuts, fDalitzEECuts, fPairCuts); + } } // end of pair name loop } @@ -173,6 +185,35 @@ struct TaggingPi0 { } LOGF(info, "Number of PCM cuts = %d", fPCMCuts.size()); } + + void DefineDalitzEECuts() + { + TString cutNamesStr = fConfigDalitzEECuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fDalitzEECuts.push_back(*dalitzeecuts::GetCut(cutname)); + } + } + LOGF(info, "Number of DalitzEE cuts = %d", fDalitzEECuts.size()); + } + + void DefinePCMibwCuts() + { + TString cutNamesStr = fConfigPCMibwCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fPCMibwCuts.push_back(*pcmcuts::GetCut(cutname)); + } + } + LOGF(info, "Number of PCM cuts = %d", fPCMibwCuts.size()); + } + void DefinePHOSCuts() { TString cutNamesStr = fConfigPHOSCuts.value; @@ -247,18 +288,22 @@ struct TaggingPi0 { bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2) { bool is_selected_pair = false; - if constexpr (pairtype == PairType::kPCMPHOS) { + if constexpr (pairtype == PairType::kPCMPCMibw) { + is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + } else if constexpr (pairtype == PairType::kPCMPHOS) { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPCMEMC) { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + } else if constexpr (pairtype == PairType::kPCMDalitz) { + is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else { is_selected_pair = true; } return is_selected_pair; } - template - void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs) + template + void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs, TEMPrimaryTracks const& emprimarytracks) { THashList* list_ev_pair = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())); THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); @@ -291,8 +336,8 @@ struct TaggingPi0 { reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(4.0); // |Zvtx| < 10 cm o2::aod::emphotonhistograms::FillHistClass(list_ev_pair, "", collision); - auto photons1_coll = photons1.sliceBy(perCollision1, collision.collisionId()); - auto photons2_coll = photons2.sliceBy(perCollision2, collision.collisionId()); + auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); for (auto& cut1 : cuts1) { for (auto& cut2 : cuts2) { @@ -320,11 +365,14 @@ struct TaggingPi0 { } } ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // pcm - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // phos or emc - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (abs(v12.Rapidity()) > maxY) { - continue; + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // phos or emc or dalitzee + if constexpr (pairtype == PairType::kPCMDalitz) { + v2.SetM(g2.mee()); } + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + // if (abs(v12.Rapidity()) > maxY) { + // continue; + // } reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Same"))->Fill(v12.M(), v1.Pt()); } // end of combination } // end of pair cut loop @@ -339,8 +387,8 @@ struct TaggingPi0 { using BinningType = ColumnBinningPolicy; BinningType colBinning{{ConfVtxBins, ConfMultBins}, true}; - template - void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs) + template + void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs, TEMPrimaryTracks const& emprimarytracks) { THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); @@ -350,8 +398,8 @@ struct TaggingPi0 { // LOGF(info, "Mixed event collisionId: (%d, %d) , counter = %d, ngpcm: (%d, %d), ngphos: (%d, %d), ngemc: (%d, %d)", // collision1.collisionId(), collision2.collisionId(), nev, collision1.ngpcm(), collision2.ngpcm(), collision1.ngphos(), collision2.ngphos(), collision1.ngemc(), collision2.ngemc()); - auto photons_coll1 = photons1.sliceBy(perCollision1, collision1.collisionId()); - auto photons_coll2 = photons2.sliceBy(perCollision2, collision2.collisionId()); + auto photons_coll1 = photons1.sliceBy(perCollision1, collision1.globalIndex()); + auto photons_coll2 = photons2.sliceBy(perCollision2, collision2.globalIndex()); // LOGF(info, "collision1: posZ = %f, numContrib = %d , sel8 = %d | collision2: posZ = %f, numContrib = %d , sel8 = %d", // collision1.posZ(), collision1.numContrib(), collision1.sel8(), collision2.posZ(), collision2.numContrib(), collision2.sel8()); @@ -372,11 +420,14 @@ struct TaggingPi0 { } ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // pcm - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // phos or emc - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (abs(v12.Rapidity()) > maxY) { - continue; + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // phos or emc or dalitzee + if constexpr (pairtype == PairType::kPCMDalitz) { + v2.SetM(g2.mee()); } + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + // if (abs(v12.Rapidity()) > maxY) { + // continue; + // } reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Mixed"))->Fill(v12.M(), v1.Pt()); } // end of different photon combinations @@ -390,20 +441,35 @@ struct TaggingPi0 { Filter collisionFilter_subsys = (o2::aod::emreducedevent::ngpcm >= 1) || (o2::aod::emreducedevent::ngphos >= 1) || (o2::aod::emreducedevent::ngemc >= 1); using MyFilteredCollisions = soa::Filtered; - Preslice perCollision_pcm = aod::v0photon::collisionId; + Filter DalitzEEFilter = o2::aod::dalitzee::sign == 0; // analyze only uls + using MyFilteredDalitzEEs = soa::Filtered; + + Preslice perCollision_pcm = aod::v0photonkf::emreducedeventId; + Preslice perCollision_dalitz = aod::dalitzee::emreducedeventId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; + void processPCMPCMibw(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) + { + SameEventPairing(collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMibwCuts, fPairCuts, legs, nullptr); + MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMibwCuts, fPairCuts, legs, nullptr); + } + void processPCMDalitz(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs, MyFilteredDalitzEEs const& dielectrons, aod::EMPrimaryTracks const& emprimarytracks) + { + SameEventPairing(collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitz, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimarytracks); + MixedEventPairing(filtered_collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitz, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimarytracks); + } + void processPCMPHOS(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::PHOSClusters const& phosclusters, aod::V0Legs const& legs) { - SameEventPairing(collisions, v0photons, phosclusters, perCollision_pcm, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs); - MixedEventPairing(filtered_collisions, v0photons, phosclusters, perCollision_pcm, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs); + SameEventPairing(collisions, v0photons, phosclusters, perCollision_pcm, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr); + MixedEventPairing(filtered_collisions, v0photons, phosclusters, perCollision_pcm, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr); } void processPCMEMC(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::SkimEMCClusters const& emcclusters, aod::V0Legs const& legs) { - SameEventPairing(collisions, v0photons, emcclusters, perCollision_pcm, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs); - MixedEventPairing(filtered_collisions, v0photons, emcclusters, perCollision_pcm, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs); + SameEventPairing(collisions, v0photons, emcclusters, perCollision_pcm, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs, nullptr); + MixedEventPairing(filtered_collisions, v0photons, emcclusters, perCollision_pcm, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs, nullptr); } void processDummy(aod::EMReducedEvents::iterator const& collision) @@ -411,6 +477,8 @@ struct TaggingPi0 { // do nothing } + PROCESS_SWITCH(TaggingPi0, processPCMPCMibw, "pairing PCM-PCMibw", false); + PROCESS_SWITCH(TaggingPi0, processPCMDalitz, "pairing PCM-Dalitz", false); PROCESS_SWITCH(TaggingPi0, processPCMPHOS, "pairing PCM-PHOS", false); PROCESS_SWITCH(TaggingPi0, processPCMEMC, "pairing PCM-EMCal", false); PROCESS_SWITCH(TaggingPi0, processDummy, "Dummy function", true); diff --git a/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx b/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx index 7ce3fc78f1f..3551ef34b9e 100644 --- a/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx +++ b/PWGEM/PhotonMeson/Tasks/TaggingPi0MC.cxx @@ -19,26 +19,18 @@ #include "TString.h" #include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/LorentzRotation.h" -#include "Math/Rotation3D.h" -#include "Math/AxisAngle.h" + #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" + #include "Common/Core/RecoDecay.h" #include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/PairCut.h" @@ -50,17 +42,24 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::aod::photonpair; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; +using MyDalitzEEs = soa::Join; +using MyDalitzEE = MyDalitzEEs::iterator; + struct TaggingPi0MC { - using MyMCV0Legs = soa::Join; + using MyMCV0Legs = soa::Join; + using MyMCTracks = soa::Join; Configurable maxY{"maxY", 0.9, "maximum rapidity for reconstructed particles"}; - Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,qc,nocut", "Comma separated list of V0 photon cuts"}; + Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis", "Comma separated list of V0 photon cuts"}; + Configurable fConfigDalitzEECuts{"cfgDalitzEECuts", "mee_0_120_tpchadrejortofreq,mee_0_120_tpchadrejortofreq_lowB", "Comma separated list of Dalitz ee cuts"}; + Configurable fConfigPCMibwCuts{"cfgPCMibwCuts", "wwire_ib", "Comma separated list of V0 photon cuts"}; Configurable fConfigPHOSCuts{"cfgPHOSCuts", "test02,test03", "Comma separated list of PHOS photon cuts"}; - Configurable fConfigEMCCuts{"fConfigEMCCuts", "custom,standard,nocut", "Comma separated list of EMCal photon cuts"}; + Configurable fConfigEMCCuts{"fConfigEMCCuts", "standard", "Comma separated list of EMCal photon cuts"}; Configurable fConfigPairCuts{"cfgPairCuts", "nocut", "Comma separated list of pair cuts"}; // Configurable for EMCal cuts @@ -77,9 +76,12 @@ struct TaggingPi0MC { OutputObj fOutputEvent{"Event"}; OutputObj fOutputPair{"Pair"}; // 2-photon pair + OutputObj fOutputPCM{"PCM"}; // v0-photon THashList* fMainList = new THashList(); std::vector fPCMCuts; + std::vector fDalitzEECuts; + std::vector fPCMibwCuts; std::vector fPHOSCuts; std::vector fEMCCuts; std::vector fPairCuts; @@ -87,6 +89,12 @@ struct TaggingPi0MC { std::vector fPairNames; void init(InitContext& context) { + if (context.mOptions.get("processPCMPCMibw")) { + fPairNames.push_back("PCMPCMibw"); + } + if (context.mOptions.get("processPCMDalitz")) { + fPairNames.push_back("PCMDalitz"); + } if (context.mOptions.get("processPCMPHOS")) { fPairNames.push_back("PCMPHOS"); } @@ -95,6 +103,8 @@ struct TaggingPi0MC { } DefinePCMCuts(); + DefineDalitzEECuts(); + DefinePCMibwCuts(); DefinePHOSCuts(); DefineEMCCuts(); DefinePairCuts(); @@ -102,6 +112,7 @@ struct TaggingPi0MC { fOutputEvent.setObject(reinterpret_cast(fMainList->FindObject("Event"))); fOutputPair.setObject(reinterpret_cast(fMainList->FindObject("Pair"))); + fOutputPCM.setObject(reinterpret_cast(fMainList->FindObject("PCM"))); } template @@ -124,13 +135,13 @@ struct TaggingPi0MC { std::string pair_cut_name = cut3.GetName(); o2::aod::emphotonhistograms::AddHistClass(list_pair_subsys_photoncut, pair_cut_name.data()); THashList* list_pair_subsys_paircut = reinterpret_cast(list_pair_subsys_photoncut->FindObject(pair_cut_name.data())); - o2::aod::emphotonhistograms::DefineHistograms(list_pair_subsys_paircut, "taggeing_pi0_mc"); + o2::aod::emphotonhistograms::DefineHistograms(list_pair_subsys_paircut, "tagging_pi0_mc", "pair"); } // end of pair cut loop } // end of cut2 loop } // end of cut1 loop } - static constexpr std::string_view pairnames[6] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PHOSEMC"}; + static constexpr std::string_view pairnames[8] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PCMDalitz", "PHOSEMC", "PCMPCMibw"}; void addhistograms() { fMainList->SetOwner(true); @@ -140,6 +151,13 @@ struct TaggingPi0MC { o2::aod::emphotonhistograms::AddHistClass(fMainList, "Event"); THashList* list_ev = reinterpret_cast(fMainList->FindObject("Event")); + o2::aod::emphotonhistograms::AddHistClass(fMainList, "PCM"); + THashList* list_pcm = reinterpret_cast(fMainList->FindObject("PCM")); + for (auto& cut : fPCMCuts) { + THashList* list_pcm_cut = o2::aod::emphotonhistograms::AddHistClass(list_pcm, cut.GetName()); + o2::aod::emphotonhistograms::DefineHistograms(list_pcm_cut, "tagging_pi0_mc", "pcm"); + } + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Pair"); THashList* list_pair = reinterpret_cast(fMainList->FindObject("Pair")); @@ -152,6 +170,12 @@ struct TaggingPi0MC { o2::aod::emphotonhistograms::AddHistClass(list_pair, pairname.data()); + if (pairname == "PCMPCMibw") { + add_pair_histograms(list_pair, pairname, fPCMCuts, fPCMibwCuts, fPairCuts); + } + if (pairname == "PCMDalitz") { + add_pair_histograms(list_pair, pairname, fPCMCuts, fDalitzEECuts, fPairCuts); + } if (pairname == "PCMPHOS") { add_pair_histograms(list_pair, pairname, fPCMCuts, fPHOSCuts, fPairCuts); } @@ -175,6 +199,35 @@ struct TaggingPi0MC { } LOGF(info, "Number of PCM cuts = %d", fPCMCuts.size()); } + + void DefineDalitzEECuts() + { + TString cutNamesStr = fConfigDalitzEECuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fDalitzEECuts.push_back(*dalitzeecuts::GetCut(cutname)); + } + } + LOGF(info, "Number of DalitzEE cuts = %d", fDalitzEECuts.size()); + } + + void DefinePCMibwCuts() + { + TString cutNamesStr = fConfigPCMibwCuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fPCMibwCuts.push_back(*pcmcuts::GetCut(cutname)); + } + } + LOGF(info, "Number of PCMibw cuts = %d", fPCMibwCuts.size()); + } + void DefinePHOSCuts() { TString cutNamesStr = fConfigPHOSCuts.value; @@ -249,21 +302,26 @@ struct TaggingPi0MC { bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2) { bool is_selected_pair = false; - if constexpr (pairtype == PairType::kPCMPHOS) { + if constexpr (pairtype == PairType::kPCMPCMibw) { + is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + } else if constexpr (pairtype == PairType::kPCMPHOS) { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else if constexpr (pairtype == PairType::kPCMEMC) { is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); + } else if constexpr (pairtype == PairType::kPCMDalitz) { + is_selected_pair = o2::aod::photonpair::IsSelectedPair(g1, g2, cut1, cut2); } else { is_selected_pair = true; } return is_selected_pair; } - template - void TruePairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs) + template + void TruePairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& cuts1, TCuts2 const& cuts2, TPairCuts const& paircuts, TLegs const& legs, TEMPrimaryTracks const& emprimarytracks, TMCParticles const& mcparticles, TMCEvents const& mcevents) { THashList* list_ev_pair = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())); THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); + THashList* list_pcm = static_cast(fMainList->FindObject("PCM")); for (auto& collision : collisions) { if ((pairtype == kPHOSPHOS || pairtype == kPCMPHOS) && !collision.isPHOSCPVreadout()) { @@ -292,8 +350,46 @@ struct TaggingPi0MC { reinterpret_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject("hCollisionCounter"))->Fill(4.0); // |Zvtx| < 10 cm o2::aod::emphotonhistograms::FillHistClass(list_ev_pair, "", collision); - auto photons1_coll = photons1.sliceBy(perCollision1, collision.collisionId()); - auto photons2_coll = photons2.sliceBy(perCollision2, collision.collisionId()); + auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); + + for (auto& cut1 : cuts1) { + for (auto& g1 : photons1_coll) { + + if (!cut1.template IsSelected(g1)) { + continue; + } + if (abs(g1.eta()) > maxY) { // photon is massless particle. rapidity = pseudo-rapidity + continue; + } + + auto pos1 = g1.template posTrack_as(); + auto ele1 = g1.template negTrack_as(); + auto pos1mc = pos1.template emmcparticle_as(); + auto ele1mc = ele1.template emmcparticle_as(); + + int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); + if (photonid1 < 0) { // check swap, true electron is reconstructed as positron and vice versa. + photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, 11, -11, 22, mcparticles); + } + + if (photonid1 > 0) { + auto mcphoton1 = mcparticles.iteratorAt(photonid1); + int pi0id1 = IsXFromY(mcphoton1, mcparticles, 22, 111); + if (pi0id1 > 0) { + auto mcpi01 = mcparticles.iteratorAt(pi0id1); + if (IsPhysicalPrimary(mcpi01.emreducedmcevent(), mcpi01, mcparticles)) { + reinterpret_cast(list_pcm->FindObject(Form("%s", cut1.GetName()))->FindObject("hPt_v0photon_Pi0_Primary"))->Fill(g1.pt()); + } else if (IsFromWD(mcpi01.emreducedmcevent(), mcpi01, mcparticles)) { + reinterpret_cast(list_pcm->FindObject(Form("%s", cut1.GetName()))->FindObject("hPt_v0photon_Pi0_FromWD"))->Fill(g1.pt()); + } else { + reinterpret_cast(list_pcm->FindObject(Form("%s", cut1.GetName()))->FindObject("hPt_v0photon_Pi0_hs"))->Fill(g1.pt()); + } + } + } + + } // end of pcm photon loop + } // end of cut loop for (auto& cut1 : cuts1) { for (auto& cut2 : cuts2) { @@ -302,26 +398,83 @@ struct TaggingPi0MC { if (!IsSelectedPair(g1, g2, cut1, cut2)) { continue; } + + auto pos1 = g1.template posTrack_as(); + auto ele1 = g1.template negTrack_as(); + auto pos1mc = pos1.template emmcparticle_as(); + auto ele1mc = ele1.template emmcparticle_as(); + + int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); + if (photonid1 < 0) { // check swap, true electron is reconstructed as positron and vice versa. + photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, 11, -11, 22, mcparticles); + } + if (photonid1 < 0) { + continue; + } + if constexpr (pairtype == PairType::kPCMPHOS || pairtype == PairType::kPCMEMC) { - auto pos = g1.template posTrack_as(); - auto ele = g1.template negTrack_as(); if constexpr (pairtype == PairType::kPCMPHOS) { - if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos, g2, 0.02, 0.4, 0.2) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele, g2, 0.02, 0.4, 0.2)) { + if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos1, g2, 0.02, 0.4, 0.2) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele1, g2, 0.02, 0.4, 0.2)) { continue; } } else if constexpr (pairtype == PairType::kPCMEMC) { - if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos, g2, 0.02, 0.4, 0.5) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele, g2, 0.02, 0.4, 0.5)) { + if (o2::aod::photonpair::DoesV0LegMatchWithCluster(pos1, g2, 0.02, 0.4, 0.5) || o2::aod::photonpair::DoesV0LegMatchWithCluster(ele1, g2, 0.02, 0.4, 0.5)) { continue; } } } + + int pi0id = -1; + if constexpr (pairtype == PairType::kPCMPCMibw) { + auto pos2 = g2.template posTrack_as(); + auto ele2 = g2.template negTrack_as(); + auto pos2mc = pos2.template emmcparticle_as(); + auto ele2mc = ele2.template emmcparticle_as(); + + int photonid2 = FindCommonMotherFrom2Prongs(pos2mc, ele2mc, -11, 11, 22, mcparticles); + if (photonid2 < 0) { // check swap, true electron is reconstructed as positron and vice versa. + photonid2 = FindCommonMotherFrom2Prongs(pos2mc, ele2mc, 11, -11, 22, mcparticles); + } + + if (photonid1 < 0 || photonid2 < 0) { + continue; + } + + auto g1mc = mcparticles.iteratorAt(photonid1); + auto g2mc = mcparticles.iteratorAt(photonid2); + pi0id = FindCommonMotherFrom2Prongs(g1mc, g2mc, 22, 22, 111, mcparticles); + } else if constexpr (pairtype == PairType::kPCMDalitz) { + auto g1mc = mcparticles.iteratorAt(photonid1); + auto pos2 = g2.template posTrack_as(); + auto ele2 = g2.template negTrack_as(); + auto pos2mc = pos2.template emmcparticle_as(); + auto ele2mc = ele2.template emmcparticle_as(); + pi0id = FindCommonMotherFrom3Prongs(g1mc, pos2mc, ele2mc, 22, -11, 11, 111, mcparticles); + } + if (pi0id < 0) { + continue; + } + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // pcm - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // phos or emc + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // phos or emc or dalitzee + if constexpr (pairtype == PairType::kPCMDalitz) { + v2.SetM(g2.mee()); + } ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - if (abs(v12.Rapidity()) > maxY) { - continue; + // if (abs(v12.Rapidity()) > maxY) { + // continue; + // } + + if (pi0id > 0) { + auto mcpi0 = mcparticles.iteratorAt(pi0id); + if (IsPhysicalPrimary(mcpi0.emreducedmcevent(), mcpi0, mcparticles)) { + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_Primary"))->Fill(v12.M(), v1.Pt()); + } else if (IsFromWD(mcpi0.emreducedmcevent(), mcpi0, mcparticles)) { + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_FromWD"))->Fill(v12.M(), v1.Pt()); + } else { + reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0_hs"))->Fill(v12.M(), v1.Pt()); + } } - reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", cut1.GetName(), cut2.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_Pi0"))->Fill(v12.M(), v1.Pt()); } // end of combination } // end of pair cut loop } // end of cut2 loop @@ -329,29 +482,37 @@ struct TaggingPi0MC { } // end of collision loop } - Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; - Filter collisionFilter_subsys = (o2::aod::emreducedevent::ngpcm >= 1) || (o2::aod::emreducedevent::ngphos >= 1) || (o2::aod::emreducedevent::ngemc >= 1); - using MyFilteredCollisions = soa::Filtered; + Filter DalitzEEFilter = o2::aod::dalitzee::sign == 0; // analyze only uls + using MyFilteredDalitzEEs = soa::Filtered; - Preslice perCollision_pcm = aod::v0photon::collisionId; + Preslice perCollision_pcm = aod::v0photonkf::emreducedeventId; + Preslice perCollision_dalitz = aod::dalitzee::emreducedeventId; Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; - void processPCMPHOS(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::PHOSClusters const& phosclusters, aod::V0Legs const& legs) + void processPCMPCMibw(aod::EMReducedEvents const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const& legs, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const& mccollisions) { - TruePairing(collisions, v0photons, phosclusters, perCollision_pcm, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs); + TruePairing(collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fPCMCuts, fPCMibwCuts, fPairCuts, legs, nullptr, mcparticles, mccollisions); + } + void processPCMDalitz(aod::EMReducedEvents const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const& legs, MyFilteredDalitzEEs const& dielectrons, MyMCTracks const& emprimarytracks, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const& mccollisions) + { + TruePairing(collisions, v0photons, dielectrons, perCollision_pcm, perCollision_dalitz, fPCMCuts, fDalitzEECuts, fPairCuts, legs, emprimarytracks, mcparticles, mccollisions); } - void processPCMEMC(aod::EMReducedEvents const& collisions, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::SkimEMCClusters const& emcclusters, aod::V0Legs const& legs) + void processPCMPHOS(aod::EMReducedEvents const& collisions, MyV0Photons const& v0photons, aod::PHOSClusters const& phosclusters, MyMCV0Legs const& legs, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const& mccollisions) { - TruePairing(collisions, v0photons, emcclusters, perCollision_pcm, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs); + TruePairing(collisions, v0photons, phosclusters, perCollision_pcm, perCollision_phos, fPCMCuts, fPHOSCuts, fPairCuts, legs, nullptr, mcparticles, mccollisions); } - void processDummy(aod::EMReducedEvents::iterator const& collision) + void processPCMEMC(aod::EMReducedEvents const& collisions, MyV0Photons const& v0photons, aod::SkimEMCClusters const& emcclusters, MyMCV0Legs const& legs, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const& mccollisions) { - // do nothing + TruePairing(collisions, v0photons, emcclusters, perCollision_pcm, perCollision_emc, fPCMCuts, fEMCCuts, fPairCuts, legs, nullptr, mcparticles, mccollisions); } + void processDummy(aod::EMReducedEvents::iterator const& collision) {} + + PROCESS_SWITCH(TaggingPi0MC, processPCMPCMibw, "pairing PCM-PCMibw", false); + PROCESS_SWITCH(TaggingPi0MC, processPCMDalitz, "pairing PCM-Dalitz", false); PROCESS_SWITCH(TaggingPi0MC, processPCMPHOS, "pairing PCM-PHOS", false); PROCESS_SWITCH(TaggingPi0MC, processPCMEMC, "pairing PCM-EMCal", false); PROCESS_SWITCH(TaggingPi0MC, processDummy, "Dummy function", true); diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx new file mode 100644 index 00000000000..c051485872c --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx @@ -0,0 +1,211 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over dalitz ee table for dalitz QC. +// Please write to: daiki.sekihata@cern.ch + +#include +#include "TString.h" +#include "THashList.h" +#include "TDirectory.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#include "Common/Core/RecoDecay.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" +#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using std::array; + +using MyDalitzEEs = soa::Join; +using MyDalitzEE = MyDalitzEEs::iterator; + +struct DalitzEEQC { + Configurable fConfigDalitzEECuts{"cfgDalitzEECuts", "mee_all_tpchadrejortofreq_lowB,nocut", "Comma separated list of dalitz ee cuts"}; + std::vector fDalitzEECuts; + + OutputObj fOutputEvent{"Event"}; + OutputObj fOutputTrack{"Track"}; + OutputObj fOutputDalitzEE{"DalitzEE"}; + THashList* fMainList = new THashList(); + + void addhistograms() + { + fMainList->SetOwner(true); + fMainList->SetName("fMainList"); + + // create sub lists first. + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Event"); + THashList* list_ev = reinterpret_cast(fMainList->FindObject("Event")); + o2::aod::emphotonhistograms::DefineHistograms(list_ev, "Event"); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Track"); + THashList* list_track = reinterpret_cast(fMainList->FindObject("Track")); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "DalitzEE"); + THashList* list_dalitzee = reinterpret_cast(fMainList->FindObject("DalitzEE")); + + for (const auto& cut : fDalitzEECuts) { + const char* cutname = cut.GetName(); + o2::aod::emphotonhistograms::AddHistClass(list_track, cutname); + o2::aod::emphotonhistograms::AddHistClass(list_dalitzee, cutname); + } + + // for single tracks + for (auto& cut : fDalitzEECuts) { + std::string_view cutname = cut.GetName(); + THashList* list = reinterpret_cast(fMainList->FindObject("Track")->FindObject(cutname.data())); + o2::aod::emphotonhistograms::DefineHistograms(list, "Track"); + } + + // for DalitzEEs + for (auto& cut : fDalitzEECuts) { + std::string_view cutname = cut.GetName(); + THashList* list = reinterpret_cast(fMainList->FindObject("DalitzEE")->FindObject(cutname.data())); + o2::aod::emphotonhistograms::DefineHistograms(list, "DalitzEE"); + } + } + + void DefineCuts() + { + TString cutNamesStr = fConfigDalitzEECuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fDalitzEECuts.push_back(*dalitzeecuts::GetCut(cutname)); + } + } + LOGF(info, "Number of Dalitz cuts = %d", fDalitzEECuts.size()); + } + + void init(InitContext& context) + { + DefineCuts(); + addhistograms(); // please call this after DefinCuts(); + + fOutputEvent.setObject(reinterpret_cast(fMainList->FindObject("Event"))); + fOutputTrack.setObject(reinterpret_cast(fMainList->FindObject("Track"))); + fOutputDalitzEE.setObject(reinterpret_cast(fMainList->FindObject("DalitzEE"))); + } + + Partition uls_pairs = o2::aod::dalitzee::sign == 0; + Partition lspp_pairs = o2::aod::dalitzee::sign == +1; + Partition lsmm_pairs = o2::aod::dalitzee::sign == -1; + + SliceCache cache; + Preslice perCollision = aod::dalitzee::emreducedeventId; + void processQC(aod::EMReducedEvents const& collisions, MyDalitzEEs const& dileptons, aod::EMPrimaryTracks const& tracks) + { + THashList* list_ev = static_cast(fMainList->FindObject("Event")); + THashList* list_dalitzee = static_cast(fMainList->FindObject("DalitzEE")); + THashList* list_track = static_cast(fMainList->FindObject("Track")); + double values[4] = {0, 0, 0, 0}; + + for (auto& collision : collisions) { + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hZvtx_before"))->Fill(collision.posZ()); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(1.0); + if (!collision.sel8()) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(2.0); + + if (collision.numContrib() < 0.5) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(3.0); + + if (abs(collision.posZ()) > 10.0) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(4.0); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hZvtx_after"))->Fill(collision.posZ()); + o2::aod::emphotonhistograms::FillHistClass(list_ev, "", collision); + + // auto dileptons_coll = dileptons.sliceBy(perCollision, collision.collisionId()); + + auto uls_pairs_per_coll = uls_pairs->sliceByCached(o2::aod::dalitzee::emreducedeventId, collision.globalIndex(), cache); + auto lspp_pairs_per_coll = lspp_pairs->sliceByCached(o2::aod::dalitzee::emreducedeventId, collision.globalIndex(), cache); + auto lsmm_pairs_per_coll = lsmm_pairs->sliceByCached(o2::aod::dalitzee::emreducedeventId, collision.globalIndex(), cache); + + for (const auto& cut : fDalitzEECuts) { + THashList* list_dalitzee_cut = static_cast(list_dalitzee->FindObject(cut.GetName())); + THashList* list_track_cut = static_cast(list_track->FindObject(cut.GetName())); + + int nuls = 0, nlspp = 0, nlsmm = 0; + for (auto& uls_pair : uls_pairs_per_coll) { + auto pos = uls_pair.posTrack_as(); + auto ele = uls_pair.negTrack_as(); + if (cut.IsSelected(uls_pair)) { + values[0] = uls_pair.mee(); + values[1] = uls_pair.pt(); + values[2] = uls_pair.dcaeeXY(); + values[3] = uls_pair.phiv(); + reinterpret_cast(list_dalitzee_cut->FindObject("hs_dilepton_uls"))->Fill(values); + nuls++; + for (auto& leg : {pos, ele}) { + o2::aod::emphotonhistograms::FillHistClass(list_track_cut, "", leg); + } + } + } // end of uls pair loop + reinterpret_cast(list_dalitzee_cut->FindObject("hNpair_uls"))->Fill(nuls); + + for (auto& lspp_pair : lspp_pairs_per_coll) { + if (cut.IsSelected(lspp_pair)) { + values[0] = lspp_pair.mee(); + values[1] = lspp_pair.pt(); + values[2] = lspp_pair.dcaeeXY(); + values[3] = lspp_pair.phiv(); + reinterpret_cast(list_dalitzee_cut->FindObject("hs_dilepton_lspp"))->Fill(values); + nlspp++; + } + } // end of lspp pair loop + reinterpret_cast(list_dalitzee_cut->FindObject("hNpair_lspp"))->Fill(nlspp); + + for (auto& lsmm_pair : lsmm_pairs_per_coll) { + if (cut.IsSelected(lsmm_pair)) { + values[0] = lsmm_pair.mee(); + values[1] = lsmm_pair.pt(); + values[2] = lsmm_pair.dcaeeXY(); + values[3] = lsmm_pair.phiv(); + reinterpret_cast(list_dalitzee_cut->FindObject("hs_dilepton_lsmm"))->Fill(values); + nlsmm++; + } + } // end of lsmm pair loop + reinterpret_cast(list_dalitzee_cut->FindObject("hNpair_lsmm"))->Fill(nlsmm); + + } // end of cut loop + } // end of collision loop + } // end of process + PROCESS_SWITCH(DalitzEEQC, processQC, "run Dalitz QC", true); + + void processDummy(aod::EMReducedEvents::iterator const& collision) {} + PROCESS_SWITCH(DalitzEEQC, processDummy, "Dummy function", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"dalitz-ee-qc"})}; +} diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx new file mode 100644 index 00000000000..8df4f53307d --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx @@ -0,0 +1,204 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over dalitz ee table for dalitz QC. +// Please write to: daiki.sekihata@cern.ch + +#include +#include "TString.h" +#include "THashList.h" +#include "TDirectory.h" +#include "Math/Vector4D.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#include "Common/Core/RecoDecay.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" +#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using std::array; + +using MyDalitzEEs = soa::Join; +using MyDalitzEE = MyDalitzEEs::iterator; + +struct DalitzEEQCMC { + Configurable fConfigDalitzEECuts{"cfgDalitzEECuts", "mee_all_tpchadrejortofreq_lowB,nocut", "Comma separated list of dalitz ee cuts"}; + std::vector fDalitzEECuts; + + OutputObj fOutputEvent{"Event"}; + OutputObj fOutputTrack{"Track"}; + OutputObj fOutputDalitzEE{"DalitzEE"}; + THashList* fMainList = new THashList(); + + void addhistograms() + { + fMainList->SetOwner(true); + fMainList->SetName("fMainList"); + + // create sub lists first. + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Event"); + THashList* list_ev = reinterpret_cast(fMainList->FindObject("Event")); + o2::aod::emphotonhistograms::DefineHistograms(list_ev, "Event"); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "Track"); + THashList* list_track = reinterpret_cast(fMainList->FindObject("Track")); + + o2::aod::emphotonhistograms::AddHistClass(fMainList, "DalitzEE"); + THashList* list_dalitzee = reinterpret_cast(fMainList->FindObject("DalitzEE")); + + for (const auto& cut : fDalitzEECuts) { + const char* cutname = cut.GetName(); + o2::aod::emphotonhistograms::AddHistClass(list_track, cutname); + o2::aod::emphotonhistograms::AddHistClass(list_dalitzee, cutname); + } + + // for single tracks + for (auto& cut : fDalitzEECuts) { + std::string_view cutname = cut.GetName(); + THashList* list = reinterpret_cast(fMainList->FindObject("Track")->FindObject(cutname.data())); + o2::aod::emphotonhistograms::DefineHistograms(list, "Track"); + } + + // for DalitzEEs + for (auto& cut : fDalitzEECuts) { + std::string_view cutname = cut.GetName(); + THashList* list = reinterpret_cast(fMainList->FindObject("DalitzEE")->FindObject(cutname.data())); + o2::aod::emphotonhistograms::DefineHistograms(list, "DalitzEE"); + } + } + + void DefineCuts() + { + TString cutNamesStr = fConfigDalitzEECuts.value; + if (!cutNamesStr.IsNull()) { + std::unique_ptr objArray(cutNamesStr.Tokenize(",")); + for (int icut = 0; icut < objArray->GetEntries(); ++icut) { + const char* cutname = objArray->At(icut)->GetName(); + LOGF(info, "add cut : %s", cutname); + fDalitzEECuts.push_back(*dalitzeecuts::GetCut(cutname)); + } + } + LOGF(info, "Number of Dalitz cuts = %d", fDalitzEECuts.size()); + } + + void init(InitContext& context) + { + DefineCuts(); + addhistograms(); // please call this after DefinCuts(); + + fOutputEvent.setObject(reinterpret_cast(fMainList->FindObject("Event"))); + fOutputTrack.setObject(reinterpret_cast(fMainList->FindObject("Track"))); + fOutputDalitzEE.setObject(reinterpret_cast(fMainList->FindObject("DalitzEE"))); + } + + template + int FindLF(TTrack const& posmc, TTrack const& elemc, TMCTracks const& mcparticles) + { + int arr[] = { + FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 111, mcparticles), FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 221, mcparticles), FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 331, mcparticles), FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 113, mcparticles), FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 223, mcparticles), FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 333, mcparticles)}; + int size = sizeof(arr) / sizeof(*arr); + int max = *std::max_element(arr, arr + size); + return max; + } + + Partition uls_pairs = o2::aod::dalitzee::sign == 0; + + SliceCache cache; + Preslice perCollision = aod::dalitzee::emreducedeventId; + using MyMCTracks = soa::Join; + void processQCMC(aod::EMReducedEvents const& collisions, MyDalitzEEs const& dileptons, MyMCTracks const& tracks, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const&) + { + THashList* list_ev = static_cast(fMainList->FindObject("Event")); + THashList* list_dalitzee = static_cast(fMainList->FindObject("DalitzEE")); + THashList* list_track = static_cast(fMainList->FindObject("Track")); + double values[4] = {0, 0, 0, 0}; + + for (auto& collision : collisions) { + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hZvtx_before"))->Fill(collision.posZ()); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(1.0); + if (!collision.sel8()) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(2.0); + + if (collision.numContrib() < 0.5) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(3.0); + + if (abs(collision.posZ()) > 10.0) { + continue; + } + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hCollisionCounter"))->Fill(4.0); + reinterpret_cast(fMainList->FindObject("Event")->FindObject("hZvtx_after"))->Fill(collision.posZ()); + o2::aod::emphotonhistograms::FillHistClass(list_ev, "", collision); + + auto uls_pairs_per_coll = uls_pairs->sliceByCached(o2::aod::dalitzee::emreducedeventId, collision.globalIndex(), cache); + + for (const auto& cut : fDalitzEECuts) { + THashList* list_dalitzee_cut = static_cast(list_dalitzee->FindObject(cut.GetName())); + THashList* list_track_cut = static_cast(list_track->FindObject(cut.GetName())); + + int nuls = 0; + for (auto& uls_pair : uls_pairs_per_coll) { + auto pos = uls_pair.posTrack_as(); + auto ele = uls_pair.negTrack_as(); + auto posmc = pos.template emmcparticle_as(); + auto elemc = ele.template emmcparticle_as(); + + int mother_id = FindLF(posmc, elemc, mcparticles); + if (mother_id < 0) { + continue; + } + auto mcmother = mcparticles.iteratorAt(mother_id); + + if (!IsPhysicalPrimary(mcmother.emreducedmcevent(), mcmother, mcparticles)) { + continue; + } + if (cut.IsSelected(uls_pair)) { + values[0] = uls_pair.mee(); + values[1] = uls_pair.pt(); + values[2] = uls_pair.dcaeeXY(); + values[3] = uls_pair.phiv(); + reinterpret_cast(list_dalitzee_cut->FindObject("hs_dilepton_uls"))->Fill(values); + nuls++; + for (auto& leg : {pos, ele}) { + o2::aod::emphotonhistograms::FillHistClass(list_track_cut, "", leg); + } + } + } // end of uls pair loop + reinterpret_cast(list_dalitzee_cut->FindObject("hNpair_uls"))->Fill(nuls); + } // end of cut loop + } // end of collision loop + } // end of process + PROCESS_SWITCH(DalitzEEQCMC, processQCMC, "run Dalitz QC", true); + + void processDummy(aod::EMReducedEvents::iterator const& collision) {} + PROCESS_SWITCH(DalitzEEQCMC, processDummy, "Dummy function", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"dalitz-ee-qc-mc"})}; +} diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index 852306803b9..cb81d1809e1 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -48,12 +48,12 @@ using namespace o2::framework::expressions; using namespace o2::soa; using std::array; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; struct PCMQC { - Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,qc,nocut", "Comma separated list of v0 photon cuts"}; + Configurable fConfigPCMCuts{"cfgPCMCuts", "analysis,wwire_ib,qc,qc_ITSTPC,qc_ITSonly,qc_TPConly,nocut", "Comma separated list of v0 photon cuts"}; std::vector fPCMCuts; @@ -124,7 +124,8 @@ struct PCMQC { fOutputV0.setObject(reinterpret_cast(fMainList->FindObject("V0"))); } - Preslice perCollision = aod::v0photon::collisionId; + // Preslice perCollision = aod::v0photon::collisionId; + Preslice perCollision = aod::v0photonkf::emreducedeventId; void processQC(aod::EMReducedEvents const& collisions, MyV0Photons const& v0photons, aod::V0Legs const& v0legs) { THashList* list_ev = static_cast(fMainList->FindObject("Event")); @@ -163,6 +164,8 @@ struct PCMQC { if (cut.IsSelected(v0)) { o2::aod::emphotonhistograms::FillHistClass(list_v0_cut, "", v0); nv0++; + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hCorrTgl"))->Fill(ele.tgl(), pos.tgl()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hCorrZ"))->Fill(ele.z(), pos.z()); for (auto& leg : {pos, ele}) { o2::aod::emphotonhistograms::FillHistClass(list_v0leg_cut, "", leg); } diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index 163f5a81b1d..b36203e5316 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -48,7 +48,7 @@ using namespace o2::framework::expressions; using namespace o2::soa; using std::array; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; struct PCMQCMC { @@ -63,10 +63,8 @@ struct PCMQCMC { OutputObj fOutputGen{"Generated"}; THashList* fMainList = new THashList(); - // static constexpr std::string_view ambtracktypes[2] = {"NonAmb", "Amb"}; void addhistograms() { - fMainList->SetOwner(true); fMainList->SetName("fMainList"); @@ -84,7 +82,6 @@ struct PCMQCMC { o2::aod::emphotonhistograms::AddHistClass(fMainList, "Generated"); THashList* list_gen = reinterpret_cast(fMainList->FindObject("Generated")); o2::aod::emphotonhistograms::DefineHistograms(list_gen, "Generated", "Photon"); - o2::aod::emphotonhistograms::DefineHistograms(list_gen, "Generated", "ConversionStudy"); for (const auto& cut : fPCMCuts) { const char* cutname = cut.GetName(); @@ -132,8 +129,8 @@ struct PCMQCMC { fOutputGen.setObject(reinterpret_cast(fMainList->FindObject("Generated"))); } - Preslice perCollision = aod::v0photon::collisionId; - using MyMCV0Legs = soa::Join; + Preslice perCollision = aod::v0photon::emreducedeventId; + using MyMCV0Legs = soa::Join; void processQCMC(soa::Join const& collisions, MyV0Photons const& v0photons, MyMCV0Legs const& v0legs, aod::EMMCParticles const& mcparticles, aod::EMReducedMCEvents const&) { THashList* list_ev = static_cast(fMainList->FindObject("Event")); @@ -202,10 +199,10 @@ struct PCMQCMC { // } // LOGF(info, "mcphoton.vx() = %f, mcphoton.vy() = %f, mcphoton.vz() = %f, mother_pdg = %d", mcphoton.vx(), mcphoton.vy(), mcphoton.vz(), mother_pdg); float rxy = sqrt(mcphoton.vx() * mcphoton.vx() + mcphoton.vy() * mcphoton.vy()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hRZ_Photon_test"))->Fill(mcphoton.vz(), rxy); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPt_Photon_test"))->Fill(v0.pt()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEta_Photon_test"))->Fill(v0.eta()); - reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPhi_Photon_test"))->Fill(v0.phi()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hRZ_Photon_hs"))->Fill(mcphoton.vz(), rxy); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPt_Photon_hs"))->Fill(v0.pt()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hEta_Photon_hs"))->Fill(v0.eta()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hPhi_Photon_hs"))->Fill(v0.phi()); } reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hConvPoint_diffX"))->Fill(elemc.vx(), v0.vx() - elemc.vx()); @@ -216,6 +213,8 @@ struct PCMQCMC { reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hConvPoint_diffZ_recalc"))->Fill(elemc.vz(), v0.recalculatedVtxZ() - elemc.vz()); nv0++; + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hCorrTgl"))->Fill(ele.tgl(), pos.tgl()); + reinterpret_cast(fMainList->FindObject("V0")->FindObject(cut.GetName())->FindObject("hCorrZ"))->Fill(ele.z(), pos.z()); for (auto& leg : {pos, ele}) { o2::aod::emphotonhistograms::FillHistClass(list_v0leg_cut, "", leg); } @@ -260,18 +259,6 @@ struct PCMQCMC { continue; } - int photonid = IsEleFromPC(mctrack, mcparticles); - if (photonid > 0) { - auto mcphoton = mcparticles.iteratorAt(photonid); - if (!IsPhysicalPrimary(mcphoton.emreducedmcevent(), mcphoton, mcparticles)) { - continue; - } - float rxy = sqrt(pow(mctrack.vx(), 2) + pow(mctrack.vy(), 2)); - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPhotonRZ"))->Fill(mctrack.vz(), rxy); - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPhotonRxy"))->Fill(mctrack.vx(), mctrack.vy()); - reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPhotonPhivsRxy"))->Fill(mctrack.phi(), rxy); - } - if (abs(mctrack.pdgCode()) == 22 && IsPhysicalPrimary(mctrack.emreducedmcevent(), mctrack, mcparticles)) { reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hPt_Photon"))->Fill(mctrack.pt()); reinterpret_cast(fMainList->FindObject("Generated")->FindObject("hY_Photon"))->Fill(mctrack.y()); diff --git a/PWGEM/PhotonMeson/Utils/MCUtilities.h b/PWGEM/PhotonMeson/Utils/MCUtilities.h index 6dd3dfc8b75..26e5bdb80f5 100644 --- a/PWGEM/PhotonMeson/Utils/MCUtilities.h +++ b/PWGEM/PhotonMeson/Utils/MCUtilities.h @@ -107,6 +107,26 @@ bool IsFromWD(TCollision const& mccollision, T const& mctrack, TMCs const& mcTra } //_______________________________________________________________________ template +int IsXFromY(T const& mctrack, TMCs const& mcTracks, const int pdgX, const int pdgY) +{ + // is photon from pi0? returns index of mother photon + if (mctrack.pdgCode() != pdgX) { + return -1; + } + if (mctrack.has_mothers()) { + int motherid = mctrack.mothersIds()[0]; // first mother + auto mp = mcTracks.iteratorAt(motherid); + int pdg_mother = mp.pdgCode(); + if (pdg_mother == pdgY) { + return motherid; + } + } else { + return -1; + } + return -1; +} +//_______________________________________________________________________ +template int IsEleFromPC(T const& mctrack, TMCs const& mcTracks) { // is election from photon conversion? returns index of mother photon @@ -163,5 +183,63 @@ int FindCommonMotherFrom2Prongs(TMCParticle1 const& p1, TMCParticle2 const& p2, return -1; return motherid1; } +template +int FindCommonMotherFrom3Prongs(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticle3 const& p3, const int expected_pdg1, const int expected_pdg2, const int expected_pdg3, const int expected_mother_pdg, TMCParticles const& mcparticles) +{ + if (p1.globalIndex() == p2.globalIndex()) + return -1; // mc particle p1 and p2 are identical. reject. + if (p2.globalIndex() == p3.globalIndex()) + return -1; // mc particle p2 and p3 are identical. reject. + if (p3.globalIndex() == p1.globalIndex()) + return -1; // mc particle p3 and p1 are identical. reject. + + if (p1.pdgCode() != expected_pdg1) + return -1; + if (p2.pdgCode() != expected_pdg2) + return -1; + if (p3.pdgCode() != expected_pdg3) + return -1; + + if (!p1.has_mothers()) + return -1; + if (!p2.has_mothers()) + return -1; + if (!p3.has_mothers()) + return -1; + + // LOGF(info,"original motherid1 = %d , motherid2 = %d", p1.mothersIds()[0], p2.mothersIds()[0]); + + int motherid1 = p1.mothersIds()[0]; + auto mother1 = mcparticles.iteratorAt(motherid1); + int mother1_pdg = mother1.pdgCode(); + + int motherid2 = p2.mothersIds()[0]; + auto mother2 = mcparticles.iteratorAt(motherid2); + int mother2_pdg = mother2.pdgCode(); + + int motherid3 = p3.mothersIds()[0]; + auto mother3 = mcparticles.iteratorAt(motherid3); + int mother3_pdg = mother3.pdgCode(); + + // LOGF(info,"motherid1 = %d , motherid2 = %d", motherid1, motherid2); + + if (motherid1 != motherid2) + return -1; + if (motherid2 != motherid3) + return -1; + if (motherid3 != motherid1) + return -1; + + if (mother1_pdg != mother2_pdg) + return -1; + if (mother2_pdg != mother3_pdg) + return -1; + if (mother3_pdg != mother1_pdg) + return -1; + + if (mother1_pdg != expected_mother_pdg) + return -1; + return motherid1; +} //_______________________________________________________________________ #endif // PWGEM_PHOTONMESON_UTILS_MCUTILITIES_H_ diff --git a/PWGEM/PhotonMeson/Utils/PCMUtilities.h b/PWGEM/PhotonMeson/Utils/PCMUtilities.h index 3c027f821e4..1db64e04b36 100644 --- a/PWGEM/PhotonMeson/Utils/PCMUtilities.h +++ b/PWGEM/PhotonMeson/Utils/PCMUtilities.h @@ -15,13 +15,15 @@ #ifndef PWGEM_PHOTONMESON_UTILS_PCMUTILITIES_H_ #define PWGEM_PHOTONMESON_UTILS_PCMUTILITIES_H_ +#include +#include "DCAFitter/HelixHelper.h" +#include "DetectorsBase/Propagator.h" +#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" //_______________________________________________________________________ -bool checkAP(float alpha, float qt) +bool checkAP(const float alpha, const float qt, const float alpha_max = 0.95, const float qt_max = 0.05) { - const float alpha_max = 0.95; - const float qt_max = 0.05; float ellipse = pow(alpha / alpha_max, 2) + pow(qt / qt_max, 2); if (ellipse < 1.0) { return true; @@ -30,6 +32,147 @@ bool checkAP(float alpha, float qt) } } //_______________________________________________________________________ +template +void Vtx_recalculation(o2::base::Propagator* prop, T lTrackPos, T lTrackNeg, float xyz[3]) +{ + float bz = prop->getNominalBz(); + + //******************************************************* + + // o2::track::TrackParametrizationWithError = TrackParCov, I use the full version to have control over the data type + o2::track::TrackParametrizationWithError trackPosInformation = getTrackParCov(lTrackPos); // first get an object that stores Track information (positive) + o2::track::TrackParametrizationWithError trackNegInformation = getTrackParCov(lTrackNeg); // first get an object that stores Track information (negative) + + o2::track::TrackAuxPar helixPos(trackPosInformation, bz); // This object is a descendant of a CircleXY and stores cirlce information with respect to the magnetic field. This object uses functions and information of the o2::track::TrackParametrizationWithError object (positive) + o2::track::TrackAuxPar helixNeg(trackNegInformation, bz); // This object is a descendant of a CircleXY and stores cirlce information with respect to the magnetic field. This object uses functions and information of the o2::track::TrackParametrizationWithError object (negative) + + xyz[0] = (helixPos.xC * helixNeg.rC + helixNeg.xC * helixPos.rC) / (helixPos.rC + helixNeg.rC); // This calculates the coordinates of the conversion point as an weighted average of the two helix centers. xC and yC should be the global coordinates for the helix center as far as I understand. But you can double check the code of trackPosInformation.getCircleParamsLoc + xyz[1] = (helixPos.yC * helixNeg.rC + helixNeg.yC * helixPos.rC) / (helixPos.rC + helixNeg.rC); // If this calculation doesn't work check if the rotateZ function, because the "documentation" says I get global coordinates but maybe i don't. + + // I am unsure about the Z calculation but this is how it is done in AliPhysics as far as I understand + o2::track::TrackParametrizationWithError trackPosInformationCopy = o2::track::TrackParametrizationWithError(trackPosInformation); + o2::track::TrackParametrizationWithError trackNegInformationCopy = o2::track::TrackParametrizationWithError(trackNegInformation); + + // I think this calculation gets the closest point on the track to the conversion point + // This alpha is a different alpha than the usual alpha and I think it is the angle between X axis and conversion point + Double_t alphaPos = TMath::Pi() + TMath::ATan2(-(xyz[1] - helixPos.yC), -(xyz[0] - helixPos.xC)); + Double_t alphaNeg = TMath::Pi() + TMath::ATan2(-(xyz[1] - helixNeg.yC), -(xyz[0] - helixNeg.xC)); + + Double_t vertexXPos = helixPos.xC + helixPos.rC * TMath::Cos(alphaPos); + Double_t vertexYPos = helixPos.yC + helixPos.rC * TMath::Sin(alphaPos); + Double_t vertexXNeg = helixNeg.xC + helixNeg.rC * TMath::Cos(alphaNeg); + Double_t vertexYNeg = helixNeg.yC + helixNeg.rC * TMath::Sin(alphaNeg); + + TVector2 vertexPos(vertexXPos, vertexYPos); + TVector2 vertexNeg(vertexXNeg, vertexYNeg); + + // Convert to local coordinate system + TVector2 vertexPosRot = vertexPos.Rotate(-trackPosInformationCopy.getAlpha()); + TVector2 vertexNegRot = vertexNeg.Rotate(-trackNegInformationCopy.getAlpha()); + + prop->propagateToX(trackPosInformationCopy, + vertexPosRot.X(), + bz, + o2::base::PropagatorImpl::MAX_SIN_PHI, + o2::base::PropagatorImpl::MAX_STEP, + o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE); + // o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); + prop->propagateToX(trackNegInformationCopy, + vertexNegRot.X(), + bz, + o2::base::PropagatorImpl::MAX_SIN_PHI, + o2::base::PropagatorImpl::MAX_STEP, + o2::base::PropagatorImpl::MatCorrType::USEMatCorrNONE); + // o2::base::PropagatorImpl::MatCorrType::USEMatCorrLUT); + + // TODO: This is still off and needs to be checked... + xyz[2] = (trackPosInformationCopy.getZ() * helixNeg.rC + trackNegInformationCopy.getZ() * helixPos.rC) / (helixPos.rC + helixNeg.rC); +} //_______________________________________________________________________ +float getPhivPair(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, int cpos, int cneg, float bz) +{ + // cos(phiv) = w*a /|w||a| + // with w = u x v + // and a = u x z / |u x z| , unit vector perpendicular to v12 and z-direction (magnetic field) + // u = v12 / |v12| , the unit vector of v12 + // v = v1 x v2 / |v1 x v2| , unit vector perpendicular to v1 and v2 + + // momentum of e+ and e- in (ax,ay,az) axis. Note that az=0 by definition. + // vector product of pep X pem + // std::array arr_pos{t1.GetPx(), t1.GetPy(), t1.GetPz()}; + // std::array arr_ele{t2.GetPx(), t2.GetPy(), t2.GetPz()}; + std::array arr_pos{pxpos, pypos, pzpos}; + std::array arr_ele{pxneg, pyneg, pzneg}; + std::array pos_x_ele{0, 0, 0}; + // LOGF(info, "Q1 = %d , Q2 = %d", cpos, cneg); + + if (cpos * cneg > 0) { // Like Sign + if (bz < 0) { + if (cpos > 0) { + pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); + } else { + pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); + } + } else { + if (cpos > 0) { + pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); + } else { + pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); + } + } + } else { // Unlike Sign + if (bz > 0) { + if (cpos > 0) { + pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); + } else { + pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); + } + } else { + if (cpos > 0) { + pos_x_ele = RecoDecay::crossProd(arr_ele, arr_pos); + } else { + pos_x_ele = RecoDecay::crossProd(arr_pos, arr_ele); + } + } + } + + // unit vector of pep X pem + float vx = pos_x_ele[0] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); + float vy = pos_x_ele[1] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); + float vz = pos_x_ele[2] / RecoDecay::sqrtSumOfSquares(pos_x_ele[0], pos_x_ele[1], pos_x_ele[2]); + + // unit vector of (pep+pem) + float ux = (pxpos + pxneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + float uy = (pypos + pyneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + float uz = (pzpos + pzneg) / RecoDecay::sqrtSumOfSquares(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); + + float ax = uy / TMath::Sqrt(ux * ux + uy * uy); + float ay = -ux / TMath::Sqrt(ux * ux + uy * uy); + + // The third axis defined by vector product (ux,uy,uz)X(vx,vy,vz) + float wx = uy * vz - uz * vy; + float wy = uz * vx - ux * vz; + // by construction, (wx,wy,wz) must be a unit vector. Measure angle between (wx,wy,wz) and (ax,ay,0). + // The angle between them should be small if the pair is conversion. This function then returns values close to pi! + return TMath::ACos(wx * ax + wy * ay); // phiv in [0,pi] //cosPhiV = wx * ax + wy * ay; +} +//_______________________________________________________________________ +float getPsiPair(float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) +{ + // float pxpos = t1.GetPx(); + // float pypos = t1.GetPy(); + // float pzpos = t1.GetPz(); + // float pxneg = t2.GetPx(); + // float pyneg = t2.GetPy(); + // float pzneg = t2.GetPz(); + + auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; + float ptot2 = RecoDecay::p2(pxpos, pypos, pzpos) * RecoDecay::p2(pxneg, pyneg, pzneg); + float argcos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}) / std::sqrt(ptot2); + float thetaPos = std::atan2(RecoDecay::sqrtSumOfSquares(pxpos, pypos), pzpos); + float thetaNeg = std::atan2(RecoDecay::sqrtSumOfSquares(pxneg, pyneg), pzneg); + float argsin = (thetaNeg - thetaPos) / std::acos(clipToPM1(argcos)); + return std::asin(clipToPM1(argsin)); +} //_______________________________________________________________________ #endif // PWGEM_PHOTONMESON_UTILS_PCMUTILITIES_H_ diff --git a/PWGEM/PhotonMeson/Utils/PairUtilities.h b/PWGEM/PhotonMeson/Utils/PairUtilities.h index 47d0d296db6..e537a865cb2 100644 --- a/PWGEM/PhotonMeson/Utils/PairUtilities.h +++ b/PWGEM/PhotonMeson/Utils/PairUtilities.h @@ -16,22 +16,21 @@ #define PWGEM_PHOTONMESON_UTILS_PAIRUTILITIES_H_ #include -#include "Framework/AnalysisTask.h" +#include -//_______________________________________________________________________ +namespace o2::aod::photonpair +{ enum PairType { kPCMPCM = 0, kPHOSPHOS = 1, kEMCEMC = 2, kPCMPHOS = 3, kPCMEMC = 4, - kPHOSEMC = 5, + kPCMDalitz = 5, + kPHOSEMC = 6, + kPCMPCMibw = 7, }; -//_______________________________________________________________________ -namespace o2::aod -{ -namespace photonpair -{ + template bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const& cut2) { @@ -39,9 +38,9 @@ bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& cut1, TCut2 const bool is_g2_selected = false; is_g1_selected = cut1.template IsSelected(g1); is_g2_selected = cut2.template IsSelected(g2); - return (is_g1_selected & is_g2_selected); + return (is_g1_selected && is_g2_selected); } -//_______________________________________________________________________ + template bool DoesV0LegMatchWithCluster(TV0Leg const& v0leg, TCluster const& cluster, const float max_deta, const float max_dphi, const float max_Ep_width) { @@ -49,12 +48,8 @@ bool DoesV0LegMatchWithCluster(TV0Leg const& v0leg, TCluster const& cluster, con float dphi = TVector2::Phi_mpi_pi(TVector2::Phi_0_2pi(v0leg.phi()) - TVector2::Phi_0_2pi(cluster.phi())); // float dR = sqrt(deta * deta + dphi * dphi); float Ep = cluster.e() / v0leg.p(); - return (pow(deta / max_deta, 2) + pow(dphi / max_dphi, 2) < 1) & (abs(Ep - 1) < max_Ep_width); + return (pow(deta / max_deta, 2) + pow(dphi / max_dphi, 2) < 1) && (abs(Ep - 1) < max_Ep_width); } -//_______________________________________________________________________ -} // namespace photonpair -} // namespace o2::aod -//_______________________________________________________________________ -//_______________________________________________________________________ -//_______________________________________________________________________ +} // namespace o2::aod::photonpair + #endif // PWGEM_PHOTONMESON_UTILS_PAIRUTILITIES_H_ diff --git a/PWGEM/PhotonMeson/Utils/TrackSelection.h b/PWGEM/PhotonMeson/Utils/TrackSelection.h new file mode 100644 index 00000000000..1254f55ec23 --- /dev/null +++ b/PWGEM/PhotonMeson/Utils/TrackSelection.h @@ -0,0 +1,235 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \brief helper functions for pair track selection +/// \author felix.schlepper@cern.ch + +#ifndef PWGEM_PHOTONMESON_UTILS_TRACKSELECTION_H_ +#define PWGEM_PHOTONMESON_UTILS_TRACKSELECTION_H_ + +#include "TPDGCode.h" +#include "Framework/AnalysisDataModel.h" + +namespace o2::pwgem::photonmeson +{ + +/** + * @brief Track has ITS and TPC + * + * @tparam TTrack track + * @param track track + * @return true if has both + */ +template +inline bool isITSTPCTrack(TTrack const& track) +{ + return track.hasITS() && track.hasTPC(); +} + +/** + * @brief Track has TPC and TRD + * + * @tparam TTrack track + * @param track track + * @return true if has both + */ +template +inline bool isTPCTRDTrack(TTrack const& track) +{ + return !track.hasITS() && track.hasTPC() && track.hasTRD(); +} + +/** + * @brief Track has ITS,TPC and TRD + * + * @tparam TTrack track + * @param track track + * @return true if has all + */ +template +inline bool isITSTPCTRDTrack(TTrack const& track) +{ + return track.hasITS() && track.hasTPC() && track.hasTRD(); +} + +/** + * @brief Track has TPC and TOF + * @tparam TTrack track + * @param track track + * @return true if has both + */ +template +inline bool isTPCTOFTrack(TTrack const& track) +{ + return !track.hasITS() && track.hasTPC() && !track.hasTRD() && track.hasTOF(); +} + +/** + * @brief Track has TPC,TRD and TOF + * @tparam TTrack track + * @param track track + * @return true if has all + */ +template +inline bool isTPCTRDTOFTrack(TTrack const& track) +{ + return !track.hasITS() && track.hasTPC() && track.hasTRD() && track.hasTOF(); +} + +/** + * @brief Track has ITS,TPC,TRD and TOF + * @tparam TTrack track + * @param track track + * @return true if has all + */ +template +inline bool isITSTPCTRDTOFTrack(TTrack const& track) +{ + return track.hasITS() && track.hasTPC() && track.hasTRD() && track.hasTOF(); +} + +/** + * @brief Track is TPC-only + * + * @tparam TTrack track + * @param track track + * @return true if tracks is TPC-only + */ +template +inline bool isTPConlyTrack(TTrack const& track) +{ + return !track.hasITS() && track.hasTPC() && !track.hasTRD() && !track.hasTOF(); +} + +/** + * @brief Track is ITS-only + * + * @tparam TTrack track + * @param track track + * @return true if tracks is ITS-only + */ +template +inline bool isITSonlyTrack(TTrack const& track) +{ + return track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF(); +} + +/** + * @brief If both V0 pairs are ITSTPC-tracks + * + * @tparam TTrack track + * @param track0 track from daughter 0 + * @param track1 track from daughter 1 + * @return true if V0 pairs are ITSTPC-tracks + */ +template +inline bool isITSTPC_ITSTPC(TTrack const& track0, TTrack const& track1) +{ + return isITSTPCTrack(track0) && isITSTPCTrack(track1); +} + +/** + * @brief If one track is TPC-only the other ITSTPC + * + * @tparam TTrack track + * @param track0 track from daughter 0 + * @param track1 track from daughter 1 + * @return true if one is TPC-only and the other ITSTPC + */ +template +inline bool isITSTPC_TPConly(TTrack const& track0, TTrack const& track1) +{ + return (isITSTPCTrack(track0) && isTPConlyTrack(track1)) || (isITSTPCTrack(track1) && isTPConlyTrack(track0)); +} + +/** + * @brief If one track is ITS-only the other ITSTPC + * + * @tparam TTrack track + * @param track0 track from daughter 0 + * @param track1 track from daughter 1 + * @return true if one is ITS-only and the other ITSTPC + */ +template +inline bool isITSTPC_ITSonly(TTrack const& track0, TTrack const& track1) +{ + return (isITSTPCTrack(track0) && isITSonlyTrack(track1)) || (isITSTPCTrack(track1) && isITSonlyTrack(track0)); +} + +/** + * @brief If V0 pairs are TPC-only tracks + * + * @tparam TTrack track + * @param track0 track from daughter 0 + * @param track1 track from daughter 1 + * @return true if both are TPC-only tracks + */ +template +inline bool isTPConly_TPConly(TTrack const& track0, TTrack const& track1) +{ + return isTPConlyTrack(track0) && isTPConlyTrack(track1); +} + +/** + * @brief If V0 pairs are ITS-only tracks + * + * @tparam TTrack track + * @param track0 track from daughter 0 + * @param track1 track from daughter 1 + * @return true if both are ITS-only tracks + */ +template +inline bool isITSonly_ITSonly(TTrack const& track0, TTrack const& track1) +{ + return isITSonlyTrack(track0) && isITSonlyTrack(track1); +} + +/** + * @brief If one V0 pair is ITS-only and the other TPC-only + * + * @tparam TTrack track + * @param track0 track from daughter 0 + * @param track1 track from daughter 1 + * @return true if either one is ITS-only while the other one is TPC-only + */ +template +inline bool isTPConly_ITSonly(TTrack const& track0, TTrack const& track1) +{ + return (isTPConlyTrack(track0) && isITSonlyTrack(track1)) || (isTPConlyTrack(track1) && isITSonlyTrack(track0)); +} + +/** + * @brief Check if MC particles have the expected&same mother particle + * + * @param mc1 MCParticle 0 + * @param mc2 MCParticle 1 + * @return true if the mother particle is the expected type and the same for both + */ +template +inline bool checkMCParticles(aod::McParticle const& mc1, aod::McParticle const& mc2) +{ + if (abs(mc1.pdgCode()) != kElectron || abs(mc2.pdgCode()) != kElectron) { + return false; + } + if (!mc1.has_mothers() || !mc2.has_mothers()) { + return false; + } + if (mc1.mothersIds()[0] != mc2.mothersIds()[0]) { + return false; + } + if (mc1.template mothers_first_as().pdgCode() != motherType) { + return false; + } + return true; +} +} // namespace o2::pwgem::photonmeson + +#endif // PWGEM_PHOTONMESON_UTILS_TRACKSELECTION_H_ diff --git a/PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h b/PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h index 4f9efd0d3fd..a9257d90ee4 100644 --- a/PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h +++ b/PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h @@ -23,16 +23,16 @@ AxisSpec const gAxis_zColl{800, -50.f, 50.f}; AxisSpec const gAxis_pT{800, 0.f, 25.f}; AxisSpec const gAxis_pT_armenteros{400, 0.f, 1.f}; AxisSpec const gAxis_pT2d{400, 0.f, 25.f}; -AxisSpec const gAxis_eta{800, -PIHalf, PIHalf}; -AxisSpec const gAxis_eta2d{400, -PIHalf, PIHalf}; -AxisSpec const gAxis_phi{800, 0.f, TwoPI}; +AxisSpec const gAxis_eta{800, -o2::constants::math::PIHalf, o2::constants::math::PIHalf}; +AxisSpec const gAxis_eta2d{400, -o2::constants::math::PIHalf, o2::constants::math::PIHalf}; +AxisSpec const gAxis_phi{800, 0.f, o2::constants::math::TwoPI}; AxisSpec const gAxis_r{800, 0.f, 200.f}; AxisSpec const gAxis_r_extended{800, 0.f, 500.f}; AxisSpec const gAxis_dr{200, -100.f, 100.f}; AxisSpec const gAxis_r2d{400, 0.f, 250.f}; AxisSpec const gAxis_z2d{1000, -250.f, 250.f}; AxisSpec const gAxis_TPCdEdxSig{401, -10.025f, 10.025f}; -AxisSpec const gAxis_radRes{800, -PI, PI}; +AxisSpec const gAxis_radRes{800, -o2::constants::math::PI, o2::constants::math::PI}; AxisSpec const gAxis_xyz{2400, -300.f, 300.f}; AxisSpec const gAxis_chi2{501, -1.f, 500.f}; AxisSpec gAxis_pT_log{800, 0.01f, 25.f}; diff --git a/PWGEM/Tasks/phosPi0.cxx b/PWGEM/Tasks/phosPi0.cxx index 161d9d0ccb8..c030939af3a 100644 --- a/PWGEM/Tasks/phosPi0.cxx +++ b/PWGEM/Tasks/phosPi0.cxx @@ -39,6 +39,7 @@ /// using namespace o2; +using namespace o2::aod::evsel; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGEM/Tasks/phosTrigQA.cxx b/PWGEM/Tasks/phosTrigQA.cxx index 86717924397..40ea10b7794 100644 --- a/PWGEM/Tasks/phosTrigQA.cxx +++ b/PWGEM/Tasks/phosTrigQA.cxx @@ -45,6 +45,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::aod::evsel; struct phosTrigQA { diff --git a/PWGHF/ALICE3/TableProducer/CMakeLists.txt b/PWGHF/ALICE3/TableProducer/CMakeLists.txt index 343b79e88ca..5a5201102e3 100644 --- a/PWGHF/ALICE3/TableProducer/CMakeLists.txt +++ b/PWGHF/ALICE3/TableProducer/CMakeLists.txt @@ -13,64 +13,64 @@ o2physics_add_dpl_workflow(candidate-creator-chic SOURCES candidateCreatorChic.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-x SOURCES candidateCreatorX.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) # Candidate selectors o2physics_add_dpl_workflow(candidate-selector-chic-to-jpsi-gamma SOURCES candidateSelectorChicToJpsiGamma.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-d0-alice3-barrel SOURCES candidateSelectorD0Alice3Barrel.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-d0-alice3-forward SOURCES candidateSelectorD0Alice3Forward.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-d0-parametrized-pid SOURCES candidateSelectorD0ParametrizedPid.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-jpsi SOURCES candidateSelectorJpsi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-lc-alice3 SOURCES candidateSelectorLcAlice3.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-lc-parametrized-pid SOURCES candidateSelectorLcParametrizedPid.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-x-to-jpsi-pi-pi SOURCES candidateSelectorXToJpsiPiPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) # Tree creators o2physics_add_dpl_workflow(tree-creator-chic-to-jpsi-gamma SOURCES treeCreatorChicToJpsiGamma.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-x-to-jpsi-pi-pi SOURCES treeCreatorXToJpsiPiPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGHF/ALICE3/TableProducer/candidateCreatorChic.cxx b/PWGHF/ALICE3/TableProducer/candidateCreatorChic.cxx index 1ec82ea56ea..6fa35ef2e7d 100644 --- a/PWGHF/ALICE3/TableProducer/candidateCreatorChic.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateCreatorChic.cxx @@ -15,23 +15,22 @@ /// /// \author Alessandro De Falco , Cagliari University -#include "ALICE3/DataModel/ECAL.h" -#include "Common/Core/trackUtilities.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" +#include "ALICE3/DataModel/ECAL.h" +#include "Common/Core/trackUtilities.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand; -// using namespace o2::aod::alice3ecal; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_chic; using namespace o2::framework::expressions; void customize(std::vector& workflowOptions) @@ -62,8 +61,10 @@ struct HfCandidateCreatorChic { Configurable selectionFlagJpsi{"selectionFlagJpsi", 1, "Selection Flag for Jpsi"}; Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; - double massJpsi = RecoDecay::getMassPDG(pdg::Code::kJPsi); - double massJpsiGamma = 0; + HfHelper hfHelper; + + double massJpsi{0.}; + double massJpsiGamma{0.}; Filter filterSelectCandidates = (aod::hf_sel_candidate_jpsi::isSelJpsiToEE >= selectionFlagJpsi || aod::hf_sel_candidate_jpsi::isSelJpsiToMuMu >= selectionFlagJpsi); @@ -76,11 +77,16 @@ struct HfCandidateCreatorChic { OutputObj hCovPVXX{TH1F("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", 100, 0., 1.e-4)}; OutputObj hCovSVXX{TH1F("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", 100, 0., 0.2)}; + void init(InitContext const&) + { + massJpsi = o2::analysis::pdg::MassJPsi; + } + void process(aod::Collision const& collision, soa::Filtered> const& jpsiCands, - aod::BigTracks const& tracks, + aod::TracksWCov const& tracks, aod::ECALs const& ecals) { // 2-prong vertex fitter (to rebuild Jpsi vertex) @@ -95,26 +101,26 @@ struct HfCandidateCreatorChic { df2.setWeightedFinalPCA(useWeightedFinalPCA); // loop over Jpsi candidates - for (auto& jpsiCand : jpsiCands) { + for (const auto& jpsiCand : jpsiCands) { if (!(jpsiCand.hfflag() & 1 << hf_cand_2prong::DecayType::JpsiToEE) && !(jpsiCand.hfflag() & 1 << hf_cand_2prong::DecayType::JpsiToMuMu)) { continue; } - if (yCandMax >= 0. && std::abs(yJpsi(jpsiCand)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yJpsi(jpsiCand)) > yCandMax) { continue; } if (jpsiCand.isSelJpsiToEE() > 0) { - hMassJpsiToEE->Fill(invMassJpsiToEE(jpsiCand)); + hMassJpsiToEE->Fill(hfHelper.invMassJpsiToEE(jpsiCand)); } if (jpsiCand.isSelJpsiToMuMu() > 0) { - hMassJpsiToMuMu->Fill(invMassJpsiToMuMu(jpsiCand)); + hMassJpsiToMuMu->Fill(hfHelper.invMassJpsiToMuMu(jpsiCand)); } hPtJpsi->Fill(jpsiCand.pt()); hCPAJpsi->Fill(jpsiCand.cpa()); // create Jpsi track to pass to DCA fitter; use cand table + rebuild vertex const std::array vertexJpsi = {jpsiCand.xSecondaryVertex(), jpsiCand.ySecondaryVertex(), jpsiCand.zSecondaryVertex()}; - array pvecJpsi = {jpsiCand.px(), jpsiCand.py(), jpsiCand.pz()}; - auto prong0 = jpsiCand.prong0_as(); - auto prong1 = jpsiCand.prong1_as(); + std::array pvecJpsi = {jpsiCand.px(), jpsiCand.py(), jpsiCand.pz()}; + auto prong0 = jpsiCand.prong0_as(); + auto prong1 = jpsiCand.prong1_as(); auto prong0TrackParCov = getTrackParCov(prong0); auto prong1TrackParCov = getTrackParCov(prong1); @@ -127,22 +133,22 @@ struct HfCandidateCreatorChic { prong1TrackParCov.propagateTo(jpsiCand.xSecondaryVertex(), bz); const std::array covJpsi = df2.calcPCACovMatrixFlat(); // define the Jpsi track - auto trackJpsi = o2::dataformats::V0(vertexJpsi, pvecJpsi, covJpsi, prong0TrackParCov, prong1TrackParCov, {0, 0}, {0, 0}); // FIXME: also needs covxyz??? + auto trackJpsi = o2::dataformats::V0(vertexJpsi, pvecJpsi, covJpsi, prong0TrackParCov, prong1TrackParCov); // FIXME: also needs covxyz??? // ----------------------------------------------------------------- // loop over gamma candidates - for (auto& ecal : ecals) { + for (const auto& ecal : ecals) { if (ecal.e() < energyGammaMin) { continue; } - auto etagamma = RecoDecay::eta(array{ecal.px(), ecal.py(), ecal.pz()}); + auto etagamma = RecoDecay::eta(std::array{ecal.px(), ecal.py(), ecal.pz()}); if (etagamma < etaGammaMin || etagamma > etaGammaMax) { // calcolare la pseudorapidità da posz continue; } - array pvecGamma{static_cast(ecal.px()), static_cast(ecal.py()), static_cast(ecal.pz())}; + std::array pvecGamma{static_cast(ecal.px()), static_cast(ecal.py()), static_cast(ecal.pz())}; // get track impact parameters // This modifies track momenta! @@ -156,7 +162,7 @@ struct HfCandidateCreatorChic { // get uncertainty of the decay length // double phi, theta; - // getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, ChicsecondaryVertex, phi, theta); + // getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, ChicsecondaryVertex, phi, theta); // auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); // auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); @@ -179,11 +185,11 @@ struct HfCandidateCreatorChic { impactParameter0.getY(), 0.f, // impactParameter1.getY(), std::sqrt(impactParameter0.getSigmaY2()), 0.f, // std::sqrt(impactParameter1.getSigmaY2()), jpsiCand.globalIndex(), ecal.globalIndex(), - hfFlag, invMassJpsiToMuMu(jpsiCand)); + hfFlag, hfHelper.invMassJpsiToMuMu(jpsiCand)); // calculate invariant mass - auto arrayMomenta = array{pvecJpsi, pvecGamma}; - massJpsiGamma = RecoDecay::m(std::move(arrayMomenta), array{massJpsi, 0.}); + auto arrayMomenta = std::array{pvecJpsi, pvecGamma}; + massJpsiGamma = RecoDecay::m(std::move(arrayMomenta), std::array{massJpsi, 0.}); if (jpsiCand.isSelJpsiToEE() > 0) { hMassChicToJpsiToEEGamma->Fill(massJpsiGamma); } @@ -207,6 +213,8 @@ struct HfCandidateCreatorChicMc { Produces rowMcMatchRec; Produces rowMcMatchGen; + HfHelper hfHelper; + OutputObj hMassJpsiToMuMuMatched{TH1F("hMassChicToJpsiToMuMuMatched", "2-prong candidates;inv. mass (J/#psi (#rightarrow #mu+ #mu-)) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; OutputObj hMassEMatched{TH1F("hMassEMatched", "2-prong candidates;inv. mass (J/#psi (#rightarrow #mu+ #mu-)) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; OutputObj hEphotonMatched{TH1F("hEphotonMatched", "2-prong candidates;inv. mass (J/#psi (#rightarrow #mu+ #mu-)) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; @@ -214,8 +222,8 @@ struct HfCandidateCreatorChicMc { void process(aod::HfCandChic const& candidates, aod::HfCand2Prong const&, - aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC, + aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, aod::ECALs const& ecals) { int indexRec = -1; @@ -225,62 +233,61 @@ struct HfCandidateCreatorChicMc { int8_t channel = 0; // Match reconstructed candidates. - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { flag = 0; origin = 0; channel = 0; auto jpsiTrack = candidate.prong0(); - auto daughterPosJpsi = jpsiTrack.prong0_as(); - auto daughterNegJpsi = jpsiTrack.prong1_as(); - auto arrayJpsiDaughters = array{daughterPosJpsi, daughterNegJpsi}; + auto daughterPosJpsi = jpsiTrack.prong0_as(); + auto daughterNegJpsi = jpsiTrack.prong1_as(); + auto arrayJpsiDaughters = std::array{daughterPosJpsi, daughterNegJpsi}; // chi_c → J/ψ gamma - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayJpsiDaughters, pdg::Code::kJPsi, array{+kMuonPlus, -kMuonPlus}, true); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayJpsiDaughters, pdg::Code::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true); if (indexRec > -1) { - hMassJpsiToMuMuMatched->Fill(invMassJpsiToMuMu(candidate.prong0())); + hMassJpsiToMuMuMatched->Fill(hfHelper.invMassJpsiToMuMu(candidate.prong0())); - int indexMother = RecoDecay::getMother(particlesMC, particlesMC.rawIteratorAt(indexRec), pdg::Code::kChiC1); - int indexMotherGamma = RecoDecay::getMother(particlesMC, particlesMC.rawIteratorAt(candidate.prong1().mcparticleId()), pdg::Code::kChiC1); + int indexMother = RecoDecay::getMother(mcParticles, mcParticles.rawIteratorAt(indexRec), pdg::Code::kChiC1); + int indexMotherGamma = RecoDecay::getMother(mcParticles, mcParticles.rawIteratorAt(candidate.prong1().mcparticleId()), pdg::Code::kChiC1); if (indexMother > -1 && indexMotherGamma == indexMother && candidate.prong1().mcparticle().pdgCode() == kGamma) { - auto particleMother = particlesMC.rawIteratorAt(indexMother); + auto particleMother = mcParticles.rawIteratorAt(indexMother); hEphotonMatched->Fill(candidate.prong1().e()); hMassEMatched->Fill(sqrt(candidate.prong1().px() * candidate.prong1().px() + candidate.prong1().py() * candidate.prong1().py() + candidate.prong1().pz() * candidate.prong1().pz())); if (particleMother.has_daughters()) { std::vector arrAllDaughtersIndex; - RecoDecay::getDaughters(particleMother, &arrAllDaughtersIndex, array{static_cast(kGamma), static_cast(pdg::Code::kJPsi)}, 1); + RecoDecay::getDaughters(particleMother, &arrAllDaughtersIndex, std::array{static_cast(kGamma), static_cast(pdg::Code::kJPsi)}, 1); if (arrAllDaughtersIndex.size() == 2) { flag = 1 << hf_cand_chic::DecayType::ChicToJpsiToMuMuGamma; - hMassChicToJpsiToMuMuGammaMatched->Fill(invMassChicToJpsiGamma(candidate)); + hMassChicToJpsiToMuMuGammaMatched->Fill(hfHelper.invMassChicToJpsiGamma(candidate)); } } } } if (flag != 0) { - auto particle = particlesMC.rawIteratorAt(indexRec); - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchRec(flag, origin, channel); } // Match generated particles. - for (auto& particle : particlesMC) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = 0; origin = 0; channel = 0; // chi_c → J/ψ gamma - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kChiC1, array{static_cast(pdg::Code::kJPsi), static_cast(kGamma)}, true)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kChiC1, std::array{static_cast(pdg::Code::kJPsi), static_cast(kGamma)}, true)) { // Match J/psi --> e+e- std::vector arrDaughter; - RecoDecay::getDaughters(particle, &arrDaughter, array{static_cast(pdg::Code::kJPsi)}, 1); - auto jpsiCandMC = particlesMC.rawIteratorAt(arrDaughter[0]); - if (RecoDecay::isMatchedMCGen(particlesMC, jpsiCandMC, pdg::Code::kJPsi, array{+kElectron, -kElectron}, true)) { + RecoDecay::getDaughters(particle, &arrDaughter, std::array{static_cast(pdg::Code::kJPsi)}, 1); + auto jpsiCandMC = mcParticles.rawIteratorAt(arrDaughter[0]); + if (RecoDecay::isMatchedMCGen(mcParticles, jpsiCandMC, pdg::Code::kJPsi, std::array{+kElectron, -kElectron}, true)) { flag = 1 << hf_cand_chic::DecayType::ChicToJpsiToEEGamma; } if (flag == 0) { - if (RecoDecay::isMatchedMCGen(particlesMC, jpsiCandMC, pdg::Code::kJPsi, array{+kMuonPlus, -kMuonPlus}, true)) { + if (RecoDecay::isMatchedMCGen(mcParticles, jpsiCandMC, pdg::Code::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { flag = 1 << hf_cand_chic::DecayType::ChicToJpsiToMuMuGamma; } } diff --git a/PWGHF/ALICE3/TableProducer/candidateCreatorX.cxx b/PWGHF/ALICE3/TableProducer/candidateCreatorX.cxx index b44147afcd1..db6bba712ee 100644 --- a/PWGHF/ALICE3/TableProducer/candidateCreatorX.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateCreatorX.cxx @@ -16,21 +16,21 @@ /// \author Rik Spijkers , Utrecht University /// \author Luca Micheletti , INFN -#include "Common/Core/trackUtilities.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" +#include "Common/Core/trackUtilities.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_x; using namespace o2::framework::expressions; void customize(std::vector& workflowOptions) @@ -60,9 +60,11 @@ struct HfCandidateCreatorX { Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; Configurable diffMassJpsiMax{"diffMassJpsiMax", 0.07, "max. diff. between Jpsi rec. and PDG mass"}; - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massJpsi = RecoDecay::getMassPDG(443); - double massJpsiPiPi; + HfHelper hfHelper; + + double massPi{0.}; + double massJpsi{0.}; + double massJpsiPiPi{0.}; Filter filterSelectCandidates = (aod::hf_sel_candidate_jpsi::isSelJpsiToEE >= selectionFlagJpsi || aod::hf_sel_candidate_jpsi::isSelJpsiToMuMu >= selectionFlagJpsi); @@ -75,11 +77,17 @@ struct HfCandidateCreatorX { OutputObj hCovPVXX{TH1F("hCovPVXX", "3-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", 100, 0., 1.e-4)}; OutputObj hCovSVXX{TH1F("hCovSVXX", "3-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", 100, 0., 0.2)}; + void init(InitContext const&) + { + massPi = o2::analysis::pdg::MassPiPlus; + massJpsi = o2::analysis::pdg::MassJPsi; + } + void process(aod::Collision const& collision, soa::Filtered> const& jpsiCands, - aod::BigTracks const& tracks) + aod::TracksWCov const& tracks) { // 2-prong vertex fitter (to rebuild Jpsi vertex) o2::vertexing::DCAFitterN<2> df2; @@ -104,33 +112,33 @@ struct HfCandidateCreatorX { df3.setWeightedFinalPCA(useWeightedFinalPCA); // loop over Jpsi candidates - for (auto& jpsiCand : jpsiCands) { + for (const auto& jpsiCand : jpsiCands) { if (!(jpsiCand.hfflag() & 1 << hf_cand_2prong::DecayType::JpsiToEE) && !(jpsiCand.hfflag() & 1 << hf_cand_2prong::DecayType::JpsiToMuMu)) { continue; } - if (yCandMax >= 0. && std::abs(yJpsi(jpsiCand)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yJpsi(jpsiCand)) > yCandMax) { continue; } if (jpsiCand.isSelJpsiToEE() > 0) { - if (std::abs(invMassJpsiToEE(jpsiCand) - massJpsi) > diffMassJpsiMax) { + if (std::abs(hfHelper.invMassJpsiToEE(jpsiCand) - massJpsi) > diffMassJpsiMax) { continue; } - hMassJpsiToEE->Fill(invMassJpsiToEE(jpsiCand)); + hMassJpsiToEE->Fill(hfHelper.invMassJpsiToEE(jpsiCand)); } if (jpsiCand.isSelJpsiToMuMu() > 0) { - if (std::abs(invMassJpsiToMuMu(jpsiCand) - massJpsi) > diffMassJpsiMax) { + if (std::abs(hfHelper.invMassJpsiToMuMu(jpsiCand) - massJpsi) > diffMassJpsiMax) { continue; } - hMassJpsiToMuMu->Fill(invMassJpsiToMuMu(jpsiCand)); + hMassJpsiToMuMu->Fill(hfHelper.invMassJpsiToMuMu(jpsiCand)); } hPtJpsi->Fill(jpsiCand.pt()); hCPAJpsi->Fill(jpsiCand.cpa()); // create Jpsi track to pass to DCA fitter; use cand table + rebuild vertex const std::array vertexJpsi = {jpsiCand.xSecondaryVertex(), jpsiCand.ySecondaryVertex(), jpsiCand.zSecondaryVertex()}; - array pvecJpsi = {jpsiCand.px(), jpsiCand.py(), jpsiCand.pz()}; - auto prong0 = jpsiCand.prong0_as(); - auto prong1 = jpsiCand.prong1_as(); + std::array pvecJpsi = {jpsiCand.px(), jpsiCand.py(), jpsiCand.pz()}; + auto prong0 = jpsiCand.prong0_as(); + auto prong1 = jpsiCand.prong1_as(); auto prong0TrackParCov = getTrackParCov(prong0); auto prong1TrackParCov = getTrackParCov(prong1); @@ -143,14 +151,14 @@ struct HfCandidateCreatorX { prong1TrackParCov.propagateTo(jpsiCand.xSecondaryVertex(), bz); const std::array covJpsi = df2.calcPCACovMatrixFlat(); // define the Jpsi track - auto trackJpsi = o2::dataformats::V0(vertexJpsi, pvecJpsi, covJpsi, prong0TrackParCov, prong1TrackParCov, {0, 0}, {0, 0}); // FIXME: also needs covxyz??? + auto trackJpsi = o2::dataformats::V0(vertexJpsi, pvecJpsi, covJpsi, prong0TrackParCov, prong1TrackParCov); // FIXME: also needs covxyz??? // used to check that prongs used for Jpsi and X reco are not the same prongs int index0Jpsi = jpsiCand.prong0Id(); int index1Jpsi = jpsiCand.prong1Id(); // loop over pi+ candidates - for (auto& trackPos : tracks) { + for (const auto& trackPos : tracks) { if (trackPos.pt() < ptPionMin) { continue; } @@ -162,7 +170,7 @@ struct HfCandidateCreatorX { } // loop over pi- candidates - for (auto& trackNeg : tracks) { + for (const auto& trackNeg : tracks) { if (trackNeg.pt() < ptPionMin) { continue; } @@ -175,8 +183,8 @@ struct HfCandidateCreatorX { auto trackParVarPos = getTrackParCov(trackPos); auto trackParVarNeg = getTrackParCov(trackNeg); - array pvecPos; - array pvecNeg; + std::array pvecPos; + std::array pvecNeg; // reconstruct the 3-prong X vertex if (df3.process(trackJpsi, trackParVarPos, trackParVarNeg) == 0) { @@ -208,7 +216,7 @@ struct HfCandidateCreatorX { // get uncertainty of the decay length double phi, theta; - getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, XsecondaryVertex, phi, theta); + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, XsecondaryVertex, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); @@ -235,8 +243,8 @@ struct HfCandidateCreatorX { hfFlag); // calculate invariant mass - auto arrayMomenta = array{pvecJpsi, pvecPos, pvecNeg}; - massJpsiPiPi = RecoDecay::m(std::move(arrayMomenta), array{massJpsi, massPi, massPi}); + auto arrayMomenta = std::array{pvecJpsi, pvecPos, pvecNeg}; + massJpsiPiPi = RecoDecay::m(std::move(arrayMomenta), std::array{massJpsi, massPi, massPi}); if (jpsiCand.isSelJpsiToEE() > 0) { hMassXToJpsiToEEPiPi->Fill(massJpsiPiPi); } @@ -263,8 +271,8 @@ struct HfCandidateCreatorXMc { void process(aod::HfCandX const& candidates, aod::HfCand2Prong const&, - aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC) + aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles) { int indexRec = -1; int pdgCodeX = pdg::Code::kX3872; @@ -275,34 +283,37 @@ struct HfCandidateCreatorXMc { int8_t channel = 0; // Match reconstructed candidates. - for (auto& candidate : candidates) { - // Printf("New rec. candidate"); + for (const auto& candidate : candidates) { flag = 0; origin = 0; channel = 0; auto jpsiTrack = candidate.prong0(); - auto daughterPosJpsi = jpsiTrack.prong0_as(); - auto daughterNegJpsi = jpsiTrack.prong1_as(); - auto arrayJpsiDaughters = array{daughterPosJpsi, daughterNegJpsi}; - auto arrayDaughters = array{candidate.prong1_as(), - candidate.prong2_as(), - daughterPosJpsi, - daughterNegJpsi}; - - // X → J/ψ π+ π- - // Printf("Checking X → J/ψ π+ π-"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayJpsiDaughters, pdg::Code::kJPsi, array{+kElectron, -kElectron}, true); + auto daughterPosJpsi = jpsiTrack.prong0_as(); + auto daughterNegJpsi = jpsiTrack.prong1_as(); + auto arrayJpsiDaughters = std::array{daughterPosJpsi, daughterNegJpsi}; + auto arrayDaughters = std::array{candidate.prong1_as(), + candidate.prong2_as(), + daughterPosJpsi, + daughterNegJpsi}; + + // X → J/ψ π+ π− + + // J/ψ → e+ e− + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayJpsiDaughters, pdg::Code::kJPsi, std::array{+kElectron, -kElectron}, true); + // X → π+ π− e+ e− if (indexRec > -1) { - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdgCodeX, array{+kPiPlus, -kPiPlus, +kElectron, -kElectron}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgCodeX, std::array{+kPiPlus, -kPiPlus, +kElectron, -kElectron}, true, &sign, 2); if (indexRec > -1) { flag = 1 << hf_cand_x::DecayType::XToJpsiToEEPiPi; } } + // J/ψ → μ+ μ− if (flag == 0) { - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayJpsiDaughters, pdg::Code::kJPsi, array{+kMuonPlus, -kMuonPlus}, true); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayJpsiDaughters, pdg::Code::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true); + // X → π+ π− μ+ μ− if (indexRec > -1) { - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdgCodeX, array{+kPiPlus, -kPiPlus, +kMuonPlus, -kMuonPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgCodeX, std::array{+kPiPlus, -kPiPlus, +kMuonPlus, -kMuonPlus}, true, &sign, 2); if (indexRec > -1) { flag = 1 << hf_cand_x::DecayType::XToJpsiToMuMuPiPi; } @@ -311,33 +322,32 @@ struct HfCandidateCreatorXMc { // Check whether the particle is non-prompt (from a b quark). if (flag != 0) { - auto particle = particlesMC.rawIteratorAt(indexRec); - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchRec(flag, origin, channel); } // Match generated particles. - for (auto& particle : particlesMC) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = 0; origin = 0; channel = 0; - // X → J/ψ π+ π- - // Printf("Checking X → J/ψ π+ π-"); - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdgCodeX, array{pdgCodeJpsi, +kPiPlus, -kPiPlus}, true)) { - // Match J/psi --> e+e- + // X → J/ψ π+ π− + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeX, std::array{pdgCodeJpsi, +kPiPlus, -kPiPlus}, true)) { std::vector arrDaughter; - RecoDecay::getDaughters(particle, &arrDaughter, array{pdgCodeJpsi}, 1); - auto jpsiCandMC = particlesMC.rawIteratorAt(arrDaughter[0]); - if (RecoDecay::isMatchedMCGen(particlesMC, jpsiCandMC, pdgCodeJpsi, array{+kElectron, -kElectron}, true)) { + RecoDecay::getDaughters(particle, &arrDaughter, std::array{pdgCodeJpsi}, 1); + auto jpsiCandMC = mcParticles.rawIteratorAt(arrDaughter[0]); + // J/ψ → e+ e− + if (RecoDecay::isMatchedMCGen(mcParticles, jpsiCandMC, pdgCodeJpsi, std::array{+kElectron, -kElectron}, true)) { flag = 1 << hf_cand_x::DecayType::XToJpsiToEEPiPi; } + // J/ψ → μ+ μ− if (flag == 0) { - if (RecoDecay::isMatchedMCGen(particlesMC, jpsiCandMC, pdgCodeJpsi, array{+kMuonPlus, -kMuonPlus}, true)) { + if (RecoDecay::isMatchedMCGen(mcParticles, jpsiCandMC, pdgCodeJpsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { flag = 1 << hf_cand_x::DecayType::XToJpsiToMuMuPiPi; } } @@ -345,7 +355,7 @@ struct HfCandidateCreatorXMc { // Check whether the particle is non-prompt (from a b quark). if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchGen(flag, origin, channel); diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorChicToJpsiGamma.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorChicToJpsiGamma.cxx index 3f8d796fe86..9105f3f6036 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorChicToJpsiGamma.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorChicToJpsiGamma.cxx @@ -15,10 +15,10 @@ /// /// \author Alessandro De Falco , Università/INFN Cagliari -#include "ALICE3/DataModel/ECAL.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -26,9 +26,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand_chic; using namespace o2::analysis; -using namespace o2::analysis::hf_cuts_chic_to_jpsi_gamma; /// Struct for applying Jpsi selection cuts struct HfCandidateSelectorChicToJpsiGamma { @@ -47,7 +45,9 @@ struct HfCandidateSelectorChicToJpsiGamma { Configurable nSigmaTofMax{"nSigmaTofMax", 3., "Nsigma cut on TOF only"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_chic_to_jpsi_gamma::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_chic_to_jpsi_gamma::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Jpsi candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_chic_to_jpsi_gamma::cuts[0], hf_cuts_chic_to_jpsi_gamma::nBinsPt, hf_cuts_chic_to_jpsi_gamma::nCutVars, hf_cuts_chic_to_jpsi_gamma::labelsPt, hf_cuts_chic_to_jpsi_gamma::labelsCutVar}, "Jpsi candidate selection per pT bin"}; + + HfHelper hfHelper; /// Selection on goodness of daughter tracks /// \note should be applied at candidate selection @@ -76,9 +76,9 @@ struct HfCandidateSelectorChicToJpsiGamma { return false; // check that the candidate pT is within the analysis range } - auto mchic = RecoDecay::getMassPDG(20443); // chi_c1(1p) - if (TMath::Abs(invMassChicToJpsiGamma(hfCandChic) - mchic) > cuts->get(pTBin, "m")) { - // Printf("Chic topol selection failed at mass diff check"); + auto mchic = o2::analysis::pdg::MassChiC1; // chi_c1(1p) + if (std::abs(hfHelper.invMassChicToJpsiGamma(hfCandChic) - mchic) > cuts->get(pTBin, "m")) { + // LOGF(debug, "Chic topol selection failed at mass diff check"); return false; // check that mass difference is within bounds } @@ -94,7 +94,7 @@ struct HfCandidateSelectorChicToJpsiGamma { return false; // CPA check } - if ((TMath::Abs(hfCandChic.impactParameter0()) > cuts->get(pTBin, "d0 Jpsi"))) { // adf: Warning: no cut on photon + if ((std::abs(hfCandChic.impactParameter0()) > cuts->get(pTBin, "d0 Jpsi"))) { // adf: Warning: no cut on photon return false; // DCA check on daughters } @@ -110,7 +110,7 @@ struct HfCandidateSelectorChicToJpsiGamma { template bool validTPCPID(const T& track) { - if (TMath::Abs(track.pt()) < ptPidTpcMin || TMath::Abs(track.pt()) >= ptPidTpcMax) { + if (std::abs(track.pt()) < ptPidTpcMin || std::abs(track.pt()) >= ptPidTpcMax) { return false; } // if (track.TPCNClsFindable() < TPCNClsFindableMin) return false; @@ -124,7 +124,7 @@ struct HfCandidateSelectorChicToJpsiGamma { template bool validTofPid(const T& track) { - if (TMath::Abs(track.pt()) < ptPidTofMin || TMath::Abs(track.pt()) >= ptPidTofMax) { + if (std::abs(track.pt()) < ptPidTofMin || std::abs(track.pt()) >= ptPidTofMax) { return false; } return true; @@ -179,9 +179,11 @@ struct HfCandidateSelectorChicToJpsiGamma { //--------------------------------------------------------------- - void process(aod::HfCandChic const& hfCandChics, aod::HfCand2Prong const&, aod::BigTracksPID const& tracks, aod::ECALs const& ecals) + void process(aod::HfCandChic const& hfCandChics, + aod::HfCand2Prong const&, + aod::ECALs const& ecals) { - for (auto& hfCandChic : hfCandChics) { // looping over chi_c candidates + for (const auto& hfCandChic : hfCandChics) { // looping over chi_c candidates // note the difference between Jpsi (index0) and pions (index1,2) auto candJpsi = hfCandChic.prong0(); auto gamma = hfCandChic.prong1_as(); @@ -223,7 +225,7 @@ struct HfCandidateSelectorChicToJpsiGamma { } hfSelChicToJpsiGammaCandidate(selJpsiToEE, selJpsiToMuMu); - // Printf("Chi_c candidate selection successful, candidate should be selected"); + // LOGF(debug, "Chi_c candidate selection successful, candidate should be selected"); } } }; diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Barrel.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Barrel.cxx index 266c897579f..73a0904414f 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Barrel.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Barrel.cxx @@ -15,21 +15,19 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include "ALICE3/DataModel/RICH.h" -#include "Common/Core/TrackSelectorPID.h" -#include "Common/DataModel/PIDResponse.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" +#include "ALICE3/DataModel/RICH.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; namespace o2::aod { @@ -45,7 +43,7 @@ DECLARE_SOA_INDEX_TABLE_USER(RICHTracksIndex, Tracks, "RICHTRK", indices::TrackI struct HfCandidateSelectorD0Alice3BarrelRichIndexBuilder { // Builder of the RICH-track index linkage Builds indB; - void init(o2::framework::InitContext&) {} + void init(InitContext&) {} }; /// Struct for applying D0 selection cuts @@ -66,24 +64,11 @@ struct HfCandidateSelectorD0Alice3Barrel { Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_d0_to_pi_k::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "D0 candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_d0_to_pi_k::cuts[0], hf_cuts_d0_to_pi_k::nBinsPt, hf_cuts_d0_to_pi_k::nCutVars, hf_cuts_d0_to_pi_k::labelsPt, hf_cuts_d0_to_pi_k::labelsCutVar}, "D0 candidate selection per pT bin"}; - using Trks = soa::Join; + HfHelper hfHelper; - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) - { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check - } - return true; - } - */ + using TracksSel = soa::Join; /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -158,11 +143,11 @@ struct HfCandidateSelectorD0Alice3Barrel { // invariant-mass cut if (trackPion.sign() > 0) { - if (std::abs(invMassD0ToPiK(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassD0ToPiK(candidate) - o2::analysis::pdg::MassD0) > cuts->get(pTBin, "m")) { return false; } } else { - if (std::abs(invMassD0barToKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassD0barToKPi(candidate) - o2::analysis::pdg::MassD0) > cuts->get(pTBin, "m")) { return false; } } @@ -179,11 +164,11 @@ struct HfCandidateSelectorD0Alice3Barrel { // cut on cos(theta*) if (trackPion.sign() > 0) { - if (std::abs(cosThetaStarD0(candidate)) > cuts->get(pTBin, "cos theta*")) { + if (std::abs(hfHelper.cosThetaStarD0(candidate)) > cuts->get(pTBin, "cos theta*")) { return false; } } else { - if (std::abs(cosThetaStarD0bar(candidate)) > cuts->get(pTBin, "cos theta*")) { + if (std::abs(hfHelper.cosThetaStarD0bar(candidate)) > cuts->get(pTBin, "cos theta*")) { return false; } } @@ -191,10 +176,14 @@ struct HfCandidateSelectorD0Alice3Barrel { return true; } - void process(aod::HfCand2Prong const& candidates, Trks const& barreltracks, const aod::McParticles& mcParticles, const aod::RICHs&, const aod::FRICHs&) + void process(aod::HfCand2Prong const& candidates, + TracksSel const& barreltracks, + aod::McParticles const& mcParticles, + aod::RICHs const&, + aod::FRICHs const&) { - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // selection flag int statusHFFlag = 0; @@ -204,7 +193,7 @@ struct HfCandidateSelectorD0Alice3Barrel { int statusD0RICHPID = 0; int statusD0TofPlusRichPid = 0; int statusD0barTofPlusRichPid = 0; - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { hfSelD0CandidateALICE3Barrel(statusHFFlag, statusD0NoPid, statusD0PerfectPid, statusD0TofPid, statusD0RICHPID, statusD0TofPlusRichPid, statusD0barTofPlusRichPid); continue; } @@ -216,8 +205,8 @@ struct HfCandidateSelectorD0Alice3Barrel { continue; } - auto trackPos = candidate.prong0_as(); - auto trackNeg = candidate.prong1_as(); + auto trackPos = candidate.prong0_as(); + auto trackNeg = candidate.prong1_as(); auto momentumPosTrack = trackPos.p(); auto momentumNegTrack = trackNeg.p(); @@ -233,10 +222,10 @@ struct HfCandidateSelectorD0Alice3Barrel { int pdgPositive = 0; int pdgNegative = 0; if (trackPos.has_mcParticle()) { - pdgPositive = trackPos.mcParticle_as().pdgCode(); + pdgPositive = trackPos.mcParticle_as().pdgCode(); } if (trackNeg.has_mcParticle()) { - pdgNegative = trackNeg.mcParticle_as().pdgCode(); + pdgNegative = trackNeg.mcParticle_as().pdgCode(); } float nsigmaTOFNegKaon = -5000.0; diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Forward.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Forward.cxx index 824a39079b5..782813029cf 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Forward.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorD0Alice3Forward.cxx @@ -15,21 +15,19 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include "ALICE3/DataModel/RICH.h" -#include "Common/Core/TrackSelectorPID.h" -#include "Common/DataModel/PIDResponse.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" +#include "ALICE3/DataModel/RICH.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; namespace o2::aod { @@ -45,7 +43,7 @@ DECLARE_SOA_INDEX_TABLE_USER(FRICHTracksIndex, Tracks, "FRICHTRK", indices::Trac struct HfCandidateSelectorD0Alice3ForwardRichIndexBuilder { // Builder of the RICH-track index linkage Builds indF; - void init(o2::framework::InitContext&) {} + void init(InitContext&) {} }; /// Struct for applying D0 selection cuts @@ -66,24 +64,11 @@ struct HfCandidateSelectorD0Alice3Forward { Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_d0_to_pi_k::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "D0 candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_d0_to_pi_k::cuts[0], hf_cuts_d0_to_pi_k::nBinsPt, hf_cuts_d0_to_pi_k::nCutVars, hf_cuts_d0_to_pi_k::labelsPt, hf_cuts_d0_to_pi_k::labelsCutVar}, "D0 candidate selection per pT bin"}; - using Trks = soa::Join; + HfHelper hfHelper; - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) - { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check - } - return true; - } - */ + using TracksSel = soa::Join; /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -158,11 +143,11 @@ struct HfCandidateSelectorD0Alice3Forward { // invariant-mass cut if (trackPion.sign() > 0) { - if (std::abs(invMassD0ToPiK(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassD0ToPiK(candidate) - o2::analysis::pdg::MassD0) > cuts->get(pTBin, "m")) { return false; } } else { - if (std::abs(invMassD0barToKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassD0barToKPi(candidate) - o2::analysis::pdg::MassD0) > cuts->get(pTBin, "m")) { return false; } } @@ -179,11 +164,11 @@ struct HfCandidateSelectorD0Alice3Forward { // cut on cos(theta*) if (trackPion.sign() > 0) { - if (std::abs(cosThetaStarD0(candidate)) > cuts->get(pTBin, "cos theta*")) { + if (std::abs(hfHelper.cosThetaStarD0(candidate)) > cuts->get(pTBin, "cos theta*")) { return false; } } else { - if (std::abs(cosThetaStarD0bar(candidate)) > cuts->get(pTBin, "cos theta*")) { + if (std::abs(hfHelper.cosThetaStarD0bar(candidate)) > cuts->get(pTBin, "cos theta*")) { return false; } } @@ -191,17 +176,21 @@ struct HfCandidateSelectorD0Alice3Forward { return true; } - void process(aod::HfCand2Prong const& candidates, Trks const& forwardtracks, const aod::McParticles& mcParticles, const aod::RICHs&, const aod::FRICHs&) + void process(aod::HfCand2Prong const& candidates, + TracksSel const& forwardtracks, + aod::McParticles const& mcParticles, + aod::RICHs const&, + aod::FRICHs const&) { - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // selection flag int statusHFFlag = 0; int statusD0NoPid = 0; int statusD0RICHPID = 0; - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { hfSelD0CandidateALICE3Forward(statusHFFlag, statusD0NoPid, statusD0RICHPID); continue; } @@ -213,8 +202,8 @@ struct HfCandidateSelectorD0Alice3Forward { continue; } - auto trackPos = candidate.prong0_as(); - auto trackNeg = candidate.prong1_as(); + auto trackPos = candidate.prong0_as(); + auto trackNeg = candidate.prong1_as(); // auto momentumPosTrack = trackPos.p(); // auto momentumNegTrack = trackNeg.p(); diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorD0ParametrizedPid.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorD0ParametrizedPid.cxx index 833f7de3713..fe110affd66 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorD0ParametrizedPid.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorD0ParametrizedPid.cxx @@ -15,21 +15,19 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include "ALICE3/DataModel/RICH.h" -#include "Common/Core/TrackSelectorPID.h" -#include "Common/DataModel/PIDResponse.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" +#include "ALICE3/DataModel/RICH.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; namespace o2::aod { @@ -44,7 +42,7 @@ DECLARE_SOA_INDEX_TABLE_USER(RICHTracksIndex, Tracks, "RICHTRK", indices::TrackI struct HfCandidateSelectorD0ParametrizedPidRichIndexBuilder { // Builder of the RICH-track index linkage Builds indB; - void init(o2::framework::InitContext&) {} + void init(InitContext&) {} }; /// Struct for applying D0 selection cuts @@ -66,24 +64,11 @@ struct HfCandidateSelectorD0ParametrizedPid { Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_d0_to_pi_k::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "D0 candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_d0_to_pi_k::cuts[0], hf_cuts_d0_to_pi_k::nBinsPt, hf_cuts_d0_to_pi_k::nCutVars, hf_cuts_d0_to_pi_k::labelsPt, hf_cuts_d0_to_pi_k::labelsCutVar}, "D0 candidate selection per pT bin"}; - using Trks = soa::Join; + HfHelper hfHelper; - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) - { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check - } - return true; - } - */ + using TracksSel = soa::Join; /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -158,11 +143,11 @@ struct HfCandidateSelectorD0ParametrizedPid { // invariant-mass cut if (trackPion.sign() > 0) { - if (std::abs(invMassD0ToPiK(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassD0ToPiK(candidate) - o2::analysis::pdg::MassD0) > cuts->get(pTBin, "m")) { return false; } } else { - if (std::abs(invMassD0barToKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassD0barToKPi(candidate) - o2::analysis::pdg::MassD0) > cuts->get(pTBin, "m")) { return false; } } @@ -179,11 +164,11 @@ struct HfCandidateSelectorD0ParametrizedPid { // cut on cos(theta*) if (trackPion.sign() > 0) { - if (std::abs(cosThetaStarD0(candidate)) > cuts->get(pTBin, "cos theta*")) { + if (std::abs(hfHelper.cosThetaStarD0(candidate)) > cuts->get(pTBin, "cos theta*")) { return false; } } else { - if (std::abs(cosThetaStarD0bar(candidate)) > cuts->get(pTBin, "cos theta*")) { + if (std::abs(hfHelper.cosThetaStarD0bar(candidate)) > cuts->get(pTBin, "cos theta*")) { return false; } } @@ -191,10 +176,14 @@ struct HfCandidateSelectorD0ParametrizedPid { return true; } - void process(aod::HfCand2Prong const& candidates, Trks const& barreltracks, const aod::McParticles& mcParticles, const aod::RICHs&, const aod::FRICHs&) + void process(aod::HfCand2Prong const& candidates, + TracksSel const& barreltracks, + aod::McParticles const& mcParticles, + aod::RICHs const&, + aod::FRICHs const&) { - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // selection flag int statusD0NoPid = 0; @@ -204,7 +193,7 @@ struct HfCandidateSelectorD0ParametrizedPid { int statusD0barPerfectPid = 0; int statusD0bar = 0; - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { hfSelD0CandidateparametrizedPID(statusD0NoPid, statusD0PerfectPid, statusD0, statusD0barNoPid, statusD0barPerfectPid, statusD0bar); continue; } @@ -215,8 +204,8 @@ struct HfCandidateSelectorD0ParametrizedPid { continue; } - auto trackPos = candidate.prong0_as(); - auto trackNeg = candidate.prong1_as(); + auto trackPos = candidate.prong0_as(); + auto trackNeg = candidate.prong1_as(); // auto momentumPosTrack = trackPos.p(); // auto momentumNegTrack = trackNeg.p(); diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorJpsi.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorJpsi.cxx index 42a82009e26..d436ecd13e8 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorJpsi.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorJpsi.cxx @@ -16,18 +16,19 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN +#include "Framework/AnalysisTask.h" + #include "ALICE3/DataModel/MID.h" #include "ALICE3/DataModel/RICH.h" #include "Common/Core/TrackSelectorPID.h" -#include "Framework/AnalysisTask.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_jpsi_to_e_e; namespace o2::aod { @@ -46,7 +47,7 @@ DECLARE_SOA_INDEX_TABLE_USER(HfTrackIndexALICE3PID, Tracks, "HFTRKIDXA3PID", //! struct HfCandidateSelectorJpsiAlice3PidIndexBuilder { Builds index; - void init(o2::framework::InitContext&) {} + void init(InitContext&) {} }; void customize(std::vector& workflowOptions) @@ -80,10 +81,27 @@ struct HfCandidateSelectorJpsi { Configurable nSigmaRichCombinedTofMax{"nSigmaRichCombinedTofMax", 5., "Nsigma cut on RICH combined with TOF"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_jpsi_to_e_e::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_jpsi_to_e_e::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Jpsi candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_jpsi_to_e_e::cuts[0], hf_cuts_jpsi_to_e_e::nBinsPt, hf_cuts_jpsi_to_e_e::nCutVars, hf_cuts_jpsi_to_e_e::labelsPt, hf_cuts_jpsi_to_e_e::labelsCutVar}, "Jpsi candidate selection per pT bin"}; - using TracksPID = soa::Join; - using ExtendedTracksPID = soa::Join; + HfHelper hfHelper; + TrackSelectorEl selectorElectron; + TrackSelectorMu selectorMuon; + + using TracksSelAlice2 = soa::Join; + using TracksSelAlice3 = soa::Join; + + void init(InitContext const& initContext) + { + selectorElectron.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorElectron.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorElectron.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorElectron.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorElectron.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorElectron.setRangePtRich(ptPidRichMin, ptPidRichMax); + selectorElectron.setRangeNSigmaRich(-nSigmaRichMax, nSigmaRichMax); + selectorElectron.setRangeNSigmaRichCondTof(-nSigmaRichCombinedTofMax, nSigmaRichCombinedTofMax); + selectorMuon = selectorElectron; + } /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -105,12 +123,12 @@ struct HfCandidateSelectorJpsi { } // cut on e+ e− invariant mass - if (std::abs(invMassJpsiToEE(candidate) - RecoDecay::getMassPDG(pdg::Code::kJPsi)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassJpsiToEE(candidate) - o2::analysis::pdg::MassJPsi) > cuts->get(pTBin, "m")) { selEE = 0; } // cut on μ+ μ− invariant mass - if (std::abs(invMassJpsiToMuMu(candidate) - RecoDecay::getMassPDG(pdg::Code::kJPsi)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassJpsiToMuMu(candidate) - o2::analysis::pdg::MassJPsi) > cuts->get(pTBin, "m")) { selMuMu = 0; } @@ -140,29 +158,20 @@ struct HfCandidateSelectorJpsi { return true; } - void processAlice2(aod::HfCand2Prong const& candidates, aod::BigTracksPIDExtended const&) + void processAlice2(aod::HfCand2Prong const& candidates, + TracksSelAlice2 const&) { - TrackSelectorPID selectorElectron(kElectron); - selectorElectron.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorElectron.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorElectron.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorElectron.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorElectron.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - selectorElectron.setRangePtRICH(ptPidRichMin, ptPidRichMax); - selectorElectron.setRangeNSigmaRICH(-nSigmaRichMax, nSigmaRichMax); - selectorElectron.setRangeNSigmaRICHCondTOF(-nSigmaRichCombinedTofMax, nSigmaRichCombinedTofMax); - // looping over 2-prong candidates - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::JpsiToEE) && !(candidate.hfflag() & 1 << DecayType::JpsiToMuMu)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::JpsiToEE) && !(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::JpsiToMuMu)) { hfSelJpsiCandidate(0, 0, 0, 0, 0, 0, 0, 0, 0); // hfSelJpsiCandidate(0, 0); continue; } - auto trackPos = candidate.prong0_as(); // positive daughter - auto trackNeg = candidate.prong1_as(); // negative daughter + auto trackPos = candidate.prong0_as(); // positive daughter + auto trackNeg = candidate.prong1_as(); // negative daughter int selectedEETopol = 1; int selectedEETpc = 1; @@ -187,8 +196,8 @@ struct HfCandidateSelectorJpsi { } // track-level electron PID TOF selection - if (selectorElectron.getStatusTrackPIDTOF(trackPos) == TrackSelectorPID::Status::PIDRejected || - selectorElectron.getStatusTrackPIDTOF(trackNeg) == TrackSelectorPID::Status::PIDRejected) { + if (selectorElectron.statusTof(trackPos) == TrackSelectorPID::Rejected || + selectorElectron.statusTof(trackNeg) == TrackSelectorPID::Rejected) { selectedEETof = 0; selectedEE = 0; // if (selectedMuMu == 0) { @@ -198,8 +207,8 @@ struct HfCandidateSelectorJpsi { } // track-level electron PID TPC selection - if (selectorElectron.getStatusTrackPIDTPC(trackPos) == TrackSelectorPID::Status::PIDRejected || - selectorElectron.getStatusTrackPIDTPC(trackNeg) == TrackSelectorPID::Status::PIDRejected) { + if (selectorElectron.statusTpc(trackPos) == TrackSelectorPID::Rejected || + selectorElectron.statusTpc(trackNeg) == TrackSelectorPID::Rejected) { selectedEETpc = 0; selectedEE = 0; } @@ -219,31 +228,22 @@ struct HfCandidateSelectorJpsi { PROCESS_SWITCH(HfCandidateSelectorJpsi, processAlice2, "Use ALICE 2 detector setup", true); - void processAlice3(aod::HfCand2Prong const& candidates, ExtendedTracksPID const&, aod::RICHs const&, aod::MIDs const&) + void processAlice3(aod::HfCand2Prong const& candidates, + TracksSelAlice3 const&, + aod::RICHs const&, + aod::MIDs const&) { - TrackSelectorPID selectorElectron(kElectron); - selectorElectron.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorElectron.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorElectron.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorElectron.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorElectron.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - selectorElectron.setRangePtRICH(ptPidRichMin, ptPidRichMax); - selectorElectron.setRangeNSigmaRICH(-nSigmaRichMax, nSigmaRichMax); - selectorElectron.setRangeNSigmaRICHCondTOF(-nSigmaRichCombinedTofMax, nSigmaRichCombinedTofMax); - - TrackSelectorPID selectorMuon(kMuonMinus); - // looping over 2-prong candidates - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::JpsiToEE) && !(candidate.hfflag() & 1 << DecayType::JpsiToMuMu)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::JpsiToEE) && !(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::JpsiToMuMu)) { hfSelJpsiCandidate(0, 0, 0, 0, 0, 0, 0, 0, 0); // hfSelJpsiCandidate(0, 0); continue; } - auto trackPos = candidate.prong0_as(); // positive daughter - auto trackNeg = candidate.prong1_as(); // negative daughter + auto trackPos = candidate.prong0_as(); // positive daughter + auto trackNeg = candidate.prong1_as(); // negative daughter int selectedEETopol = 1; int selectedEETpc = 1; @@ -276,8 +276,8 @@ struct HfCandidateSelectorJpsi { } //} else { // track-level electron PID TOF selection - if (selectorElectron.getStatusTrackPIDTOF(trackPos) == TrackSelectorPID::Status::PIDRejected || - selectorElectron.getStatusTrackPIDTOF(trackNeg) == TrackSelectorPID::Status::PIDRejected) { + if (selectorElectron.statusTof(trackPos) == TrackSelectorPID::Rejected || + selectorElectron.statusTof(trackNeg) == TrackSelectorPID::Rejected) { selectedEETof = 0; selectedEE = 0; // if (selectedMuMu == 0) { @@ -287,8 +287,8 @@ struct HfCandidateSelectorJpsi { } // track-level electron PID RICH selection - if (selectorElectron.getStatusTrackPIDRICH(trackPos) == TrackSelectorPID::Status::PIDRejected || - selectorElectron.getStatusTrackPIDRICH(trackNeg) == TrackSelectorPID::Status::PIDRejected) { + if (selectorElectron.statusRich(trackPos) == TrackSelectorPID::Rejected || + selectorElectron.statusRich(trackNeg) == TrackSelectorPID::Rejected) { selectedEERich = 0; selectedEE = 0; } @@ -300,8 +300,8 @@ struct HfCandidateSelectorJpsi { // } // track-level muon PID MID selection - if (selectorMuon.getStatusTrackPIDMID(trackPos) != TrackSelectorPID::Status::PIDAccepted || - selectorMuon.getStatusTrackPIDMID(trackNeg) != TrackSelectorPID::Status::PIDAccepted) { + if (selectorMuon.statusMid(trackPos) != TrackSelectorPID::Accepted || + selectorMuon.statusMid(trackNeg) != TrackSelectorPID::Accepted) { selectedMuMuMid = 0; selectedMuMu = 0; } diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorLcAlice3.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorLcAlice3.cxx index 8e1d8cca627..0121da597cc 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorLcAlice3.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorLcAlice3.cxx @@ -16,21 +16,19 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include "ALICE3/DataModel/RICH.h" -#include "Common/Core/TrackSelectorPID.h" -#include "Common/DataModel/PIDResponse.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" +#include "ALICE3/DataModel/RICH.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_lc_to_p_k_pi; namespace o2::aod { @@ -46,7 +44,7 @@ DECLARE_SOA_INDEX_TABLE_USER(RICHTracksIndex, Tracks, "RICHTRK", indices::TrackI struct HfCandidateSelectorLcAlice3RichIndexBuilder { // Builder of the RICH-track index linkage Builds indB; - void init(o2::framework::InitContext&) {} + void init(InitContext&) {} }; /// Struct for applying Lc selection cuts @@ -68,24 +66,11 @@ struct HfCandidateSelectorLcAlice3 { // topological cuts Configurable decayLengthXYNormalisedMin{"decayLengthXYNormalisedMin", 3., "Min. normalised decay length"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_lc_to_p_k_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Lc candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_lc_to_p_k_pi::cuts[0], hf_cuts_lc_to_p_k_pi::nBinsPt, hf_cuts_lc_to_p_k_pi::nCutVars, hf_cuts_lc_to_p_k_pi::labelsPt, hf_cuts_lc_to_p_k_pi::labelsCutVar}, "Lc candidate selection per pT bin"}; - using Trks = soa::Join; + HfHelper hfHelper; - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) - { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check - } - return true; - } - */ + using TracksSel = soa::Join; /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -148,11 +133,11 @@ struct HfCandidateSelectorLcAlice3 { } if (trackProton.globalIndex() == candidate.prong0Id()) { - if (std::abs(invMassLcToPKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassLcToPKPi(candidate) - o2::analysis::pdg::MassLambdaCPlus) > cuts->get(pTBin, "m")) { return false; } } else { - if (std::abs(invMassLcToPiKP(candidate) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassLcToPiKP(candidate) - o2::analysis::pdg::MassLambdaCPlus) > cuts->get(pTBin, "m")) { return false; } } @@ -160,9 +145,13 @@ struct HfCandidateSelectorLcAlice3 { return true; } - void process(aod::HfCand3Prong const& candidates, Trks const& barreltracks, const aod::McParticles& mcParticles, const aod::RICHs&, const aod::FRICHs&) + void process(aod::HfCand3Prong const& candidates, + TracksSel const& barreltracks, + aod::McParticles const& mcParticles, + aod::RICHs const&, + aod::FRICHs const&) { - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // selection flag @@ -175,7 +164,7 @@ struct HfCandidateSelectorLcAlice3 { int statusLcToPiKPTofPid = 0; int statusLcToPiKPTofPlusRichPid = 0; - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { hfSelLcCandidateALICE3(statusLcToPKPiNoPid, statusLcToPKPiPerfectPid, statusLcToPKPiTofPid, statusLcToPKPiTofPlusRichPid, statusLcToPiKPNoPid, statusLcToPiKPPerfectPid, statusLcToPiKPTofPid, statusLcToPiKPTofPlusRichPid); continue; } @@ -186,9 +175,9 @@ struct HfCandidateSelectorLcAlice3 { continue; } - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) auto momentumPos1Track = trackPos1.p(); auto momentumNegTrack = trackNeg.p(); diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorLcParametrizedPid.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorLcParametrizedPid.cxx index 70ce968e1c1..335008ef1e7 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorLcParametrizedPid.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorLcParametrizedPid.cxx @@ -16,21 +16,19 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include "ALICE3/DataModel/RICH.h" -#include "Common/Core/TrackSelectorPID.h" -#include "Common/DataModel/PIDResponse.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/PID.h" +#include "ALICE3/DataModel/RICH.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_lc_to_p_k_pi; namespace o2::aod { @@ -46,7 +44,7 @@ DECLARE_SOA_INDEX_TABLE_USER(RICHTracksIndex, Tracks, "RICHTRK", indices::TrackI struct HfCandidateSelectorLcParametrizedPidRichIndexBuilder { // Builder of the RICH-track index linkage Builds indB; - void init(o2::framework::InitContext&) {} + void init(InitContext&) {} }; /// Struct for applying Lc selection cuts @@ -69,24 +67,11 @@ struct HfCandidateSelectorLcParametrizedPid { // topological cuts Configurable decayLengthXYNormalisedMin{"decayLengthXYNormalisedMin", 3., "Normalised decay length"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_lc_to_p_k_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Lc candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_lc_to_p_k_pi::cuts[0], hf_cuts_lc_to_p_k_pi::nBinsPt, hf_cuts_lc_to_p_k_pi::nCutVars, hf_cuts_lc_to_p_k_pi::labelsPt, hf_cuts_lc_to_p_k_pi::labelsCutVar}, "Lc candidate selection per pT bin"}; - using Trks = soa::Join; + HfHelper hfHelper; - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) - { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check - } - return true; - } - */ + using TracksSel = soa::Join; /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -149,11 +134,11 @@ struct HfCandidateSelectorLcParametrizedPid { } if (trackProton.globalIndex() == candidate.prong0Id()) { - if (std::abs(invMassLcToPKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassLcToPKPi(candidate) - o2::analysis::pdg::MassLambdaCPlus) > cuts->get(pTBin, "m")) { return false; } } else { - if (std::abs(invMassLcToPiKP(candidate) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassLcToPiKP(candidate) - o2::analysis::pdg::MassLambdaCPlus) > cuts->get(pTBin, "m")) { return false; } } @@ -161,9 +146,13 @@ struct HfCandidateSelectorLcParametrizedPid { return true; } - void process(aod::HfCand3Prong const& candidates, Trks const& barreltracks, const aod::McParticles& mcParticles, const aod::RICHs&, const aod::FRICHs&) + void process(aod::HfCand3Prong const& candidates, + TracksSel const& barreltracks, + aod::McParticles const& mcParticles, + aod::RICHs const&, + aod::FRICHs const&) { - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // selection flag int statusLcToPKPiNoPid = 0; @@ -173,7 +162,7 @@ struct HfCandidateSelectorLcParametrizedPid { int statusLcToPiKPPerfectPid = 0; int statusLcToPiKP = 0; - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { hfSelLcCandidateparametrizedPID(statusLcToPKPiNoPid, statusLcToPKPiPerfectPid, statusLcToPKPi, statusLcToPiKPNoPid, statusLcToPiKPPerfectPid, statusLcToPiKP); continue; } @@ -184,9 +173,9 @@ struct HfCandidateSelectorLcParametrizedPid { continue; } - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) bool topolLcToPKPi = selectionTopolConjugate(candidate, trackPos1, trackNeg, trackPos2); bool topolLcToPiKP = selectionTopolConjugate(candidate, trackPos2, trackNeg, trackPos1); diff --git a/PWGHF/ALICE3/TableProducer/candidateSelectorXToJpsiPiPi.cxx b/PWGHF/ALICE3/TableProducer/candidateSelectorXToJpsiPiPi.cxx index a8b66b90b56..d56919dfe5a 100644 --- a/PWGHF/ALICE3/TableProducer/candidateSelectorXToJpsiPiPi.cxx +++ b/PWGHF/ALICE3/TableProducer/candidateSelectorXToJpsiPiPi.cxx @@ -19,6 +19,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -26,9 +27,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand_x; using namespace o2::analysis; -using namespace o2::analysis::hf_cuts_x_to_jpsi_pi_pi; /// Struct for applying Jpsi selection cuts struct HfCandidateSelectorXToJpsiPiPi { @@ -47,7 +46,11 @@ struct HfCandidateSelectorXToJpsiPiPi { Configurable nSigmaTofMax{"nSigmaTofMax", 3., "Nsigma cut on TOF only"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_x_to_jpsi_pi_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_x_to_jpsi_pi_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Jpsi candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_x_to_jpsi_pi_pi::cuts[0], hf_cuts_x_to_jpsi_pi_pi::nBinsPt, hf_cuts_x_to_jpsi_pi_pi::nCutVars, hf_cuts_x_to_jpsi_pi_pi::labelsPt, hf_cuts_x_to_jpsi_pi_pi::labelsCutVar}, "Jpsi candidate selection per pT bin"}; + + HfHelper hfHelper; + + using TracksSel = soa::Join; /// Selection on goodness of daughter tracks /// \note should be applied at candidate selection @@ -71,23 +74,22 @@ struct HfCandidateSelectorXToJpsiPiPi { auto candpT = hfCandX.pt(); int pTBin = findBin(binsPt, candpT); if (pTBin == -1) { - // Printf("X topol selection failed at getpTBin"); + // LOGF(debug, "X topol selection failed at getpTBin"); return false; } if (candpT < ptCandMin || candpT >= ptCandMax) { - // Printf("X topol selection failed at cand pT check"); + // LOGF(debug, "X topol selection failed at cand pT check"); return false; // check that the candidate pT is within the analysis range } - // TODO: replace hardcoded mass with "RecoDecay::getMassPDG(9920443)" - if (TMath::Abs(invMassXToJpsiPiPi(hfCandX) - 3.87168) > cuts->get(pTBin, "m")) { - // Printf("X topol selection failed at mass diff check"); + if (std::abs(hfHelper.invMassXToJpsiPiPi(hfCandX) - o2::analysis::pdg::MassX3872) > cuts->get(pTBin, "m")) { + // LOGF(debug, "X topol selection failed at mass diff check"); return false; // check that mass difference is within bounds } if ((hfCandJpsi.pt() < cuts->get(pTBin, "pT Jpsi")) || (trackNeg.pt() < cuts->get(pTBin, "pT Pi")) || (trackPos.pt() < cuts->get(pTBin, "pT Pi"))) { - // Printf("X topol selection failed at daughter pT check"); + // LOGF(debug, "X topol selection failed at daughter pT check"); return false; // cut on daughter pT } @@ -95,9 +97,9 @@ struct HfCandidateSelectorXToJpsiPiPi { return false; // CPA check } - if ((TMath::Abs(hfCandX.impactParameter0()) > cuts->get(pTBin, "d0 Jpsi")) || - (TMath::Abs(hfCandX.impactParameter1()) > cuts->get(pTBin, "d0 Pi")) || - (TMath::Abs(hfCandX.impactParameter2()) > cuts->get(pTBin, "d0 Pi"))) { + if ((std::abs(hfCandX.impactParameter0()) > cuts->get(pTBin, "d0 Jpsi")) || + (std::abs(hfCandX.impactParameter1()) > cuts->get(pTBin, "d0 Pi")) || + (std::abs(hfCandX.impactParameter2()) > cuts->get(pTBin, "d0 Pi"))) { return false; // DCA check on daughters } @@ -113,7 +115,7 @@ struct HfCandidateSelectorXToJpsiPiPi { template bool validTPCPID(const T& track) { - if (TMath::Abs(track.pt()) < ptPidTpcMin || TMath::Abs(track.pt()) >= ptPidTpcMax) { + if (std::abs(track.pt()) < ptPidTpcMin || std::abs(track.pt()) >= ptPidTpcMax) { return false; } // if (track.TPCNClsFindable() < TPCNClsFindableMin) return false; @@ -127,7 +129,7 @@ struct HfCandidateSelectorXToJpsiPiPi { template bool validTofPid(const T& track) { - if (TMath::Abs(track.pt()) < ptPidTofMin || TMath::Abs(track.pt()) >= ptPidTofMax) { + if (std::abs(track.pt()) < ptPidTofMin || std::abs(track.pt()) >= ptPidTofMax) { return false; } return true; @@ -187,13 +189,15 @@ struct HfCandidateSelectorXToJpsiPiPi { // } } - void process(aod::HfCandX const& hfCandXs, aod::HfCand2Prong const&, aod::BigTracksPID const& tracks) + void process(aod::HfCandX const& hfCandXs, + aod::HfCand2Prong const&, + TracksSel const& tracks) { - for (auto& hfCandX : hfCandXs) { // looping over X candidates + for (const auto& hfCandX : hfCandXs) { // looping over X candidates // note the difference between Jpsi (index0) and pions (index1,2) auto candJpsi = hfCandX.prong0(); - auto trackPos = hfCandX.prong1_as(); // positive daughter - auto trackNeg = hfCandX.prong2_as(); // negative daughter + auto trackPos = hfCandX.prong1_as(); // positive daughter + auto trackNeg = hfCandX.prong2_as(); // negative daughter int selJpsiToEE = 1; int selJpsiToMuMu = 1; @@ -215,7 +219,7 @@ struct HfCandidateSelectorXToJpsiPiPi { // daughter track validity selection if (!daughterSelection(trackPos) || !daughterSelection(trackNeg)) { hfSelXToJpsiPiPiCandidate(0, 0); - // Printf("X candidate selection failed at daughter selection"); + // LOGF(debug, "X candidate selection failed at daughter selection"); continue; } @@ -224,18 +228,18 @@ struct HfCandidateSelectorXToJpsiPiPi { if (!selectionTopol(hfCandX, candJpsi, trackPos, trackNeg)) { hfSelXToJpsiPiPiCandidate(0, 0); - // Printf("X candidate selection failed at selection topology"); + // LOGF(debug, "X candidate selection failed at selection topology"); continue; } if (selectionPID(trackPos) == 0 || selectionPID(trackNeg) == 0) { hfSelXToJpsiPiPiCandidate(0, 0); - // Printf("X candidate selection failed at selection PID"); + // LOGF(debug, "X candidate selection failed at selection PID"); continue; } hfSelXToJpsiPiPiCandidate(selJpsiToEE, selJpsiToMuMu); - // Printf("X candidate selection successful, candidate should be selected"); + // LOGF(debug, "X candidate selection successful, candidate should be selected"); } } }; diff --git a/PWGHF/ALICE3/TableProducer/treeCreatorChicToJpsiGamma.cxx b/PWGHF/ALICE3/TableProducer/treeCreatorChicToJpsiGamma.cxx index 558efd85cf7..3ed3424e288 100644 --- a/PWGHF/ALICE3/TableProducer/treeCreatorChicToJpsiGamma.cxx +++ b/PWGHF/ALICE3/TableProducer/treeCreatorChicToJpsiGamma.cxx @@ -18,18 +18,16 @@ /// \author Alessandro De Falco , Università/INFN Cagliari /// \author Luca Micheletti , INFN -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand_chic; namespace o2::aod { @@ -64,7 +62,7 @@ DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); } // namespace full -DECLARE_SOA_TABLE(HfCandChicFull, "AOD", "HFCANDChicFull", +DECLARE_SOA_TABLE(HfCandChicFulls, "AOD", "HFCANDCHICFULL", collision::BCId, collision::NumContrib, collision::PosX, @@ -96,7 +94,7 @@ DECLARE_SOA_TABLE(HfCandChicFull, "AOD", "HFCANDChicFull", full::MCflag, full::OriginMcRec); -DECLARE_SOA_TABLE(HfCandChicFullEvents, "AOD", "HFCANDChicFullE", +DECLARE_SOA_TABLE(HfCandChicFullEs, "AOD", "HFCANDCHICFULLE", collision::BCId, collision::NumContrib, collision::PosX, @@ -105,7 +103,7 @@ DECLARE_SOA_TABLE(HfCandChicFullEvents, "AOD", "HFCANDChicFullE", full::IsEventReject, full::RunNumber); -DECLARE_SOA_TABLE(HfCandChicFullParticles, "AOD", "HFCANDChicFullP", +DECLARE_SOA_TABLE(HfCandChicFullPs, "AOD", "HFCANDCHICFULLP", collision::BCId, full::Pt, full::Eta, @@ -119,25 +117,27 @@ DECLARE_SOA_TABLE(HfCandChicFullParticles, "AOD", "HFCANDChicFullP", /// Writes the full information in an output TTree struct HfTreeCreatorChicToJpsiGamma { - Produces rowCandidateFull; - Produces rowCandidateFullEvents; - Produces rowCandidateFullParticles; + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + + HfHelper hfHelper; void init(InitContext const&) { } void process(aod::Collisions const& collisions, - aod::McCollisions const& mccollisions, + aod::McCollisions const& mcCollisions, soa::Join const& candidates, soa::Join const& particles, - aod::BigTracksPID const& tracks, + aod::Tracks const& tracks, aod::HfCand2Prong const& jpsiCands) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { rowCandidateFullEvents( collision.bcId(), collision.numContrib(), @@ -151,10 +151,10 @@ struct HfTreeCreatorChicToJpsiGamma { // Filling candidate properties int indexCand = 0; rowCandidateFull.reserve(candidates.size()); - for (auto& candidate : candidates) { - array pvecChic = {candidate.px(), candidate.py(), candidate.pz()}; - array pvecJpsi = {candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()}; - array pvecGamma = {candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()}; + for (const auto& candidate : candidates) { + std::array pvecChic = {candidate.px(), candidate.py(), candidate.pz()}; + std::array pvecJpsi = {candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()}; + std::array pvecGamma = {candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()}; auto pchic = RecoDecay::p(pvecChic); auto pjpsi = RecoDecay::p(pvecJpsi); auto pl1 = std::abs(RecoDecay::dotProd(pvecChic, pvecJpsi)) / pchic; @@ -170,8 +170,8 @@ struct HfTreeCreatorChicToJpsiGamma { float FunctionY) { if (FunctionSelection >= 1) { rowCandidateFull( - candidate.prong0().prong0_as().collision().bcId(), - candidate.prong0().prong0_as().collision().numContrib(), + candidate.prong0().prong0().collision().bcId(), + candidate.prong0().prong0().collision().numContrib(), candidate.posX(), candidate.posY(), candidate.posZ(), @@ -202,21 +202,21 @@ struct HfTreeCreatorChicToJpsiGamma { candidate.originMcRec()); } }; - fillTable(0, candidate.isSelChicToJpsiToMuMuGamma(), invMassChicToJpsiGamma(candidate), ctChic(candidate), yChic(candidate)); - // fillTable(1, candidate.isSelChicToJpsiToEEGamma(), invMassChicToJpsiGamma(candidate), ctChic(candidate), yChic(candidate)); + fillTable(0, candidate.isSelChicToJpsiToMuMuGamma(), hfHelper.invMassChicToJpsiGamma(candidate), hfHelper.ctChic(candidate), hfHelper.yChic(candidate)); + // fillTable(1, candidate.isSelChicToJpsiToEEGamma(), hfHelper.invMassChicToJpsiGamma(candidate), hfHelper.ctChic(candidate), hfHelper.yChic(candidate)); } // Filling particle properties - float massChic = RecoDecay::getMassPDG(pdg::Code::kChiC1); + float massChic = o2::analysis::pdg::MassChiC1; rowCandidateFullParticles.reserve(particles.size()); - for (auto& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::ChicToJpsiToEEGamma || std::abs(particle.flagMcMatchGen()) == 1 << DecayType::ChicToJpsiToMuMuGamma) { + for (const auto& particle : particles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_chic::DecayType::ChicToJpsiToEEGamma || std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_chic::DecayType::ChicToJpsiToMuMuGamma) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), particle.eta(), particle.phi(), - RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, massChic), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, massChic), 0., // put here the jpsi mass particle.flagMcMatchGen(), particle.originMcGen()); diff --git a/PWGHF/ALICE3/TableProducer/treeCreatorXToJpsiPiPi.cxx b/PWGHF/ALICE3/TableProducer/treeCreatorXToJpsiPiPi.cxx index 367d2e76b52..527605893e6 100644 --- a/PWGHF/ALICE3/TableProducer/treeCreatorXToJpsiPiPi.cxx +++ b/PWGHF/ALICE3/TableProducer/treeCreatorXToJpsiPiPi.cxx @@ -17,18 +17,16 @@ /// /// \author Luca Micheletti , INFN -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand_x; namespace o2::aod { @@ -76,7 +74,7 @@ DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); } // namespace full -DECLARE_SOA_TABLE(HfCandXFull, "AOD", "HFCANDXFull", +DECLARE_SOA_TABLE(HfCandXFulls, "AOD", "HFCANDXFULL", collision::BCId, collision::NumContrib, collision::PosX, @@ -120,7 +118,7 @@ DECLARE_SOA_TABLE(HfCandXFull, "AOD", "HFCANDXFull", full::MCflag, full::OriginMcRec); -DECLARE_SOA_TABLE(HfCandXFullEvents, "AOD", "HFCANDXFullE", +DECLARE_SOA_TABLE(HfCandXFullEvs, "AOD", "HFCANDXFULLEV", collision::BCId, collision::NumContrib, collision::PosX, @@ -129,7 +127,7 @@ DECLARE_SOA_TABLE(HfCandXFullEvents, "AOD", "HFCANDXFullE", full::IsEventReject, full::RunNumber); -DECLARE_SOA_TABLE(HfCandXFullParticles, "AOD", "HFCANDXFullP", +DECLARE_SOA_TABLE(HfCandXFullPs, "AOD", "HFCANDXFULLP", collision::BCId, full::Pt, full::Eta, @@ -142,24 +140,28 @@ DECLARE_SOA_TABLE(HfCandXFullParticles, "AOD", "HFCANDXFullP", /// Writes the full information in an output TTree struct HfTreeCreatorXToJpsiPiPi { - Produces rowCandidateFull; - Produces rowCandidateFullEvents; - Produces rowCandidateFullParticles; + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + + HfHelper hfHelper; + + using TracksWPid = soa::Join; void init(InitContext const&) { } void process(aod::Collisions const& collisions, - aod::McCollisions const& mccollisions, + aod::McCollisions const& mcCollisions, soa::Join const& candidates, soa::Join const& particles, - aod::BigTracksPID const& tracks) + TracksWPid const& tracks) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { rowCandidateFullEvents( collision.bcId(), collision.numContrib(), @@ -173,7 +175,7 @@ struct HfTreeCreatorXToJpsiPiPi { // Filling candidate properties int indexCand = 0; rowCandidateFull.reserve(candidates.size()); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!candidate.isSelXToJpsiToMuMuPiPi()) { continue; } @@ -189,8 +191,8 @@ struct HfTreeCreatorXToJpsiPiPi { float FunctionPiBalance) { if (FunctionSelection >= 1) { rowCandidateFull( - candidate.prong1_as().collision().bcId(), - candidate.prong1_as().collision().numContrib(), + candidate.prong1_as().collision().bcId(), + candidate.prong1_as().collision().numContrib(), candidate.posX(), candidate.posY(), candidate.posZ(), @@ -209,12 +211,12 @@ struct HfTreeCreatorXToJpsiPiPi { candidate.impactParameter0(), candidate.impactParameter1(), candidate.impactParameter2(), - candidate.prong1_as().tofNSigmaPi(), - candidate.prong1_as().tofNSigmaKa(), - candidate.prong1_as().tofNSigmaPr(), - candidate.prong2_as().tofNSigmaPi(), - candidate.prong2_as().tofNSigmaKa(), - candidate.prong2_as().tofNSigmaPr(), + candidate.prong1_as().tofNSigmaPi(), + candidate.prong1_as().tofNSigmaKa(), + candidate.prong1_as().tofNSigmaPr(), + candidate.prong2_as().tofNSigmaPi(), + candidate.prong2_as().tofNSigmaKa(), + candidate.prong2_as().tofNSigmaPr(), 1 << CandFlag, FunctionInvMass, candidate.pt(), @@ -234,20 +236,20 @@ struct HfTreeCreatorXToJpsiPiPi { } }; - fillTable(0, candidate.isSelXToJpsiToMuMuPiPi(), invMassXToJpsiPiPi(candidate), ctX(candidate), yX(candidate), qX(candidate), dRX(candidate, 1), dRX(candidate, 2), balancePtPionsX(candidate)); + fillTable(0, candidate.isSelXToJpsiToMuMuPiPi(), hfHelper.invMassXToJpsiPiPi(candidate), hfHelper.ctX(candidate), hfHelper.yX(candidate), hfHelper.qX(candidate), hfHelper.dRX(candidate, 1), hfHelper.dRX(candidate, 2), hfHelper.balancePtPionsX(candidate)); } // Filling particle properties float massX = 3.872; rowCandidateFullParticles.reserve(particles.size()); - for (auto& particle : particles) { + for (const auto& particle : particles) { if (std::abs(particle.flagMcMatchGen()) == 1 << hf_cand_x::DecayType::XToJpsiToEEPiPi || std::abs(particle.flagMcMatchGen()) == 1 << hf_cand_x::DecayType::XToJpsiToMuMuPiPi) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), particle.eta(), particle.phi(), - RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, massX), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, massX), particle.flagMcMatchGen(), particle.originMcGen()); } diff --git a/PWGHF/ALICE3/Tasks/CMakeLists.txt b/PWGHF/ALICE3/Tasks/CMakeLists.txt index a4088183a4b..140815e7585 100644 --- a/PWGHF/ALICE3/Tasks/CMakeLists.txt +++ b/PWGHF/ALICE3/Tasks/CMakeLists.txt @@ -11,45 +11,45 @@ o2physics_add_dpl_workflow(task-chic SOURCES taskChic.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-d0-alice3-barrel SOURCES taskD0Alice3Barrel.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-d0-alice3-forward SOURCES taskD0Alice3Forward.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-d0-parametrized-pid SOURCES taskD0ParametrizedPid.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-jpsi SOURCES taskJpsi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-lc-alice3 SOURCES taskLcAlice3.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-lc-parametrized-pid SOURCES taskLcParametrizedPid.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-qa-pid-rejection SOURCES taskQaPidRejection.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-x SOURCES taskX.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGHF/ALICE3/Tasks/taskChic.cxx b/PWGHF/ALICE3/Tasks/taskChic.cxx index 3ebf46ce663..84cbb958146 100644 --- a/PWGHF/ALICE3/Tasks/taskChic.cxx +++ b/PWGHF/ALICE3/Tasks/taskChic.cxx @@ -15,11 +15,10 @@ /// \author Gian Michele Innocenti , CERN /// \author Alessandro De Falco , Cagliari University -#include - #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -27,11 +26,8 @@ using namespace o2; using namespace o2::aod; using namespace o2::analysis; -using namespace o2::analysis::hf_cuts_chic_to_jpsi_gamma; using namespace o2::framework; -using namespace o2::aod::hf_cand_chic; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; void customize(std::vector& workflowOptions) { @@ -48,6 +44,8 @@ struct HfTaskChic { Configurable modeChicToJpsiToMuMuGamma{"modeChicToJpsiToMuMuGamma", true, "Perform Jpsi to mu+mu- analysis"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_chic_to_jpsi_gamma::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_chic::isSelChicToJpsiToEEGamma >= selectionFlagChic || aod::hf_sel_candidate_chic::isSelChicToJpsiToMuMuGamma >= selectionFlagChic); HistogramRegistry registry{ @@ -56,7 +54,7 @@ struct HfTaskChic { {"hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, {"hPtCand", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{150, 0., 15.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { registry.add("hMass", "2-prong candidates;inv. mass (J/#psi #gamma) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{200, 3., 4.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hDeltaMass", "2-prong candidates;inv. mass (J/#psi #gamma) - inv. mass (J/#psi) + mass^{PDG} (J/#psi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{200, 3., 4.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -75,16 +73,16 @@ struct HfTaskChic { void process(soa::Filtered> const& candidates) { int decayMode = modeChicToJpsiToMuMuGamma ? hf_cand_chic::DecayType::ChicToJpsiToMuMuGamma : hf_cand_chic::DecayType::ChicToJpsiToEEGamma; - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!(candidate.hfflag() & 1 << decayMode)) { continue; } - if (yCandMax >= 0. && std::abs(yChic(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yChic(candidate)) > yCandMax) { continue; } - registry.fill(HIST("hMass"), invMassChicToJpsiGamma(candidate), candidate.pt()); - registry.fill(HIST("hDeltaMass"), invMassChicToJpsiGamma(candidate) - candidate.jpsiToMuMuMass() + RecoDecay::getMassPDG(pdg::Code::kJPsi), candidate.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassChicToJpsiGamma(candidate), candidate.pt()); + registry.fill(HIST("hDeltaMass"), hfHelper.invMassChicToJpsiGamma(candidate) - candidate.jpsiToMuMuMass() + o2::analysis::pdg::MassJPsi, candidate.pt()); registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); @@ -109,6 +107,8 @@ struct HfTaskChicMc { Configurable modeChicToJpsiToMuMuGamma{"modeChicToJpsiToMuMuGamma", true, "Perform Jpsi to mu+mu- analysis"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_chic_to_jpsi_gamma::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_chic::isSelChicToJpsiToEEGamma >= selectionFlagChic || aod::hf_sel_candidate_chic::isSelChicToJpsiToMuMuGamma >= selectionFlagChic); HistogramRegistry registry{ @@ -118,7 +118,7 @@ struct HfTaskChicMc { {"hPtGen", "2-prong candidates (gen. matched);#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{150, 0., 15.}}}}, {"hPtGenSig", "2-prong candidates (rec. matched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{150, 0., 15.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { registry.add("hCPARecSig", "2-prong candidates (rec. matched);cosine of pointing angle;entries", {HistType::kTH2F, {{500, 0.9, 1.0}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hCPARecBg", "2-prong candidates (rec. unmatched);cosine of pointing angle;entries", {HistType::kTH2F, {{500, 0.9, 1.0}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -153,59 +153,57 @@ struct HfTaskChicMc { } void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { // MC rec. - // Printf("MC Candidates: %d", candidates.size()); int decayMode = modeChicToJpsiToMuMuGamma ? hf_cand_chic::DecayType::ChicToJpsiToMuMuGamma : hf_cand_chic::DecayType::ChicToJpsiToEEGamma; - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!(candidate.hfflag() & 1 << decayMode)) { continue; } - if (yCandMax >= 0. && std::abs(yChic(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yChic(candidate)) > yCandMax) { continue; } if (candidate.flagMcMatchRec() == 1 << decayMode) { // FIXME the access to the MC particle gen not yet functional - // int indexMother = RecoDecay::getMother(particlesMC, particlesMC.rawIteratorAt(candidate.prong1().mcParticle_as().globalIndex()), 20443); - // auto particleMother = particlesMC.rawIteratorAt(indexMother); + // int indexMother = RecoDecay::getMother(mcParticles, mcParticles.rawIteratorAt(candidate.prong1().mcParticle_as().globalIndex()), 20443); + // auto particleMother = mcParticles.rawIteratorAt(indexMother); // registry.fill(HIST("hPtGenSig"), particleMother.pt()); registry.fill(HIST("hPtRecSig"), candidate.pt()); registry.fill(HIST("hCPARecSig"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEtaRecSig"), candidate.eta(), candidate.pt()); registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("hDeltaMassRecSig"), invMassChicToJpsiGamma(candidate) - candidate.jpsiToMuMuMass() + RecoDecay::getMassPDG(pdg::Code::kJPsi), candidate.pt()); - registry.fill(HIST("hMassRecSig"), invMassChicToJpsiGamma(candidate), candidate.pt()); + registry.fill(HIST("hDeltaMassRecSig"), hfHelper.invMassChicToJpsiGamma(candidate) - candidate.jpsiToMuMuMass() + o2::analysis::pdg::MassJPsi), candidate.pt(); + registry.fill(HIST("hMassRecSig"), hfHelper.invMassChicToJpsiGamma(candidate), candidate.pt()); registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), candidate.pt()); registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1(), candidate.pt()); registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), candidate.pt()); - registry.fill(HIST("hCtRecSig"), ctChic(candidate), candidate.pt()); - registry.fill(HIST("hYRecSig"), yChic(candidate), candidate.pt()); + registry.fill(HIST("hCtRecSig"), hfHelper.ctChic(candidate), candidate.pt()); + registry.fill(HIST("hYRecSig"), hfHelper.yChic(candidate), candidate.pt()); } else { registry.fill(HIST("hPtRecBg"), candidate.pt()); registry.fill(HIST("hCPARecBg"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEtaRecBg"), candidate.eta(), candidate.pt()); registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("hDeltaMassRecBg"), invMassChicToJpsiGamma(candidate) - candidate.jpsiToMuMuMass() + RecoDecay::getMassPDG(pdg::Code::kJPsi), candidate.pt()); - registry.fill(HIST("hMassRecBg"), invMassChicToJpsiGamma(candidate), candidate.pt()); + registry.fill(HIST("hDeltaMassRecBg"), hfHelper.invMassChicToJpsiGamma(candidate) - candidate.jpsiToMuMuMass() + o2::analysis::pdg::MassJPsi), candidate.pt(); + registry.fill(HIST("hMassRecBg"), hfHelper.invMassChicToJpsiGamma(candidate), candidate.pt()); registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), candidate.pt()); registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1(), candidate.pt()); registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), candidate.pt()); - registry.fill(HIST("hCtRecBg"), ctChic(candidate), candidate.pt()); - registry.fill(HIST("hYRecBg"), yChic(candidate), candidate.pt()); + registry.fill(HIST("hCtRecBg"), hfHelper.ctChic(candidate), candidate.pt()); + registry.fill(HIST("hYRecBg"), hfHelper.yChic(candidate), candidate.pt()); } } // rec // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { if (particle.flagMcMatchGen() == 1 << decayMode) { - auto mchic = RecoDecay::getMassPDG(pdg::Code::kChiC1); // chi_c1(1p) - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, mchic)) > yCandMax) { - // Printf("MC Gen.: Y rejection: %g", RecoDecay::Y(array{particle.px(), particle.py(), particle.pz()}, 3.87168)); + auto mchic = o2::analysis::pdg::MassChiC1; // chi_c1(1p) + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, mchic)) > yCandMax) { continue; } @@ -215,7 +213,7 @@ struct HfTaskChicMc { // properties of gen matched chic, to get a first look at some cuts float ptProngs[3]; int counter = 0; - for (auto& dau : particle.daughters_as()) { + for (const auto& dau : particle.daughters_as()) { ptProngs[counter] = dau.pt(); counter++; } diff --git a/PWGHF/ALICE3/Tasks/taskD0Alice3Barrel.cxx b/PWGHF/ALICE3/Tasks/taskD0Alice3Barrel.cxx index d6d1892540c..b5af1967d3b 100644 --- a/PWGHF/ALICE3/Tasks/taskD0Alice3Barrel.cxx +++ b/PWGHF/ALICE3/Tasks/taskD0Alice3Barrel.cxx @@ -15,26 +15,25 @@ /// \author Gian Michele Innocenti , CERN /// \author Vít Kučera , CERN -// #include "Common/DataModel/Centrality.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; /// Fills MC histograms. struct HfTaskD0Alice3Barrel { // Configurable centralitySelectionMin{"centralitySelectionMin", 0.0, "Lower boundary of centrality selection"}; // Configurable centralitySelectionMax{"centralitySelectionMax", 0.0, "Higher boundary of centrality selection"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_d0_alice3_barrel::isSelHfFlag >= 1); HistogramRegistry registry{ @@ -60,29 +59,31 @@ struct HfTaskD0Alice3Barrel { {"hMassSigD0PerfectPid", "2-prong candidates (matched);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{120, 1.5848, 2.1848}, {150, 0., 30.}, {8, 0., 4.}}}}, {"hMassBkgD0PerfectPid", "2-prong candidates (checked);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{120, 1.5848, 2.1848}, {150, 0., 30.}, {8, 0., 4.}}}}}}; - // void process(soa::Join::iterator const& collision, soa::Filtered> const& candidates, soa::Join const& particlesMC, aod::BigTracksMC const& tracks) - void process(soa::Filtered> const& candidates, soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + // void process(soa::Join::iterator const& collision, soa::Filtered> const& candidates, soa::Join const& mcParticles, aod::TracksWMc const& tracks) + void process(soa::Filtered> const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { // float centrality = collision.centV0M(); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // if (centrality<=centralitySelectionMin && centrality>centralitySelectionMax) { // continue; // } - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (std::abs(yD0(candidate)) > 4.0) { + if (std::abs(hfHelper.yD0(candidate)) > 4.0) { continue; } - auto massD0 = invMassD0ToPiK(candidate); - auto massD0bar = invMassD0barToKPi(candidate); + auto massD0 = hfHelper.invMassD0ToPiK(candidate); + auto massD0bar = hfHelper.invMassD0barToKPi(candidate); auto ptCandidate = candidate.pt(); - auto rapidityCandidate = std::abs(yD0(candidate)); + auto rapidityCandidate = std::abs(hfHelper.yD0(candidate)); if (candidate.isSelD0NoPid() >= 1) { registry.fill(HIST("hMassSigBkgD0NoPid"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0NoPid"), massD0, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0NoPid"), massD0, ptCandidate, rapidityCandidate); @@ -91,7 +92,7 @@ struct HfTaskD0Alice3Barrel { if (candidate.isSelD0TofPid() >= 1) { registry.fill(HIST("hMassSigBkgD0TofPid"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0TofPid"), massD0, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0TofPid"), massD0, ptCandidate, rapidityCandidate); @@ -100,10 +101,10 @@ struct HfTaskD0Alice3Barrel { if (candidate.isSelD0RichPid() >= 1) { registry.fill(HIST("hMassSigBkgD0RICHPID"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0RICHPID"), massD0, ptCandidate, rapidityCandidate); } else { - if (candidate.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassReflBkgD0RICHPID"), massD0, ptCandidate, rapidityCandidate); } registry.fill(HIST("hMassBkgD0RICHPID"), massD0, ptCandidate, rapidityCandidate); @@ -112,7 +113,7 @@ struct HfTaskD0Alice3Barrel { if (candidate.isSelD0TofPlusRichPid() >= 1) { registry.fill(HIST("hMassSigBkgD0TofPlusRichPid"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0TofPlusRichPid"), massD0, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0TofPlusRichPid"), massD0, ptCandidate, rapidityCandidate); @@ -121,7 +122,7 @@ struct HfTaskD0Alice3Barrel { if (candidate.isSelD0barTofPlusRichPid() >= 1) { registry.fill(HIST("hMassSigBkgD0barTofPlusRichPid"), massD0bar, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0barTofPlusRichPid"), massD0bar, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0barTofPlusRichPid"), massD0bar, ptCandidate, rapidityCandidate); @@ -130,7 +131,7 @@ struct HfTaskD0Alice3Barrel { if (candidate.isSelD0PerfectPid() >= 1) { registry.fill(HIST("hMassSigBkgD0PerfectPid"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0PerfectPid"), massD0, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0PerfectPid"), massD0, ptCandidate, rapidityCandidate); @@ -138,13 +139,13 @@ struct HfTaskD0Alice3Barrel { } } - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::D0ToPiK) { - if (std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > 4.0) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0)) > 4.0) { continue; } auto ptGen = particle.pt(); - auto yGen = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto yGen = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0); registry.fill(HIST("hMassGen"), ptGen, std::abs(yGen)); } } diff --git a/PWGHF/ALICE3/Tasks/taskD0Alice3Forward.cxx b/PWGHF/ALICE3/Tasks/taskD0Alice3Forward.cxx index e33b4add3b6..5b880ad250e 100644 --- a/PWGHF/ALICE3/Tasks/taskD0Alice3Forward.cxx +++ b/PWGHF/ALICE3/Tasks/taskD0Alice3Forward.cxx @@ -19,20 +19,20 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; /// Fills MC histograms. struct HfTaskD0Alice3Forward { Filter filterSelectCandidates = (aod::hf_sel_candidate_d0_alice3_forward::isSelHfFlag >= 1); + HfHelper hfHelper; + HistogramRegistry registry{ "registry", {{"hMassGen", "2-prong candidates (generated); #it{p}_{T}; #it{y}", {HistType::kTH2F, {{150, 0., 30.}, {8, 0, 4.0}}}}, @@ -41,24 +41,25 @@ struct HfTaskD0Alice3Forward { {"hMassBkgD0ForwardRICHPID", "2-prong candidates (checked);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{120, 1.5848, 2.1848}, {150, 0., 30.}, {8, 0., 4.}}}}}}; void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { - for (auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (std::abs(yD0(candidate)) > 4.0) { + if (std::abs(hfHelper.yD0(candidate)) > 4.0) { continue; } - auto massD0 = invMassD0ToPiK(candidate); - // auto massD0bar = invMassD0barToKPi(candidate); + auto massD0 = hfHelper.invMassD0ToPiK(candidate); + // auto massD0bar = hfHelper.invMassD0barToKPi(candidate); auto ptCandidate = candidate.pt(); - auto rapidityCandidate = std::abs(yD0(candidate)); + auto rapidityCandidate = std::abs(hfHelper.yD0(candidate)); if (candidate.isSelD0FRichPid() >= 1) { registry.fill(HIST("hMassSigBkgD0ForwardRICHPID"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0ForwardRICHPID"), massD0, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0ForwardRICHPID"), massD0, ptCandidate, rapidityCandidate); @@ -66,13 +67,13 @@ struct HfTaskD0Alice3Forward { } } - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::D0ToPiK) { - if (std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > 4.0) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0)) > 4.0) { continue; } auto ptGen = particle.pt(); - auto yGen = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto yGen = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0); registry.fill(HIST("hMassGen"), ptGen, std::abs(yGen)); } } diff --git a/PWGHF/ALICE3/Tasks/taskD0ParametrizedPid.cxx b/PWGHF/ALICE3/Tasks/taskD0ParametrizedPid.cxx index d33daab318d..989ad01d0ca 100644 --- a/PWGHF/ALICE3/Tasks/taskD0ParametrizedPid.cxx +++ b/PWGHF/ALICE3/Tasks/taskD0ParametrizedPid.cxx @@ -19,21 +19,21 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; /// Fills MC histograms. struct HfTaskD0ParametrizedPid { // Configurable centralitySelectionMin{"centralitySelectionMin", 0.0, "Lower boundary of centrality selection"}; // Configurable centralitySelectionMax{"centralitySelectionMax", 30000.0, "Higher boundary of centrality selection"}; + HfHelper hfHelper; + using McParticlesHf = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_d0_parametrized_pid::isSelD0NoPid >= 1 || aod::hf_sel_candidate_d0_parametrized_pid::isSelD0barNoPid >= 1); @@ -57,29 +57,31 @@ struct HfTaskD0ParametrizedPid { {"hMassSigD0PerfectPid", "2-prong candidates (matched);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{120, 1.5848, 2.1848}, {150, 0., 30.}, {8, 0., 4.}}}}, {"hMassBkgD0PerfectPid", "2-prong candidates (checked);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{120, 1.5848, 2.1848}, {150, 0., 30.}, {8, 0., 4.}}}}}}; - void process(soa::Filtered> const& candidates, McParticlesHf const& particlesMC, aod::BigTracksMC const& tracks) - // void process(const o2::aod::Collision& collision, soa::Filtered> const& candidates, soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + void process(soa::Filtered> const& candidates, + McParticlesHf const& mcParticles, + aod::TracksWMc const& tracks) + // void process(const o2::aod::Collision& collision, soa::Filtered> const& candidates, soa::Join const& mcParticles, aod::TracksWMc const& tracks) { // float ncontributor = collision.numContrib(); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // if (ncontributor<=centralitySelectionMin && ncontributor>centralitySelectionMax) { // continue; // } - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (std::abs(yD0(candidate)) > 4.0) { + if (std::abs(hfHelper.yD0(candidate)) > 4.0) { continue; } - auto massD0 = invMassD0ToPiK(candidate); - // auto massD0bar = invMassD0barToKPi(candidate); + auto massD0 = hfHelper.invMassD0ToPiK(candidate); + // auto massD0bar = hfHelper.invMassD0barToKPi(candidate); auto ptCandidate = candidate.pt(); - auto rapidityCandidate = std::abs(yD0(candidate)); + auto rapidityCandidate = std::abs(hfHelper.yD0(candidate)); if (candidate.isSelD0NoPid() >= 1) { registry.fill(HIST("hMassSigBkgD0NoPid"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0NoPid"), massD0, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0NoPid"), massD0, ptCandidate, rapidityCandidate); @@ -88,10 +90,10 @@ struct HfTaskD0ParametrizedPid { if (candidate.isSelD0() >= 1) { registry.fill(HIST("hMassSigBkgD0"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0"), massD0, ptCandidate, rapidityCandidate); } else { - if (candidate.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassReflBkgD0"), massD0, ptCandidate, rapidityCandidate); } registry.fill(HIST("hMassBkgD0"), massD0, ptCandidate, rapidityCandidate); @@ -100,7 +102,7 @@ struct HfTaskD0ParametrizedPid { if (candidate.isSelD0PerfectPid() >= 1) { registry.fill(HIST("hMassSigBkgD0PerfectPid"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0PerfectPid"), massD0, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0PerfectPid"), massD0, ptCandidate, rapidityCandidate); @@ -108,18 +110,18 @@ struct HfTaskD0ParametrizedPid { } } - for (auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { // if (ncontributor<=centralitySelectionMin && ncontributor>centralitySelectionMax) { // continue; // } float maxFiducialY = 0.8; float minFiducialY = -0.8; - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::D0ToPiK) { - if (std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > 4.0) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0)) > 4.0) { continue; } auto ptGen = particle.pt(); - auto yGen = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto yGen = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0); registry.fill(HIST("hGenPtVsY"), ptGen, std::abs(yGen)); if (ptGen < 5.0) { maxFiducialY = -0.2 / 15 * ptGen * ptGen + 1.9 / 15 * ptGen + 0.5; diff --git a/PWGHF/ALICE3/Tasks/taskJpsi.cxx b/PWGHF/ALICE3/Tasks/taskJpsi.cxx index 36bedc20c4e..28d6e338766 100644 --- a/PWGHF/ALICE3/Tasks/taskJpsi.cxx +++ b/PWGHF/ALICE3/Tasks/taskJpsi.cxx @@ -19,14 +19,14 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_jpsi_to_e_e; void customize(std::vector& workflowOptions) { @@ -47,6 +47,8 @@ struct HfTaskJpsi { Configurable selectedMid{"selectedMid", false, "select MID for Jpsi to mu+mu-"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_jpsi_to_e_e::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_jpsi::isSelJpsiToEETopol >= selectionFlagJpsi || aod::hf_sel_candidate_jpsi::isSelJpsiToMuMuTopol >= selectionFlagJpsi); HistogramRegistry registry{ @@ -55,7 +57,7 @@ struct HfTaskJpsi { {"hPtProng0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 20.}}}}, {"hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 20.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { if (modeJpsiToMuMu) { registry.add("hMass", "2-prong candidates;inv. mass (#mu^{#plus} #mu^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{200, 2., 4.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -76,9 +78,9 @@ struct HfTaskJpsi { void process(soa::Filtered> const& candidates) { - int decayMode = modeJpsiToMuMu ? DecayType::JpsiToMuMu : DecayType::JpsiToEE; + int decayMode = modeJpsiToMuMu ? aod::hf_cand_2prong::DecayType::JpsiToMuMu : aod::hf_cand_2prong::DecayType::JpsiToEE; - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!(candidate.hfflag() & 1 << decayMode)) { continue; @@ -106,14 +108,14 @@ struct HfTaskJpsi { } } } - if (yCandMax >= 0. && std::abs(yJpsi(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yJpsi(candidate)) > yCandMax) { continue; } if (modeJpsiToMuMu) { - registry.fill(HIST("hMass"), invMassJpsiToMuMu(candidate), candidate.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassJpsiToMuMu(candidate), candidate.pt()); } else { - registry.fill(HIST("hMass"), invMassJpsiToEE(candidate), candidate.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassJpsiToEE(candidate), candidate.pt()); } registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); @@ -144,6 +146,8 @@ struct HfTaskJpsiMc { Configurable selectedMid{"selectedMid", false, "select MID for Jpsi to mu+mu-"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_jpsi_to_e_e::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + using McParticlesHf = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_jpsi::isSelJpsiToEETopol >= selectionFlagJpsi || aod::hf_sel_candidate_jpsi::isSelJpsiToMuMuTopol >= selectionFlagJpsi); @@ -160,7 +164,7 @@ struct HfTaskJpsiMc { {"hEtaRecBg", "2-prong candidates (rec. unmatched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, {"hEtaGen", "2-prong candidates (gen. matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { if (modeJpsiToMuMu) { registry.add("hMassSig", "2-prong candidates (rec matched);inv. mass (#mu^{#plus} #mu^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{200, 2., 4.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -192,13 +196,13 @@ struct HfTaskJpsiMc { } void process(soa::Filtered> const& candidates, - McParticlesHf const& particlesMC, aod::BigTracksMC const& tracks) + McParticlesHf const& mcParticles, + aod::TracksWMc const& tracks) { // MC rec. - // Printf("MC Candidates: %d", candidates.size()); - int decayMode = modeJpsiToMuMu ? DecayType::JpsiToMuMu : DecayType::JpsiToEE; + int decayMode = modeJpsiToMuMu ? aod::hf_cand_2prong::DecayType::JpsiToMuMu : aod::hf_cand_2prong::DecayType::JpsiToEE; - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!(candidate.hfflag() & 1 << decayMode)) { continue; @@ -227,21 +231,21 @@ struct HfTaskJpsiMc { } } - if (yCandMax >= 0. && std::abs(yJpsi(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yJpsi(candidate)) > yCandMax) { continue; } if (candidate.flagMcMatchRec() == 1 << decayMode) { // Get the corresponding MC particle. - auto indexMother = RecoDecay::getMother(particlesMC, candidate.prong0_as().mcParticle_as(), pdg::Code::kJPsi, true); - auto particleMother = particlesMC.rawIteratorAt(indexMother); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong0_as().mcParticle_as(), pdg::Code::kJPsi, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("hPtGenSig"), particleMother.pt()); // gen. level pT registry.fill(HIST("hPtRecSig"), candidate.pt()); // rec. level pT registry.fill(HIST("hCPARecSig"), candidate.cpa()); registry.fill(HIST("hEtaRecSig"), candidate.eta()); if (modeJpsiToMuMu) { - registry.fill(HIST("hMassSig"), invMassJpsiToMuMu(candidate), candidate.pt()); + registry.fill(HIST("hMassSig"), hfHelper.invMassJpsiToMuMu(candidate), candidate.pt()); } else { - registry.fill(HIST("hMassSig"), invMassJpsiToEE(candidate), candidate.pt()); + registry.fill(HIST("hMassSig"), hfHelper.invMassJpsiToEE(candidate), candidate.pt()); } registry.fill(HIST("hDecLengthSig"), candidate.decayLength(), candidate.pt()); registry.fill(HIST("hDecLengthXYSig"), candidate.decayLengthXY(), candidate.pt()); @@ -249,18 +253,18 @@ struct HfTaskJpsiMc { registry.fill(HIST("hd0Prong1Sig"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hd0d0Sig"), candidate.impactParameterProduct(), candidate.pt()); registry.fill(HIST("hChi2PCASig"), candidate.chi2PCA(), candidate.pt()); - registry.fill(HIST("hCtSig"), ctJpsi(candidate), candidate.pt()); - registry.fill(HIST("hYSig"), yJpsi(candidate), candidate.pt()); - registry.fill(HIST("hYGenSig"), RecoDecay::y(array{particleMother.px(), particleMother.py(), particleMother.pz()}, RecoDecay::getMassPDG(particleMother.pdgCode())), particleMother.pt()); + registry.fill(HIST("hCtSig"), hfHelper.ctJpsi(candidate), candidate.pt()); + registry.fill(HIST("hYSig"), hfHelper.yJpsi(candidate), candidate.pt()); + registry.fill(HIST("hYGenSig"), RecoDecay::y(std::array{particleMother.px(), particleMother.py(), particleMother.pz()}, o2::analysis::pdg::MassJPsi), particleMother.pt()); } else { registry.fill(HIST("hPtRecBg"), candidate.pt()); registry.fill(HIST("hCPARecBg"), candidate.cpa()); registry.fill(HIST("hEtaRecBg"), candidate.eta()); if (modeJpsiToMuMu) { - registry.fill(HIST("hMassBg"), invMassJpsiToMuMu(candidate), candidate.pt()); + registry.fill(HIST("hMassBg"), hfHelper.invMassJpsiToMuMu(candidate), candidate.pt()); } else { - registry.fill(HIST("hMassBg"), invMassJpsiToEE(candidate), candidate.pt()); + registry.fill(HIST("hMassBg"), hfHelper.invMassJpsiToEE(candidate), candidate.pt()); } registry.fill(HIST("hDecLengthBg"), candidate.decayLength(), candidate.pt()); registry.fill(HIST("hDecLengthxyBg"), candidate.decayLengthXY(), candidate.pt()); @@ -268,20 +272,19 @@ struct HfTaskJpsiMc { registry.fill(HIST("hd0Prong1Bg"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hd0d0Bg"), candidate.impactParameterProduct(), candidate.pt()); registry.fill(HIST("hChi2PCABg"), candidate.chi2PCA(), candidate.pt()); - registry.fill(HIST("hCtBg"), ctJpsi(candidate), candidate.pt()); - registry.fill(HIST("hYBg"), yJpsi(candidate), candidate.pt()); + registry.fill(HIST("hCtBg"), hfHelper.ctJpsi(candidate), candidate.pt()); + registry.fill(HIST("hYBg"), hfHelper.yJpsi(candidate), candidate.pt()); } } // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { if (particle.flagMcMatchGen() == 1 << decayMode) { - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > yCandMax) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassJPsi)) > yCandMax) { continue; } registry.fill(HIST("hPtGen"), particle.pt()); registry.fill(HIST("hEtaGen"), particle.eta()); - registry.fill(HIST("hYGen"), RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())), particle.pt()); + registry.fill(HIST("hYGen"), RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassJPsi), particle.pt()); // registry.fill(HIST("hPtGenProng0"), particle.daughter0_as().pt(), particle.pt()); // registry.fill(HIST("hPtGenProng1"), particle.daughter1_as().pt(), particle.pt()); } diff --git a/PWGHF/ALICE3/Tasks/taskLcAlice3.cxx b/PWGHF/ALICE3/Tasks/taskLcAlice3.cxx index 52853151494..2f60fd79f3c 100644 --- a/PWGHF/ALICE3/Tasks/taskLcAlice3.cxx +++ b/PWGHF/ALICE3/Tasks/taskLcAlice3.cxx @@ -19,20 +19,20 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_lc_to_p_k_pi; /// Fills MC histograms. struct HfTaskLcAlice3 { Filter filterSelectCandidates = (aod::hf_sel_candidate_lc_alice3::isSelLcToPKPiNoPid == 1 || aod::hf_sel_candidate_lc_alice3::isSelLcToPiKPNoPid == 1); + HfHelper hfHelper; + HistogramRegistry registry{ "registry", {{"hMassGen", "3-prong candidates (generated); #it{p}_{T}; #it{y}", {HistType::kTH2F, {{150, 0., 30.}, {8, 0, 4.0}}}}, @@ -50,24 +50,25 @@ struct HfTaskLcAlice3 { {"hMassBkgLcPerfectPid", "3-prong candidates (checked);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{500, 1.6, 3.1}, {150, 0., 30.}, {8, 0., 4.}}}}}}; void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { - for (auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { continue; } - if (std::abs(yLc(candidate)) > 4.0) { + if (std::abs(hfHelper.yLc(candidate)) > 4.0) { continue; } - auto massLc = invMassLcToPKPi(candidate); - auto massLcSwap = invMassLcToPiKP(candidate); + auto massLc = hfHelper.invMassLcToPKPi(candidate); + auto massLcSwap = hfHelper.invMassLcToPiKP(candidate); auto ptCandidate = candidate.pt(); - auto rapidityCandidate = std::abs(yLc(candidate)); + auto rapidityCandidate = std::abs(hfHelper.yLc(candidate)); if (candidate.isSelLcToPKPiNoPid() == 1) { registry.fill(HIST("hMassSigBkgLcNoPid"), massLc, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { registry.fill(HIST("hMassSigLcNoPid"), massLc, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcNoPid"), massLc, ptCandidate, rapidityCandidate); @@ -75,7 +76,7 @@ struct HfTaskLcAlice3 { } if (candidate.isSelLcToPiKPNoPid() == 1) { registry.fill(HIST("hMassSigBkgLcNoPid"), massLcSwap, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { registry.fill(HIST("hMassSigLcNoPid"), massLcSwap, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcNoPid"), massLcSwap, ptCandidate, rapidityCandidate); @@ -84,7 +85,7 @@ struct HfTaskLcAlice3 { if (candidate.isSelLcToPKPiTofPid() == 1) { registry.fill(HIST("hMassSigBkgLcTofPid"), massLc, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { registry.fill(HIST("hMassSigLcTofPid"), massLc, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcTofPid"), massLc, ptCandidate, rapidityCandidate); @@ -92,7 +93,7 @@ struct HfTaskLcAlice3 { } if (candidate.isSelLcToPiKPTofPid() == 1) { registry.fill(HIST("hMassSigBkgLcTofPid"), massLcSwap, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { registry.fill(HIST("hMassSigLcTofPid"), massLcSwap, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcTofPid"), massLcSwap, ptCandidate, rapidityCandidate); @@ -101,7 +102,7 @@ struct HfTaskLcAlice3 { if (candidate.isSelLcToPKPiTofPlusRichPid() == 1) { registry.fill(HIST("hMassSigBkgLcTofPlusRichPid"), massLc, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { registry.fill(HIST("hMassSigLcTofPlusRichPid"), massLc, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcTofPlusRichPid"), massLc, ptCandidate, rapidityCandidate); @@ -109,7 +110,7 @@ struct HfTaskLcAlice3 { } if (candidate.isSelLcToPiKPTofPlusRichPid() == 1) { registry.fill(HIST("hMassSigBkgLcTofPlusRichPid"), massLcSwap, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { registry.fill(HIST("hMassSigLcTofPlusRichPid"), massLcSwap, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcTofPlusRichPid"), massLcSwap, ptCandidate, rapidityCandidate); @@ -118,7 +119,7 @@ struct HfTaskLcAlice3 { if (candidate.isSelLcToPKPiPerfectPid() == 1) { registry.fill(HIST("hMassSigBkgLcPerfectPid"), massLc, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { registry.fill(HIST("hMassSigLcPerfectPid"), massLc, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcPerfectPid"), massLc, ptCandidate, rapidityCandidate); @@ -126,7 +127,7 @@ struct HfTaskLcAlice3 { } if (candidate.isSelLcToPiKPPerfectPid() == 1) { registry.fill(HIST("hMassSigBkgLcPerfectPid"), massLcSwap, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { registry.fill(HIST("hMassSigLcPerfectPid"), massLcSwap, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcPerfectPid"), massLcSwap, ptCandidate, rapidityCandidate); @@ -134,13 +135,13 @@ struct HfTaskLcAlice3 { } } - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::LcToPKPi) { - if (std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > 4.0) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassLambdaCPlus)) > 4.0) { continue; } auto ptGen = particle.pt(); - auto yGen = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto yGen = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassLambdaCPlus); registry.fill(HIST("hMassGen"), ptGen, std::abs(yGen)); } } diff --git a/PWGHF/ALICE3/Tasks/taskLcParametrizedPid.cxx b/PWGHF/ALICE3/Tasks/taskLcParametrizedPid.cxx index 18be6808652..8759f1a2956 100644 --- a/PWGHF/ALICE3/Tasks/taskLcParametrizedPid.cxx +++ b/PWGHF/ALICE3/Tasks/taskLcParametrizedPid.cxx @@ -19,18 +19,18 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_lc_to_p_k_pi; /// Fills MC histograms. struct HfTaskLcParametrizedPid { + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_lc_parametrized_pid::isSelLcToPKPiNoPid == 1 || aod::hf_sel_candidate_lc_parametrized_pid::isSelLcToPiKPNoPid == 1); HistogramRegistry registry{ @@ -47,24 +47,25 @@ struct HfTaskLcParametrizedPid { {"hMassBkgLcPerfectPid", "3-prong candidates (checked);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{500, 1.6, 3.1}, {150, 0., 30.}, {8, 0., 4.}}}}}}; void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { - for (auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { continue; } - if (std::abs(yLc(candidate)) > 4.0) { + if (std::abs(hfHelper.yLc(candidate)) > 4.0) { continue; } - auto massLc = invMassLcToPKPi(candidate); - auto massLcSwap = invMassLcToPiKP(candidate); + auto massLc = hfHelper.invMassLcToPKPi(candidate); + auto massLcSwap = hfHelper.invMassLcToPiKP(candidate); auto ptCandidate = candidate.pt(); - auto rapidityCandidate = std::abs(yLc(candidate)); + auto rapidityCandidate = std::abs(hfHelper.yLc(candidate)); if (candidate.isSelLcToPKPiNoPid() == 1) { registry.fill(HIST("hMassSigBkgLcNoPid"), massLc, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { registry.fill(HIST("hMassSigLcNoPid"), massLc, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcNoPid"), massLc, ptCandidate, rapidityCandidate); @@ -72,7 +73,7 @@ struct HfTaskLcParametrizedPid { } if (candidate.isSelLcToPiKPNoPid() == 1) { registry.fill(HIST("hMassSigBkgLcNoPid"), massLcSwap, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { registry.fill(HIST("hMassSigLcNoPid"), massLcSwap, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcNoPid"), massLcSwap, ptCandidate, rapidityCandidate); @@ -81,7 +82,7 @@ struct HfTaskLcParametrizedPid { if (candidate.isSelLcToPKPi() == 1) { registry.fill(HIST("hMassSigBkgLc"), massLc, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPKPiPerfectPid() == 1) { registry.fill(HIST("hMassSigLc"), massLc, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLc"), massLc, ptCandidate, rapidityCandidate); @@ -89,7 +90,7 @@ struct HfTaskLcParametrizedPid { } if (candidate.isSelLcToPiKP() == 1) { registry.fill(HIST("hMassSigBkgLc"), massLcSwap, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi) && candidate.isSelLcToPiKPPerfectPid() == 1) { registry.fill(HIST("hMassSigLc"), massLcSwap, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLc"), massLcSwap, ptCandidate, rapidityCandidate); @@ -98,7 +99,7 @@ struct HfTaskLcParametrizedPid { if (candidate.isSelLcToPKPiPerfectPid() == 1) { registry.fill(HIST("hMassSigBkgLcPerfectPid"), massLc, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { registry.fill(HIST("hMassSigLcPerfectPid"), massLc, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcPerfectPid"), massLc, ptCandidate, rapidityCandidate); @@ -106,7 +107,7 @@ struct HfTaskLcParametrizedPid { } if (candidate.isSelLcToPiKPPerfectPid() == 1) { registry.fill(HIST("hMassSigBkgLcPerfectPid"), massLcSwap, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::LcToPKPi)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { registry.fill(HIST("hMassSigLcPerfectPid"), massLcSwap, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgLcPerfectPid"), massLcSwap, ptCandidate, rapidityCandidate); @@ -114,13 +115,13 @@ struct HfTaskLcParametrizedPid { } } - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::LcToPKPi) { - if (std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > 4.0) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassLambdaCPlus)) > 4.0) { continue; } auto ptGen = particle.pt(); - auto yGen = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto yGen = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassLambdaCPlus); registry.fill(HIST("hMassGen"), ptGen, std::abs(yGen)); } } diff --git a/PWGHF/ALICE3/Tasks/taskQaPidRejection.cxx b/PWGHF/ALICE3/Tasks/taskQaPidRejection.cxx index fbf951d47a2..0588792aa01 100644 --- a/PWGHF/ALICE3/Tasks/taskQaPidRejection.cxx +++ b/PWGHF/ALICE3/Tasks/taskQaPidRejection.cxx @@ -16,18 +16,19 @@ /// \author Henrique J C Zanoli , Utrecht University /// \author Nicolo' Jacazio , CERN -#include "TEfficiency.h" -#include "TList.h" -#include "TPDGCode.h" +#include +#include +#include + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/DCA.h" #include "ALICE3/DataModel/MID.h" #include "ALICE3/DataModel/RICH.h" #include "Common/Core/TrackSelectorPID.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/DCA.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -50,11 +51,11 @@ DECLARE_SOA_INDEX_TABLE_USER(HfTrackIndexALICE3PID, Tracks, "HFTRKIDXA3PID", //! } // namespace o2::aod struct HfTaskQaPidRejectionAlice3PidIndexBuilder { - Builds index; - void init(o2::framework::InitContext&) {} + Builds index; + void init(InitContext&) {} }; -void customize(std::vector& workflowOptions) +void customize(std::vector& workflowOptions) { std::vector options{ {"rej-el", VariantType::Int, 1, {"Efficiency for the Electron PDG code"}}, @@ -68,7 +69,7 @@ void customize(std::vector& workflowOptions) #include "Framework/runDataProcessing.h" /// Task to QA the efficiency of a particular particle defined by particlePDG -template +template struct HfTaskQaPidRejection { // Particle selection Configurable nBinsEta{"nBinsEta", 40, "Number of eta bins"}; @@ -92,15 +93,35 @@ struct HfTaskQaPidRejection { Configurable nSigmaRichMax{"nSigmaRichMax", 3., "Nsigma cut on RICH only"}; Configurable nSigmaRichCombinedTofMax{"nSigmaRichCombinedTofMax", 0., "Nsigma cut on RICH combined with TOF"}; + TrackSelectorEl selectorElectron; + TrackSelectorMu selectorMuon; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + TrackSelectorPr selectorProton; + static constexpr PDG_t PDGs[5] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton}; static_assert(particle < 5 && "Maximum of particles reached"); static constexpr int particlePDG = PDGs[particle]; - using TracksPID = soa::Join; + + using TracksWPid = soa::Join; HistogramRegistry histos{"HistogramsRejection"}; void init(InitContext&) { + selectorElectron.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorElectron.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorElectron.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorElectron.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorElectron.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorElectron.setRangePtRich(ptPidRichMin, ptPidRichMax); + selectorElectron.setRangeNSigmaRich(-nSigmaRichMax, nSigmaRichMax); + selectorElectron.setRangeNSigmaRichCondTof(-nSigmaRichCombinedTofMax, nSigmaRichCombinedTofMax); + selectorMuon = selectorElectron; + selectorPion = selectorElectron; + selectorKaon = selectorElectron; + selectorProton = selectorElectron; + AxisSpec ptAxis{nBinsPt, ptMin, ptMax}; AxisSpec etaAxis{nBinsEta, etaMin, etaMax}; @@ -137,32 +158,13 @@ struct HfTaskQaPidRejection { histos.add("trackingMIDselMuon/peta", commonTitle + " Primary;" + p, kTH2D, {ptAxis, etaAxis}); } - void process(const o2::soa::Join& collisions, - const o2::soa::Join& tracks, - const o2::aod::McCollisions& mcCollisions, - const o2::aod::McParticles& mcParticles, aod::RICHs const&, aod::MIDs const&) + void process(const soa::Join& collisions, + const soa::Join& tracks, + const aod::McCollisions& mcCollisions, + const aod::McParticles& mcParticles, + const aod::RICHs&, + const aod::MIDs&) { - TrackSelectorPID selectorElectron(kElectron); - selectorElectron.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorElectron.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorElectron.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorElectron.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorElectron.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - selectorElectron.setRangePtRICH(ptPidRichMin, ptPidRichMax); - selectorElectron.setRangeNSigmaRICH(-nSigmaRichMax, nSigmaRichMax); - selectorElectron.setRangeNSigmaRICHCondTOF(-nSigmaRichCombinedTofMax, nSigmaRichCombinedTofMax); - - auto selectorPion(selectorElectron); - selectorPion.setPDG(kPiPlus); - - auto selectorKaon(selectorElectron); - selectorKaon.setPDG(kKPlus); - - auto selectorProton(selectorElectron); - selectorProton.setPDG(kProton); - - TrackSelectorPID selectorMuon(kMuonPlus); - std::vector recoEvt(collisions.size()); std::vector recoTracks(tracks.size()); LOGF(info, "%d", particlePDG); @@ -171,15 +173,15 @@ struct HfTaskQaPidRejection { if (particlePDG != 0 && mcParticle.pdgCode() != particlePDG) { // Checking PDG code continue; } - bool isTOFhpElectron = !(selectorElectron.getStatusTrackPIDTOF(track) == TrackSelectorPID::Status::PIDRejected); - bool isRICHhpElectron = !(selectorElectron.getStatusTrackPIDRICH(track) == TrackSelectorPID::Status::PIDRejected); - bool isTOFhpPion = !(selectorPion.getStatusTrackPIDTOF(track) == TrackSelectorPID::Status::PIDRejected); - bool isRICHhpPion = !(selectorPion.getStatusTrackPIDRICH(track) == TrackSelectorPID::Status::PIDRejected); - bool isTOFhpKaon = !(selectorKaon.getStatusTrackPIDTOF(track) == TrackSelectorPID::Status::PIDRejected); - bool isRICHhpKaon = !(selectorKaon.getStatusTrackPIDRICH(track) == TrackSelectorPID::Status::PIDRejected); - bool isTOFhpProton = !(selectorProton.getStatusTrackPIDTOF(track) == TrackSelectorPID::Status::PIDRejected); - bool isRICHhpProton = !(selectorProton.getStatusTrackPIDRICH(track) == TrackSelectorPID::Status::PIDRejected); - bool isMIDhpMuon = (selectorMuon.getStatusTrackPIDMID(track) == TrackSelectorPID::Status::PIDAccepted); + bool isTOFhpElectron = !(selectorElectron.statusTof(track) == TrackSelectorPID::Rejected); + bool isRICHhpElectron = !(selectorElectron.statusRich(track) == TrackSelectorPID::Rejected); + bool isTOFhpPion = !(selectorPion.statusTof(track) == TrackSelectorPID::Rejected); + bool isRICHhpPion = !(selectorPion.statusRich(track) == TrackSelectorPID::Rejected); + bool isTOFhpKaon = !(selectorKaon.statusTof(track) == TrackSelectorPID::Rejected); + bool isRICHhpKaon = !(selectorKaon.statusRich(track) == TrackSelectorPID::Rejected); + bool isTOFhpProton = !(selectorProton.statusTof(track) == TrackSelectorPID::Rejected); + bool isRICHhpProton = !(selectorProton.statusRich(track) == TrackSelectorPID::Rejected); + bool isMIDhpMuon = (selectorMuon.statusMid(track) == TrackSelectorPID::Accepted); if (mcParticle.isPhysicalPrimary()) { histos.fill(HIST("tracking/pteta"), track.pt(), track.eta()); @@ -271,12 +273,31 @@ struct HfTaskQaPidRejectionGeneral { Configurable nSigmaRichMax{"nSigmaRichMax", 3., "Nsigma cut on RICH only"}; Configurable nSigmaRichCombinedTofMax{"nSigmaRichCombinedTofMax", 0., "Nsigma cut on RICH combined with TOF"}; - using TracksPID = soa::Join; + TrackSelectorEl selectorElectron; + TrackSelectorMu selectorMuon; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + TrackSelectorPr selectorProton; + + using TracksWPid = soa::Join; HistogramRegistry histos{"HistogramsRejection"}; void init(InitContext&) { + selectorElectron.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorElectron.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorElectron.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorElectron.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorElectron.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorElectron.setRangePtRich(ptPidRichMin, ptPidRichMax); + selectorElectron.setRangeNSigmaRich(-nSigmaRichMax, nSigmaRichMax); + selectorElectron.setRangeNSigmaRichCondTof(-nSigmaRichCombinedTofMax, nSigmaRichCombinedTofMax); + selectorMuon = selectorElectron; + selectorPion = selectorElectron; + selectorKaon = selectorElectron; + selectorProton = selectorElectron; + AxisSpec ptAxis{nBinsPt, ptMin, ptMax}; AxisSpec etaAxis{nBinsEta, etaMin, etaMax}; @@ -330,32 +351,13 @@ struct HfTaskQaPidRejectionGeneral { histos.add("hKaonMID/peta", commonTitle + " Primary;" + p, kTH2D, {ptAxis, etaAxis}); } - void process(const o2::soa::Join& collisions, - const o2::soa::Join& tracks, - const o2::aod::McCollisions& mcCollisions, - const o2::aod::McParticles& mcParticles, aod::RICHs const&, aod::MIDs const&) + void process(const soa::Join& collisions, + const soa::Join& tracks, + const aod::McCollisions& mcCollisions, + const aod::McParticles& mcParticles, + const aod::RICHs&, + const aod::MIDs&) { - TrackSelectorPID selectorElectron(kElectron); - selectorElectron.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorElectron.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorElectron.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorElectron.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorElectron.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - selectorElectron.setRangePtRICH(ptPidRichMin, ptPidRichMax); - selectorElectron.setRangeNSigmaRICH(-nSigmaRichMax, nSigmaRichMax); - selectorElectron.setRangeNSigmaRICHCondTOF(-nSigmaRichCombinedTofMax, nSigmaRichCombinedTofMax); - - auto selectorPion(selectorElectron); - selectorPion.setPDG(kPiPlus); - - auto selectorKaon(selectorElectron); - selectorKaon.setPDG(kKPlus); - - auto selectorProton(selectorElectron); - selectorProton.setPDG(kProton); - - TrackSelectorPID selectorMuon(kMuonPlus); - for (const auto& track : tracks) { if (std::abs(track.eta()) > etaMaxSel || track.pt() < ptMinSel) { @@ -376,11 +378,11 @@ struct HfTaskQaPidRejectionGeneral { histos.fill(HIST("hKaonNoSel/pteta"), track.pt(), track.eta()); } - bool isRICHhpElectron = !(selectorElectron.getStatusTrackPIDRICH(track) == TrackSelectorPID::Status::PIDRejected); - // bool isRICHhpPion = !(selectorPion.getStatusTrackPIDRICH(track) == TrackSelectorPID::Status::PIDRejected); - // bool isRICHhpKaon = !(selectorKaon.getStatusTrackPIDRICH(track) == TrackSelectorPID::Status::PIDRejected); - // bool isRICHhpProton = !(selectorProton.getStatusTrackPIDRICH(track) == TrackSelectorPID::Status::PIDRejected); - bool isMIDhpMuon = (selectorMuon.getStatusTrackPIDMID(track) == TrackSelectorPID::Status::PIDAccepted); + bool isRICHhpElectron = !(selectorElectron.statusRich(track) == TrackSelectorPID::Rejected); + // bool isRICHhpPion = !(selectorPion.statusRich(track) == TrackSelectorPID::Rejected); + // bool isRICHhpKaon = !(selectorKaon.statusRich(track) == TrackSelectorPID::Rejected); + // bool isRICHhpProton = !(selectorProton.statusRich(track) == TrackSelectorPID::Rejected); + bool isMIDhpMuon = (selectorMuon.statusMid(track) == TrackSelectorPID::Accepted); bool isRICHElLoose = isRICHhpElectron; @@ -504,19 +506,19 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) WorkflowSpec w; w.push_back(adaptAnalysisTask(cfgc)); if (cfgc.options().get("rej-el")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-electron"})); + w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-electron"})); } if (cfgc.options().get("rej-ka")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-kaon"})); + w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-kaon"})); } if (cfgc.options().get("rej-pr")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-proton"})); + w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-proton"})); } if (cfgc.options().get("rej-mu")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-mu"})); + w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-mu"})); } if (cfgc.options().get("rej-pi")) { - w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-pion"})); + w.push_back(adaptAnalysisTask>(cfgc, TaskName{"hf-task-qa-pid-rejection-pion"})); } w.push_back(adaptAnalysisTask(cfgc)); return w; diff --git a/PWGHF/ALICE3/Tasks/taskX.cxx b/PWGHF/ALICE3/Tasks/taskX.cxx index 7369f6f7eb6..f5ae86c1516 100644 --- a/PWGHF/ALICE3/Tasks/taskX.cxx +++ b/PWGHF/ALICE3/Tasks/taskX.cxx @@ -19,6 +19,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -26,11 +27,8 @@ using namespace o2; using namespace o2::aod; using namespace o2::analysis; -using namespace o2::analysis::hf_cuts_x_to_jpsi_pi_pi; using namespace o2::framework; -using namespace o2::aod::hf_cand_x; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; void customize(std::vector& workflowOptions) { @@ -47,6 +45,8 @@ struct HfTaskX { Configurable modeXToJpsiToMuMuPiPi{"modeXToJpsiToMuMuPiPi", false, "Perform Jpsi to mu+mu- analysis"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_x_to_jpsi_pi_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_x::isSelXToJpsiToEEPiPi >= selectionFlagX || aod::hf_sel_candidate_x::isSelXToJpsiToMuMuPiPi >= selectionFlagX); HistogramRegistry registry{ @@ -56,7 +56,7 @@ struct HfTaskX { {"hPtProng2", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, {"hPtCand", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{150, 0., 15.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { registry.add("hMass", "3-prong candidates;inv. mass (J/#psi #pi+ #pi-) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{200, 3., 4.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hDecLength", "3-prong candidates;decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.01}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -74,15 +74,15 @@ struct HfTaskX { void process(soa::Filtered> const& candidates) { int decayMode = modeXToJpsiToMuMuPiPi ? hf_cand_x::DecayType::XToJpsiToMuMuPiPi : hf_cand_x::DecayType::XToJpsiToEEPiPi; - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!(candidate.hfflag() & 1 << decayMode)) { continue; } - if (yCandMax >= 0. && std::abs(yX(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yX(candidate)) > yCandMax) { continue; } - registry.fill(HIST("hMass"), invMassXToJpsiPiPi(candidate), candidate.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassXToJpsiPiPi(candidate), candidate.pt()); registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); @@ -108,6 +108,8 @@ struct HfTaskXMc { Configurable modeXToJpsiToMuMuPiPi{"modeXToJpsiToMuMuPiPi", false, "Perform Jpsi to mu+mu- analysis"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_x_to_jpsi_pi_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_x::isSelXToJpsiToEEPiPi >= selectionFlagX || aod::hf_sel_candidate_x::isSelXToJpsiToMuMuPiPi >= selectionFlagX); HistogramRegistry registry{ @@ -117,7 +119,7 @@ struct HfTaskXMc { {"hPtGen", "3-prong candidates (gen. matched);#it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{150, 0., 15.}}}}, {"hPtGenSig", "3-prong candidates (rec. matched);#it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{150, 0., 15.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { registry.add("hCPARecSig", "3-prong candidates (rec. matched);cosine of pointing angle;entries", {HistType::kTH2F, {{500, 0.9, 1.0}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hCPARecBg", "3-prong candidates (rec. unmatched);cosine of pointing angle;entries", {HistType::kTH2F, {{500, 0.9, 1.0}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -155,28 +157,28 @@ struct HfTaskXMc { } void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { // MC rec. - // Printf("MC Candidates: %d", candidates.size()); int decayMode = modeXToJpsiToMuMuPiPi ? hf_cand_x::DecayType::XToJpsiToMuMuPiPi : hf_cand_x::DecayType::XToJpsiToEEPiPi; - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!(candidate.hfflag() & 1 << decayMode)) { continue; } - if (yCandMax >= 0. && std::abs(yX(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yX(candidate)) > yCandMax) { continue; } if (candidate.flagMcMatchRec() == 1 << decayMode) { - auto indexMother = RecoDecay::getMother(particlesMC, candidate.prong1_as().mcParticle_as>(), 9920443, true); - auto particleMother = particlesMC.rawIteratorAt(indexMother); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), 9920443, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("hPtGenSig"), particleMother.pt()); registry.fill(HIST("hPtRecSig"), candidate.pt()); registry.fill(HIST("hCPARecSig"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEtaRecSig"), candidate.eta(), candidate.pt()); registry.fill(HIST("hDeclengthRecSig"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("hMassRecSig"), invMassXToJpsiPiPi(candidate), candidate.pt()); + registry.fill(HIST("hMassRecSig"), hfHelper.invMassXToJpsiPiPi(candidate), candidate.pt()); registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hd0Prong2RecSig"), candidate.impactParameter2(), candidate.pt()); @@ -184,15 +186,15 @@ struct HfTaskXMc { registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1(), candidate.pt()); registry.fill(HIST("hPtProng2RecSig"), candidate.ptProng2(), candidate.pt()); registry.fill(HIST("hChi2PCASig"), candidate.chi2PCA(), candidate.pt()); - registry.fill(HIST("hCtSig"), ctX(candidate), candidate.pt()); - registry.fill(HIST("hYSig"), yX(candidate), candidate.pt()); + registry.fill(HIST("hCtSig"), hfHelper.ctX(candidate), candidate.pt()); + registry.fill(HIST("hYSig"), hfHelper.yX(candidate), candidate.pt()); } else { registry.fill(HIST("hPtRecBg"), candidate.pt()); registry.fill(HIST("hCPARecBg"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEtaRecBg"), candidate.eta(), candidate.pt()); registry.fill(HIST("hDeclengthRecBg"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("hMassRecBg"), invMassXToJpsiPiPi(candidate), candidate.pt()); + registry.fill(HIST("hMassRecBg"), hfHelper.invMassXToJpsiPiPi(candidate), candidate.pt()); registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hd0Prong2RecBg"), candidate.impactParameter2(), candidate.pt()); @@ -200,17 +202,14 @@ struct HfTaskXMc { registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1(), candidate.pt()); registry.fill(HIST("hPtProng2RecBg"), candidate.ptProng2(), candidate.pt()); registry.fill(HIST("hChi2PCABg"), candidate.chi2PCA(), candidate.pt()); - registry.fill(HIST("hCtBg"), ctX(candidate), candidate.pt()); - registry.fill(HIST("hYBg"), yX(candidate), candidate.pt()); + registry.fill(HIST("hCtBg"), hfHelper.ctX(candidate), candidate.pt()); + registry.fill(HIST("hYBg"), hfHelper.yX(candidate), candidate.pt()); } } // rec // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { if (particle.flagMcMatchGen() == 1 << decayMode) { - // TODO: add X(3872) mass such that we can use the getMassPDG function instead of hardcoded mass - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, 3.87168)) > yCandMax) { - // Printf("MC Gen.: Y rejection: %g", RecoDecay::Y(array{particle.px(), particle.py(), particle.pz()}, 3.87168)); + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassX3872)) > yCandMax) { continue; } registry.fill(HIST("hPtGen"), particle.pt()); @@ -219,7 +218,7 @@ struct HfTaskXMc { // properties of gen matched X(3872), to get a first look at some cuts float ptProngs[3]; int counter = 0; - for (auto& daugh : particle.daughters_as()) { + for (const auto& daugh : particle.daughters_as()) { ptProngs[counter] = daugh.pt(); counter++; } diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h new file mode 100644 index 00000000000..accb9182910 --- /dev/null +++ b/PWGHF/Core/HfHelper.h @@ -0,0 +1,885 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file HfHelper.h +/// \brief Class with helper functions for HF analyses +/// +/// \author Vít Kučera , Inha University + +#ifndef PWGHF_CORE_HFHELPER_H_ +#define PWGHF_CORE_HFHELPER_H_ + +#include +#include +#include + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/PDG.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +class HfHelper +{ + public: + /// Default constructor + HfHelper() = default; + + /// Default destructor + ~HfHelper() = default; + + // 2-prong + + // D0(bar) → π± K∓ + + template + auto ctD0(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassD0); + } + + template + auto yD0(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassD0); + } + + template + auto eD0(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassD0); + } + + template + auto invMassD0ToPiK(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassKPlus}); + } + + template + auto invMassD0barToKPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassPiPlus}); + } + + template + auto cosThetaStarD0(const T& candidate) + { + return candidate.cosThetaStar(std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassKPlus}, o2::analysis::pdg::MassD0, 1); + } + + template + auto cosThetaStarD0bar(const T& candidate) + { + return candidate.cosThetaStar(std::array{o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassPiPlus}, o2::analysis::pdg::MassD0, 0); + } + + // J/ψ + + template + auto ctJpsi(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassJPsi); + } + + template + auto yJpsi(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassJPsi); + } + + template + auto eJpsi(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassJPsi); + } + + // J/ψ → e+ e− + template + auto invMassJpsiToEE(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassElectron, o2::analysis::pdg::MassElectron}); + } + // J/ψ → μ+ μ− + + template + auto invMassJpsiToMuMu(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassMuonPlus, o2::analysis::pdg::MassMuonMinus}); + } + + // hf_cand_casc + + template + auto invMassLcToK0sP(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassProton, o2::analysis::pdg::MassK0Short}); // first daughter is bachelor + } + + template + auto invMassGammaToEE(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassElectron, o2::analysis::pdg::MassElectron}); + } + + template + auto ctV0K0s(const T& candidate) + { + return candidate.ctV0(o2::analysis::pdg::MassK0Short); + } + + template + auto ctV0Lambda(const T& candidate) + { + return candidate.ctV0(o2::analysis::pdg::MassLambda0); + } + + // B± → D0bar(D0) π± + + template + auto ctBplus(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassBPlus); + } + + template + auto yBplus(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassBPlus); + } + + template + auto eBplus(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassBPlus); + } + + template + auto invMassBplusToD0Pi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassD0, o2::analysis::pdg::MassPiPlus}); + } + + template + auto cosThetaStarBplus(const T& candidate) + { + return candidate.cosThetaStar(std::array{o2::analysis::pdg::MassD0, o2::analysis::pdg::MassPiPlus}, o2::analysis::pdg::MassBPlus, 1); + } + + // 3-prong + + // D± → π± K∓ π± + + template + auto ctDplus(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassDPlus); + } + + template + auto yDplus(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassDPlus); + } + + template + auto eDplus(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassDPlus); + } + + template + auto invMassDplusToPiKPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassPiPlus}); + } + + template + auto invMassDplusToPiKPi(const T& pVec0, const T& pVec1, const T& pVec2) + { + return RecoDecay::m(std::array{pVec0, pVec1, pVec2}, + std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassPiPlus}); + } + + // Ds± → K± K∓ π± + + template + auto ctDs(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassDS); + } + + template + auto yDs(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassDS); + } + + template + auto eDs(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassDS); + } + + template + auto invMassDsToKKPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassPiPlus}); + } + + template + auto invMassDsToPiKK(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassKPlus}); + } + + template + auto deltaMassPhiDsToKKPi(const T& candidate) + { + double invMassKKpair = RecoDecay::m(std::array{candidate.pVectorProng0(), candidate.pVectorProng1()}, std::array{o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassKPlus}); + return std::abs(invMassKKpair - o2::analysis::pdg::MassPhi); + } + + template + auto deltaMassPhiDsToPiKK(const T& candidate) + { + double invMassKKpair = RecoDecay::m(std::array{candidate.pVectorProng1(), candidate.pVectorProng2()}, std::array{o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassKPlus}); + return std::abs(invMassKKpair - o2::analysis::pdg::MassPhi); + } + + /// Calculate the cosine of the angle between the pion and the opposite sign kaon in the phi rest frame + /// \param candidate Ds candidate from aod::HfCand3Prong table + /// \param option mass hypothesis considered: 0 = KKPi, 1 = PiKK + /// \return cosine of pion-kaon angle in the phi rest frame + template + auto cosPiKPhiRestFrame(const T& candidate, int option) + { + // Ported from AliAODRecoDecayHF3Prong::CosPiKPhiRFrame + std::array momPi; + std::array momK1; + std::array momK2; + + if (option == 0) { // KKPi + momPi = candidate.pVectorProng2(); + momK1 = candidate.pVectorProng1(); + momK2 = candidate.pVectorProng0(); + } else { // PiKK + momPi = candidate.pVectorProng0(); + momK1 = candidate.pVectorProng1(); + momK2 = candidate.pVectorProng2(); + } + + ROOT::Math::PxPyPzMVector vecPi(momPi[0], momPi[1], momPi[2], o2::analysis::pdg::MassPiPlus); + ROOT::Math::PxPyPzMVector vecK1(momK1[0], momK1[1], momK1[2], o2::analysis::pdg::MassKPlus); + ROOT::Math::PxPyPzMVector vecK2(momK2[0], momK2[1], momK2[2], o2::analysis::pdg::MassKPlus); + ROOT::Math::PxPyPzMVector vecPhi = vecK1 + vecK2; + + ROOT::Math::Boost boostToPhiRestFrame(vecPhi.BoostToCM()); + auto momPiPhiRestFrame = boostToPhiRestFrame(vecPi).Vect(); + auto momK1PhiRestFrame = boostToPhiRestFrame(vecK1).Vect(); + + return momPiPhiRestFrame.Dot(momK1PhiRestFrame) / std::sqrt(momPiPhiRestFrame.Mag2() * momK1PhiRestFrame.Mag2()); + } + + template + auto cos3PiKDsToKKPi(const T& candidate) + { + auto cosPiK = cosPiKPhiRestFrame(candidate, 0); + return cosPiK * cosPiK * cosPiK; + } + + template + auto cos3PiKDsToPiKK(const T& candidate) + { + auto cosPiK = cosPiKPhiRestFrame(candidate, 1); + return cosPiK * cosPiK * cosPiK; + } + + // Λc± → p± K∓ π± + + template + auto ctLc(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassLambdaCPlus); + } + + template + auto yLc(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassLambdaCPlus); + } + + template + auto eLc(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassLambdaCPlus); + } + + template + auto invMassLcToPKPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassProton, o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassPiPlus}); + } + + template + auto invMassLcToPiKP(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassProton}); + } + + // Ξc± → p± K∓ π± + + template + auto ctXic(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassXiCPlus); + } + + template + auto yXic(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassXiCPlus); + } + + template + auto eXic(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassXiCPlus); + } + + template + auto invMassXicToPKPi(const T& candidate) + { + return invMassLcToPKPi(candidate); + } + + template + auto invMassXicToPiKP(const T& candidate) + { + return invMassLcToPiKP(candidate); + } + + // hf_cand_casc_lf_2prong + + template + auto invMassXiczeroToXiPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassXiMinus, o2::analysis::pdg::MassPiPlus}); + } + + template + auto invMassOmegaczeroToOmegaPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassOmegaMinus, o2::analysis::pdg::MassPiPlus}); + } + + // hf_cand_casc_lf_3prong + + template + auto invMassXicplusToXiPiPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassXiMinus, o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassPiPlus}); + } + + // hf_cand_x + + // X → Jpsi π+ π- + template + auto ctX(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassX3872); + } + + template + auto yX(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassX3872); + } + + template + auto eX(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassX3872); + } + + template + auto invMassXToJpsiPiPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassJPsi, o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassPiPlus}); + } + + /// Difference between the X mass and the sum of the J/psi and di-pion masses + template + auto qX(const T& candidate) + { + auto piVec1 = std::array{candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()}; + auto piVec2 = std::array{candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()}; + + auto arrayMomenta = std::array{piVec1, piVec2}; + double massPiPi = RecoDecay::m(arrayMomenta, std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassPiPlus}); + + double massJpsiPiPi = invMassXToJpsiPiPi(candidate); + return std::abs(massJpsiPiPi - o2::analysis::pdg::MassJPsi - massPiPi); + } + + /// Angular difference between the J/psi and the pion + template + auto dRX(const T& candidate, int numPi) + { + double etaJpsi = RecoDecay::eta(std::array{candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()}); + double phiJpsi = RecoDecay::phi(candidate.pxProng0(), candidate.pyProng0()); + + double etaPi, phiPi; + + if (numPi <= 1) { + etaPi = RecoDecay::eta(std::array{candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()}); + phiPi = RecoDecay::phi(candidate.pxProng1(), candidate.pyProng1()); + } else { + etaPi = RecoDecay::eta(std::array{candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()}); + phiPi = RecoDecay::phi(candidate.pxProng2(), candidate.pyProng2()); + } + + double deltaEta = etaJpsi - etaPi; + double deltaPhi = RecoDecay::constrainAngle(phiJpsi - phiPi, -o2::constants::math::PI); + + return RecoDecay::sqrtSumOfSquares(deltaEta, deltaPhi); + } + + /// Difference in pT between the two pions + template + auto balancePtPionsX(const T& candidate) + { + double ptPi1 = RecoDecay::pt(candidate.pxProng1(), candidate.pyProng1()); + double ptPi2 = RecoDecay::pt(candidate.pxProng2(), candidate.pyProng2()); + return std::abs(ptPi1 - ptPi2) / (ptPi1 + ptPi2); + } + + // Ξcc±± → p± K∓ π± π± + + template + auto ctXicc(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassXiCCPlusPlus); + } + + template + auto yXicc(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassXiCCPlusPlus); + } + + template + auto eXicc(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassXiCCPlusPlus); + } + + template + auto invMassXiccToXicPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassXiCPlus, o2::analysis::pdg::MassPiPlus}); + } + + // chic → Jpsi gamma + + template + auto ctChic(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassChiC1); + } + + template + auto yChic(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassChiC1); + } + + template + auto eChic(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassChiC1); + } + template + auto invMassChicToJpsiGamma(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassJPsi, 0.}); + } + + // Λb → Λc+ π- → p K- π+ π- + + template + auto ctLb(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassLambdaB0); + } + + template + auto yLb(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassLambdaB0); + } + + template + auto eLb(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassLambdaB0); + } + template + auto invMassLbToLcPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassLambdaCPlus, o2::analysis::pdg::MassPiPlus}); + } + + // B0(B0bar) → D∓ π± + + template + auto ctB0(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassB0); + } + + template + auto yB0(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassB0); + } + + template + auto eB0(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassB0); + } + + template + auto invMassB0ToDPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassDMinus, o2::analysis::pdg::MassPiPlus}); + } + + template + auto cosThetaStarB0(const T& candidate) + { + return candidate.cosThetaStar(std::array{o2::analysis::pdg::MassDMinus, o2::analysis::pdg::MassPiPlus}, o2::analysis::pdg::MassB0, 1); + } + + // Bs(bar) → Ds∓ π± + + template + auto ctBs(const T& candidate) + { + return candidate.ct(o2::analysis::pdg::MassBS); + } + + template + auto yBs(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassBS); + } + + template + auto eBs(const T& candidate) + { + return candidate.e(o2::analysis::pdg::MassBS); + } + + template + auto invMassBsToDsPi(const T& candidate) + { + return candidate.m(std::array{o2::analysis::pdg::MassDSBar, o2::analysis::pdg::MassPiPlus}); + } + + template + auto cosThetaStarBs(const T& candidate) + { + return candidate.cosThetaStar(std::array{o2::analysis::pdg::MassDSBar, o2::analysis::pdg::MassPiPlus}, o2::analysis::pdg::MassBS, 1); + } + + /// Σc0,++ → Λc+(→pK-π+) π-,+ + + /// @brief Sc inv. mass using reco mass for Lc in pKpi and PDG mass for pion + template + auto invMassScRecoLcToPKPi(const T& candidateSc, const U& candidateLc) + { + return candidateSc.m(std::array{static_cast(invMassLcToPKPi(candidateLc)), o2::analysis::pdg::MassPiPlus}); + } + + /// @brief Sc inv. mass using reco mass for Lc in piKp and PDG mass for pion + template + auto invMassScRecoLcToPiKP(const T& candidateSc, const U& candidateLc) + { + return candidateSc.m(std::array{static_cast(invMassLcToPiKP(candidateLc)), o2::analysis::pdg::MassPiPlus}); + } + + template + auto ySc0(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassSigmaC0); + } + + template + auto yScPlusPlus(const T& candidate) + { + return candidate.y(o2::analysis::pdg::MassSigmaCPlusPlus); + } + + /// Apply topological cuts as defined in SelectorCuts.h + /// \param candB0 B0 candidate + /// \param cuts B0 candidate selection per pT bin" + /// \param binsPt pT bin limits + /// \return true if candidate passes all selections + template + bool selectionB0ToDPiTopol(const T1& candB0, const T2& cuts, const T3& binsPt) + { + auto ptCandB0 = candB0.pt(); + auto ptD = RecoDecay::pt(candB0.pxProng0(), candB0.pyProng0()); + auto ptPi = RecoDecay::pt(candB0.pxProng1(), candB0.pyProng1()); + + int pTBin = o2::analysis::findBin(binsPt, ptCandB0); + if (pTBin == -1) { + // LOGF(info, "B0 topol selection failed at getpTBin"); + return false; + } + + // // check that the candidate pT is within the analysis range + // if (ptCandB0 < ptCandMin || ptCandB0 >= ptCandMax) { + // return false; + // } + + // B0 mass cut + if (std::abs(invMassB0ToDPi(candB0) - o2::analysis::pdg::MassB0) > cuts->get(pTBin, "m")) { + // Printf("B0 topol selection failed at mass diff check"); + return false; + } + + // pion pt + if (ptPi < cuts->get(pTBin, "pT Pi")) { + return false; + } + + // D- pt + if (ptD < cuts->get(pTBin, "pT D")) { + return false; + } + + /* + // D mass cut | already applied in candidateSelectorDplusToPiKPi.cxx + if (std::abs(invMassDplusToPiKPi(hfCandD) - o2::analysis::pdg::MassDMinus) > cuts->get(pTBin, "DeltaMD")) { + return false; + } + */ + + // B0 Decay length + if (candB0.decayLength() < cuts->get(pTBin, "B0 decLen")) { + return false; + } + + // B0 Decay length XY + if (candB0.decayLengthXY() < cuts->get(pTBin, "B0 decLenXY")) { + return false; + } + + // B0 chi2PCA cut + if (candB0.chi2PCA() > cuts->get(pTBin, "Chi2PCA")) { + return false; + } + + // B0 CPA cut + if (candB0.cpa() < cuts->get(pTBin, "CPA")) { + return false; + } + + // d0 of pi + if (std::abs(candB0.impactParameter1()) < cuts->get(pTBin, "d0 Pi")) { + return false; + } + + // d0 of D + if (std::abs(candB0.impactParameter0()) < cuts->get(pTBin, "d0 D")) { + return false; + } + + return true; + } + + /// Apply PID selection + /// \param pidTrackPi PID status of trackPi (prong1 of B0 candidate) + /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \return true if prong1 of B0 candidate passes all selections + template + bool selectionB0ToDPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + { + if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { + return false; + } + if (acceptPIDNotApplicable && pidTrackPi == TrackSelectorPID::Rejected) { + return false; + } + + return true; + } + + // Apply topological cuts as defined in SelectorCuts.h + /// \param candBp B+ candidate + /// \param cuts B+ candidate selection per pT bin" + /// \param binsPt pT bin limits + /// \return true if candidate passes all selections + template + bool selectionBplusToD0PiTopol(const T1& candBp, const T2& cuts, const T3& binsPt) + { + auto ptcandBp = candBp.pt(); + auto ptPi = RecoDecay::pt(candBp.pxProng1(), candBp.pyProng1()); + + int pTBin = o2::analysis::findBin(binsPt, ptcandBp); + if (pTBin == -1) { + return false; + } + + // B+ mass cut + if (std::abs(invMassBplusToD0Pi(candBp) - o2::analysis::pdg::MassBPlus) > cuts->get(pTBin, "m")) { + return false; + } + + // pion pt + if (ptPi < cuts->get(pTBin, "pT Pi")) { + return false; + } + + // d0(D0)xd0(pi) + if (candBp.impactParameterProduct() > cuts->get(pTBin, "Imp. Par. Product")) { + return false; + } + + // B Decay length + if (candBp.decayLength() < cuts->get(pTBin, "B decLen")) { + return false; + } + + // B Decay length XY + if (candBp.decayLengthXY() < cuts->get(pTBin, "B decLenXY")) { + return false; + } + + // B+ CPA cut + if (candBp.cpa() < cuts->get(pTBin, "CPA")) { + return false; + } + + return true; + } + + /// Apply PID selection + /// \param pidTrackPi PID status of trackPi (prong1 of B+ candidate) + /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \return true if prong1 of B+ candidate passes all selections + template + bool selectionBplusToD0PiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + { + if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { + return false; + } + if (acceptPIDNotApplicable && pidTrackPi == TrackSelectorPID::Rejected) { + return false; + } + + return true; + } + + /// Apply topological cuts as defined in SelectorCuts.h + /// \param candBs Bs candidate + /// \param cuts Bs candidate selections + /// \param binsPt pT bin limits + /// \return true if candidate passes all selections + template + bool selectionBsToDsPiTopol(const T1& candBs, const T2& cuts, const T3& binsPt) + { + auto ptCandBs = candBs.pt(); + auto ptDs = RecoDecay::pt(candBs.pxProng0(), candBs.pyProng0()); + auto ptPi = RecoDecay::pt(candBs.pxProng1(), candBs.pyProng1()); + + int pTBin = o2::analysis::findBin(binsPt, ptCandBs); + if (pTBin == -1) { + return false; + } + + // Bs mass cut + if (std::abs(invMassBsToDsPi(candBs) - o2::analysis::pdg::MassBS) > cuts->get(pTBin, "m")) { + return false; + } + + // pion pt + if (ptPi < cuts->get(pTBin, "pT Pi")) { + return false; + } + + // Ds pt + if (ptDs < cuts->get(pTBin, "pT Ds")) { + return false; + } + + // Bs Decay length + if (candBs.decayLength() < cuts->get(pTBin, "Bs decLen")) { + return false; + } + + // Bs Decay length XY + if (candBs.decayLengthXY() < cuts->get(pTBin, "Bs decLenXY")) { + return false; + } + + // Bs chi2PCA cut + if (candBs.chi2PCA() > cuts->get(pTBin, "Chi2PCA")) { + return false; + } + + // Bs CPA cut + if (candBs.cpa() < cuts->get(pTBin, "CPA")) { + return false; + } + + // d0 of pi + if (std::abs(candBs.impactParameter1()) < cuts->get(pTBin, "d0 Pi")) { + return false; + } + + // d0 of Ds + if (std::abs(candBs.impactParameter0()) < cuts->get(pTBin, "d0 Ds")) { + return false; + } + + // d0(Ds)xd0(pi) + if (candBs.impactParameterProduct() > cuts->get(pTBin, "Imp. Par. Product")) { + return false; + } + + return true; + } + + /// Apply PID selection + /// \param pidTrackPi PID status of trackPi (prong1 of Bs candidate) + /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \return true if prong1 of Bs candidate passes all selections + template + bool selectionBsToDsPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + { + if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { + return false; + } + if (acceptPIDNotApplicable && pidTrackPi == TrackSelectorPID::Rejected) { + return false; + } + + return true; + } + + private: +}; + +#endif // PWGHF_CORE_HFHELPER_H_ diff --git a/PWGHF/Core/HfMlResponse.h b/PWGHF/Core/HfMlResponse.h new file mode 100644 index 00000000000..7a39be07fec --- /dev/null +++ b/PWGHF/Core/HfMlResponse.h @@ -0,0 +1,45 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file HFMLResponse.h +/// \brief Class to compute the ML response for HF-analysis selections +/// \author Fabio Catalano , CERN +/// \author Alexandre Bigot , IPHC Strasbourg + +#ifndef PWGHF_CORE_HFMLRESPONSE_H_ +#define PWGHF_CORE_HFMLRESPONSE_H_ + +#include + +#include +#include +#include + +#include "CCDB/CcdbApi.h" +#include "Framework/Array2D.h" +#include "Tools/ML/MlResponse.h" + +namespace o2::analysis +{ + +template +class HfMlResponse : public o2::analysis::MlResponse +{ + public: + /// Default constructor + HfMlResponse() = default; + /// Default destructor + virtual ~HfMlResponse() = default; +}; + +} // namespace o2::analysis + +#endif // PWGHF_CORE_HFMLRESPONSE_H_ diff --git a/PWGHF/Core/PDG.h b/PWGHF/Core/PDG.h new file mode 100644 index 00000000000..34d5dcd1a09 --- /dev/null +++ b/PWGHF/Core/PDG.h @@ -0,0 +1,139 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file PDG.h +/// \brief PDG features +/// \note Use PWGHF/Core/make_pdg_header.py to generate the enums and mass declarations. + +#ifndef PWGHF_CORE_PDG_H_ +#define PWGHF_CORE_PDG_H_ + +namespace o2::analysis::pdg +{ +/// \brief Declarations of named PDG codes of particles missing in ROOT PDG_t +/// \note Follow kCamelCase naming convention +/// \link https://root.cern/doc/master/TPDGCode_8h.html +enum Code { + kB0 = 511, + kB0Bar = -511, + kBPlus = 521, + kBS = 531, + kBSBar = -531, + kD0 = 421, + kD0Bar = -421, + kDMinus = -411, + kDPlus = 411, + kDS = 431, + kDSBar = -431, + kDStar = 413, + kChiC1 = 20443, + kJPsi = 443, + kLambdaB0 = 5122, + kLambdaCPlus = 4122, + kOmegaC0 = 4332, + kPhi = 333, + kSigmaC0 = 4112, + kSigmaCPlusPlus = 4222, + kX3872 = 9920443, + kXi0 = 3322, + kXiB0 = 5232, + kXiCCPlusPlus = 4422, + kXiCPlus = 4232, + kXiCZero = 4132 +}; + +/// \brief Declarations of masses for additional particles +constexpr double MassB0 = 5.27953; +constexpr double MassB0Bar = 5.27953; +constexpr double MassBPlus = 5.27915; +constexpr double MassBS = 5.3663; +constexpr double MassBSBar = 5.3663; +constexpr double MassD0 = 1.86484; +constexpr double MassD0Bar = 1.86484; +constexpr double MassDMinus = 1.86962; +constexpr double MassDPlus = 1.86962; +constexpr double MassDS = 1.9685; +constexpr double MassDSBar = 1.9685; +constexpr double MassDStar = 2.01027; +constexpr double MassChiC1 = 3.51066; +constexpr double MassJPsi = 3.096916; +constexpr double MassLambdaB0 = 5.6202; +constexpr double MassLambdaCPlus = 2.28646; +constexpr double MassOmegaC0 = 2.6952; +constexpr double MassPhi = 1.019455; +constexpr double MassSigmaC0 = 2.45376; +constexpr double MassSigmaCPlusPlus = 2.45402; +constexpr double MassX3872 = 3.87165; +constexpr double MassXi0 = 1.31486; +constexpr double MassXiB0 = 5.7924; +constexpr double MassXiCCPlusPlus = 3.62155; +constexpr double MassXiCPlus = 2.4679; +constexpr double MassXiCZero = 2.471; + +/// \brief Declarations of masses for particles in ROOT PDG_t +constexpr double MassDown = 0.0048; +constexpr double MassDownBar = 0.0048; +constexpr double MassUp = 0.0024; +constexpr double MassUpBar = 0.0024; +constexpr double MassStrange = 0.104; +constexpr double MassStrangeBar = 0.104; +constexpr double MassCharm = 1.27; +constexpr double MassCharmBar = 1.27; +constexpr double MassBottom = 4.68; +constexpr double MassBottomBar = 4.68; +constexpr double MassTop = 171.2; +constexpr double MassTopBar = 171.2; +constexpr double MassGluon = 0.0; +constexpr double MassElectron = 0.00051099891; +constexpr double MassPositron = 0.00051099891; +constexpr double MassNuE = 0.0; +constexpr double MassNuEBar = 0.0; +constexpr double MassMuonMinus = 0.105658; +constexpr double MassMuonPlus = 0.105658; +constexpr double MassNuMu = 0.0; +constexpr double MassNuMuBar = 0.0; +constexpr double MassTauMinus = 1.77684; +constexpr double MassTauPlus = 1.77684; +constexpr double MassNuTau = 0.0; +constexpr double MassNuTauBar = 0.0; +constexpr double MassGamma = 0.0; +constexpr double MassZ0 = 91.187; +constexpr double MassWPlus = 80.398; +constexpr double MassWMinus = 80.398; +constexpr double MassPi0 = 0.134977; +constexpr double MassK0Long = 0.497614; +constexpr double MassPiPlus = 0.13957; +constexpr double MassPiMinus = 0.13957; +constexpr double MassProton = 0.938272; +constexpr double MassProtonBar = 0.938272; +constexpr double MassNeutron = 0.939565; +constexpr double MassNeutronBar = 0.939565; +constexpr double MassK0Short = 0.497614; +constexpr double MassK0 = 0.497614; +constexpr double MassK0Bar = 0.497614; +constexpr double MassKPlus = 0.493677; +constexpr double MassKMinus = 0.493677; +constexpr double MassLambda0 = 1.11568; +constexpr double MassLambda0Bar = 1.11568; +constexpr double MassLambda1520 = 1.5195; +constexpr double MassSigmaMinus = 1.19744; +constexpr double MassSigmaBarPlus = 1.19744; +constexpr double MassSigmaPlus = 1.18937; +constexpr double MassSigmaBarMinus = 1.18937; +constexpr double MassSigma0 = 1.192642; +constexpr double MassSigma0Bar = 1.192642; +constexpr double MassXiMinus = 1.32171; +constexpr double MassXiPlusBar = 1.32171; +constexpr double MassOmegaMinus = 1.67245; +constexpr double MassOmegaPlusBar = 1.67245; +} // namespace o2::analysis::pdg + +#endif // PWGHF_CORE_PDG_H_ diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index b7f1c746526..1a455d13e71 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -15,60 +15,11 @@ #ifndef PWGHF_CORE_SELECTORCUTS_H_ #define PWGHF_CORE_SELECTORCUTS_H_ -#include -#include - -#include "Framework/Configurable.h" +#include // std::string +#include // std::vector namespace o2::analysis { -namespace pdg -{ -/// \brief Declarations of named PDG codes of HF particles missing in ROOT PDG_t. -/// \note Follow kCamelCase naming convention -/// \link https://root.cern/doc/master/TPDGCode_8h.html -enum Code { - kD0 = 421, - kD0Bar = -421, - kDPlus = 411, - kDMinus = -411, - kDStar = 413, - kDS = 431, - kLambdaCPlus = 4122, - kXiCZero = 4132, - kXiCPlus = 4232, - kXiCCPlusPlus = 4422, - kLambdaB0 = 5122, - kJPsi = 443, - kChiC1 = 20443, - kB0 = 511, - kB0Bar = -511, - kBPlus = 521, - kBS = 531, - kX3872 = 9920443, - kSigmaC0 = 4112, - kSigmaCPlusPlus = 4222, - kOmegaC0 = 4332, - kPhi = 333 -}; -} // namespace pdg - -/// Finds pT bin in an array. -/// \param bins array of pT bins -/// \param value pT -/// \return index of the pT bin -/// \note Accounts for the offset so that pt bin array can be used to also configure a histogram axis. -template -int findBin(T1 const& binsPt, T2 value) -{ - if (value < binsPt->front()) { - return -1; - } - if (value >= binsPt->back()) { - return -1; - } - return std::distance(binsPt->begin(), std::upper_bound(binsPt->begin(), binsPt->end(), value)) - 1; -} // namespace per channel @@ -89,7 +40,7 @@ constexpr double binsPtTrack[nBinsPtTrack + 1] = { 1000.0}; auto vecBinsPtTrack = std::vector{binsPtTrack, binsPtTrack + nBinsPtTrack + 1}; -// default values for the cuts +// default values for the cuts of displaced tracks constexpr double cutsTrack[nBinsPtTrack][nCutVarsTrack] = {{0.0025, 10.}, /* 0 < pt < 0.5 */ {0.0025, 10.}, /* 0.5 < pt < 1 */ {0.0025, 10.}, /* 1 < pt < 1.5 */ @@ -97,6 +48,14 @@ constexpr double cutsTrack[nBinsPtTrack][nCutVarsTrack] = {{0.0025, 10.}, /* 0 {0.0000, 10.}, /* 2 < pt < 3 */ {0.0000, 10.}}; /* 3 < pt < 1000 */ +// default values for the cuts of primary tracks (e.g. D* soft pions) +constexpr double cutsTrackPrimary[nBinsPtTrack][nCutVarsTrack] = {{0.0000, 2.}, /* 0 < pt < 0.5 */ + {0.0000, 2.}, /* 0.5 < pt < 1 */ + {0.0000, 2.}, /* 1 < pt < 1.5 */ + {0.0000, 2.}, /* 1.5 < pt < 2 */ + {0.0000, 2.}, /* 2 < pt < 3 */ + {0.0000, 2.}}; /* 3 < pt < 1000 */ + // row labels static const std::vector labelsPtTrack{}; @@ -126,6 +85,59 @@ static const std::vector labelsPt{}; static const std::vector labelsCutBdt = {"BDTbkg", "BDTprompt", "BDTnonprompt"}; } // namespace hf_cuts_bdt_multiclass +namespace hf_cuts_ml +{ +// direction of the cut +enum CutDirection { + CutGreater = 0, // require score < cut value + CutSmaller, // require score > cut value + CutNot // do not cut on score +}; + +static constexpr int nBinsPt = 6; +static constexpr int nCutScores = 3; +// default values for the pT bin edges, offset by 1 from the bin numbers in cuts array +constexpr double binsPt[nBinsPt + 1] = { + 0., + 1., + 2., + 4., + 6., + 10., + 50.}; +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; + +// default values for the ML model paths, one model per pT bin +static const std::vector modelPaths = { + ""}; + +// default values for the cut directions +constexpr int cutDir[nCutScores] = {CutGreater, CutSmaller, CutSmaller}; +auto vecCutDir = std::vector{cutDir, cutDir + nCutScores}; + +// default values for the cuts +constexpr double cuts[nBinsPt][nCutScores] = { + {0.5, 0.5, 0.5}, + {0.5, 0.5, 0.5}, + {0.5, 0.5, 0.5}, + {0.5, 0.5, 0.5}, + {0.5, 0.5, 0.5}, + {0.5, 0.5, 0.5}}; + +// row labels +static const std::vector labelsPt = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", +}; + +// column labels +static const std::vector labelsCutScore = {"score class 1", "score class 2", "score class 3"}; +} // namespace hf_cuts_ml + namespace hf_cuts_presel_2prong { static constexpr int nBinsPt = 2; @@ -174,10 +186,33 @@ static const std::vector labelsPt{}; static const std::vector labelsCutVar = {"massMin", "massMax", "cosp", "decL"}; } // namespace hf_cuts_presel_3prong +namespace hf_cuts_presel_dstar +{ +static constexpr int nBinsPt = 2; +static constexpr int nCutVars = 2; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double binsPt[nBinsPt + 1] = { + 1., + 5., + 1000.0}; +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; + +// default values for the cuts +constexpr double cuts[nBinsPt][nCutVars] = {{0.17, 0.05}, /* 1 < pt < 5 */ + {0.17, 0.08}}; /* 5 < pt < 1000 */ + +// row labels +static const std::vector labelsPt{}; + +// column labels +static const std::vector labelsCutVar = {"deltaMassMax", "deltaMassD0"}; +} // namespace hf_cuts_presel_dstar + namespace hf_cuts_d0_to_pi_k { static constexpr int nBinsPt = 25; -static constexpr int nCutVars = 14; +static constexpr int nCutVars = 15; // default values for the pT bin edges (can be used to configure histogram axis) // offset by 1 from the bin numbers in cuts array constexpr double binsPt[nBinsPt + 1] = { @@ -210,31 +245,31 @@ constexpr double binsPt[nBinsPt + 1] = { auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; // default values for the cuts -constexpr double cuts[nBinsPt][nCutVars] = {{0.400, 350. * 1E-4, 0.8, 0.5, 0.5, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.80, 0., 0., 10., 10., 0.06}, /* 0 < pT < 0.5 */ - {0.400, 350. * 1E-4, 0.8, 0.5, 0.5, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.80, 0., 0., 10., 10., 0.06}, /* 0.5 < pT < 1 */ - {0.400, 300. * 1E-4, 0.8, 0.4, 0.4, 1000. * 1E-4, 1000. * 1E-4, -25000. * 1E-8, 0.80, 0., 0., 10., 10., 0.06}, /* 1 < pT < 1.5 */ - {0.400, 300. * 1E-4, 0.8, 0.4, 0.4, 1000. * 1E-4, 1000. * 1E-4, -25000. * 1E-8, 0.80, 0., 0., 10., 10., 0.06}, /* 1.5 < pT < 2 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -20000. * 1E-8, 0.90, 0., 0., 10., 10., 0.06}, /* 2 < pT < 2.5 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -20000. * 1E-8, 0.90, 0., 0., 10., 10., 0.06}, /* 2.5 < pT < 3 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -12000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 3 < pT < 3.5 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -12000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 3.5 < pT < 4 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 4 < pT < 4.5 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 4.5 < pT < 5 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 5 < pT < 5.5 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 5.5 < pT < 6 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 6 < pT < 6.5 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 6.5 < pT < 7 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -7000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 7 < pT < 7.5 */ - {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -7000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 7.5 < pT < 8 */ - {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 8 < pT < 9 */ - {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 9 < pT < 10 */ - {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 10 < pT < 12 */ - {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 10000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 12 < pT < 16 */ - {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 16 < pT < 20 */ - {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 20 < pT < 24 */ - {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 24 < pT < 36 */ - {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0., 10., 10., 0.06}, /* 36 < pT < 50 */ - {0.400, 300. * 1E-4, 1.0, 0.6, 0.6, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.80, 0., 0., 10., 10., 0.06}}; /* 50 < pT < 100 */ +constexpr double cuts[nBinsPt][nCutVars] = {{0.400, 350. * 1E-4, 0.8, 0.5, 0.5, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.80, 0., 0., 10., 10., 0.06, 0.5}, /* 0 < pT < 0.5 */ + {0.400, 350. * 1E-4, 0.8, 0.5, 0.5, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.80, 0., 0., 10., 10., 0.06, 0.5}, /* 0.5 < pT < 1 */ + {0.400, 300. * 1E-4, 0.8, 0.4, 0.4, 1000. * 1E-4, 1000. * 1E-4, -25000. * 1E-8, 0.80, 0., 0., 10., 10., 0.06, 0.5}, /* 1 < pT < 1.5 */ + {0.400, 300. * 1E-4, 0.8, 0.4, 0.4, 1000. * 1E-4, 1000. * 1E-4, -25000. * 1E-8, 0.80, 0., 0., 10., 10., 0.06, 0.5}, /* 1.5 < pT < 2 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -20000. * 1E-8, 0.90, 0., 0., 10., 10., 0.06, 0.5}, /* 2 < pT < 2.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -20000. * 1E-8, 0.90, 0., 0., 10., 10., 0.06, 0.5}, /* 2.5 < pT < 3 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -12000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 3 < pT < 3.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -12000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 3.5 < pT < 4 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 4 < pT < 4.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 4.5 < pT < 5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 5 < pT < 5.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 5.5 < pT < 6 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 6 < pT < 6.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -8000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 6.5 < pT < 7 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -7000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 7 < pT < 7.5 */ + {0.400, 300. * 1E-4, 0.8, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -7000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 7.5 < pT < 8 */ + {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 8 < pT < 9 */ + {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 9 < pT < 10 */ + {0.400, 300. * 1E-4, 0.9, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, -5000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 10 < pT < 12 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 10000. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 12 < pT < 16 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 16 < pT < 20 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 20 < pT < 24 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 24 < pT < 36 */ + {0.400, 300. * 1E-4, 1.0, 0.7, 0.7, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.85, 0., 0., 10., 10., 0.06, 0.5}, /* 36 < pT < 50 */ + {0.400, 300. * 1E-4, 1.0, 0.6, 0.6, 1000. * 1E-4, 1000. * 1E-4, 999999. * 1E-8, 0.80, 0., 0., 10., 10., 0.06, 0.5}}; /* 50 < pT < 100 */ // row labels static const std::vector labelsPt = { @@ -265,7 +300,7 @@ static const std::vector labelsPt = { "pT bin 24"}; // column labels -static const std::vector labelsCutVar = {"m", "DCA", "cos theta*", "pT K", "pT Pi", "d0K", "d0pi", "d0d0", "cos pointing angle", "cos pointing angle xy", "normalized decay length XY", "decay length", "decay length XY", "minimum decay length"}; +static const std::vector labelsCutVar = {"m", "DCA", "cos theta*", "pT K", "pT Pi", "d0K", "d0pi", "d0d0", "cos pointing angle", "cos pointing angle xy", "min norm decay length XY", "max decay length", "max decay length XY", "min decay length", "norm dauImpPar XY"}; } // namespace hf_cuts_d0_to_pi_k namespace hf_cuts_lc_to_p_k_pi @@ -661,6 +696,32 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"m", "CPA", "Chi2PCA", "d0 D", "d0 Pi", "pT D", "pT Pi", "B0 decLen", "B0 decLenXY", "Imp. Par. Product", "DeltaMD", "Cos ThetaStar"}; } // namespace hf_cuts_b0_to_d_pi +namespace hf_cuts_bs_to_ds_pi +{ +static constexpr int nBinsPt = 2; +static constexpr int nCutVars = 10; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double binsPt[nBinsPt + 1] = { + 0, + 1.0, + 2.0}; + +auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; + +// default values for the cuts +// DeltaM CPA chi2PCA d0Ds d0Pi pTDs pTPi BsDecayLength BsDecayLengthXY IPProd +constexpr double cuts[nBinsPt][nCutVars] = {{1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}, /* 0 < pt < 1 */ + {1., 0.8, 1., 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0.}}; /* 1 < pt < 2 */ +// row labels +static const std::vector labelsPt = { + "pT bin 0", + "pT bin 1"}; + +// column labels +static const std::vector labelsCutVar = {"m", "CPA", "Chi2PCA", "d0 Ds", "d0 Pi", "pT Ds", "pT Pi", "Bs decLen", "Bs decLenXY", "Imp. Par. Product"}; +} // namespace hf_cuts_bs_to_ds_pi + namespace hf_cuts_bplus_to_d0_pi { static constexpr int nBinsPt = 12; diff --git a/PWGHF/Core/make_pdg_header.py b/PWGHF/Core/make_pdg_header.py new file mode 100644 index 00000000000..c9038196285 --- /dev/null +++ b/PWGHF/Core/make_pdg_header.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 + +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +"""! +@brief Generates the body of a C++ header with PDG codes and particle masses. +@author Vít Kučera , Inha University +@date 2023-09-21 +""" + +from ctypes import c_bool +from enum import Enum + +import ROOT # pylint: disable=import-error + + +# Enum of PDG_t particles +class PdgROOT(Enum): + kDown = ROOT.kDown + kDownBar = ROOT.kDownBar + kUp = ROOT.kUp + kUpBar = ROOT.kUpBar + kStrange = ROOT.kStrange + kStrangeBar = ROOT.kStrangeBar + kCharm = ROOT.kCharm + kCharmBar = ROOT.kCharmBar + kBottom = ROOT.kBottom + kBottomBar = ROOT.kBottomBar + kTop = ROOT.kTop + kTopBar = ROOT.kTopBar + kGluon = ROOT.kGluon + kElectron = ROOT.kElectron + kPositron = ROOT.kPositron + kNuE = ROOT.kNuE + kNuEBar = ROOT.kNuEBar + kMuonMinus = ROOT.kMuonMinus + kMuonPlus = ROOT.kMuonPlus + kNuMu = ROOT.kNuMu + kNuMuBar = ROOT.kNuMuBar + kTauMinus = ROOT.kTauMinus + kTauPlus = ROOT.kTauPlus + kNuTau = ROOT.kNuTau + kNuTauBar = ROOT.kNuTauBar + kGamma = ROOT.kGamma + kZ0 = ROOT.kZ0 + kWPlus = ROOT.kWPlus + kWMinus = ROOT.kWMinus + kPi0 = ROOT.kPi0 + kK0Long = ROOT.kK0Long + kPiPlus = ROOT.kPiPlus + kPiMinus = ROOT.kPiMinus + kProton = ROOT.kProton + kProtonBar = ROOT.kProtonBar + kNeutron = ROOT.kNeutron + kNeutronBar = ROOT.kNeutronBar + kK0Short = ROOT.kK0Short + kK0 = ROOT.kK0 + kK0Bar = ROOT.kK0Bar + kKPlus = ROOT.kKPlus + kKMinus = ROOT.kKMinus + kLambda0 = ROOT.kLambda0 + kLambda0Bar = ROOT.kLambda0Bar + kLambda1520 = ROOT.kLambda1520 + kSigmaMinus = ROOT.kSigmaMinus + kSigmaBarPlus = ROOT.kSigmaBarPlus + kSigmaPlus = ROOT.kSigmaPlus + kSigmaBarMinus = ROOT.kSigmaBarMinus + kSigma0 = ROOT.kSigma0 + kSigma0Bar = ROOT.kSigma0Bar + kXiMinus = ROOT.kXiMinus + kXiPlusBar = ROOT.kXiPlusBar + kOmegaMinus = ROOT.kOmegaMinus + kOmegaPlusBar = ROOT.kOmegaPlusBar + + +# Enum of additional particles +class Pdg(Enum): + kB0 = 511 + kB0Bar = -511 + kBPlus = 521 + kBS = 531 + kBSBar = -531 + kD0 = 421 + kD0Bar = -421 + kDMinus = -411 + kDPlus = 411 + kDS = 431 + kDSBar = -431 + kDStar = 413 + kChiC1 = 20443 + kJPsi = 443 + kLambdaB0 = 5122 + kLambdaCPlus = 4122 + kOmegaC0 = 4332 + kPhi = 333 + kSigmaC0 = 4112 + kSigmaCPlusPlus = 4222 + kX3872 = 9920443 + kXi0 = 3322 + kXiB0 = 5232 + kXiCCPlusPlus = 4422 + kXiCPlus = 4232 + kXiCZero = 4132 + + +def mass(code): + """Returns particle mass from o2::O2DatabasePDG except for special cases.""" + # Special cases (present in TDatabasePDG but with wrong values) + # Missing particles should be added in O2DatabasePDG.h. + if abs(code) == Pdg.kXiCCPlusPlus.value: + return 3.62155 # PDG 2022: https://pdg.lbl.gov/2022/listings/rpp2022-list-xicc-plus-plus.pdf + if abs(code) == Pdg.kOmegaC0.value: + return 2.69520 # PDG 2022: https://pdg.lbl.gov/2022/listings/rpp2022-list-omegac-zero.pdf + # Default case + success = c_bool(True) + return ROOT.o2.O2DatabasePDG.Mass(code, success) + + +def declare_mass(pdg, type="double") -> str: + """Returns a C++ declaration of a particle mass constant.""" + return f"constexpr {type} Mass{pdg.name[1:]} = {mass(pdg.value)};\n" + + +# Start of enum declarations of additional particles +str_enum_head = """/// \\brief Declarations of named PDG codes of particles missing in ROOT PDG_t +/// \\note Follow kCamelCase naming convention +/// \\link https://root.cern/doc/master/TPDGCode_8h.html +enum Code { +""" +# End of enum declarations of additional particles +str_enum_foot = "};\n" +# Documentation string for mass declarations of additional particles +str_mass_o2_head = """/// \\brief Declarations of masses for additional particles +""" +# Documentation string for mass declarations of PDG_t particles +str_mass_root_head = """/// \\brief Declarations of masses for particles in ROOT PDG_t +""" + +# Additional particles +str_enum = str_enum_head +str_mass_o2 = str_mass_o2_head +for c in Pdg: + str_enum += f" {c.name} = {c.value},\n" + str_mass_o2 += declare_mass(c) +str_enum = str_enum[:-2] + "\n" # Remove the last comma. +str_enum += str_enum_foot + +# PDG_t particles +str_mass_root = str_mass_root_head +for d in PdgROOT: + str_mass_root += declare_mass(d) + +# Header body +str_header = "\n".join([str_enum, str_mass_o2, str_mass_root]) +print(str_header) diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 81ead3b6418..35a58606074 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -15,22 +15,20 @@ /// \note /// /// \author Alexandre Bigot , IPHC Strasbourg +/// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Bari #ifndef PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ #define PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/PIDResponse.h" #include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/Vertex.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponse.h" -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; +#include "PWGHF/DataModel/CandidateReconstructionTables.h" namespace o2 { @@ -43,7 +41,7 @@ DECLARE_SOA_COLUMN(Bz, bz, float); //! Magnetic field in z-direction DECLARE_SOA_COLUMN(OriginalCollisionCount, originalCollisionCount, int); //! Size of COLLISION table processed } // namespace hf_reduced_collision -DECLARE_SOA_TABLE(HfReducedCollisions, "AOD", "HFREDCOLLISION", //! Table with collision for reduced workflow +DECLARE_SOA_TABLE(HfRedCollisions, "AOD", "HFREDCOLLISION", //! Table with collision for reduced workflow soa::Index<>, collision::PosX, collision::PosY, @@ -56,9 +54,9 @@ DECLARE_SOA_TABLE(HfReducedCollisions, "AOD", "HFREDCOLLISION", //! Table with c collision::CovZZ, hf_reduced_collision::Bz); -using HfReducedCollision = HfReducedCollisions::iterator; +using HfRedCollision = HfRedCollisions::iterator; -DECLARE_SOA_TABLE(HfOriginalCollisionsCounter, "AOD", "HFCOLCOUNTER", //! Table with original number of collisions +DECLARE_SOA_TABLE(HfOrigColCounts, "AOD", "HFORIGCOLCOUNT", //! Table with original number of collisions hf_reduced_collision::OriginalCollisionCount); namespace hf_track_par_cov @@ -79,101 +77,153 @@ DECLARE_SOA_COLUMN(C1PtZ, c1PtZ, float); //! Covariance matrix DECLARE_SOA_COLUMN(C1PtSnp, c1PtSnp, float); //! Covariance matrix DECLARE_SOA_COLUMN(C1PtTgl, c1PtTgl, float); //! Covariance matrix DECLARE_SOA_COLUMN(C1Pt21Pt2, c1Pt21Pt2, float); //! Covariance matrix - -DECLARE_SOA_COLUMN(Px, px, float); //! Momentum in x-direction in GeV/c -DECLARE_SOA_COLUMN(Py, py, float); //! Momentum in y-direction in GeV/c -DECLARE_SOA_COLUMN(Pz, pz, float); //! Momentum in z-direction in GeV/c } // namespace hf_track_par_cov // general columns -#define HFTRACKPARCOV_COLUMNS \ - aod::track::X, \ - aod::track::Alpha, \ - aod::track::Y, \ - aod::track::Z, \ - aod::track::Snp, \ - aod::track::Tgl, \ - aod::track::Signed1Pt, \ - hf_track_par_cov::CYY, \ - hf_track_par_cov::CZY, \ - hf_track_par_cov::CZZ, \ - hf_track_par_cov::CSnpY, \ - hf_track_par_cov::CSnpZ, \ - hf_track_par_cov::CSnpSnp, \ - hf_track_par_cov::CTglY, \ - hf_track_par_cov::CTglZ, \ - hf_track_par_cov::CTglSnp, \ - hf_track_par_cov::CTglTgl, \ - hf_track_par_cov::C1PtY, \ - hf_track_par_cov::C1PtZ, \ - hf_track_par_cov::C1PtSnp, \ - hf_track_par_cov::C1PtTgl, \ - hf_track_par_cov::C1Pt21Pt2, \ - hf_track_par_cov::Px, \ - hf_track_par_cov::Py, \ - hf_track_par_cov::Pz +#define HFTRACKPAR_COLUMNS \ + aod::track::X, \ + aod::track::Alpha, \ + aod::track::Y, \ + aod::track::Z, \ + aod::track::Snp, \ + aod::track::Tgl, \ + aod::track::Signed1Pt + +#define HFTRACKPARCOV_COLUMNS \ + hf_track_par_cov::CYY, \ + hf_track_par_cov::CZY, \ + hf_track_par_cov::CZZ, \ + hf_track_par_cov::CSnpY, \ + hf_track_par_cov::CSnpZ, \ + hf_track_par_cov::CSnpSnp, \ + hf_track_par_cov::CTglY, \ + hf_track_par_cov::CTglZ, \ + hf_track_par_cov::CTglSnp, \ + hf_track_par_cov::CTglTgl, \ + hf_track_par_cov::C1PtY, \ + hf_track_par_cov::C1PtZ, \ + hf_track_par_cov::C1PtSnp, \ + hf_track_par_cov::C1PtTgl, \ + hf_track_par_cov::C1Pt21Pt2 namespace hf_track_index_reduced { -DECLARE_SOA_INDEX_COLUMN(HfReducedCollision, hfReducedCollision); //! ReducedCollision index -DECLARE_SOA_INDEX_COLUMN(Track, track); //! Track index -DECLARE_SOA_COLUMN(HasTPC, hasTPC, bool); //! Flag to check if track has a TPC match -DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); //! Flag to check if track has a TOF match +DECLARE_SOA_INDEX_COLUMN(HfRedCollision, hfRedCollision); //! ReducedCollision index +DECLARE_SOA_COLUMN(TrackId, trackId, int); //! Original track index +DECLARE_SOA_COLUMN(Prong0Id, prong0Id, int); //! Original track index +DECLARE_SOA_COLUMN(Prong1Id, prong1Id, int); //! Original track index +DECLARE_SOA_COLUMN(Prong2Id, prong2Id, int); //! Original track index +DECLARE_SOA_COLUMN(HasTPC, hasTPC, bool); //! Flag to check if track has a TPC match +DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); //! Flag to check if track has a TOF match } // namespace hf_track_index_reduced -DECLARE_SOA_TABLE(HfTracksReduced, "AOD", "HFTRACKRED", //! Table with track information for reduced workflow +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRedTrackBases, "AOD", "HFREDTRACKBASE", //! Table with track information for reduced workflow soa::Index<>, hf_track_index_reduced::TrackId, - hf_track_index_reduced::HfReducedCollisionId, - HFTRACKPARCOV_COLUMNS); + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + aod::track::Px, + aod::track::Py, + aod::track::Pz); -namespace hf_track_pid_reduced -{ -DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of the track in GeV/c -} // namespace hf_track_pid_reduced +DECLARE_SOA_TABLE(HfRedTracksCov, "AOD", "HFREDTRACKCOV", //! Table with track covariance information for reduced workflow + soa::Index<>, + HFTRACKPARCOV_COLUMNS); -// table with all attributes needed to call getStatusTrackPIDTpcAndTof() in the selector task -DECLARE_SOA_TABLE(HfTracksPidReduced, "AOD", "HFTRACKPIDRED", //! Table with PID track information for reduced workflow +// table with all attributes needed to call statusTpcAndTof() in the selector task +DECLARE_SOA_TABLE(HfRedTracksPid, "AOD", "HFREDTRACKPID", //! Table with PID track information for reduced workflow o2::soa::Index<>, - hf_track_index_reduced::HfReducedCollisionId, - hf_track_pid_reduced::Pt, hf_track_index_reduced::HasTPC, hf_track_index_reduced::HasTOF, - pidtpc::TPCNSigmaEl, - pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, - pidtpc::TPCNSigmaKa, - pidtpc::TPCNSigmaPr, - pidtof::TOFNSigmaEl, - pidtof::TOFNSigmaMu, - pidtof::TOFNSigmaPi, - pidtof::TOFNSigmaKa, - pidtof::TOFNSigmaPr); - -namespace hf_cand_3prong_reduced -{ -DECLARE_SOA_COLUMN(CPA, cpa, float); //! Cosinus pointing angle -DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length in cm -DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass of 3prong candidate in GeV/c2 + pidtof::TOFNSigmaPi); + +DECLARE_SOA_EXTENDED_TABLE_USER(HfRedTracksExt, HfRedTrackBases, "HFREDTRACKEXT", //! Track parameters at collision vertex + aod::track::Pt); -template -auto invMassDplusToPiKPi(const T& pVec0, const T& pVec1, const T& pVec2) +using HfRedTracks = HfRedTracksExt; + +namespace hf_charm_cand_reduced { - return RecoDecay::m(std::array{pVec0, pVec1, pVec2}, - std::array{RecoDecay::getMassPDG(kPiPlus), - RecoDecay::getMassPDG(kKPlus), - RecoDecay::getMassPDG(kPiPlus)}); -} -} // namespace hf_cand_3prong_reduced - -DECLARE_SOA_TABLE(HfCand3ProngReduced, "AOD", "HFCAND3PRONGRED", //! Table with 3prong candidate information for reduced workflow +DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass of 2prong candidate in GeV/c2 +DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! Invariant mass of 2prong candidate in GeV/c2 +DECLARE_SOA_COLUMN(InvMassD0Bar, invMassD0Bar, float); //! Invariant mass of 2prong candidate in GeV/c2 +DECLARE_SOA_COLUMN(MlScoreBkg, mlScoreBkg, float); //! ML score for background class +DECLARE_SOA_COLUMN(MlScorePrompt, mlScorePrompt, float); //! ML score for prompt class +DECLARE_SOA_COLUMN(MlScoreNonprompt, mlScoreNonprompt, float); //! ML score for non-prompt class +} // namespace hf_charm_cand_reduced + +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRed2Prongs, "AOD", "HFRED2PRONG", //! Table with 2prong candidate information for reduced workflow + o2::soa::Index<>, + hf_track_index_reduced::Prong0Id, hf_track_index_reduced::Prong1Id, + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_charm_cand_reduced::InvMassD0, hf_charm_cand_reduced::InvMassD0Bar, + aod::track::Px, + aod::track::Py, + aod::track::Pz); + +DECLARE_SOA_TABLE(HfRed2ProngsCov, "AOD", "HFRED2PRONGSCOV", //! Table with 2prong candidate covariance for reduced workflow o2::soa::Index<>, - hf_track_index::Prong0Id, hf_track_index::Prong1Id, hf_track_index::Prong2Id, - hf_track_index_reduced::HfReducedCollisionId, HFTRACKPARCOV_COLUMNS, - hf_cand_3prong_reduced::CPA, - hf_cand_3prong_reduced::DecayLength, - hf_cand_3prong_reduced::InvMass); + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(HfRed2ProngsMl, "AOD", "HFRED2PRONGML", //! Table with 2prong candidate ML scores + hf_charm_cand_reduced::MlScoreBkg, + hf_charm_cand_reduced::MlScorePrompt, + hf_charm_cand_reduced::MlScoreNonprompt); + +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRed3Prongs, "AOD", "HFRED3PRONG", //! Table with 3prong candidate information for reduced workflow + o2::soa::Index<>, + hf_track_index_reduced::Prong0Id, hf_track_index_reduced::Prong1Id, hf_track_index_reduced::Prong2Id, + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_charm_cand_reduced::InvMass, + aod::track::Px, + aod::track::Py, + aod::track::Pz); + +DECLARE_SOA_TABLE(HfRed3ProngsCov, "AOD", "HFRED3PRONGSCOV", //! Table with 3prong candidate covariance for reduced workflow + o2::soa::Index<>, + HFTRACKPARCOV_COLUMNS, + o2::soa::Marker<2>); + +DECLARE_SOA_TABLE(HfRed3ProngsMl, "AOD", "HFRED3PRONGML", //! Table with 3prong candidate ML scores + hf_charm_cand_reduced::MlScoreBkg, + hf_charm_cand_reduced::MlScorePrompt, + hf_charm_cand_reduced::MlScoreNonprompt, + o2::soa::Marker<1>); + +// Beauty candidates prongs +namespace hf_cand_b0_reduced +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3Prongs, "_0"); //! Prong0 index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +} // namespace hf_cand_b0_reduced + +DECLARE_SOA_TABLE(HfRedB0Prongs, "AOD", "HFREDB0PRONG", + hf_cand_b0_reduced::Prong0Id, hf_cand_b0_reduced::Prong1Id); + +using HfRedCandB0 = soa::Join; + +namespace hf_cand_bplus_reduced +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed2Prongs, "_0"); //! Prong0 index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +} // namespace hf_cand_bplus_reduced + +DECLARE_SOA_TABLE(HfRedBplusProngs, "AOD", "HFREDBPPRONG", + hf_cand_bplus_reduced::Prong0Id, hf_cand_bplus_reduced::Prong1Id); + +using HfRedCandBplus = soa::Join; namespace hf_b0_mc { @@ -192,24 +242,21 @@ DECLARE_SOA_COLUMN(EtaProng1, etaProng1, float); //! Pseudorapidity of the track } // namespace hf_b0_mc // table with results of reconstruction level MC matching -DECLARE_SOA_TABLE(HfDPiMcRecReduced, "AOD", "HFDPIMCRECRED", //! Table with reconstructed MC information on DPi(<-B0) pairs for reduced workflow - hf_cand_b0::Prong0Id, - hf_track_index::Prong1Id, +DECLARE_SOA_TABLE(HfMcRecRedDpPis, "AOD", "HFMCRECREDDPPI", //! Table with reconstructed MC information on DPi(<-B0) pairs for reduced workflow + hf_cand_b0_reduced::Prong0Id, + hf_cand_b0_reduced::Prong1Id, hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::OriginMcRec, hf_cand_b0::DebugMcRec, hf_b0_mc::PtMother); // Table with same size as HFCANDB0 -DECLARE_SOA_TABLE(HfB0McRecReduced, "AOD", "HFB0MCRECRED", //! Reconstruction-level MC information on B0 candidates for reduced workflow +DECLARE_SOA_TABLE(HfMcRecRedB0s, "AOD", "HFMCRECREDB0", //! Reconstruction-level MC information on B0 candidates for reduced workflow hf_cand_b0::FlagMcMatchRec, - hf_cand_b0::OriginMcRec, hf_cand_b0::DebugMcRec, hf_b0_mc::PtMother); -DECLARE_SOA_TABLE(HfB0McGenReduced, "AOD", "HFB0MCGENRED", //! Generation-level MC information on B0 candidates for reduced workflow +DECLARE_SOA_TABLE(HfMcGenRedB0s, "AOD", "HFMCGENREDB0", //! Generation-level MC information on B0 candidates for reduced workflow hf_cand_b0::FlagMcMatchGen, - hf_cand_b0::OriginMcGen, hf_b0_mc::PtTrack, hf_b0_mc::YTrack, hf_b0_mc::EtaTrack, @@ -225,18 +272,74 @@ DECLARE_SOA_TABLE(HfB0McGenReduced, "AOD", "HFB0MCGENRED", //! Generation-level namespace hf_cand_b0_config { DECLARE_SOA_COLUMN(MySelectionFlagD, mySelectionFlagD, int8_t); //! Flag to filter selected D+ mesons +DECLARE_SOA_COLUMN(MyInvMassWindowDPi, myInvMassWindowDPi, float); //! Half-width of the B0 invariant-mass window in GeV/c2 } // namespace hf_cand_b0_config -DECLARE_SOA_TABLE(HfCandB0Config, "AOD", "HFCANDB0CONFIG", //! Table with configurables information for reduced workflow - hf_cand_b0_config::MySelectionFlagD); +DECLARE_SOA_TABLE(HfCandB0Configs, "AOD", "HFCANDB0CONFIG", //! Table with configurables information for reduced workflow + hf_cand_b0_config::MySelectionFlagD, + hf_cand_b0_config::MyInvMassWindowDPi); + +namespace hf_bplus_mc +{ +// MC Rec +DECLARE_SOA_COLUMN(PtMother, ptMother, float); //! Transverse momentum of the mother in GeV/c +// MC Gen +DECLARE_SOA_COLUMN(PtTrack, ptTrack, float); //! Transverse momentum of the track in GeV/c +DECLARE_SOA_COLUMN(YTrack, yTrack, float); //! Rapidity of the track +DECLARE_SOA_COLUMN(EtaTrack, etaTrack, float); //! Pseudorapidity of the track +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of the track's prong0 in GeV/c +DECLARE_SOA_COLUMN(YProng0, yProng0, float); //! Rapidity of the track's prong0 +DECLARE_SOA_COLUMN(EtaProng0, etaProng0, float); //! Pseudorapidity of the track's prong0 +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of the track's prong1 in GeV/c +DECLARE_SOA_COLUMN(YProng1, yProng1, float); //! Rapidity of the track's prong1 +DECLARE_SOA_COLUMN(EtaProng1, etaProng1, float); //! Pseudorapidity of the track's prong1 +} // namespace hf_bplus_mc + +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfMcRecRedD0Pis, "AOD", "HFMCRECREDD0PI", //! Table with reconstructed MC information on D0Pi(<-B+) pairs for reduced workflow + hf_cand_bplus_reduced::Prong0Id, + hf_cand_bplus_reduced::Prong1Id, + hf_cand_bplus::FlagMcMatchRec, + hf_bplus_mc::PtMother); + +// Table with same size as HFCANDBPLUS +DECLARE_SOA_TABLE(HfMcRecRedBps, "AOD", "HFMCRECREDBP", //! Reconstruction-level MC information on B+ candidates for reduced workflow + hf_cand_bplus::FlagMcMatchRec, + hf_bplus_mc::PtMother); + +DECLARE_SOA_TABLE(HfMcGenRedBps, "AOD", "HFMCGENREDBP", //! Generation-level MC information on B+ candidates for reduced workflow + hf_cand_bplus::FlagMcMatchGen, + hf_bplus_mc::PtTrack, + hf_bplus_mc::YTrack, + hf_bplus_mc::EtaTrack, + hf_bplus_mc::PtProng0, + hf_bplus_mc::YProng0, + hf_bplus_mc::EtaProng0, + hf_bplus_mc::PtProng1, + hf_bplus_mc::YProng1, + hf_bplus_mc::EtaProng1); + +// store all configurables values used in the first part of the workflow +// so we can use them in the Bplus part +namespace hf_cand_bplus_config +{ +DECLARE_SOA_COLUMN(MySelectionFlagD0, mySelectionFlagD0, int8_t); //! Flag to filter selected D0 mesons +DECLARE_SOA_COLUMN(MySelectionFlagD0bar, mySelectionFlagD0bar, int8_t); //! Flag to filter selected D0 mesons +DECLARE_SOA_COLUMN(MyInvMassWindowD0Pi, myInvMassWindowD0Pi, float); //! Half-width of the Bplus invariant-mass window in GeV/c2 +} // namespace hf_cand_bplus_config +DECLARE_SOA_TABLE(HfCandBpConfigs, "AOD", "HFCANDBPCONFIG", //! Table with configurables information for reduced workflow + hf_cand_bplus_config::MySelectionFlagD0, + hf_cand_bplus_config::MySelectionFlagD0bar, + hf_cand_bplus_config::MyInvMassWindowD0Pi); } // namespace aod namespace soa { -DECLARE_EQUIVALENT_FOR_INDEX(aod::HfCand3ProngBase, aod::HfCand3ProngReduced); -DECLARE_EQUIVALENT_FOR_INDEX(aod::StoredTracks, aod::HfTracksReduced); -DECLARE_EQUIVALENT_FOR_INDEX(aod::StoredTracks, aod::HfTracksPidReduced); +DECLARE_EQUIVALENT_FOR_INDEX(aod::HfCand2ProngBase, aod::HfRed2Prongs); +DECLARE_EQUIVALENT_FOR_INDEX(aod::HfCand3ProngBase, aod::HfRed3Prongs); +DECLARE_EQUIVALENT_FOR_INDEX(aod::StoredTracks, aod::HfRedTrackBases); +DECLARE_EQUIVALENT_FOR_INDEX(aod::Collisions, aod::HfRedCollisions); } // namespace soa } // namespace o2 #endif // PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.cxx b/PWGHF/D2H/Macros/HFInvMassFitter.cxx index af87ec560eb..9b1ac55cd31 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.cxx +++ b/PWGHF/D2H/Macros/HFInvMassFitter.cxx @@ -17,16 +17,17 @@ /// \author Xinye Peng /// \author Biao Zhang -#include "RooRealVar.h" -#include "RooDataSet.h" -#include "RooWorkspace.h" -#include "RooAddPdf.h" -#include "RooExtendPdf.h" -#include "RooPlot.h" -#include "RooHist.h" -#include "RooDataHist.h" #include "HFInvMassFitter.h" +#include +#include +#include +#include +#include +#include +#include +#include + using namespace RooFit; using namespace std; diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.h b/PWGHF/D2H/Macros/HFInvMassFitter.h index 8c2b077f2cd..6ac9357c5c2 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.h +++ b/PWGHF/D2H/Macros/HFInvMassFitter.h @@ -19,24 +19,23 @@ #ifndef PWGHF_D2H_MACROS_HFINVMASSFITTER_H_ #define PWGHF_D2H_MACROS_HFINVMASSFITTER_H_ -#include -#include -#include -#include -#include -#include -#include +#include // std::string + +#include #include -#include -#include #include +#include +#include #include -#include +#include +#include #include +#include +#include +#include using namespace RooFit; -using namespace std; class TF1; class TH1F; diff --git a/PWGHF/D2H/Macros/config_efficiency.yml b/PWGHF/D2H/Macros/config_efficiency.yml new file mode 100644 index 00000000000..d8f6af3cbfe --- /dev/null +++ b/PWGHF/D2H/Macros/config_efficiency.yml @@ -0,0 +1,37 @@ +input: + filename: /home/abigot/HFStudies/ML/training_samples/merged_signal_results.root + treename: hf-task-dplus/ + histoname: + reconstructed: + All: null # hPtRecSig + Prompt: hPtRecSigPrompt + Nonprompt: hPtRecSigNonPrompt + generated: + All: null #hPtVsYGen + Prompt: hPtVsYGenPrompt + Nonprompt: hPtVsYGenNonPrompt + +pt_bins_limits: null # options available: list of bin limits, null to deactivate + +rapidity: + axis: Y # rapidity axis in input histograms, options available: X, Y + cut: 0.5 # selection |y| < cut on the generated histogram, null if not cut + +output: + dir: efficiency/ + save: + TEfficiency: True # save TEfficiency instances in output .root file + TH1: True # save TH1 histograms in output .root file + TCanvas: # save TCanvas instances in extra files (on top of the standard output .root file) + individual: True # for individual canvas (All, Prompt, Nonprompt separately) + overlap: True # for overlap canvas (see overlap entry below) + extension: pdf, png # root not needed, all canvas are stored in .root file anyway + plots: + label: AccEffPreselDplusToPiKPi # label in output files (file names, .root entries) + y_axis: + name: "(Acc #times #varepsilon)" + min: 1.e-2 + max: 1. + log_scale: True + overlap: Prompt, Nonprompt # options available: All, Prompt, Nonprompt, null (if not overlap wanted) + watermark: "#color[619]{THIS WORK}" # watermark on top left of the plot's frame diff --git a/PWGHF/D2H/Macros/efficiency.py b/PWGHF/D2H/Macros/efficiency.py new file mode 100644 index 00000000000..0bb5fbb5faf --- /dev/null +++ b/PWGHF/D2H/Macros/efficiency.py @@ -0,0 +1,446 @@ +#!/usr/bin/env python3 + +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. + +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". + +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +""" +file: efficiency.py +brief: script for (acceptance-times-)efficiency computation +usage: python3 efficiency.py CONFIG +author: Alexandre Bigot , Strasbourg University +""" + +import argparse +import os +import sys +from typing import Dict, List, Optional, Union + +import numpy as np # pylint: disable=import-error +import yaml # pylint: disable=import-error + +# pylint: disable=import-error, no-name-in-module +from ROOT import ( + TH1, + TH1F, + TH2, + TCanvas, + TEfficiency, + TFile, + TLatex, + TLegend, + kAzure, + kBlack, + kFullCircle, + kFullSquare, + kOpenSquare, + kRed, +) +from style_formatter import set_global_style, set_object_style + +# options for object style +COLOR = {"All": kBlack, "Prompt": kRed + 1, "Nonprompt": kAzure + 4} +MARKERSTYLE = {"All": kFullSquare, "Prompt": kFullCircle, "Nonprompt": kOpenSquare} +LINEWIDTH = {"All": 1, "Prompt": 1, "Nonprompt": 2} + +LINESTYLE = {"All": 1, "Prompt": 2, "Nonprompt": 7} + + +def enforce_list(x: Union[str, List[str]]) -> List[str]: + """ + Helper method to enforce list type + + Parameters + ---------- + - x: a string or a list of string + + Returns + ---------- + - x_list if x was not a list, x itself otherwise + """ + + if not isinstance(x, list): + # handle possible whitespaces in config file entry + x_list = x.split(",") + for i, element in enumerate(x_list): + x_list[i] = element.strip() # remove possible whitespaces + return x_list + + return x + + +def enforce_trailing_slash(path: str) -> str: + """ + Helper method to enforce '/' at the and of directory name + + Parameters + ---------- + - path: some path + + Returns + ---------- + - path with a trailing slash at the end if it was not there yet + """ + + if path is not None and path[-1] != "/": + path += "/" + + return path + + +# pylint: disable=too-many-arguments +def configure_canvas( + name_canvas: str, + pt_min: Union[int, float], + y_axis_min: Union[int, float], + pt_max: Union[int, float], + y_axis_max: Union[int, float], + title: str, + log_y_axis: bool, +) -> TCanvas: + """ + Helper method to configure canvas + + Parameters + ---------- + - name_canvas: name of the canvas + - pt_min: lower limit of x axis + - y_axis_min: lower limit of y axis + - pt_max: upper limit of x axis + - y_axis_max: upper limit of y axis + - title: title of the canvas + - log_y_axis: switch for log scale along y axis + + Returns + ---------- + - c_eff: TCanvas instance + """ + + c_eff = TCanvas(name_canvas, "", 800, 800) + c_eff.DrawFrame(pt_min, y_axis_min, pt_max, y_axis_max, title) + if log_y_axis: + c_eff.SetLogy() + + return c_eff + + +def save_canvas(canvas: TCanvas, out_dir: str, name_file: str, extension: List[str]) -> None: + """ + Save canvas in formats chosen by extension + + Parameters + ---------- + - canvas: a TCanvas instance + - out_dir: output directory where canvas will be saved + - name_file: name of the output file + - extension: file format + """ + + for ext in extension: + canvas.SaveAs(out_dir + name_file + "." + ext) + + +def __set_object_style(obj: Union[TEfficiency, TH1], key: str) -> None: + """ + Helper method to set style of TEfficiency or TH1 object with local options + + Parameters + ---------- + - obj: TEfficiency or TH1 object + - key: key of options dictionary + """ + + set_object_style( + obj, color=COLOR[key], markerstyle=MARKERSTYLE[key], linewidth=LINEWIDTH[key], linestyle=LINESTYLE[key] + ) + + +def compute_efficiency( + h_rec: Union[TH1, TH2], + h_gen: Union[TH1, TH2], + axis_rapidity: str = "Y", + rapidity_cut: Optional[float] = None, + pt_bins_limits: Optional[np.ndarray] = None, +) -> TEfficiency: + """ + Helper method to compute the efficiency as function of the feature in axis. + + Parameters + ---------- + - h_rec: histogram with the reconstructed information + - h_gen: histogram with the generated information + - rapidity_cut: applies the selection |y| < y_cut to the efficiency + - axis_rapidity: histogram axis containting rapidity + + Returns + ---------- + - efficiency: a TEfficiency instance + """ + + epsilon = 0.0001 + + is_reco_2d, is_gen_2d = False, False + if h_rec.GetDimension() == 2: + is_reco_2d = True + if h_gen.GetDimension() == 2: + is_gen_2d = True + + if is_reco_2d: + if axis_rapidity == "Y": + h_rec = h_rec.ProjectionX() + else: + h_rec = h_rec.ProjectionY() + + if is_gen_2d: + if axis_rapidity == "Y": + if rapidity_cut is not None: + h_gen.GetYaxis().SetRangeUser(-1.0 * rapidity_cut + epsilon, rapidity_cut - epsilon) + h_gen = h_gen.ProjectionX() + else: + if rapidity_cut is not None: + h_gen.GetXaxis().SetRangeUser(-1.0 * rapidity_cut + epsilon, rapidity_cut - epsilon) + h_gen = h_gen.ProjectionY() + + # rebin histograms, if enabled + if pt_bins_limits is not None: + n_bins = pt_bins_limits.shape[0] - 1 + h_rec = h_rec.Rebin(n_bins, "hRec", pt_bins_limits) + h_gen = h_gen.Rebin(n_bins, "hGen", pt_bins_limits) + + efficiency = TEfficiency(h_rec, h_gen) + + return efficiency + + +def get_th1_from_tefficiency(teff: TEfficiency, h_eff: TH1) -> TH1: + """ + Helper method to convert TEfficiency object to TH1 + + Parameters + ---------- + - teff: TEfficiency instance + - h_eff: clone of histogram with reconstructed information + + Returns + ---------- + - h_eff: histogram containing teff information + """ + + n_bins = h_eff.GetXaxis().GetNbins() + for i_bin in range(1, n_bins + 1): + h_eff.SetBinContent(i_bin, teff.GetEfficiency(i_bin)) + if ( + abs(teff.GetEfficiencyErrorLow(i_bin) - teff.GetEfficiencyErrorUp(i_bin)) + / teff.GetEfficiencyErrorLow(i_bin) + > 1e-02 + ): + print( + f"\033[93mWARNING: efficiency error is asymmetric in bin {i_bin}," + " setting the maximum error in the histogram!\033[0m" + ) + # TH1 can't handle asymmetric errors so we take the max + err = max(teff.GetEfficiencyErrorLow(i_bin), teff.GetEfficiencyErrorUp(i_bin)) + else: + err = teff.GetEfficiencyErrorLow(i_bin) + + h_eff.SetBinError(i_bin, err) + + return h_eff + + +# pylint: disable=too-many-locals, too-many-branches, too-many-statements +def main(cfg: Dict, batch: bool) -> None: + """ + Main function + + Parameters + ----------------- + - config: dictionary with config read from a yaml file + - batch: bool to suppress video output + """ + + set_global_style(padleftmargin=0.14, padbottommargin=0.12, titlesize=0.045, labelsize=0.04) + + # input configuration + name_file = cfg["input"]["filename"] + name_tree = cfg["input"]["treename"] + file = TFile.Open(name_file) + name_tree = enforce_trailing_slash(name_tree) if name_tree is not None else "" + + # fill dictionaries with histograms + dic_rec: Dict[str, Optional[Union[TH1, TH2]]] = {} + dic_gen: Dict[str, Optional[Union[TH1, TH2]]] = {} + for key, histoname in cfg["input"]["histoname"]["reconstructed"].items(): + if histoname is None: + dic_rec[key] = None + else: + dic_rec[key] = file.Get(name_tree + histoname) + for key, histoname in cfg["input"]["histoname"]["generated"].items(): + if histoname is None: + dic_gen[key] = None + else: + dic_gen[key] = file.Get(name_tree + histoname) + + # configure pt binning + pt_bins_limits: Optional[np.ndarray] = None + pt_min, pt_max = 0.0, 36.0 # default values + is_retrieved_pt_interval = False + if cfg["pt_bins_limits"] is not None: + pt_bins_limits = np.array(enforce_list(cfg["pt_bins_limits"]), "d") + + if pt_bins_limits is not None: + pt_min = pt_bins_limits[0] + pt_max = pt_bins_limits[-1] + is_retrieved_pt_interval = True + + # configure possible cut on rapidity + rapidity_cut = cfg["rapidity"]["cut"] + axis_rapidity = cfg["rapidity"]["axis"] + + # output configuration + out_dir = enforce_trailing_slash(cfg["output"]["dir"]) + out_label = cfg["output"]["plots"]["label"] + name_axis = cfg["output"]["plots"]["y_axis"]["name"] + y_axis_min = cfg["output"]["plots"]["y_axis"]["min"] + y_axis_max = cfg["output"]["plots"]["y_axis"]["max"] + log_y_axis = cfg["output"]["plots"]["y_axis"]["log_scale"] + if name_axis is None: + name_axis = "#varepsilon" # default value + title = ";#it{p}_{T} (GeV/#it{c});" + name_axis + ";" + + overlap: Union[str, List[str]] = str() + if cfg["output"]["plots"]["overlap"] is not None: + overlap = enforce_list(cfg["output"]["plots"]["overlap"]) + + # output save options + save_tefficiency = cfg["output"]["save"]["TEfficiency"] + save_th1 = cfg["output"]["save"]["TH1"] + save_tcanvas_individual = cfg["output"]["save"]["TCanvas"]["individual"] + save_tcanvas_overlap = cfg["output"]["save"]["TCanvas"]["overlap"] + extension: List[str] = ["pdf"] # default value + if cfg["output"]["save"]["TCanvas"]["extension"] is None: + if save_tcanvas_individual or save_tcanvas_overlap: + print( + "\033[93mWARNING: No extension provided for saving canvas in extra file," + " '.pdf' set as default.\033[0m" + ) + else: + extension = enforce_list(cfg["output"]["save"]["TCanvas"]["extension"]) + + if os.path.isdir(out_dir): + print((f"\033[93mWARNING: Output directory '{out_dir}' already exists," " overwrites possibly ongoing!\033[0m")) + else: + os.makedirs(out_dir) + + # plots watermark configuration + latex = TLatex() + latex.SetNDC() + latex.SetTextSize(0.035) + latex.SetTextAlign(13) # align at top + latex.SetTextFont(42) + watermark = cfg["output"]["plots"]["watermark"] + + # open output file + out_file = TFile(out_dir + out_label + ".root", "recreate") + + # compute efficiencies + efficiencies = {} + for (key, h_rec), (_, h_gen) in zip(dic_rec.items(), dic_gen.items()): + if h_rec is not None and h_gen is not None: + # compute efficiency, store it in TEfficiency instance and configure it + efficiencies[key] = compute_efficiency(h_rec, h_gen, axis_rapidity, rapidity_cut, pt_bins_limits) + efficiencies[key].SetName("TEfficiency_" + out_label + key) + efficiencies[key].SetTitle(title) + __set_object_style(efficiencies[key], key) + + # save TEfficiency instance in output file, if enabled + if save_tefficiency: + efficiencies[key].Write() + + # retrieve pt_min and pt_max from imported histogram + if not is_retrieved_pt_interval: + pt_min, pt_max = h_rec.GetXaxis().GetXmin(), h_rec.GetXaxis().GetXmax() + is_retrieved_pt_interval = True + + # plot efficiency on canvas + c_eff = configure_canvas(f"c{out_label + key}", pt_min, y_axis_min, pt_max, y_axis_max, title, log_y_axis) + efficiencies[key].Draw("same") # to draw TEfficiency in TCanvas + latex.DrawLatex(0.18, 0.92, watermark) + c_eff.Write() + # save canvas in separate file, if enabled + if save_tcanvas_individual: + save_canvas(c_eff, out_dir, out_label + key, extension) + + # convert TEfficiency instance to TH1 histogram in output file, if save enabled + if save_th1: + if pt_bins_limits is not None: + h_eff = TH1F("h" + out_label + key, title, len(pt_bins_limits) - 1, pt_bins_limits) + h_eff = get_th1_from_tefficiency(efficiencies[key], h_eff) + else: + h_eff = get_th1_from_tefficiency(efficiencies[key], h_rec.Clone("h" + out_label + key)) + h_eff.SetTitle(title) + __set_object_style(h_eff, key) + h_eff.Write() + + elif h_rec != h_gen: # one histogram name is None, the other is not + print( + f"\033[91mERROR: efficiency for {key} could not be computed," + " one of the histogram names is None!\033[0m" + ) + sys.exit() + else: # both histogram names are None + efficiencies[key] = None + print(f"\033[94mEfficiency for {key} not computed.\033[0m") + + # overlap plots, if enabled + if overlap: + c_overlap = configure_canvas( + f"cOverlap{''.join(overlap)}", pt_min, y_axis_min, pt_max, y_axis_max, title, log_y_axis + ) + + leg = TLegend(0.6, 0.2, 0.8, 0.4) + leg.SetTextSize(0.045) + leg.SetFillStyle(0) + + for key, teff in efficiencies.items(): + if key in overlap: + if teff is None: + print(f"\033[91mERROR: efficiency for {key} could not be computed," " cannot overlap it!\033[0m") + sys.exit() + + leg.AddEntry(teff, key, "p") + teff.Draw("same") + + leg.Draw() + latex.DrawLatex(0.18, 0.92, watermark) + + if save_tcanvas_overlap: + save_canvas(c_overlap, out_dir, out_label + "Overlap", extension) + c_overlap.Write() + + # close output file + out_file.Close() + + if not batch: + input("Press enter to exit") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Arguments") + parser.add_argument("config", metavar="text", default="config.yml", help="config file name for ml") + parser.add_argument("--batch", help="suppress video output", action="store_true") + args = parser.parse_args() + + print("Loading analysis configuration: ...", end="\r") + with open(args.config, "r", encoding="utf-8") as yml_cfg: + configuration = yaml.load(yml_cfg, yaml.FullLoader) + print("Loading analysis configuration: Done!") + + main(configuration, args.batch) diff --git a/PWGHF/D2H/Macros/runMassFitter.C b/PWGHF/D2H/Macros/runMassFitter.C index 65abd0ad2dd..0c4c44f9ff7 100644 --- a/PWGHF/D2H/Macros/runMassFitter.C +++ b/PWGHF/D2H/Macros/runMassFitter.C @@ -19,13 +19,14 @@ #if !defined(__CINT__) || defined(__CLING__) -#include -#include -#include - #include "HFInvMassFitter.h" -#include "Riostream.h" -#include "TROOT.h" + +#include // std::cout +#include // std::string +#include // std::vector + +#include +#include // if .h file not found, please include your local rapidjson/document.h and rapidjson/filereadstream.h here #include @@ -539,7 +540,7 @@ int runMassFitter(TString configFileName) hRawYieldsSignificance->SetBinContent(iPt + 1, significance); hRawYieldsSignificance->SetBinError(iPt + 1, significanceErr); hRawYieldsSgnOverBkg->SetBinContent(iPt + 1, rawYield / bkg); - hRawYieldsSgnOverBkg->SetBinError(iPt + 1, rawYield / bkg * TMath::Sqrt(rawYieldErr / rawYield * rawYieldErr / rawYield + bkgErr / bkg * bkgErr / bkg)); + hRawYieldsSgnOverBkg->SetBinError(iPt + 1, rawYield / bkg * std::sqrt(rawYieldErr / rawYield * rawYieldErr / rawYield + bkgErr / bkg * bkgErr / bkg)); hRawYieldsSignal->SetBinContent(iPt + 1, rawYield); hRawYieldsSignal->SetBinError(iPt + 1, rawYieldErr); hRawYieldsBkg->SetBinContent(iPt + 1, bkg); diff --git a/PWGHF/D2H/TableProducer/CMakeLists.txt b/PWGHF/D2H/TableProducer/CMakeLists.txt index 077b565e56e..8c29bb72154 100644 --- a/PWGHF/D2H/TableProducer/CMakeLists.txt +++ b/PWGHF/D2H/TableProducer/CMakeLists.txt @@ -13,19 +13,34 @@ o2physics_add_dpl_workflow(candidate-creator-b0-reduced SOURCES candidateCreatorB0Reduced.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(candidate-creator-bplus-reduced + SOURCES candidateCreatorBplusReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) # Candidate selectors o2physics_add_dpl_workflow(candidate-selector-b0-to-d-pi-reduced SOURCES candidateSelectorB0ToDPiReduced.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(candidate-selector-bplus-to-d0-pi-reduced + SOURCES candidateSelectorBplusToD0PiReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) # Data creators +o2physics_add_dpl_workflow(data-creator-d0-pi-reduced + SOURCES dataCreatorD0PiReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(data-creator-dplus-pi-reduced SOURCES dataCreatorDplusPiReduced.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) diff --git a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx index cdba14e5006..963dda509ec 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -14,13 +14,13 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -34,6 +34,7 @@ using namespace o2::framework::expressions; /// Reconstruction of B0 candidates struct HfCandidateCreatorB0Reduced { Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in ReducedDataModel.h // vertexing Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; @@ -44,19 +45,20 @@ struct HfCandidateCreatorB0Reduced { Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B0 is smaller than this"}; Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; // selection - Configurable invMassWindowB0{"invMassWindowB0", 0.3, "invariant-mass window for B0 candidates"}; + Configurable invMassWindowDPiTolerance{"invMassWindowDPiTolerance", 0.01, "invariant-mass window tolerance for DPi pair preselections (GeV/c2)"}; + // variable that will store the value of invMassWindowDPi (defined in dataCreatorDplusPiReduced.cxx) + float myInvMassWindowDPi{1.}; - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massD = RecoDecay::getMassPDG(pdg::Code::kDMinus); - double massB0 = RecoDecay::getMassPDG(pdg::Code::kB0); - double massDPi{0.}; + double massPi{0.}; + double massD{0.}; + double massB0{0.}; double bz{0.}; // Fitter for B vertex (2-prong vertex filter) o2::vertexing::DCAFitterN<2> df2; - Preslice candsDPerCollision = hf_track_index_reduced::hfReducedCollisionId; - Preslice tracksPionPerCollision = hf_track_index_reduced::hfReducedCollisionId; + Preslice> candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> tracksPionPerCollision = hf_track_index_reduced::hfRedCollisionId; HistogramRegistry registry{"registry"}; @@ -68,6 +70,11 @@ struct HfCandidateCreatorB0Reduced { registry.add("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 0.2}}}); registry.add("hEvents", "Events;;entries", HistType::kTH1F, {{1, 0.5, 1.5}}); + // invariant-mass window cut + massPi = o2::analysis::pdg::MassPiPlus; + massD = o2::analysis::pdg::MassDMinus; + massB0 = o2::analysis::pdg::MassB0; + // Initialize fitter df2.setPropagateToPCA(propagateToPCA); df2.setMaxR(maxR); @@ -78,11 +85,21 @@ struct HfCandidateCreatorB0Reduced { df2.setWeightedFinalPCA(useWeightedFinalPCA); } - void process(aod::HfReducedCollisions const& collisions, - aod::HfCand3ProngReduced const& candsD, - aod::HfTracksReduced const& tracksPion, - aod::HfOriginalCollisionsCounter const& collisionsCounter) + void process(aod::HfRedCollisions const& collisions, + soa::Join const& candsD, + soa::Join const& tracksPion, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCandB0Configs const& configs) { + // DPi invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowDPi = config.myInvMassWindowDPi(); + } + // invMassWindowDPiTolerance is used to apply a slightly tighter cut than in DPi pair preselection + // to avoid accepting DPi pairs that were not formed in DPi pair creator + double invMass2DPiMin = (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance) * (massB0 - myInvMassWindowDPi + invMassWindowDPiTolerance); + double invMass2DPiMax = (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance) * (massB0 + myInvMassWindowDPi - invMassWindowDPiTolerance); + for (const auto& collisionCounter : collisionsCounter) { registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); } @@ -110,9 +127,19 @@ struct HfCandidateCreatorB0Reduced { auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); for (const auto& trackPion : tracksPionThisCollision) { + // this track is among daughters + if (trackPion.trackId() == candD.prong0Id() || trackPion.trackId() == candD.prong1Id() || trackPion.trackId() == candD.prong2Id()) { + continue; + } + auto trackParCovPi = getTrackParCov(trackPion); std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; + // compute invariant mass square and apply selection + auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{massD, massPi}); + if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { + continue; + } // --------------------------------- // reconstruct the 2-prong B0 vertex if (df2.process(trackParCovD, trackParCovPi) == 0) { @@ -133,13 +160,7 @@ struct HfCandidateCreatorB0Reduced { df2.getTrack(0).getPxPyPzGlo(pVecD); // momentum of D at the B0 vertex df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the B0 vertex - // compute invariant - massDPi = RecoDecay::m(array{pVecD, pVecPion}, array{massD, massPi}); - - if (std::abs(massDPi - massB0) > invMassWindowB0) { - continue; - } - registry.fill(HIST("hMassB0ToDPi"), massDPi); + registry.fill(HIST("hMassB0ToDPi"), std::sqrt(invMass2DPi)); // compute impact parameters of D and Pi o2::dataformats::DCA dcaD; @@ -150,7 +171,7 @@ struct HfCandidateCreatorB0Reduced { // get uncertainty of the decay length double phi, theta; // getPointDirection modifies phi and theta - getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB0, phi, theta); + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB0, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); @@ -166,8 +187,9 @@ struct HfCandidateCreatorB0Reduced { pVecPion[0], pVecPion[1], pVecPion[2], dcaD.getY(), dcaPion.getY(), std::sqrt(dcaD.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2()), - candD.globalIndex(), trackPion.globalIndex(), hfFlag); + + rowCandidateProngs(candD.globalIndex(), trackPion.globalIndex()); } // pi loop } // D loop } // collision loop @@ -177,16 +199,17 @@ struct HfCandidateCreatorB0Reduced { /// Extends the table base with expression columns and performs MC matching. struct HfCandidateCreatorB0ReducedExpressions { Spawns rowCandidateB0; - Produces rowB0McRec; + Spawns rowTracksExt; + Produces rowB0McRec; - void processMc(HfDPiMcRecReduced const& rowsDPiMcRec) + void processMc(HfMcRecRedDpPis const& rowsDPiMcRec, HfRedB0Prongs const& candsB0) { - for (const auto& candB0 : *rowCandidateB0) { + for (const auto& candB0 : candsB0) { for (const auto& rowDPiMcRec : rowsDPiMcRec) { if ((rowDPiMcRec.prong0Id() != candB0.prong0Id()) || (rowDPiMcRec.prong1Id() != candB0.prong1Id())) { continue; } - rowB0McRec(rowDPiMcRec.flagMcMatchRec(), rowDPiMcRec.originMcRec(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); + rowB0McRec(rowDPiMcRec.flagMcMatchRec(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); } } } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx new file mode 100644 index 00000000000..41161236b64 --- /dev/null +++ b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx @@ -0,0 +1,219 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file candidateCreatorBplusReduced.cxx +/// \brief Reconstruction of B+ candidates +/// +/// \author Antonio Palasciano , Università degli Studi di Bari + +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/V0.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// Reconstruction of B+ candidates +struct HfCandidateCreatorBplusReduced { + Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in ReducedDataModel.h + + // vertexing + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; + Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B+ is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + // selection + Configurable invMassWindowD0PiTolerance{"invMassWindowD0PiTolerance", 0.01, "invariant-mass window tolerance for D0Pi pair preselections (GeV/c2)"}; + // variable that will store the value of invMassWindowD0Pi (defined in dataCreatorD0PiReduced.cxx) + float myInvMassWindowD0Pi{1.}; + + double massPi{0.}; + double massD0{0.}; + double massBplus{0.}; + double bz{0.}; + + // Fitter for B vertex (2-prong vertex filter) + o2::vertexing::DCAFitterN<2> df2; + + Preslice> candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> tracksPionPerCollision = hf_track_index_reduced::hfRedCollisionId; + + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + // histograms + registry.add("hMassBplusToD0Pi", "2-prong candidates;inv. mass (B^{+} #rightarrow #overline{D^{0}}#pi^{#plus} #rightarrow #pi^{#minus}K^{#plus}#pi^{#plus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 3., 8.}}}); + registry.add("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); + registry.add("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 0.2}}}); + registry.add("hEvents", "Events;;entries", HistType::kTH1F, {{1, 0.5, 1.5}}); + + // Initialize fitter + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + + // invariant-mass window cut + massPi = o2::analysis::pdg::MassPiPlus; + massD0 = o2::analysis::pdg::MassD0; + massBplus = o2::analysis::pdg::MassBPlus; + } + + void process(aod::HfRedCollisions const& collisions, + soa::Join const& candsD, + soa::Join const& tracksPion, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCandBpConfigs const& configs) + { + // D0Pi invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowD0Pi = config.myInvMassWindowD0Pi(); + } + // invMassWindowD0PiTolerance is used to apply a slightly tighter cut than in D0Pi pair preselection + // to avoid accepting D0Pi pairs that were not formed in D0Pi pair creator + double invMass2D0PiMin = (massBplus - myInvMassWindowD0Pi + invMassWindowD0PiTolerance) * (massBplus - myInvMassWindowD0Pi + invMassWindowD0PiTolerance); + double invMass2D0PiMax = (massBplus + myInvMassWindowD0Pi - invMassWindowD0PiTolerance) * (massBplus + myInvMassWindowD0Pi - invMassWindowD0PiTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + static int ncol = 0; + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + + if (ncol % 10000 == 0) { + LOG(debug) << ncol << " collisions parsed"; + } + ncol++; + + // Set the magnetic field from ccdb + bz = collision.bz(); + df2.setBz(bz); + + auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); + for (const auto& candD0 : candsDThisColl) { + auto trackParCovD = getTrackParCov(candD0); + std::array pVecD0 = {candD0.px(), candD0.py(), candD0.pz()}; + + auto tracksPionThisCollision = tracksPion.sliceBy(tracksPionPerCollision, thisCollId); + for (const auto& trackPion : tracksPionThisCollision) { + auto trackParCovPi = getTrackParCov(trackPion); + std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; + + // compute invariant mass square and apply selection + auto invMass2D0Pi = RecoDecay::m2(std::array{pVecD0, pVecPion}, std::array{massD0, massPi}); + if ((invMass2D0Pi < invMass2D0PiMin) || (invMass2D0Pi > invMass2D0PiMax)) { + continue; + } + // --------------------------------- + // reconstruct the 2-prong B+ vertex + if (df2.process(trackParCovD, trackParCovPi) == 0) { + continue; + } + // D0Pi passed B+ reconstruction + + // calculate relevant properties + const auto& secondaryVertexBplus = df2.getPCACandidate(); + auto chi2PCA = df2.getChi2AtPCACandidate(); + auto covMatrixPCA = df2.calcPCACovMatrixFlat(); + registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + + // propagate D0 and Pi to the B+ vertex + df2.propagateTracksToVertex(); + // track.getPxPyPzGlo(pVec) modifies pVec of track + df2.getTrack(0).getPxPyPzGlo(pVecD0); // momentum of D0 at the B+ vertex + df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the B+ vertex + + registry.fill(HIST("hMassBplusToD0Pi"), std::sqrt(invMass2D0Pi)); + + // compute impact parameters of D0 and Pi + o2::dataformats::DCA dcaD0; + o2::dataformats::DCA dcaPion; + trackParCovD.propagateToDCA(primaryVertex, bz, &dcaD0); + trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); + + // get uncertainty of the decay length + double phi, theta; + // getPointDirection modifies phi and theta + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexBplus, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + int hfFlag = BIT(hf_cand_bplus::DecayType::BplusToD0Pi); + + // fill the candidate table for the B+ here: + rowCandidateBase(thisCollId, + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexBplus[0], secondaryVertexBplus[1], secondaryVertexBplus[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecD0[0], pVecD0[1], pVecD0[2], + pVecPion[0], pVecPion[1], pVecPion[2], + dcaD0.getY(), dcaPion.getY(), + std::sqrt(dcaD0.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2()), + hfFlag); + + rowCandidateProngs(candD0.globalIndex(), trackPion.globalIndex()); + } // pi loop + } // D0 loop + } // collision loop + } // process +}; // struct + +/// Extends the table base with expression columns and performs MC matching. +struct HfCandidateCreatorBplusReducedExpressions { + Spawns rowCandidateBPlus; + Spawns rowTracksExt; + Produces rowBplusMcRec; + + void processMc(HfMcRecRedD0Pis const& rowsD0PiMcRec, HfRedBplusProngs const& candsBplus) + { + for (const auto& candBplus : candsBplus) { + for (const auto& rowD0PiMcRec : rowsD0PiMcRec) { + if ((rowD0PiMcRec.prong0Id() != candBplus.prong0Id()) || (rowD0PiMcRec.prong1Id() != candBplus.prong1Id())) { + continue; + } + rowBplusMcRec(rowD0PiMcRec.flagMcMatchRec(), rowD0PiMcRec.ptMother()); + } + } + } + PROCESS_SWITCH(HfCandidateCreatorBplusReducedExpressions, processMc, "Process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index d49aecd2a51..4b88fcdaa98 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -14,10 +14,12 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -26,9 +28,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand_b0; // from CandidateReconstructionTables.h using namespace o2::analysis; -using namespace o2::analysis::hf_cuts_b0_to_d_pi; // from SelectorCuts.h struct HfCandidateSelectorB0ToDPiReduced { Produces hfSelB0ToDPiCandidate; // table defined in CandidateSelectionTables.h @@ -37,7 +37,7 @@ struct HfCandidateSelectorB0ToDPiReduced { Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; // Enable PID Configurable usePid{"usePid", true, "Switch for PID selection at track level"}; - Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::PIDNotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; // TPC PID Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; @@ -50,28 +50,31 @@ struct HfCandidateSelectorB0ToDPiReduced { Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_b0_to_d_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_b0_to_d_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "B0 candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_b0_to_d_pi::cuts[0], hf_cuts_b0_to_d_pi::nBinsPt, hf_cuts_b0_to_d_pi::nCutVars, hf_cuts_b0_to_d_pi::labelsPt, hf_cuts_b0_to_d_pi::labelsCutVar}, "B0 candidate selection per pT bin"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + // check if selectionFlagD (defined in dataCreatorDplusPiReduced.cxx) and usePid configurables are in sync bool selectionFlagDAndUsePidInSync = true; // variable that will store the value of selectionFlagD (defined in dataCreatorDplusPiReduced.cxx) int mySelectionFlagD = -1; - TrackSelectorPID selectorPion; + HfHelper hfHelper; + TrackSelectorPi selectorPion; HistogramRegistry registry{"registry"}; + using TracksPion = soa::Join; + void init(InitContext const& initContext) { if (usePid) { - selectorPion.setPDG(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); } if (activateQA) { @@ -89,9 +92,9 @@ struct HfCandidateSelectorB0ToDPiReduced { } } - void process(HfCandB0 const& hfCandsB0, - HfTracksPidReduced const&, - HfCandB0Config const& configs) + void process(HfRedCandB0 const& hfCandsB0, + TracksPion const&, + HfCandB0Configs const& configs) { // get DplusPi creator configurable for (const auto& config : configs) { @@ -126,7 +129,7 @@ struct HfCandidateSelectorB0ToDPiReduced { } // topological cuts - if (!hf_sel_candidate_b0::selectionTopol(hfCandB0, cuts, binsPt)) { + if (!hfHelper.selectionB0ToDPiTopol(hfCandB0, cuts, binsPt)) { hfSelB0ToDPiCandidate(statusB0ToDPi); // LOGF(info, "B0 candidate selection failed at topology selection"); continue; @@ -143,9 +146,9 @@ struct HfCandidateSelectorB0ToDPiReduced { } // track-level PID selection if (usePid) { - auto trackPi = hfCandB0.prong1_as(); - int pidTrackPi = selectorPion.getStatusTrackPIDTpcAndTof(trackPi); - if (!hf_sel_candidate_b0::selectionPID(pidTrackPi, acceptPIDNotApplicable.value)) { + auto trackPi = hfCandB0.prong1_as(); + int pidTrackPi = selectorPion.statusTpcAndTof(trackPi); + if (!hfHelper.selectionB0ToDPiPid(pidTrackPi, acceptPIDNotApplicable.value)) { // LOGF(info, "B0 candidate selection failed at PID selection"); hfSelB0ToDPiCandidate(statusB0ToDPi); continue; diff --git a/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx new file mode 100644 index 00000000000..7f986259452 --- /dev/null +++ b/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx @@ -0,0 +1,171 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file candidateSelectorBplusToD0PiReduced.cxx +/// \brief B+ → D0bar π+ candidate selector +/// +/// \author Antonio Palasciano , Università degli Studi di Bari + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::analysis; + +struct HfCandidateSelectorBplusToD0PiReduced { + Produces hfSelBplusToD0PiCandidate; // table defined in CandidateSelectionTables.h + + Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; + Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; + // Enable PID + Configurable usePid{"usePid", true, "Switch for PID selection at track level"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + // topological cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_bplus_to_d0_pi::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_bplus_to_d0_pi::cuts[0], hf_cuts_bplus_to_d0_pi::nBinsPt, hf_cuts_bplus_to_d0_pi::nCutVars, hf_cuts_bplus_to_d0_pi::labelsPt, hf_cuts_bplus_to_d0_pi::labelsCutVar}, "B+ candidate selection per pT bin"}; + // QA switch + Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + + bool selectionFlagDAndUsePidInSync = true; + // variable that will store the value of selectionFlagD (defined in dataCreatorD0PiReduced.cxx) + int mySelectionFlagD0 = -1; + int mySelectionFlagD0bar = -1; + + HfHelper hfHelper; + TrackSelectorPi selectorPion; + + HistogramRegistry registry{"registry"}; + + using TracksPion = soa::Join; + + void init(InitContext const& initContext) + { + if (usePid) { + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + } + + if (activateQA) { + constexpr int kNBinsSelections = 1 + SelectionStep::NSelectionSteps; + std::string labels[kNBinsSelections]; + labels[0] = "No selection"; + labels[1 + SelectionStep::RecoSkims] = "Skims selection"; + labels[1 + SelectionStep::RecoTopol] = "Skims & Topological selections"; + labels[1 + SelectionStep::RecoPID] = "Skims & Topological & PID selections"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { + registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + } + } + + void process(HfRedCandBplus const& hfCandBs, + TracksPion const&, + HfCandBpConfigs const& configs) + { + // get DplusPi creator configurable + for (const auto& config : configs) { + mySelectionFlagD0 = config.mySelectionFlagD0(); + mySelectionFlagD0bar = config.mySelectionFlagD0bar(); + + if ((usePid && !mySelectionFlagD0) || (usePid && !mySelectionFlagD0bar)) { + selectionFlagDAndUsePidInSync = false; + LOG(warning) << "PID selections required on B+ daughters (usePid=true) but no PID selections on D candidates were required a priori."; + } + if ((!usePid && mySelectionFlagD0) || (!usePid && mySelectionFlagD0bar)) { + selectionFlagDAndUsePidInSync = false; + LOG(warning) << "No PID selections required on Bp daughters (usePid=false) but PID selections on D candidates were required a priori."; + } + } + + for (const auto& hfCandBp : hfCandBs) { + int statusBplus = 0; + auto ptCandBplus = hfCandBp.pt(); + + // check if flagged as B+ → D π + if (!TESTBIT(hfCandBp.hfflag(), hf_cand_bplus::DecayType::BplusToD0Pi)) { + hfSelBplusToD0PiCandidate(statusBplus); + if (activateQA) { + registry.fill(HIST("hSelections"), 1, ptCandBplus); + } + // LOGF(info, "B+ candidate selection failed at hfflag check"); + continue; + } + SETBIT(statusBplus, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusBplus = 1 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoSkims, ptCandBplus); + } + + // topological cuts + if (!hfHelper.selectionBplusToD0PiTopol(hfCandBp, cuts, binsPt)) { + hfSelBplusToD0PiCandidate(statusBplus); + // LOGF(info, "B+ candidate selection failed at topology selection"); + continue; + } + SETBIT(statusBplus, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusBplus = 3 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandBplus); + } + + // checking if selectionFlagD and usePid are in sync + if (!selectionFlagDAndUsePidInSync) { + hfSelBplusToD0PiCandidate(statusBplus); + continue; + } + // track-level PID selection + if (usePid) { + auto trackPi = hfCandBp.prong1_as(); + int pidTrackPi = selectorPion.statusTpcAndTof(trackPi); + if (!hfHelper.selectionBplusToD0PiPid(pidTrackPi, acceptPIDNotApplicable.value)) { + // LOGF(info, "B+ candidate selection failed at PID selection"); + hfSelBplusToD0PiCandidate(statusBplus); + continue; + } + SETBIT(statusBplus, SelectionStep::RecoPID); // RecoPID = 2 --> statusBplus = 7 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoPID, ptCandBplus); + } + } + hfSelBplusToD0PiCandidate(statusBplus); + // LOGF(info, "B+ candidate selection passed all selections"); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/TableProducer/dataCreatorD0PiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorD0PiReduced.cxx new file mode 100644 index 00000000000..64d51116fed --- /dev/null +++ b/PWGHF/D2H/TableProducer/dataCreatorD0PiReduced.cxx @@ -0,0 +1,548 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file dataCreatorD0PiReduced.cxx +/// \brief Creation of D0-Pi pairs +/// +/// \author Antonio Palasciano , Università degli Studi di Bari +/// \author Fabrizio Grosa , CERN + +#include + +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/V0.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +using namespace o2; +using namespace o2::analysis; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// event types +enum Event : uint8_t { + Processed = 0, + NoD0PiSelected, + D0PiSelected, + kNEvent +}; + +/// Creation of D0-Pi pairs +struct HfDataCreatorD0PiReduced { + // Produces AOD tables to store track information + Produces hfReducedCollision; + Produces hfCollisionCounter; + Produces hfTrackPion; + Produces hfTrackCovPion; + Produces hfTrackPidPion; + Produces hfCand2Prong; + Produces hfCand2ProngCov; + Produces hfCand2ProngMl; + Produces rowCandidateConfig; + Produces rowHfD0PiMcRecReduced; + Produces rowHfBpMcGenReduced; + + // vertexing + // Configurable bz{"bz", 5., "magnetic field"}; + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; + Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B+ is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + // selection + Configurable usePionIsGlobalTrackWoDCA{"usePionIsGlobalTrackWoDCA", true, "check isGlobalTrackWoDCA status for pions, for Run3 studies"}; + Configurable ptPionMin{"ptPionMin", 0.5, "minimum pion pT threshold (GeV/c)"}; + Configurable> binsPtPion{"binsPtPion", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for pion DCA XY pT-dependent cut"}; + Configurable> cutsTrackPionDCA{"cutsTrackPionDCA", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for pions"}; + Configurable invMassWindowD0Pi{"invMassWindowD0Pi", 0.3, "invariant-mass window for D0Pi pair preselections (GeV/c2)"}; + Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; + Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; + // magnetic field setting from CCDB + Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; + Configurable ccdbPathGeo{"ccdbPathGeo", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + + HfHelper hfHelper; + + // CCDB service + Service ccdb; + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + int runNumber; + + // O2DatabasePDG service + Service pdg; + + double massPi{0.}; + double massD0{0.}; + double massBplus{0.}; + double invMass2D0PiMin{0.}; + double invMass2D0PiMax{0.}; + double bz{0.}; + + bool isHfCandBplusConfigFilled = false; + + // Fitter to redo D0-vertex to get extrapolated daughter tracks (2-prong vertex filter) + o2::vertexing::DCAFitterN<2> df2; + + using TracksPidAll = soa::Join; + using TracksPIDWithSel = soa::Join; + using TracksPIDWithSelAndMc = soa::Join; + using CandsDFiltered = soa::Filtered>; + using CandsDFilteredWithMl = soa::Filtered>; + + Filter filterSelectCandidates = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar); + + Preslice candsDPerCollision = aod::track_association::collisionId; + Preslice candsDPerCollisionWithMl = aod::track_association::collisionId; + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + // histograms + constexpr int kNBinsEvents = kNEvent; + std::string labels[kNBinsEvents]; + labels[Event::Processed] = "processed"; + labels[Event::NoD0PiSelected] = "without D0Pi pairs"; + labels[Event::D0PiSelected] = "with D0Pi pairs"; + static const AxisSpec axisEvents = {kNBinsEvents, 0.5, kNBinsEvents + 0.5, ""}; + registry.add("hEvents", "Events;;entries", HistType::kTH1F, {axisEvents}); + for (int iBin = 0; iBin < kNBinsEvents; iBin++) { + registry.get(HIST("hEvents"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + + registry.add("hMassD0ToKPi", "D^{0}} candidates;inv. mass (K^{#minus} #pi^{#plus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); + registry.add("hPtD0", "D^{0} candidates;D^{0} candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add("hPtPion", "#pi^{#plus} candidates;#pi^{#plus} candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add("hCPAD0", "D^{0} candidates;D^{0} cosine of pointing angle;entries", {HistType::kTH1F, {{110, -1.1, 1.1}}}); + + // Initialize fitter + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + + // Configure CCDB access + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); + runNumber = 0; + + // invariant-mass window cut + massPi = o2::analysis::pdg::MassPiPlus; + massD0 = o2::analysis::pdg::MassD0; + massBplus = o2::analysis::pdg::MassBPlus; + invMass2D0PiMin = (massBplus - invMassWindowD0Pi) * (massBplus - invMassWindowD0Pi); + invMass2D0PiMax = (massBplus + invMassWindowD0Pi) * (massBplus + invMassWindowD0Pi); + } + + /// Pion selection (D0 Pi <-- B+) + /// \param trackPion is a track with the pion hypothesis + /// \param track0 is prong0 of selected D0 candidate + /// \param track1 is prong1 of selected D0 candidate + /// \param candD0 is the D0 candidate + /// \return true if trackPion passes all cuts + template + bool isPionSelected(const T1& trackPion, const T2& track0, const T2& track1, const T3& candD0) + { + // check isGlobalTrackWoDCA status for pions if wanted + if (usePionIsGlobalTrackWoDCA && !trackPion.isGlobalTrackWoDCA()) { + return false; + } + // minimum pT selection + if (trackPion.pt() < ptPionMin || !isSelectedTrackDCA(trackPion)) { + return false; + } + // reject pion not compatible with D0/D0bar hypothesis + if (!((candD0.isSelD0() >= selectionFlagD0 && trackPion.sign() < 0) || (candD0.isSelD0bar() >= selectionFlagD0bar && trackPion.sign() > 0))) { + // LOGF(debug, "D0: %d, D0bar%d, sign: %d", candD0.isSelD0(), candD0.isSelD0bar(), track.sign()); + return false; + } + // reject pions that are D daughters + if (trackPion.globalIndex() == track0.globalIndex() || trackPion.globalIndex() == track1.globalIndex()) { + return false; + } + + return true; + } + + /// Single-track cuts for pions on dcaXY + /// \param track is a track + /// \return true if track passes all cuts + template + bool isSelectedTrackDCA(const T& track) + { + auto pTBinTrack = findBin(binsPtPion, track.pt()); + if (pTBinTrack == -1) { + return false; + } + + if (std::abs(track.dcaXY()) < cutsTrackPionDCA->get(pTBinTrack, "min_dcaxytoprimary")) { + return false; // minimum DCAxy + } + if (std::abs(track.dcaXY()) > cutsTrackPionDCA->get(pTBinTrack, "max_dcaxytoprimary")) { + return false; // maximum DCAxy + } + return true; + } + + template + void runDataCreation(aod::Collision const& collision, + C const& candsD0, + aod::TrackAssoc const& trackIndices, + T const& tracks, + P const& particlesMc, + aod::BCsWithTimestamps const& bcs) + { + // helpers for ReducedTables filling + int indexHfReducedCollision = hfReducedCollision.lastIndex() + 1; + // std::map where the key is the track.globalIndex() and + // the value is the track index in the table of the selected pions + std::map selectedTracksPion; + bool fillHfReducedCollision = false; + + auto primaryVertex = getPrimaryVertex(collision); + + // Set the magnetic field from ccdb. + // The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, + // but this is not true when running on Run2 data/MC already converted into AO2Ds. + auto bc = collision.bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + } + df2.setBz(bz); + + auto thisCollId = collision.globalIndex(); + for (const auto& candD0 : candsD0) { + int indexHfCand2Prong = hfCand2Prong.lastIndex() + 1; + bool fillHfCand2Prong = false; + float invMassD0{-1.f}, invMassD0bar{-1.f}; + + if (candD0.isSelD0() >= selectionFlagD0) { + invMassD0 = hfHelper.invMassD0ToPiK(candD0); + registry.fill(HIST("hMassD0ToKPi"), invMassD0); + } + if (candD0.isSelD0bar() >= selectionFlagD0bar) { + invMassD0bar = hfHelper.invMassD0barToKPi(candD0); + registry.fill(HIST("hMassD0ToKPi"), invMassD0bar); + } + registry.fill(HIST("hPtD0"), candD0.pt()); + registry.fill(HIST("hCPAD0"), candD0.cpa()); + + auto track0 = candD0.template prong0_as(); + auto track1 = candD0.template prong1_as(); + auto trackParCov0 = getTrackParCov(track0); + auto trackParCov1 = getTrackParCov(track1); + + std::array pVec0 = {track0.px(), track0.py(), track0.pz()}; + std::array pVec1 = {track1.px(), track1.py(), track1.pz()}; + + auto dca0 = o2::dataformats::DCA(track0.dcaXY(), track0.dcaZ(), track0.cYY(), track0.cZY(), track0.cZZ()); + auto dca1 = o2::dataformats::DCA(track1.dcaXY(), track1.dcaZ(), track1.cYY(), track1.cZY(), track1.cZZ()); + + // repropagate tracks to this collision if needed + if (track0.collisionId() != thisCollId) { + trackParCov0.propagateToDCA(primaryVertex, bz, &dca0); + } + + if (track1.collisionId() != thisCollId) { + trackParCov1.propagateToDCA(primaryVertex, bz, &dca1); + } + + // --------------------------------- + // reconstruct 2-prong secondary vertex (D0) + if (df2.process(trackParCov0, trackParCov1) == 0) { + continue; + } + + const auto& secondaryVertexD0 = df2.getPCACandidate(); + // propagate the 2 prongs to the secondary vertex + trackParCov0.propagateTo(secondaryVertexD0[0], bz); + trackParCov1.propagateTo(secondaryVertexD0[0], bz); + + // update pVec of tracks + df2.getTrack(0).getPxPyPzGlo(pVec0); + df2.getTrack(1).getPxPyPzGlo(pVec1); + + // D0(bar) → π∓ K± + std::array pVecD0 = RecoDecay::pVec(pVec0, pVec1); + auto trackParCovD0 = o2::dataformats::V0(df2.getPCACandidatePos(), pVecD0, df2.calcPCACovMatrixFlat(), trackParCov0, trackParCov1); + + for (const auto& trackId : trackIndices) { + auto trackPion = trackId.template track_as(); + + // apply selections on pion tracks + if (!isPionSelected(trackPion, track0, track1, candD0) || !isSelectedTrackDCA(trackPion)) { + continue; + } + registry.fill(HIST("hPtPion"), trackPion.pt()); + std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; + // compute invariant mass square and apply selection + auto invMass2D0Pi = RecoDecay::m2(std::array{pVecD0, pVecPion}, std::array{massD0, massPi}); + if ((invMass2D0Pi < invMass2D0PiMin) || (invMass2D0Pi > invMass2D0PiMax)) { + continue; + } + + // fill Pion tracks table + // if information on track already stored, go to next track + if (!selectedTracksPion.count(trackPion.globalIndex())) { + hfTrackPion(trackPion.globalIndex(), indexHfReducedCollision, + trackPion.x(), trackPion.alpha(), + trackPion.y(), trackPion.z(), trackPion.snp(), + trackPion.tgl(), trackPion.signed1Pt()); + hfTrackCovPion(trackPion.cYY(), trackPion.cZY(), trackPion.cZZ(), + trackPion.cSnpY(), trackPion.cSnpZ(), + trackPion.cSnpSnp(), trackPion.cTglY(), trackPion.cTglZ(), + trackPion.cTglSnp(), trackPion.cTglTgl(), + trackPion.c1PtY(), trackPion.c1PtZ(), trackPion.c1PtSnp(), + trackPion.c1PtTgl(), trackPion.c1Pt21Pt2()); + hfTrackPidPion(trackPion.hasTPC(), trackPion.hasTOF(), + trackPion.tpcNSigmaPi(), trackPion.tofNSigmaPi()); + // add trackPion.globalIndex() to a list + // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another D candidate + // and keep track of their index in hfTrackPion for McRec purposes + selectedTracksPion[trackPion.globalIndex()] = hfTrackPion.lastIndex(); + } + + if constexpr (doMc) { + // we check the MC matching to be stored + auto arrayDaughtersD0 = std::array{track0, track1}; + auto arrayDaughtersBplus = std::array{track0, track1, trackPion}; + int8_t sign{0}; + int8_t flag{0}; + // B+ → D0(bar) π+ → (K+ π-) π+ + // Printf("Checking B+ → D0bar π+"); + auto indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersBplus, pdg::Code::kBPlus, std::array{+kPiPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + if (indexRec > -1) { + // D0bar → K+ π- + // Printf("Checking D0bar → K+ π-"); + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersD0, pdg::Code::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1); + if (indexRec > -1) { + flag = sign * BIT(hf_cand_bplus::DecayType::BplusToD0Pi); + } else { + LOGF(info, "WARNING: B+ decays in the expected final state but the condition on the intermediate state is not fulfilled"); + } + } + auto indexMother = RecoDecay::getMother(particlesMc, trackPion.template mcParticle_as

(), pdg::Code::kBPlus, true); + auto particleMother = particlesMc.rawIteratorAt(indexMother); + + rowHfD0PiMcRecReduced(indexHfCand2Prong, selectedTracksPion[trackPion.globalIndex()], flag, particleMother.pt()); + } + fillHfCand2Prong = true; + } // pion loop + if (fillHfCand2Prong) { // fill candD0 table only once per D0 candidate + hfCand2Prong(track0.globalIndex(), track1.globalIndex(), + indexHfReducedCollision, + trackParCovD0.getX(), trackParCovD0.getAlpha(), + trackParCovD0.getY(), trackParCovD0.getZ(), trackParCovD0.getSnp(), + trackParCovD0.getTgl(), trackParCovD0.getQ2Pt(), + candD0.xSecondaryVertex(), candD0.ySecondaryVertex(), candD0.zSecondaryVertex(), invMassD0, invMassD0bar); + hfCand2ProngCov(trackParCovD0.getSigmaY2(), trackParCovD0.getSigmaZY(), trackParCovD0.getSigmaZ2(), + trackParCovD0.getSigmaSnpY(), trackParCovD0.getSigmaSnpZ(), + trackParCovD0.getSigmaSnp2(), trackParCovD0.getSigmaTglY(), trackParCovD0.getSigmaTglZ(), + trackParCovD0.getSigmaTglSnp(), trackParCovD0.getSigmaTgl2(), + trackParCovD0.getSigma1PtY(), trackParCovD0.getSigma1PtZ(), trackParCovD0.getSigma1PtSnp(), + trackParCovD0.getSigma1PtTgl(), trackParCovD0.getSigma1Pt2()); + if constexpr (withMl) { + hfCand2ProngMl(candD0.mlProbD0()[0], candD0.mlProbD0()[1], candD0.mlProbD0()[2]); + } + fillHfReducedCollision = true; + } + } // candsD loop + registry.fill(HIST("hEvents"), 1 + Event::Processed); + if (!fillHfReducedCollision) { + registry.fill(HIST("hEvents"), 1 + Event::NoD0PiSelected); + return; + } + registry.fill(HIST("hEvents"), 1 + Event::D0PiSelected); + // fill collision table if it contains a D0Pi pair a minima + hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), + collision.covXX(), collision.covXY(), collision.covYY(), + collision.covXZ(), collision.covYZ(), collision.covZZ(), + bz); + } + + void runMcGen(aod::McParticles const& particlesMc) + { + // Match generated particles. + for (const auto& particle : particlesMc) { + int8_t sign{0}; + int8_t flag{0}; + // B+ → D0bar π+ + if (RecoDecay::isMatchedMCGen(particlesMc, particle, pdg::Code::kBPlus, std::array{static_cast(pdg::Code::kD0), +kPiPlus}, true)) { + // Match D0bar -> π- K+ + auto candD0MC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + // Printf("Checking D0bar -> π- K+"); + if (RecoDecay::isMatchedMCGen(particlesMc, candD0MC, static_cast(pdg::Code::kD0), std::array{+kPiPlus, -kKPlus}, true, &sign)) { + flag = sign * BIT(hf_cand_bplus::DecayType::BplusToD0Pi); + } + } + + // save information for B+ task + if (!TESTBIT(std::abs(flag), hf_cand_bplus::DecayType::BplusToD0Pi)) { + continue; + } + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, massBplus); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(std::array{daught.px(), daught.py(), daught.pz()}, pdg->Mass(daught.pdgCode())); + counter++; + } + rowHfBpMcGenReduced(flag, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1]); + } // gen + } + + void processData(aod::Collisions const& collisions, + CandsDFiltered const& candsD0, + aod::TrackAssoc const& trackIndices, + TracksPIDWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B+ workflow + if (!isHfCandBplusConfigFilled) { + rowCandidateConfig(selectionFlagD0.value, selectionFlagD0bar.value, invMassWindowD0Pi.value); + isHfCandBplusConfigFilled = true; + } + + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsDPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisCollision, tracks, tracks, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorD0PiReduced, processData, "Process without MC info and without ML info", true); + + void processDataWithMl(aod::Collisions const& collisions, + CandsDFilteredWithMl const& candsD0, + aod::TrackAssoc const& trackIndices, + TracksPIDWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B+ workflow + if (!isHfCandBplusConfigFilled) { + rowCandidateConfig(selectionFlagD0.value, selectionFlagD0bar.value, invMassWindowD0Pi.value); + isHfCandBplusConfigFilled = true; + } + + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsDPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisCollision, tracks, tracks, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorD0PiReduced, processDataWithMl, "Process without MC info and with ML info", false); + + void processMc(aod::Collisions const& collisions, + CandsDFiltered const& candsD0, + aod::TrackAssoc const& trackIndices, + TracksPIDWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B+ workflow + if (!isHfCandBplusConfigFilled) { + rowCandidateConfig(selectionFlagD0.value, selectionFlagD0bar.value, invMassWindowD0Pi.value); + isHfCandBplusConfigFilled = true; + } + + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsDPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisCollision, tracks, particlesMc, bcs); + } + + runMcGen(particlesMc); + } + PROCESS_SWITCH(HfDataCreatorD0PiReduced, processMc, "Process with MC info and without ML info", false); + + void processMcWithMl(aod::Collisions const& collisions, + CandsDFilteredWithMl const& candsD0, + aod::TrackAssoc const& trackIndices, + TracksPIDWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B+ workflow + if (!isHfCandBplusConfigFilled) { + rowCandidateConfig(selectionFlagD0.value, selectionFlagD0bar.value, invMassWindowD0Pi.value); + isHfCandBplusConfigFilled = true; + } + + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsDPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisCollision, tracks, particlesMc, bcs); + } + + runMcGen(particlesMc); + } + PROCESS_SWITCH(HfDataCreatorD0PiReduced, processMcWithMl, "Process with MC info and with ML info", false); + +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/TableProducer/dataCreatorDplusPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorDplusPiReduced.cxx index 65b61440354..e92be945f36 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorDplusPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorDplusPiReduced.cxx @@ -13,21 +13,28 @@ /// \brief Creation of Dplus-Pi pairs /// /// \author Alexandre Bigot , IPHC Strasbourg +/// \author Fabrizio Grosa , CERN + +#include -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" using namespace o2; +using namespace o2::analysis; using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; @@ -43,12 +50,17 @@ enum Event : uint8_t { /// Creation of Dplus-Pi pairs struct HfDataCreatorDplusPiReduced { // Produces AOD tables to store track information - Produces hfReducedCollision; - Produces hfCollisionCounter; - Produces hfTrackPion; - Produces hfTrackPidPion; - Produces hfCand3Prong; - Produces rowCandidateConfig; + Produces hfReducedCollision; + Produces hfCollisionCounter; + Produces hfTrackPion; + Produces hfTrackCovPion; + Produces hfTrackPidPion; + Produces hfCand3Prong; + Produces hfCand3ProngCov; + Produces hfCand3ProngMl; + Produces rowCandidateConfig; + Produces rowHfDPiMcRecReduced; + Produces rowHfB0McGenReduced; // vertexing // Configurable bz{"bz", 5., "magnetic field"}; @@ -64,7 +76,7 @@ struct HfDataCreatorDplusPiReduced { Configurable ptPionMin{"ptPionMin", 0.5, "minimum pion pT threshold (GeV/c)"}; Configurable> binsPtPion{"binsPtPion", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for pion DCA XY pT-dependent cut"}; Configurable> cutsTrackPionDCA{"cutsTrackPionDCA", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for pions"}; - Configurable invMassWindowB0{"invMassWindowB0", 0.3, "invariant-mass window for B0 candidates"}; + Configurable invMassWindowDPi{"invMassWindowDPi", 0.3, "invariant-mass window for DPi pair preselections (GeV/c2)"}; Configurable selectionFlagD{"selectionFlagD", 1, "Selection Flag for D"}; // magnetic field setting from CCDB @@ -74,16 +86,22 @@ struct HfDataCreatorDplusPiReduced { Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + HfHelper hfHelper; + + // CCDB service Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber; - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massD = RecoDecay::getMassPDG(pdg::Code::kDMinus); - double massB0 = RecoDecay::getMassPDG(pdg::Code::kB0); - double massDPi{0.}; - double invMassD{0.}; + // O2DatabasePDG service + Service pdg; + + double massPi{0.}; + double massD{0.}; + double massB0{0.}; + double invMass2DPiMin{0.}; + double invMass2DPiMax{0.}; double bz{0.}; bool isHfCandB0ConfigFilled = false; @@ -91,12 +109,17 @@ struct HfDataCreatorDplusPiReduced { // Fitter to redo D-vertex to get extrapolated daughter tracks (3-prong vertex filter) o2::vertexing::DCAFitterN<3> df3; - using TracksPIDWithSel = soa::Join; + using TracksPidAll = soa::Join; + using TracksPIDWithSel = soa::Join; + using TracksPIDWithSelAndMc = soa::Join; using CandsDFiltered = soa::Filtered>; + using CandsDFilteredWithMl = soa::Filtered>; Filter filterSelectCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagD); Preslice candsDPerCollision = aod::track_association::collisionId; + Preslice candsDPerCollisionWithMl = aod::track_association::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; HistogramRegistry registry{"registry"}; @@ -135,6 +158,13 @@ struct HfDataCreatorDplusPiReduced { ccdb->setLocalObjectValidityChecking(); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); runNumber = 0; + + // invariant-mass window cut + massPi = o2::analysis::pdg::MassPiPlus; + massD = o2::analysis::pdg::MassDMinus; + massB0 = o2::analysis::pdg::MassB0; + invMass2DPiMin = (massB0 - invMassWindowDPi) * (massB0 - invMassWindowDPi); + invMass2DPiMax = (massB0 + invMassWindowDPi) * (massB0 + invMassWindowDPi); } /// Pion selection (D Pi <-- B0) @@ -185,256 +215,204 @@ struct HfDataCreatorDplusPiReduced { return true; } - void process(aod::Collisions const& collisions, - CandsDFiltered const& candsD, - aod::TrackAssoc const& trackIndices, - TracksPIDWithSel const&, - aod::BCsWithTimestamps const&) + template + void runDataCreation(aod::Collision const& collision, + C const& candsD, + aod::TrackAssoc const& trackIndices, + T const& tracks, + P const& particlesMc, + aod::BCsWithTimestamps const& bcs) { - // store configurables needed for B0 workflow - if (!isHfCandB0ConfigFilled) { - rowCandidateConfig(selectionFlagD.value); - isHfCandB0ConfigFilled = true; + // helpers for ReducedTables filling + int indexHfReducedCollision = hfReducedCollision.lastIndex() + 1; + // std::map where the key is the track.globalIndex() and + // the value is the track index in the table of the selected pions + std::map selectedTracksPion; + bool fillHfReducedCollision = false; + + auto primaryVertex = getPrimaryVertex(collision); + + // Set the magnetic field from ccdb. + // The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, + // but this is not true when running on Run2 data/MC already converted into AO2Ds. + auto bc = collision.bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; } + df3.setBz(bz); - static int aodNumber = 0; - aodNumber++; - - // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize()); - - static int nCol = 0; - for (const auto& collision : collisions) { - nCol++; + auto thisCollId = collision.globalIndex(); + for (const auto& candD : candsD) { + int indexHfCand3Prong = hfCand3Prong.lastIndex() + 1; + bool fillHfCand3Prong = false; + float invMassD = hfHelper.invMassDplusToPiKPi(candD); + + registry.fill(HIST("hMassDToPiKPi"), invMassD); + registry.fill(HIST("hPtD"), candD.pt()); + registry.fill(HIST("hCPAD"), candD.cpa()); + + // track0 <-> pi, track1 <-> K, track2 <-> pi + auto track0 = candD.template prong0_as(); + auto track1 = candD.template prong1_as(); + auto track2 = candD.template prong2_as(); + auto trackParCov0 = getTrackParCov(track0); + auto trackParCov1 = getTrackParCov(track1); + auto trackParCov2 = getTrackParCov(track2); + + std::array pVec0 = {track0.px(), track0.py(), track0.pz()}; + std::array pVec1 = {track1.px(), track1.py(), track1.pz()}; + std::array pVec2 = {track2.px(), track2.py(), track2.pz()}; + + auto dca0 = o2::dataformats::DCA(track0.dcaXY(), track0.dcaZ(), track0.cYY(), track0.cZY(), track0.cZZ()); + auto dca1 = o2::dataformats::DCA(track1.dcaXY(), track1.dcaZ(), track1.cYY(), track1.cZY(), track1.cZZ()); + auto dca2 = o2::dataformats::DCA(track2.dcaXY(), track2.dcaZ(), track2.cYY(), track2.cZY(), track2.cZZ()); + + // repropagate tracks to this collision if needed + if (track0.collisionId() != thisCollId) { + trackParCov0.propagateToDCA(primaryVertex, bz, &dca0); + } - // helpers for ReducedTables filling - int hfReducedCollisionIndex = hfReducedCollision.lastIndex() + 1; - std::vector selectedTracksPion; - selectedTracksPion.reserve(trackIndices.size()); - bool fillHfReducedCollision = false; + if (track1.collisionId() != thisCollId) { + trackParCov1.propagateToDCA(primaryVertex, bz, &dca1); + } - auto primaryVertex = getPrimaryVertex(collision); - if (nCol % 10000 == 0) { - LOG(debug) << nCol << " collisions parsed"; + if (track2.collisionId() != thisCollId) { + trackParCov2.propagateToDCA(primaryVertex, bz, &dca2); } - // Set the magnetic field from ccdb. - // The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, - // but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.bc_as(); - if (runNumber != bc.runNumber()) { - LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; - initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); - bz = o2::base::Propagator::Instance()->getNominalBz(); - LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + // --------------------------------- + // reconstruct 3-prong secondary vertex (D±) + if (df3.process(trackParCov0, trackParCov1, trackParCov2) == 0) { + continue; } - df3.setBz(bz); - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - for (const auto& candD : candsDThisColl) { - bool fillHfCand3Prong = false; - float invMassD; - - registry.fill(HIST("hMassDToPiKPi"), invMassDplusToPiKPi(candD)); - registry.fill(HIST("hPtD"), candD.pt()); - registry.fill(HIST("hCPAD"), candD.cpa()); - - // track0 <-> pi, track1 <-> K, track2 <-> pi - auto track0 = candD.prong0_as(); - auto track1 = candD.prong1_as(); - auto track2 = candD.prong2_as(); - auto trackParCov0 = getTrackParCov(track0); - auto trackParCov1 = getTrackParCov(track1); - auto trackParCov2 = getTrackParCov(track2); - - std::array pVec0 = {track0.px(), track0.py(), track0.pz()}; - std::array pVec1 = {track1.px(), track1.py(), track1.pz()}; - std::array pVec2 = {track2.px(), track2.py(), track2.pz()}; - - auto dca0 = o2::dataformats::DCA(track0.dcaXY(), track0.dcaZ(), track0.cYY(), track0.cZY(), track0.cZZ()); - auto dca1 = o2::dataformats::DCA(track1.dcaXY(), track1.dcaZ(), track1.cYY(), track1.cZY(), track1.cZZ()); - auto dca2 = o2::dataformats::DCA(track2.dcaXY(), track2.dcaZ(), track2.cYY(), track2.cZY(), track2.cZZ()); - - // repropagate tracks to this collision if needed - if (track0.collisionId() != thisCollId) { - trackParCov0.propagateToDCA(primaryVertex, bz, &dca0); - } + const auto& secondaryVertexD = df3.getPCACandidate(); + // propagate the 3 prongs to the secondary vertex + trackParCov0.propagateTo(secondaryVertexD[0], bz); + trackParCov1.propagateTo(secondaryVertexD[0], bz); + trackParCov2.propagateTo(secondaryVertexD[0], bz); - if (track1.collisionId() != thisCollId) { - trackParCov1.propagateToDCA(primaryVertex, bz, &dca1); - } + // update pVec of tracks + df3.getTrack(0).getPxPyPzGlo(pVec0); + df3.getTrack(1).getPxPyPzGlo(pVec1); + df3.getTrack(2).getPxPyPzGlo(pVec2); - if (track2.collisionId() != thisCollId) { - trackParCov2.propagateToDCA(primaryVertex, bz, &dca2); - } + // D∓ → π∓ K± π∓ + std::array pVecPiK = RecoDecay::pVec(pVec0, pVec1); + std::array pVecD = RecoDecay::pVec(pVec0, pVec1, pVec2); + auto trackParCovPiK = o2::dataformats::V0(df3.getPCACandidatePos(), pVecPiK, df3.calcPCACovMatrixFlat(), trackParCov0, trackParCov1); + auto trackParCovD = o2::dataformats::V0(df3.getPCACandidatePos(), pVecD, df3.calcPCACovMatrixFlat(), trackParCovPiK, trackParCov2); - // --------------------------------- - // reconstruct 3-prong secondary vertex (D±) - if (df3.process(trackParCov0, trackParCov1, trackParCov2) == 0) { + for (const auto& trackId : trackIndices) { + auto trackPion = trackId.template track_as(); + + // apply selections on pion tracks + if (!isPionSelected(trackPion, track0, track1, track2) || !isSelectedTrackDCA(trackPion)) { continue; } - - const auto& secondaryVertexD = df3.getPCACandidate(); - // propagate the 3 prongs to the secondary vertex - trackParCov0.propagateTo(secondaryVertexD[0], bz); - trackParCov1.propagateTo(secondaryVertexD[0], bz); - trackParCov2.propagateTo(secondaryVertexD[0], bz); - - // update pVec of tracks - df3.getTrack(0).getPxPyPzGlo(pVec0); - df3.getTrack(1).getPxPyPzGlo(pVec1); - df3.getTrack(2).getPxPyPzGlo(pVec2); - - // D∓ → π∓ K± π∓ - std::array pVecPiK = RecoDecay::pVec(pVec0, pVec1); - std::array pVecD = RecoDecay::pVec(pVec0, pVec1, pVec2); - auto trackParCovPiK = o2::dataformats::V0(df3.getPCACandidatePos(), pVecPiK, df3.calcPCACovMatrixFlat(), - trackParCov0, trackParCov1, {0, 0}, {0, 0}); - auto trackParCovD = o2::dataformats::V0(df3.getPCACandidatePos(), pVecD, df3.calcPCACovMatrixFlat(), - trackParCovPiK, trackParCov2, {0, 0}, {0, 0}); - - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - for (const auto& trackId : trackIdsThisCollision) { - auto trackPion = trackId.track_as(); - - // apply selections on pion tracks - if (!isPionSelected(trackPion, track0, track1, track2) || !isSelectedTrackDCA(trackPion)) { - continue; - } - registry.fill(HIST("hPtPion"), trackPion.pt()); - std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; - // compute invariant mass and apply selection - massDPi = RecoDecay::m(std::array{pVecD, pVecPion}, std::array{massD, massPi}); - if (std::abs(massDPi - massB0) > invMassWindowB0) { - continue; - } - - invMassD = hf_cand_3prong_reduced::invMassDplusToPiKPi(pVec0, pVec1, pVec2); - - // fill Pion tracks table - // if information on track already stored, go to next track - if (!std::count(selectedTracksPion.begin(), selectedTracksPion.end(), trackPion.globalIndex())) { - hfTrackPion(trackPion.globalIndex(), hfReducedCollisionIndex, - trackPion.x(), trackPion.alpha(), - trackPion.y(), trackPion.z(), trackPion.snp(), - trackPion.tgl(), trackPion.signed1Pt(), - trackPion.cYY(), trackPion.cZY(), trackPion.cZZ(), - trackPion.cSnpY(), trackPion.cSnpZ(), - trackPion.cSnpSnp(), trackPion.cTglY(), trackPion.cTglZ(), - trackPion.cTglSnp(), trackPion.cTglTgl(), - trackPion.c1PtY(), trackPion.c1PtZ(), trackPion.c1PtSnp(), - trackPion.c1PtTgl(), trackPion.c1Pt21Pt2(), - trackPion.px(), trackPion.py(), trackPion.pz()); - hfTrackPidPion(hfReducedCollisionIndex, - trackPion.pt(), - trackPion.hasTPC(), trackPion.hasTOF(), - trackPion.tpcNSigmaEl(), trackPion.tpcNSigmaMu(), trackPion.tpcNSigmaPi(), trackPion.tpcNSigmaKa(), trackPion.tpcNSigmaPr(), - trackPion.tofNSigmaEl(), trackPion.tofNSigmaMu(), trackPion.tofNSigmaPi(), trackPion.tofNSigmaKa(), trackPion.tofNSigmaPr()); - // add trackPion.globalIndex() to a list - // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another D candidate - selectedTracksPion.emplace_back(trackPion.globalIndex()); - } - fillHfCand3Prong = true; - } // pion loop - if (fillHfCand3Prong) { // fill candDplus table only once per D candidate - hfCand3Prong(track0.globalIndex(), track1.globalIndex(), track2.globalIndex(), - hfReducedCollisionIndex, - trackParCovD.getX(), trackParCovD.getAlpha(), - trackParCovD.getY(), trackParCovD.getZ(), trackParCovD.getSnp(), - trackParCovD.getTgl(), trackParCovD.getQ2Pt(), - trackParCovD.getSigmaY2(), trackParCovD.getSigmaZY(), trackParCovD.getSigmaZ2(), - trackParCovD.getSigmaSnpY(), trackParCovD.getSigmaSnpZ(), - trackParCovD.getSigmaSnp2(), trackParCovD.getSigmaTglY(), trackParCovD.getSigmaTglZ(), - trackParCovD.getSigmaTglSnp(), trackParCovD.getSigmaTgl2(), - trackParCovD.getSigma1PtY(), trackParCovD.getSigma1PtZ(), trackParCovD.getSigma1PtSnp(), - trackParCovD.getSigma1PtTgl(), trackParCovD.getSigma1Pt2(), - pVecD[0], pVecD[1], pVecD[2], - candD.cpa(), - candD.decayLength(), - invMassD); - fillHfReducedCollision = true; + registry.fill(HIST("hPtPion"), trackPion.pt()); + std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; + // compute invariant mass square and apply selection + auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{massD, massPi}); + if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { + continue; } - } // candsD loop - registry.fill(HIST("hEvents"), 1 + Event::Processed); - if (!fillHfReducedCollision) { - registry.fill(HIST("hEvents"), 1 + Event::NoDPiSelected); - continue; - } - registry.fill(HIST("hEvents"), 1 + Event::DPiSelected); - // fill collision table if it contains a DPi pair a minima - hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), - collision.covXX(), collision.covXY(), collision.covYY(), - collision.covXZ(), collision.covYZ(), collision.covZZ(), - bz); - } // collision - } // process -}; // struct - -/// Performs MC matching. -struct HfDataCreatorDplusPiReducedMc { - Produces rowHfDPiMcRecReduced; - Produces rowHfB0McGenReduced; - - void init(InitContext const&) {} - - void processMc(aod::HfCand3ProngReduced const& candsD, - aod::HfTracksReduced const& tracksPion, - aod::BigTracksMC const&, - aod::McParticles const& particlesMc) - { - int indexRec = -1; - int8_t sign = 0; - int8_t flag = 0; - int8_t origin = 0; - int8_t debug = 0; - for (const auto& candD : candsD) { - auto arrayDaughtersD = array{candD.prong0_as(), - candD.prong1_as(), - candD.prong2_as()}; - - for (const auto& trackPion : tracksPion) { - if (trackPion.hfReducedCollisionId() != candD.hfReducedCollisionId()) { - continue; + // fill Pion tracks table + // if information on track already stored, go to next track + if (!selectedTracksPion.count(trackPion.globalIndex())) { + hfTrackPion(trackPion.globalIndex(), indexHfReducedCollision, + trackPion.x(), trackPion.alpha(), + trackPion.y(), trackPion.z(), trackPion.snp(), + trackPion.tgl(), trackPion.signed1Pt()); + hfTrackCovPion(trackPion.cYY(), trackPion.cZY(), trackPion.cZZ(), + trackPion.cSnpY(), trackPion.cSnpZ(), + trackPion.cSnpSnp(), trackPion.cTglY(), trackPion.cTglZ(), + trackPion.cTglSnp(), trackPion.cTglTgl(), + trackPion.c1PtY(), trackPion.c1PtZ(), trackPion.c1PtSnp(), + trackPion.c1PtTgl(), trackPion.c1Pt21Pt2()); + hfTrackPidPion(trackPion.hasTPC(), trackPion.hasTOF(), + trackPion.tpcNSigmaPi(), trackPion.tofNSigmaPi()); + // add trackPion.globalIndex() to a list + // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another D candidate + // and keep track of their index in hfTrackPion for McRec purposes + selectedTracksPion[trackPion.globalIndex()] = hfTrackPion.lastIndex(); } - // const auto& trackId = trackPion.globalIndex(); - auto arrayDaughtersB0 = array{candD.prong0_as(), - candD.prong1_as(), - candD.prong2_as(), - trackPion.track_as()}; - // B0 → D- π+ → (π- K+ π-) π+ - // Printf("Checking B0 → D- π+"); - indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersB0, pdg::Code::kB0, array{-kPiPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 2); - if (indexRec > -1) { - // D- → π- K+ π- - // Printf("Checking D- → π- K+ π-"); - indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersD, pdg::Code::kDMinus, array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + + if constexpr (doMc) { + // we check the MC matching to be stored + auto arrayDaughtersD = std::array{track0, track1, track2}; + auto arrayDaughtersB0 = std::array{track0, track1, track2, trackPion}; + int8_t sign{0}; + int8_t flag{0}; + int8_t debug{0}; + // B0 → D- π+ → (π- K+ π-) π+ + auto indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersB0, pdg::Code::kB0, std::array{-kPiPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); if (indexRec > -1) { - flag = sign * BIT(hf_cand_b0::DecayType::B0ToDPi); - } else { - debug = 1; - LOGF(info, "WARNING: B0 decays in the expected final state but the condition on the intermediate state is not fulfilled"); + // D- → π- K+ π- + // Printf("Checking D- → π- K+ π-"); + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersD, pdg::Code::kDMinus, std::array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + if (indexRec > -1) { + flag = sign * BIT(hf_cand_b0::DecayType::B0ToDPi); + } else { + debug = 1; + LOGF(debug, "B0 decays in the expected final state but the condition on the intermediate state is not fulfilled"); + } } + auto indexMother = RecoDecay::getMother(particlesMc, trackPion.template mcParticle_as

(), pdg::Code::kB0, true); + auto particleMother = particlesMc.rawIteratorAt(indexMother); + rowHfDPiMcRecReduced(indexHfCand3Prong, selectedTracksPion[trackPion.globalIndex()], flag, debug, particleMother.pt()); } - auto indexMother = RecoDecay::getMother(particlesMc, trackPion.track_as().mcParticle_as(), pdg::Code::kB0, true); - auto particleMother = particlesMc.rawIteratorAt(indexMother); - - rowHfDPiMcRecReduced(candD.globalIndex(), trackPion.globalIndex(), flag, origin, debug, particleMother.pt()); + fillHfCand3Prong = true; + } // pion loop + if (fillHfCand3Prong) { // fill candDplus table only once per D candidate + hfCand3Prong(track0.globalIndex(), track1.globalIndex(), track2.globalIndex(), + indexHfReducedCollision, + trackParCovD.getX(), trackParCovD.getAlpha(), + trackParCovD.getY(), trackParCovD.getZ(), trackParCovD.getSnp(), + trackParCovD.getTgl(), trackParCovD.getQ2Pt(), + candD.xSecondaryVertex(), candD.ySecondaryVertex(), candD.zSecondaryVertex(), invMassD); + hfCand3ProngCov(trackParCovD.getSigmaY2(), trackParCovD.getSigmaZY(), trackParCovD.getSigmaZ2(), + trackParCovD.getSigmaSnpY(), trackParCovD.getSigmaSnpZ(), + trackParCovD.getSigmaSnp2(), trackParCovD.getSigmaTglY(), trackParCovD.getSigmaTglZ(), + trackParCovD.getSigmaTglSnp(), trackParCovD.getSigmaTgl2(), + trackParCovD.getSigma1PtY(), trackParCovD.getSigma1PtZ(), trackParCovD.getSigma1PtSnp(), + trackParCovD.getSigma1PtTgl(), trackParCovD.getSigma1Pt2()); + if constexpr (withMl) { + hfCand3ProngMl(candD.mlProbDplusToPiKPi()[0], candD.mlProbDplusToPiKPi()[1], candD.mlProbDplusToPiKPi()[2]); + } + fillHfReducedCollision = true; } - } // rec + } // candsD loop + + registry.fill(HIST("hEvents"), 1 + Event::Processed); + if (!fillHfReducedCollision) { + registry.fill(HIST("hEvents"), 1 + Event::NoDPiSelected); + return; + } + registry.fill(HIST("hEvents"), 1 + Event::DPiSelected); + // fill collision table if it contains a DPi pair a minima + hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), + collision.covXX(), collision.covXY(), collision.covYY(), + collision.covXZ(), collision.covYZ(), collision.covZZ(), + bz); + } + void runMcGen(aod::McParticles const& particlesMc) + { // Match generated particles. - for (auto const& particle : particlesMc) { - // Printf("New gen. candidate"); - flag = 0; - origin = 0; + for (const auto& particle : particlesMc) { + int8_t sign{0}; + int8_t flag{0}; // B0 → D- π+ - if (RecoDecay::isMatchedMCGen(particlesMc, particle, pdg::Code::kB0, array{-static_cast(pdg::Code::kDPlus), +kPiPlus}, true)) { + if (RecoDecay::isMatchedMCGen(particlesMc, particle, pdg::Code::kB0, std::array{-static_cast(pdg::Code::kDPlus), +kPiPlus}, true)) { // Match D- -> π- K+ π- auto candDMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); // Printf("Checking D- -> π- K+ π-"); - if (RecoDecay::isMatchedMCGen(particlesMc, candDMC, -static_cast(pdg::Code::kDPlus), array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign)) { + if (RecoDecay::isMatchedMCGen(particlesMc, candDMC, -static_cast(pdg::Code::kDPlus), std::array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign)) { flag = sign * BIT(hf_cand_b0::DecayType::B0ToDPi); } } @@ -445,32 +423,127 @@ struct HfDataCreatorDplusPiReducedMc { } auto ptParticle = particle.pt(); - auto yParticle = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(pdg::Code::kB0)); + auto yParticle = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, massB0); auto etaParticle = particle.eta(); std::array ptProngs; std::array yProngs; std::array etaProngs; int counter = 0; - for (auto const& daught : particle.daughters_as()) { + for (const auto& daught : particle.daughters_as()) { ptProngs[counter] = daught.pt(); etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(array{daught.px(), daught.py(), daught.pz()}, RecoDecay::getMassPDG(daught.pdgCode())); + yProngs[counter] = RecoDecay::y(std::array{daught.px(), daught.py(), daught.pz()}, pdg->Mass(daught.pdgCode())); counter++; } - rowHfB0McGenReduced(flag, origin, - ptParticle, yParticle, etaParticle, + rowHfB0McGenReduced(flag, ptParticle, yParticle, etaParticle, ptProngs[0], yProngs[0], etaProngs[0], ptProngs[1], yProngs[1], etaProngs[1]); } // gen + } + + void processData(aod::Collisions const& collisions, + CandsDFiltered const& candsD, + aod::TrackAssoc const& trackIndices, + TracksPIDWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B0 workflow + if (!isHfCandB0ConfigFilled) { + rowCandidateConfig(selectionFlagD.value, invMassWindowDPi.value); + isHfCandB0ConfigFilled = true; + } + + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisCollision, tracks, tracks, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorDplusPiReduced, processData, "Process without MC info and without ML info", true); + + void processDataWithMl(aod::Collisions const& collisions, + CandsDFilteredWithMl const& candsD, + aod::TrackAssoc const& trackIndices, + TracksPIDWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B0 workflow + if (!isHfCandB0ConfigFilled) { + rowCandidateConfig(selectionFlagD.value, invMassWindowDPi.value); + isHfCandB0ConfigFilled = true; + } + + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); - } // processMc - PROCESS_SWITCH(HfDataCreatorDplusPiReducedMc, processMc, "Process MC", false); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisCollision, tracks, tracks, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorDplusPiReduced, processDataWithMl, "Process without MC info and with ML info", false); + + void processMc(aod::Collisions const& collisions, + CandsDFiltered const& candsD, + aod::TrackAssoc const& trackIndices, + TracksPIDWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B0 workflow + if (!isHfCandB0ConfigFilled) { + rowCandidateConfig(selectionFlagD.value, invMassWindowDPi.value); + isHfCandB0ConfigFilled = true; + } + + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisCollision, tracks, particlesMc, bcs); + } + runMcGen(particlesMc); + } + PROCESS_SWITCH(HfDataCreatorDplusPiReduced, processMc, "Process with MC info and without ML info", false); + + void processMcWithMl(aod::Collisions const& collisions, + CandsDFilteredWithMl const& candsD, + aod::TrackAssoc const& trackIndices, + TracksPIDWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B0 workflow + if (!isHfCandB0ConfigFilled) { + rowCandidateConfig(selectionFlagD.value, invMassWindowDPi.value); + isHfCandB0ConfigFilled = true; + } + + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize()); + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsD, trackIndices, tracks, particlesMc, bcs); + } + runMcGen(particlesMc); + } + PROCESS_SWITCH(HfDataCreatorDplusPiReduced, processMcWithMl, "Process with MC info and with ML info", false); }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 7075147db65..6d39156516d 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -11,65 +11,75 @@ o2physics_add_dpl_workflow(task-b0 SOURCES taskB0.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-b0-reduced SOURCES taskB0Reduced.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-bplus SOURCES taskBplus.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-bplus-reduced + SOURCES taskBplusReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-bs + SOURCES taskBs.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-d0 SOURCES taskD0.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-dplus SOURCES taskDplus.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-ds SOURCES taskDs.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-lb SOURCES taskLb.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-lc SOURCES taskLc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-lc-to-k0s-p SOURCES taskLcToK0sP.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-omegac-st SOURCES taskOmegacSt.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-sigmac SOURCES taskSigmac.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-xic SOURCES taskXic.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-xicc SOURCES taskXicc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGHF/D2H/Tasks/taskB0.cxx b/PWGHF/D2H/Tasks/taskB0.cxx index c5961a7b06e..6c7762d7e87 100644 --- a/PWGHF/D2H/Tasks/taskB0.cxx +++ b/PWGHF/D2H/Tasks/taskB0.cxx @@ -16,8 +16,10 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -26,10 +28,6 @@ using namespace o2; using namespace o2::aod; using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_cand_b0; // from CandidateReconstructionTables.h -using namespace o2::analysis::hf_cuts_b0_to_d_pi; // from SelectorCuts.h using namespace o2::framework::expressions; /// B0 analysis task @@ -43,7 +41,11 @@ struct HfTaskB0 { // MC checks Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "Flag to enable DecayType histogram"}; - using TracksWithSel = soa::Join; + // O2DatabasePDG service + Service pdg; + HfHelper hfHelper; + + using TracksWithSel = soa::Join; Filter filterSelectCandidates = (aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0); @@ -125,12 +127,12 @@ struct HfTaskB0 { registry.add("hPtGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); if (checkDecayTypeMc) { - constexpr uint8_t kNBinsDecayTypeMc = DecayTypeMc::NDecayTypeMc; + constexpr uint8_t kNBinsDecayTypeMc = hf_cand_b0::DecayTypeMc::NDecayTypeMc; TString labels[kNBinsDecayTypeMc]; - labels[DecayTypeMc::B0ToDplusPiToPiKPiPi] = "B^{0} #rightarrow (D^{#minus} #rightarrow #pi^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; - labels[DecayTypeMc::B0ToDsPiToKKPiPi] = "B^{0} #rightarrow (D^{#minus}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; - labels[DecayTypeMc::PartlyRecoDecay] = "Partly reconstructed decay channel"; - labels[DecayTypeMc::OtherDecay] = "Other decays"; + labels[hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi] = "B^{0} #rightarrow (D^{#minus} #rightarrow #pi^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; + labels[hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi] = "B^{0} #rightarrow (D^{#minus}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; + labels[hf_cand_b0::DecayTypeMc::PartlyRecoDecay] = "Partly reconstructed decay channel"; + labels[hf_cand_b0::DecayTypeMc::OtherDecay] = "Other decays"; static const AxisSpec axisDecayType = {kNBinsDecayTypeMc, 0.5, kNBinsDecayTypeMc + 0.5, ""}; registry.add("hDecayTypeMc", "DecayType", {HistType::kTH3F, {axisDecayType, axisMassB0, axisPt}}); for (uint8_t iBin = 0; iBin < kNBinsDecayTypeMc; ++iBin) { @@ -149,13 +151,15 @@ struct HfTaskB0 { return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; } - void process(soa::Filtered> const& candidates, soa::Join const&, TracksWithSel const&) + void process(soa::Filtered> const& candidates, + soa::Join const&, + TracksWithSel const&) { - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yB0(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { continue; } @@ -164,7 +168,7 @@ struct HfTaskB0 { auto ptCandB0 = candidate.pt(); - registry.fill(HIST("hMass"), invMassB0ToDPi(candidate), ptCandB0); + registry.fill(HIST("hMass"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); registry.fill(HIST("hPtCand"), ptCandB0); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); @@ -175,48 +179,48 @@ struct HfTaskB0 { registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), ptCandB0); registry.fill(HIST("hCPA"), candidate.cpa(), ptCandB0); registry.fill(HIST("hEta"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidity"), yB0(candidate), ptCandB0); + registry.fill(HIST("hRapidity"), hfHelper.yB0(candidate), ptCandB0); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), ptCandB0); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandB0); registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), ptCandB0); registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), ptCandB0); - registry.fill(HIST("hInvMassD"), invMassDplusToPiKPi(candD), ptCandB0); + registry.fill(HIST("hInvMassD"), hfHelper.invMassDplusToPiKPi(candD), ptCandB0); } // candidate loop } // process /// B0 MC analysis and fill histograms void processMc(soa::Filtered> const& candidates, - soa::Join const& particlesMc, - aod::BigTracksMC const&, + soa::Join const& mcParticles, + aod::TracksWMc const&, soa::Join const&) { // MC rec - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yB0(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { continue; } auto ptCandB0 = candidate.pt(); auto candD = candidate.prong0_as>(); - auto invMassCandB0 = invMassB0ToDPi(candidate); + auto invMassCandB0 = hfHelper.invMassB0ToDPi(candidate); int flagMcMatchRecB0 = std::abs(candidate.flagMcMatchRec()); if (TESTBIT(flagMcMatchRecB0, hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi)) { - auto indexMother = RecoDecay::getMother(particlesMc, candidate.prong1_as().mcParticle_as>(), pdg::Code::kB0, true); - auto particleMother = particlesMc.rawIteratorAt(indexMother); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), pdg::Code::kB0, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("hPtGenSig"), particleMother.pt()); registry.fill(HIST("hPtRecSig"), ptCandB0); registry.fill(HIST("hCPARecSig"), candidate.cpa(), ptCandB0); registry.fill(HIST("hCPAxyRecSig"), candidate.cpaXY(), ptCandB0); registry.fill(HIST("hEtaRecSig"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidityRecSig"), yB0(candidate), ptCandB0); + registry.fill(HIST("hRapidityRecSig"), hfHelper.yB0(candidate), ptCandB0); registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), ptCandB0); registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), ptCandB0); - registry.fill(HIST("hMassRecSig"), invMassB0ToDPi(candidate), ptCandB0); + registry.fill(HIST("hMassRecSig"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), ptCandB0); registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), ptCandB0); registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), ptCandB0); @@ -228,17 +232,17 @@ struct HfTaskB0 { registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandB0); if (checkDecayTypeMc) { - registry.fill(HIST("hDecayTypeMc"), 1 + DecayTypeMc::B0ToDplusPiToPiKPiPi, invMassCandB0, ptCandB0); + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi, invMassCandB0, ptCandB0); } } else { registry.fill(HIST("hPtRecBg"), ptCandB0); registry.fill(HIST("hCPARecBg"), candidate.cpa(), ptCandB0); registry.fill(HIST("hCPAxyRecBg"), candidate.cpaXY(), ptCandB0); registry.fill(HIST("hEtaRecBg"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidityRecBg"), yB0(candidate), ptCandB0); + registry.fill(HIST("hRapidityRecBg"), hfHelper.yB0(candidate), ptCandB0); registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), ptCandB0); registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), ptCandB0); - registry.fill(HIST("hMassRecBg"), invMassB0ToDPi(candidate), ptCandB0); + registry.fill(HIST("hMassRecBg"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), ptCandB0); registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), ptCandB0); registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), ptCandB0); @@ -250,24 +254,23 @@ struct HfTaskB0 { registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandB0); if (checkDecayTypeMc) { - if (TESTBIT(flagMcMatchRecB0, DecayTypeMc::B0ToDsPiToKKPiPi)) { // B0 → Ds- π+ → (K- K+ π-) π+ - registry.fill(HIST("hDecayTypeMc"), 1 + DecayTypeMc::B0ToDsPiToKKPiPi, invMassCandB0, ptCandB0); - } else if (TESTBIT(flagMcMatchRecB0, DecayTypeMc::PartlyRecoDecay)) { // Partly reconstructed decay channel - registry.fill(HIST("hDecayTypeMc"), 1 + DecayTypeMc::PartlyRecoDecay, invMassCandB0, ptCandB0); + if (TESTBIT(flagMcMatchRecB0, hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi)) { // B0 → Ds- π+ → (K- K+ π-) π+ + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi, invMassCandB0, ptCandB0); + } else if (TESTBIT(flagMcMatchRecB0, hf_cand_b0::DecayTypeMc::PartlyRecoDecay)) { // Partly reconstructed decay channel + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_b0::DecayTypeMc::PartlyRecoDecay, invMassCandB0, ptCandB0); } else { - registry.fill(HIST("hDecayTypeMc"), 1 + DecayTypeMc::OtherDecay, invMassCandB0, ptCandB0); + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_b0::DecayTypeMc::OtherDecay, invMassCandB0, ptCandB0); } } } } // rec // MC gen. level - // Printf("MC Particles: %d", particlesMc.size()); - for (auto const& particle : particlesMc) { + for (const auto& particle : mcParticles) { if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_b0::DecayType::B0ToDPi)) { auto ptParticle = particle.pt(); - auto yParticle = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(pdg::Code::kB0)); + auto yParticle = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassB0); if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { continue; } @@ -276,10 +279,10 @@ struct HfTaskB0 { std::array yProngs; std::array etaProngs; int counter = 0; - for (auto const& daught : particle.daughters_as()) { + for (const auto& daught : particle.daughters_as()) { ptProngs[counter] = daught.pt(); etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(array{daught.px(), daught.py(), daught.pz()}, RecoDecay::getMassPDG(daught.pdgCode())); + yProngs[counter] = RecoDecay::y(std::array{daught.px(), daught.py(), daught.pz()}, pdg->Mass(daught.pdgCode())); counter++; } diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index b9faaf3894f..d316b0c0ca4 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -17,7 +17,9 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/RecoDecay.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -28,7 +30,6 @@ using namespace o2::aod; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_b0; // from CandidateReconstructionTables.h /// B0 analysis task struct HfTaskB0Reduced { @@ -39,6 +40,8 @@ struct HfTaskB0Reduced { Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_b0_to_d_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0); HistogramRegistry registry{ @@ -47,7 +50,7 @@ struct HfTaskB0Reduced { {"hPtProng1", "B0 candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 10.}}}}, {"hPtCand", "B0 candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0., 50.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { registry.add("hMass", "B^{0} candidates;inv. mass D^{#minus}#pi^{#plus} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{300, 4.5, 6.0}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hDecLength", "B^{0} candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 0.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -126,21 +129,21 @@ struct HfTaskB0Reduced { return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; } - void process(soa::Filtered> const& candidates, - aod::HfCand3ProngReduced const&) + void process(soa::Filtered> const& candidates, + aod::HfRed3Prongs const&) { - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yB0(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { continue; } auto ptCandB0 = candidate.pt(); - auto candD = candidate.prong0_as(); + auto candD = candidate.prong0_as(); - registry.fill(HIST("hMass"), invMassB0ToDPi(candidate), ptCandB0); + registry.fill(HIST("hMass"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); registry.fill(HIST("hPtCand"), ptCandB0); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); @@ -151,7 +154,7 @@ struct HfTaskB0Reduced { registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), ptCandB0); registry.fill(HIST("hCPA"), candidate.cpa(), ptCandB0); registry.fill(HIST("hEta"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidity"), yB0(candidate), ptCandB0); + registry.fill(HIST("hRapidity"), hfHelper.yB0(candidate), ptCandB0); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), ptCandB0); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandB0); registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), ptCandB0); @@ -161,21 +164,26 @@ struct HfTaskB0Reduced { } // process /// B0 MC analysis and fill histograms - void processMc(soa::Join const& candidates, - aod::HfB0McGenReduced const& particlesMc, - aod::HfCand3ProngReduced const&) + void processMc(soa::Join const& candidates, + aod::HfMcGenRedB0s const& mcParticles, + aod::HfRed3Prongs const&) { // MC rec - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { if (!TESTBIT(candidate.hfflag(), hf_cand_b0::DecayType::B0ToDPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yB0(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yB0(candidate)) > yCandRecoMax) { continue; } auto ptCandB0 = candidate.pt(); - auto candD = candidate.prong0_as(); + auto candD = candidate.prong0_as(); + std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; + std::array posSvD{candD.xSecondaryVertex(), candD.ySecondaryVertex(), candD.zSecondaryVertex()}; + std::array momD{candD.px(), candD.py(), candD.pz()}; + auto cospD = RecoDecay::cpa(posPv, posSvD, momD); + auto decLenD = RecoDecay::distance(posPv, posSvD); if (TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_b0::DecayType::B0ToDPi)) { registry.fill(HIST("hPtGenSig"), candidate.ptMother()); @@ -183,43 +191,42 @@ struct HfTaskB0Reduced { registry.fill(HIST("hCPARecSig"), candidate.cpa(), ptCandB0); registry.fill(HIST("hCPAxyRecSig"), candidate.cpaXY(), ptCandB0); registry.fill(HIST("hEtaRecSig"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidityRecSig"), yB0(candidate), ptCandB0); + registry.fill(HIST("hRapidityRecSig"), hfHelper.yB0(candidate), ptCandB0); registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), ptCandB0); registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), ptCandB0); - registry.fill(HIST("hMassRecSig"), invMassB0ToDPi(candidate), ptCandB0); + registry.fill(HIST("hMassRecSig"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), ptCandB0); registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), ptCandB0); registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), ptCandB0); registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1(), ptCandB0); registry.fill(HIST("hImpParProdB0RecSig"), candidate.impactParameterProduct(), ptCandB0); registry.fill(HIST("hDecLengthNormRecSig"), candidate.decayLengthXYNormalised(), ptCandB0); - registry.fill(HIST("hCPADRecSig"), candD.cpa(), ptCandB0); - registry.fill(HIST("hDecLengthDRecSig"), candD.decayLength(), ptCandB0); + registry.fill(HIST("hCPADRecSig"), cospD, ptCandB0); + registry.fill(HIST("hDecLengthDRecSig"), decLenD, ptCandB0); registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandB0); } else { registry.fill(HIST("hPtRecBg"), ptCandB0); registry.fill(HIST("hCPARecBg"), candidate.cpa(), ptCandB0); registry.fill(HIST("hCPAxyRecBg"), candidate.cpaXY(), ptCandB0); registry.fill(HIST("hEtaRecBg"), candidate.eta(), ptCandB0); - registry.fill(HIST("hRapidityRecBg"), yB0(candidate), ptCandB0); + registry.fill(HIST("hRapidityRecBg"), hfHelper.yB0(candidate), ptCandB0); registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), ptCandB0); registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), ptCandB0); - registry.fill(HIST("hMassRecBg"), invMassB0ToDPi(candidate), ptCandB0); + registry.fill(HIST("hMassRecBg"), hfHelper.invMassB0ToDPi(candidate), ptCandB0); registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), ptCandB0); registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), ptCandB0); registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), ptCandB0); registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1(), ptCandB0); registry.fill(HIST("hImpParProdB0RecBg"), candidate.impactParameterProduct(), ptCandB0); registry.fill(HIST("hDecLengthNormRecBg"), candidate.decayLengthXYNormalised(), ptCandB0); - registry.fill(HIST("hCPADRecBg"), candD.cpa(), ptCandB0); - registry.fill(HIST("hDecLengthDRecBg"), candD.decayLength(), ptCandB0); + registry.fill(HIST("hCPADRecBg"), cospD, ptCandB0); + registry.fill(HIST("hDecLengthDRecBg"), decLenD, ptCandB0); registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandB0); } } // rec // MC gen. level - // Printf("MC Particles: %d", particlesMc.size()); - for (auto const& particle : particlesMc) { + for (const auto& particle : mcParticles) { auto ptParticle = particle.ptTrack(); auto yParticle = particle.yTrack(); auto etaParticle = particle.etaTrack(); diff --git a/PWGHF/D2H/Tasks/taskBplus.cxx b/PWGHF/D2H/Tasks/taskBplus.cxx index fb2ac6ee208..b8e9cafbeb0 100644 --- a/PWGHF/D2H/Tasks/taskBplus.cxx +++ b/PWGHF/D2H/Tasks/taskBplus.cxx @@ -20,8 +20,10 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -30,9 +32,6 @@ using namespace o2; using namespace o2::aod; using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_bplus; -using namespace o2::analysis::hf_cuts_bplus_to_d0_pi; using namespace o2::framework::expressions; // string definitions, used for histogram axis labels @@ -48,8 +47,14 @@ struct HfTaskBplus { Configurable selectionFlagBplus{"selectionFlagBplus", 1, "Selection Flag for B+"}; Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_bplus_to_d0_pi::vecBinsPt}, "pT bin limits"}; + // O2DatabasePDG service + Service pdg; + HfHelper hfHelper; + Partition> selectedBPlusCandidates = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= selectionFlagBplus; Partition> selectedBPlusCandidatesMC = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= selectionFlagBplus; @@ -64,7 +69,7 @@ struct HfTaskBplus { {"hPtGenSig", bPlusCandMatch + "candidate #it{p}_{T}^{gen.} (GeV/#it{c});" + entries, {HistType::kTH1F, {{300, 0., 30.}}}}, {"hPtGen", mcParticleMatched + "candidate #it{p}_{T} (GeV/#it{c});" + entries, {HistType::kTH1F, {{300, 0., 30.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { const AxisSpec axisMass{150, 4.5, 6.0}; const AxisSpec axisCPA{120, -1.1, 1.1}; @@ -94,6 +99,7 @@ struct HfTaskBplus { registry.add("hInvMassD0", bPlusCandTitle + "prong0, D0 inv. mass (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {{500, 1.4, 2.4}, axisPtB}}); registry.add("hCPAFinerBinning", bPlusCandTitle + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); registry.add("hCPAxyFinerBinning", bPlusCandTitle + "candidate cosine of pointing angle xy;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); + // histograms MC: Gen Level registry.add("hEtaGen", mcParticleMatched + "candidate #it{#eta}^{gen};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); registry.add("hYGen", mcParticleMatched + "candidate #it{y}^{gen};" + stringPt, {HistType::kTH2F, {axisRapidity, axisPtB}}); registry.add("hPtProng0Gen", mcParticleMatched + "prong 0 #it{p}_{T}^{gen} (GeV/#it{c});" + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); @@ -102,6 +108,11 @@ struct HfTaskBplus { registry.add("hYProng1Gen", mcParticleMatched + "prong 1 #it{y}^{gen};" + stringPt, {HistType::kTH2F, {axisRapidity, axisPtB}}); registry.add("hEtaProng0Gen", mcParticleMatched + "prong 0 #it{#eta}^{gen};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); registry.add("hEtaProng1Gen", mcParticleMatched + "prong 1 #it{#eta}^{gen};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); + registry.add("hPtGenWithRapidityBelowHalf", "MC particles (generated - |#it{y}^{gen}|<0.5);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hEtaGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hYGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + // histograms MC: Reco Level registry.add("hCPARecSig", bPlusCandMatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); registry.add("hCPARecBg", bPlusCandUnmatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); registry.add("hCPAxyRecSig", bPlusCandMatch + "candidate CPAxy;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); @@ -135,131 +146,160 @@ struct HfTaskBplus { registry.add("hCPAxyFinerBinningRecBg", bPlusCandMatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); } - void process(aod::Collisions const& collision, soa::Join const&, soa::Join const&, aod::BigTracks const&) + /// Selection of B+ daughter in geometrical acceptance + /// \param etaProng is the pseudorapidity of B+ prong + /// \param ptProng is the pT of B+ prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + void process(aod::Collisions const& collision, + soa::Join const&, + soa::Join const&, + aod::Tracks const&) { for (const auto& candidate : selectedBPlusCandidates) { if (!TESTBIT(candidate.hfflag(), hf_cand_bplus::DecayType::BplusToD0Pi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yBplus(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { continue; } - + auto ptCandBplus = candidate.pt(); auto candD0 = candidate.prong0_as>(); - auto candPi = candidate.prong1_as(); + auto candPi = candidate.prong1(); - registry.fill(HIST("hMass"), invMassBplusToD0Pi(candidate), candidate.pt()); - registry.fill(HIST("hPtCand"), candidate.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassBplusToD0Pi(candidate), ptCandBplus); + registry.fill(HIST("hPtCand"), ptCandBplus); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); - registry.fill(HIST("hd0d0"), candidate.impactParameterProduct(), candidate.pt()); - registry.fill(HIST("hDecLength"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("hDecLengthXY"), candidate.decayLengthXY(), candidate.pt()); - registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), candidate.pt()); - registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), candidate.pt()); - registry.fill(HIST("hCPA"), candidate.cpa(), candidate.pt()); - registry.fill(HIST("hCPAxy"), candidate.cpaXY(), candidate.pt()); - registry.fill(HIST("hEta"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hRapidity"), yBplus(candidate), candidate.pt()); - registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), candidate.pt()); - registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), candidate.pt()); - registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), candidate.pt()); - registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), candidate.pt()); + registry.fill(HIST("hd0d0"), candidate.impactParameterProduct(), ptCandBplus); + registry.fill(HIST("hDecLength"), candidate.decayLength(), ptCandBplus); + registry.fill(HIST("hDecLengthXY"), candidate.decayLengthXY(), ptCandBplus); + registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), ptCandBplus); + registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), ptCandBplus); + registry.fill(HIST("hCPA"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxy"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hEta"), candidate.eta(), ptCandBplus); + registry.fill(HIST("hRapidity"), hfHelper.yBplus(candidate), ptCandBplus); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), ptCandBplus); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandBplus); + registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), ptCandBplus); + registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), ptCandBplus); if (candPi.sign() > 0) { - registry.fill(HIST("hInvMassD0"), invMassD0barToKPi(candD0), candidate.pt()); + registry.fill(HIST("hInvMassD0"), hfHelper.invMassD0barToKPi(candD0), ptCandBplus); } else { - registry.fill(HIST("hInvMassD0"), invMassD0ToPiK(candD0), candidate.pt()); + registry.fill(HIST("hInvMassD0"), hfHelper.invMassD0ToPiK(candD0), ptCandBplus); } - registry.fill(HIST("hCPAFinerBinning"), candidate.cpa(), candidate.pt()); - registry.fill(HIST("hCPAxyFinerBinning"), candidate.cpaXY(), candidate.pt()); + registry.fill(HIST("hCPAFinerBinning"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyFinerBinning"), candidate.cpaXY(), ptCandBplus); } // candidate loop } // process void processMc(soa::Join const&, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks, aod::HfCand2Prong const&) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks, + aod::HfCand2Prong const&) { // MC rec for (const auto& candidate : selectedBPlusCandidatesMC) { if (!TESTBIT(candidate.hfflag(), hf_cand_bplus::DecayType::BplusToD0Pi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yBplus(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { continue; } + auto ptCandBplus = candidate.pt(); + // auto candD0 = candidate.prong0_as(); if (TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_bplus::DecayType::BplusToD0Pi)) { - auto indexMother = RecoDecay::getMother(particlesMC, candidate.prong1_as().mcParticle_as>(), pdg::Code::kBPlus, true); - auto particleMother = particlesMC.rawIteratorAt(indexMother); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), pdg::Code::kBPlus, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("hPtGenSig"), particleMother.pt()); - registry.fill(HIST("hPtRecSig"), candidate.pt()); - registry.fill(HIST("hCPARecSig"), candidate.cpa(), candidate.pt()); - registry.fill(HIST("hCPAxyRecSig"), candidate.cpaXY(), candidate.pt()); - registry.fill(HIST("hCPAFinerBinningRecSig"), candidate.cpa(), candidate.pt()); - registry.fill(HIST("hCPAxyFinerBinningRecSig"), candidate.cpaXY(), candidate.pt()); - registry.fill(HIST("hEtaRecSig"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hRapidityRecSig"), yBplus(candidate), candidate.pt()); - registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), candidate.pt()); - registry.fill(HIST("hMassRecSig"), invMassBplusToD0Pi(candidate), candidate.pt()); - registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), candidate.pt()); - registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), candidate.pt()); - registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), candidate.pt()); - registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1(), candidate.pt()); - registry.fill(HIST("hd0d0RecSig"), candidate.impactParameterProduct(), candidate.pt()); - registry.fill(HIST("hDecLengthNormRecSig"), candidate.decayLengthXYNormalised(), candidate.pt()); + registry.fill(HIST("hPtRecSig"), ptCandBplus); + registry.fill(HIST("hCPARecSig"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyRecSig"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hCPAFinerBinningRecSig"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyFinerBinningRecSig"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hEtaRecSig"), candidate.eta(), ptCandBplus); + registry.fill(HIST("hRapidityRecSig"), hfHelper.yBplus(candidate), ptCandBplus); + registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), ptCandBplus); + registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), ptCandBplus); + registry.fill(HIST("hMassRecSig"), hfHelper.invMassBplusToD0Pi(candidate), ptCandBplus); + registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), ptCandBplus); + registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), ptCandBplus); + registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), ptCandBplus); + registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1(), ptCandBplus); + registry.fill(HIST("hd0d0RecSig"), candidate.impactParameterProduct(), ptCandBplus); + registry.fill(HIST("hDecLengthNormRecSig"), candidate.decayLengthXYNormalised(), ptCandBplus); } else { - registry.fill(HIST("hPtRecBg"), candidate.pt()); - registry.fill(HIST("hCPARecBg"), candidate.cpa(), candidate.pt()); - registry.fill(HIST("hCPAxyRecBg"), candidate.cpaXY(), candidate.pt()); - registry.fill(HIST("hCPAFinerBinningRecBg"), candidate.cpa(), candidate.pt()); - registry.fill(HIST("hCPAxyFinerBinningRecBg"), candidate.cpaXY(), candidate.pt()); - registry.fill(HIST("hEtaRecBg"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hRapidityRecBg"), yBplus(candidate), candidate.pt()); - registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), candidate.pt()); - registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), candidate.pt()); - registry.fill(HIST("hMassRecBg"), invMassBplusToD0Pi(candidate), candidate.pt()); - registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), candidate.pt()); - registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), candidate.pt()); - registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), candidate.pt()); - registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1(), candidate.pt()); - registry.fill(HIST("hd0d0RecBg"), candidate.impactParameterProduct(), candidate.pt()); - registry.fill(HIST("hDecLengthNormRecBg"), candidate.decayLengthXYNormalised(), candidate.pt()); + registry.fill(HIST("hPtRecBg"), ptCandBplus); + registry.fill(HIST("hCPARecBg"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyRecBg"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hCPAFinerBinningRecBg"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyFinerBinningRecBg"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hEtaRecBg"), candidate.eta(), ptCandBplus); + registry.fill(HIST("hRapidityRecBg"), hfHelper.yBplus(candidate), ptCandBplus); + registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), ptCandBplus); + registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), ptCandBplus); + registry.fill(HIST("hMassRecBg"), hfHelper.invMassBplusToD0Pi(candidate), ptCandBplus); + registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), ptCandBplus); + registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), ptCandBplus); + registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), ptCandBplus); + registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1(), ptCandBplus); + registry.fill(HIST("hd0d0RecBg"), candidate.impactParameterProduct(), ptCandBplus); + registry.fill(HIST("hDecLengthNormRecBg"), candidate.decayLengthXYNormalised(), ptCandBplus); } } // rec // MC gen. level - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bplus::DecayType::BplusToD0Pi)) { - auto yParticle = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(pdg::Code::kBPlus)); + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassBPlus); if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { continue; } float ptProngs[2], yProngs[2], etaProngs[2]; int counter = 0; - for (auto& daught : particle.daughters_as()) { + for (const auto& daught : particle.daughters_as()) { ptProngs[counter] = daught.pt(); etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(array{daught.px(), daught.py(), daught.pz()}, RecoDecay::getMassPDG(daught.pdgCode())); + yProngs[counter] = RecoDecay::y(std::array{daught.px(), daught.py(), daught.pz()}, pdg->Mass(daught.pdgCode())); counter++; } - registry.fill(HIST("hPtProng0Gen"), ptProngs[0], particle.pt()); - registry.fill(HIST("hPtProng1Gen"), ptProngs[1], particle.pt()); - registry.fill(HIST("hYProng0Gen"), yProngs[0], particle.pt()); - registry.fill(HIST("hYProng1Gen"), yProngs[1], particle.pt()); - registry.fill(HIST("hEtaProng0Gen"), etaProngs[0], particle.pt()); - registry.fill(HIST("hEtaProng1Gen"), etaProngs[1], particle.pt()); + registry.fill(HIST("hPtProng0Gen"), ptProngs[0], ptParticle); + registry.fill(HIST("hPtProng1Gen"), ptProngs[1], ptParticle); + registry.fill(HIST("hYProng0Gen"), yProngs[0], ptParticle); + registry.fill(HIST("hYProng1Gen"), yProngs[1], ptParticle); + registry.fill(HIST("hEtaProng0Gen"), etaProngs[0], ptParticle); + registry.fill(HIST("hEtaProng1Gen"), etaProngs[1], ptParticle); // if (yCandMax >= 0. && (std::abs(yProngs[0]) > yCandMax || std::abs(yProngs[1]) > yCandMax)) // continue; - registry.fill(HIST("hPtGen"), particle.pt()); - registry.fill(HIST("hYGen"), yParticle, particle.pt()); - registry.fill(HIST("hEtaGen"), particle.eta(), particle.pt()); + registry.fill(HIST("hPtGen"), ptParticle); + registry.fill(HIST("hYGen"), yParticle, ptParticle); + registry.fill(HIST("hEtaGen"), particle.eta(), ptParticle); + // generated B0 with |y|<0.5 + if (std::abs(yParticle) < 0.5) { + registry.fill(HIST("hPtGenWithRapidityBelowHalf"), ptParticle); + } + + // reject B0 daughters that are not in geometrical acceptance + if (!isProngInAcceptance(etaProngs[0], ptProngs[0]) || !isProngInAcceptance(etaProngs[1], ptProngs[1])) { + continue; + } + registry.fill(HIST("hPtGenWithProngsInAcceptance"), ptParticle); + registry.fill(HIST("hYGenWithProngsInAcceptance"), yParticle, ptParticle); + registry.fill(HIST("hEtaGenWithProngsInAcceptance"), particle.eta(), ptParticle); } } // gen } // processMc diff --git a/PWGHF/D2H/Tasks/taskBplusReduced.cxx b/PWGHF/D2H/Tasks/taskBplusReduced.cxx new file mode 100644 index 00000000000..0224cec2f31 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskBplusReduced.cxx @@ -0,0 +1,312 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file taskBplusReduced.cxx +/// \brief B+ → D0bar π+ → (π+ K-) π+ analysis task +/// +/// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// string definitions, used for histogram axis labels +const TString stringPt = "#it{p}_{T} (GeV/#it{c})"; +const TString bPlusCandTitle = "B+ candidates;"; +const TString entries = "entries"; +const TString bPlusCandMatch = "B+ candidates (matched);"; +const TString bPlusCandUnmatch = "B+ candidates (unmatched);"; +const TString mcParticleMatched = "MC particles (matched);"; + +/// B+ analysis task +struct HfTaskBplusReduced { + Configurable selectionFlagBplus{"selectionFlagBplus", 1, "Selection Flag for Bplus"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; + Configurable> binsPt{"binsPt", std::vector{hf_cuts_bplus_to_d0_pi::vecBinsPt}, "pT bin limits"}; + + HfHelper hfHelper; + + Filter filterSelectCandidates = (aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= selectionFlagBplus); + + HistogramRegistry registry{ + "registry", + {{"hPtProng0", bPlusCandTitle + "prong 0 #it{p}_{T} (GeV/#it{c});" + entries, {HistType::kTH1F, {{1000, 0., 50.}}}}, + {"hPtProng1", bPlusCandTitle + "prong 1 #it{p}_{T} (GeV/#it{c});" + entries, {HistType::kTH1F, {{200, 0., 10.}}}}, + {"hPtCand", bPlusCandTitle + "candidate #it{p}_{T} (GeV/#it{c});" + entries, {HistType::kTH1F, {{1000, 0., 50.}}}}, + {"hCentrality", "centrality;centrality percentile;" + entries, {HistType::kTH1F, {{100, 0., 100.}}}}, + {"hPtRecSig", bPlusCandMatch + "candidate #it{p}_{T} (GeV/#it{c});" + entries, {HistType::kTH1F, {{300, 0., 30.}}}}, + {"hPtRecBg", bPlusCandUnmatch + "candidate #it{p}_{T} (GeV/#it{c});" + entries, {HistType::kTH1F, {{300, 0., 30.}}}}, + {"hPtGenSig", bPlusCandMatch + "candidate #it{p}_{T}^{gen.} (GeV/#it{c});" + entries, {HistType::kTH1F, {{300, 0., 30.}}}}, + {"hPtGen", mcParticleMatched + "candidate #it{p}_{T} (GeV/#it{c});" + entries, {HistType::kTH1F, {{300, 0., 30.}}}}}}; + + void init(InitContext&) + { + const AxisSpec axisMass{150, 4.5, 6.0}; + const AxisSpec axisCPA{120, -1.1, 1.1}; + const AxisSpec axisCPAFiner{300, 0.85, 1.0}; + const AxisSpec axisPtProng{100, 0., 10.}; + const AxisSpec axisD0Prong{200, -0.05, 0.05}; + const AxisSpec axisImpParProd{200, -0.001, 0.001}; + const AxisSpec axisDecLength{100, 0., 0.5}; + const AxisSpec axisNormDecLength{40, 0., 20}; + const AxisSpec axisEta{100, -2., 2.}; + const AxisSpec axisRapidity{100, -2., 2.}; + const AxisSpec axisPtB{(std::vector)binsPt, "#it{p}_{T}^{B^{+}} (GeV/#it{c})"}; + // histograms process + registry.add("hMass", bPlusCandTitle + "inv. mass #bar{D^{0}}#pi^{+} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMass, axisPtB}}); + registry.add("hDecLength", bPlusCandTitle + "decay length (cm);" + stringPt, {HistType::kTH2F, {axisDecLength, axisPtB}}); + registry.add("hDecLengthXY", bPlusCandTitle + "decay length xy (cm);" + stringPt, {HistType::kTH2F, {axisDecLength, axisPtB}}); + registry.add("hd0Prong0", bPlusCandTitle + "prong 0 DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisD0Prong, axisPtB}}); + registry.add("hd0Prong1", bPlusCandTitle + "prong 1 DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisD0Prong, axisPtB}}); + registry.add("hCPA", bPlusCandTitle + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); + registry.add("hCPAxy", bPlusCandTitle + "candidate cosine of pointing angle xy;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); + registry.add("hEta", bPlusCandTitle + "candidate #it{#eta};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); + registry.add("hRapidity", bPlusCandTitle + "candidate #it{y};" + stringPt, {HistType::kTH2F, {axisRapidity, axisPtB}}); + registry.add("hImpParErr", bPlusCandTitle + "candidate impact parameter error (cm);" + stringPt, {HistType::kTH2F, {{100, -1., 1.}, axisPtB}}); + registry.add("hDecLenErr", bPlusCandTitle + "candidate decay length error (cm);" + stringPt, {HistType::kTH2F, {{100, 0., 1.}, axisPtB}}); + registry.add("hDecLenXYErr", bPlusCandTitle + "candidate decay length xy error (cm);" + stringPt, {HistType::kTH2F, {{100, 0., 1.}, axisPtB}}); + registry.add("hd0d0", bPlusCandTitle + "candidate product of DCAxy to prim. vertex (cm^{2});" + stringPt, {HistType::kTH2F, {axisImpParProd, axisPtB}}); + registry.add("hInvMassD0", bPlusCandTitle + "prong0, D0 inv. mass (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {{500, 1.4, 2.4}, axisPtB}}); + registry.add("hCPAFinerBinning", bPlusCandTitle + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); + registry.add("hCPAxyFinerBinning", bPlusCandTitle + "candidate cosine of pointing angle xy;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); + // histograms processMC - Gen Level + registry.add("hEtaGen", mcParticleMatched + "candidate #it{#eta}^{gen};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); + registry.add("hYGen", mcParticleMatched + "candidate #it{y}^{gen};" + stringPt, {HistType::kTH2F, {axisRapidity, axisPtB}}); + registry.add("hPtProng0Gen", mcParticleMatched + "prong 0 #it{p}_{T}^{gen} (GeV/#it{c});" + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtProng1Gen", mcParticleMatched + "prong 1 #it{p}_{T}^{gen} (GeV/#it{c});" + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hYProng0Gen", mcParticleMatched + "prong 0 #it{y}^{gen};" + stringPt, {HistType::kTH2F, {axisRapidity, axisPtB}}); + registry.add("hYProng1Gen", mcParticleMatched + "prong 1 #it{y}^{gen};" + stringPt, {HistType::kTH2F, {axisRapidity, axisPtB}}); + registry.add("hEtaProng0Gen", mcParticleMatched + "prong 0 #it{#eta}^{gen};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); + registry.add("hEtaProng1Gen", mcParticleMatched + "prong 1 #it{#eta}^{gen};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); + registry.add("hPtProngsVsPtBGen", mcParticleMatched + "prong 0 #it{p}_{T}^{gen} (GeV/#it{c});prong 1 #it{p}_{T}^{gen} (GeV/#it{c});" + stringPt, {HistType::kTH3F, {axisPtProng, axisPtProng, axisPtB}}); + registry.add("hYProngsVsBplusGen", mcParticleMatched + "prong 0 #it{y}^{gen};prong 1 #it{y}^{gen};" + stringPt, {HistType::kTH3F, {axisRapidity, axisRapidity, axisPtB}}); + registry.add("hEtaProngsVsBplusGen", mcParticleMatched + "prong 0 #it{#eta}^{gen};prong 1 #it{#eta}^{gen};" + stringPt, {HistType::kTH3F, {axisEta, axisEta, axisPtB}}); + registry.add("hPtGenWithRapidityBelowHalf", "MC particles (generated - |#it{y}^{gen}|<0.5);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hEtaGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hYGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + // histograms processMC - Reco Level + registry.add("hCPARecSig", bPlusCandMatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); + registry.add("hCPARecBg", bPlusCandUnmatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); + registry.add("hCPAxyRecSig", bPlusCandMatch + "candidate CPAxy;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); + registry.add("hCPAxyRecBg", bPlusCandUnmatch + "candidate CPAxy;" + stringPt, {HistType::kTH2F, {axisCPA, axisPtB}}); + registry.add("hEtaRecSig", bPlusCandMatch + "candidate #it{#eta};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); + registry.add("hEtaRecBg", bPlusCandUnmatch + "candidate #it{#eta};" + stringPt, {HistType::kTH2F, {axisEta, axisPtB}}); + registry.add("hRapidityRecSig", bPlusCandMatch + "candidate #it{y};" + stringPt, {HistType::kTH2F, {axisRapidity, axisPtB}}); + registry.add("hRapidityRecBg", bPlusCandUnmatch + "candidate #it{#y};" + stringPt, {HistType::kTH2F, {axisRapidity, axisPtB}}); + registry.add("hPtProng0RecSig", bPlusCandMatch + "prong 0 #it{p}_{T} (GeV/#it{c});" + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtProng1RecSig", bPlusCandMatch + "prong 1 #it{p}_{T} (GeV/#it{c});" + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtProngsVsBplusRecBg", bPlusCandUnmatch + "prong 0 #it{p}_{T} (GeV/#it{c});prong 1 #it{p}_{T} (GeV/#it{c});" + stringPt, {HistType::kTH3F, {axisPtProng, axisPtProng, axisPtB}}); + registry.add("hPtProng0RecBg", bPlusCandUnmatch + "prong 0 #it{p}_{T} (GeV/#it{c});" + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtProng1RecBg", bPlusCandUnmatch + "prong 1 #it{p}_{T} (GeV/#it{c});" + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hMassRecSig", bPlusCandMatch + "inv. mass #bar{D^{0}}#pi^{+} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMass, axisPtB}}); + registry.add("hMassRecBg", bPlusCandUnmatch + "inv. mass #bar{D^{0}}#pi^{+} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMass, axisPtB}}); + registry.add("hd0Prong0RecSig", bPlusCandMatch + "prong 0 DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisD0Prong, axisPtB}}); + registry.add("hd0Prong1RecSig", bPlusCandMatch + "prong 1 DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisD0Prong, axisPtB}}); + registry.add("hd0Prong0RecBg", bPlusCandUnmatch + "prong 0 DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisD0Prong, axisPtB}}); + registry.add("hd0Prong1RecBg", bPlusCandUnmatch + "prong 1 DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisD0Prong, axisPtB}}); + registry.add("hDecLengthRecSig", bPlusCandMatch + "candidate decay length (cm);" + stringPt, {HistType::kTH2F, {axisDecLength, axisPtB}}); + registry.add("hDecLengthXYRecSig", bPlusCandMatch + "candidate decay length xy (cm);" + stringPt, {HistType::kTH2F, {axisDecLength, axisPtB}}); + registry.add("hDecLengthRecBg", bPlusCandUnmatch + "candidate decay length (cm);" + stringPt, {HistType::kTH2F, {axisDecLength, axisPtB}}); + registry.add("hDecLengthXYRecBg", bPlusCandUnmatch + "candidate decay length xy(cm);" + stringPt, {HistType::kTH2F, {axisDecLength, axisPtB}}); + registry.add("hDecLengthNormRecSig", bPlusCandMatch + "candidate normalized decay length (cm);" + stringPt, {HistType::kTH2F, {axisNormDecLength, axisPtB}}); + registry.add("hDecLengthNormRecBg", bPlusCandUnmatch + "candidate normalized decay length (cm);" + stringPt, {HistType::kTH2F, {axisNormDecLength, axisPtB}}); + registry.add("hd0d0RecSig", bPlusCandMatch + "product of DCAxy to prim. vertex (cm^{2});" + stringPt, {HistType::kTH2F, {axisImpParProd, axisPtB}}); + registry.add("hd0d0RecBg", bPlusCandUnmatch + "product of DCAxy to prim. vertex (cm^{2});" + stringPt, {HistType::kTH2F, {axisImpParProd, axisPtB}}); + // MC histograms with finer binning + registry.add("hCPAFinerBinningRecSig", bPlusCandMatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); + registry.add("hCPAFinerBinningRecBg", bPlusCandMatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); + registry.add("hCPAxyFinerBinningRecSig", bPlusCandMatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); + registry.add("hCPAxyFinerBinningRecBg", bPlusCandMatch + "candidate cosine of pointing angle;" + stringPt, {HistType::kTH2F, {axisCPAFiner, axisPtB}}); + // histograms prong0(D0) - Reco Level + registry.add("hCPAD0RecSig", bPlusCandMatch + "prong0 (D^{0}) cosine of pointing angle;#it{p}_{T}(D0) (GeV/#it{c})" + entries, {HistType::kTH2F, {{220, 0., 1.1}, {120, 0., 60.}}}); + registry.add("hCPAD0RecBg", bPlusCandUnmatch + "prong0 (D^{0}) cosine of pointing angle;#it{p}_{T}(D0) (GeV/#it{c})" + entries, {HistType::kTH2F, {{220, 0., 1.1}, {120, 0., 60.}}}); + registry.add("hDecLengthD0RecSig", bPlusCandMatch + "prong0 D^{0} decay length (cm);#it{p}_{T}(D0) (GeV/#it{c})" + entries, {HistType::kTH2F, {{100, 0., 0.5}, {120, 0., 60.}}}); + registry.add("hDecLengthD0RecBg", bPlusCandUnmatch + "prong0 D^{0} candidate decay length (cm);#it{p}_{T}(D0) (GeV/#it{c})" + entries, {HistType::kTH2F, {{100, 0., 0.5}, {120, 0., 60.}}}); + } + + /// Selection of B+ daughter in geometrical acceptance + /// \param etaProng is the pseudorapidity of B+ prong + /// \param ptProng is the pT of B+ prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + void process(soa::Filtered> const& candidates, + aod::HfRed2Prongs const&, + aod::HfRedTracks const&) + { + for (const auto& candidate : candidates) { + if (!TESTBIT(candidate.hfflag(), hf_cand_bplus::DecayType::BplusToD0Pi)) { + continue; + } + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + + auto candD0 = candidate.prong0_as(); + auto candPi = candidate.prong1_as(); + auto ptCandBplus = candidate.pt(); + auto invMassD0 = (candPi.signed1Pt() < 0) ? candD0.invMassD0() : candD0.invMassD0Bar(); + + registry.fill(HIST("hMass"), hfHelper.invMassBplusToD0Pi(candidate), ptCandBplus); + registry.fill(HIST("hPtCand"), ptCandBplus); + registry.fill(HIST("hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), candidate.ptProng1()); + registry.fill(HIST("hd0d0"), candidate.impactParameterProduct(), ptCandBplus); + registry.fill(HIST("hDecLength"), candidate.decayLength(), ptCandBplus); + registry.fill(HIST("hDecLengthXY"), candidate.decayLengthXY(), ptCandBplus); + registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), ptCandBplus); + registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), ptCandBplus); + registry.fill(HIST("hCPA"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxy"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hEta"), candidate.eta(), ptCandBplus); + registry.fill(HIST("hRapidity"), hfHelper.yBplus(candidate), ptCandBplus); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), ptCandBplus); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandBplus); + registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), ptCandBplus); + registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), ptCandBplus); + registry.fill(HIST("hInvMassD0"), invMassD0, ptCandBplus); + registry.fill(HIST("hCPAFinerBinning"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyFinerBinning"), candidate.cpaXY(), ptCandBplus); + } // candidate loop + } // process + + /// B+ MC analysis and fill histograms + void processMc(soa::Join const& candidates, + aod::HfMcGenRedBps const& mcParticles, + aod::HfRed2Prongs const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (!TESTBIT(candidate.hfflag(), hf_cand_bplus::DecayType::BplusToD0Pi)) { + continue; + } + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + + auto ptCandBplus = candidate.pt(); + auto candD0 = candidate.prong0_as(); + std::array posPv{candidate.posX(), candidate.posY(), candidate.posZ()}; + std::array posSvD{candD0.xSecondaryVertex(), candD0.ySecondaryVertex(), candD0.zSecondaryVertex()}; + std::array momD{candD0.px(), candD0.py(), candD0.pz()}; + auto cospD0 = RecoDecay::cpa(posPv, posSvD, momD); + auto decLenD0 = RecoDecay::distance(posPv, posSvD); + + if (TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_bplus::DecayType::BplusToD0Pi)) { + + registry.fill(HIST("hPtGenSig"), candidate.ptMother()); + registry.fill(HIST("hPtRecSig"), ptCandBplus); + registry.fill(HIST("hCPARecSig"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyRecSig"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hCPAFinerBinningRecSig"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyFinerBinningRecSig"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hEtaRecSig"), candidate.eta(), ptCandBplus); + registry.fill(HIST("hRapidityRecSig"), hfHelper.yBplus(candidate), ptCandBplus); + registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), ptCandBplus); + registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), ptCandBplus); + registry.fill(HIST("hMassRecSig"), hfHelper.invMassBplusToD0Pi(candidate), ptCandBplus); + registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), ptCandBplus); + registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), ptCandBplus); + registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), ptCandBplus); + registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1(), ptCandBplus); + registry.fill(HIST("hd0d0RecSig"), candidate.impactParameterProduct(), ptCandBplus); + registry.fill(HIST("hDecLengthNormRecSig"), candidate.decayLengthXYNormalised(), ptCandBplus); + registry.fill(HIST("hCPAD0RecSig"), cospD0, candidate.ptProng0()); + registry.fill(HIST("hDecLengthD0RecSig"), decLenD0, candidate.ptProng0()); + } else { + registry.fill(HIST("hPtRecBg"), ptCandBplus); + registry.fill(HIST("hCPARecBg"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyRecBg"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hCPAFinerBinningRecBg"), candidate.cpa(), ptCandBplus); + registry.fill(HIST("hCPAxyFinerBinningRecBg"), candidate.cpaXY(), ptCandBplus); + registry.fill(HIST("hEtaRecBg"), candidate.eta(), ptCandBplus); + registry.fill(HIST("hRapidityRecBg"), hfHelper.yBplus(candidate), ptCandBplus); + registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), ptCandBplus); + registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), ptCandBplus); + registry.fill(HIST("hMassRecBg"), hfHelper.invMassBplusToD0Pi(candidate), ptCandBplus); + registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), ptCandBplus); + registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), ptCandBplus); + registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), ptCandBplus); + registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1(), ptCandBplus); + registry.fill(HIST("hd0d0RecBg"), candidate.impactParameterProduct(), ptCandBplus); + registry.fill(HIST("hDecLengthNormRecBg"), candidate.decayLengthXYNormalised(), ptCandBplus); + registry.fill(HIST("hCPAD0RecBg"), cospD0, candidate.ptProng0()); + registry.fill(HIST("hDecLengthD0RecBg"), decLenD0, candidate.ptProng0()); + } + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + auto etaParticle = particle.etaTrack(); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + continue; + } + + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array yProngs = {particle.yProng0(), particle.yProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + + registry.fill(HIST("hPtProng0Gen"), ptProngs[0], ptParticle); + registry.fill(HIST("hPtProng1Gen"), ptProngs[1], ptParticle); + registry.fill(HIST("hPtProngsVsPtBGen"), ptProngs[0], ptProngs[1], ptParticle); + registry.fill(HIST("hYProng0Gen"), yProngs[0], ptParticle); + registry.fill(HIST("hYProng1Gen"), yProngs[1], ptParticle); + registry.fill(HIST("hYProngsVsBplusGen"), yProngs[0], yProngs[1], ptParticle); + registry.fill(HIST("hEtaProng0Gen"), etaProngs[0], ptParticle); + registry.fill(HIST("hEtaProng1Gen"), etaProngs[1], ptParticle); + registry.fill(HIST("hEtaProngsVsBplusGen"), etaProngs[0], etaProngs[1], ptParticle); + + registry.fill(HIST("hPtGen"), ptParticle); + registry.fill(HIST("hYGen"), yParticle, ptParticle); + registry.fill(HIST("hEtaGen"), etaParticle, ptParticle); + + // generated B+ with |y|<0.5 + if (std::abs(yParticle) < 0.5) { + registry.fill(HIST("hPtGenWithRapidityBelowHalf"), ptParticle); + } + + // generated B+ with daughters in geometrical acceptance + if (isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1])) { + registry.fill(HIST("hPtGenWithProngsInAcceptance"), ptParticle); + registry.fill(HIST("hYGenWithProngsInAcceptance"), yParticle, ptParticle); + registry.fill(HIST("hEtaGenWithProngsInAcceptance"), etaParticle, ptParticle); + } + } // gen + } // process + PROCESS_SWITCH(HfTaskBplusReduced, processMc, "Process MC", false); +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskBs.cxx b/PWGHF/D2H/Tasks/taskBs.cxx new file mode 100644 index 00000000000..b429ca41803 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskBs.cxx @@ -0,0 +1,317 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file taskBs.cxx +/// \brief Bs → Ds π+ → (K- K+ π-) π+ analysis task +/// \note adapted from taskB0.cxx +/// +/// \author Phil Stahlhut + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// Bs analysis task +struct HfTaskBs { + Configurable selectionFlagBs{"selectionFlagBs", 1, "Selection Flag for Bs"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; + Configurable> binsPt{"binsPt", std::vector{hf_cuts_bs_to_ds_pi::vecBinsPt}, "pT bin limits"}; + // MC checks + Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "Flag to enable DecayType histogram"}; + + Service pdg; + HfHelper hfHelper; + + using TracksWithSel = soa::Join; + + Filter filterSelectCandidates = (aod::hf_sel_candidate_bs::isSelBsToDsPi >= selectionFlagBs); + + HistogramRegistry registry{ + "registry", + {{"hPtProng0", "B^{0}_{s} candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0., 40.}}}}, + {"hPtProng1", "B^{0}_{s} candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 16.}}}}, + {"hPtCand", "B^{0}_{s} candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0., 40.}}}}}}; + + void init(InitContext const&) + { + static const AxisSpec axisMassBs = {300, 4.5, 6.0, "inv. mass (GeV/#it{c}^{2})"}; + static const AxisSpec axisPt = {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}; + + registry.add("hEta", "B^{0}_{s} candidates;B^{0}_{s} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hRapidity", "B^{0}_{s} candidates;B^{0}_{s} candidate #it{y};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hCPA", "B^{0}_{s} candidates;B^{0}_{s} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{110, -1.1, 1.1}, axisPt}}); + registry.add("hMass", "B^{0}_{s} candidates;inv. mass D^{#mp}_{s} #pi^{#pm} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisMassBs, axisPt}}); + registry.add("hDecLength", "B^{0}_{s} candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 0.4}, axisPt}}); + registry.add("hDecLenErr", "B^{0}_{s} candidates;B^{0}_{s} candidate decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, axisPt}}); + registry.add("hDecLengthXY", "B^{0}_{s} candidates;decay length xy (cm);entries", {HistType::kTH2F, {{200, 0., 0.4}, axisPt}}); + registry.add("hDecLenXYErr", "B^{0}_{s} candidates;B^{0}_{s} candidate decay length xy error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, axisPt}}); + registry.add("hd0Prong0", "B^{0}_{s} candidates;prong 0 (D^{#pm}_{s}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -0.05, 0.05}, axisPt}}); + registry.add("hd0Prong1", "B^{0}_{s} candidates;prong 1 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{100, -0.05, 0.05}, axisPt}}); + registry.add("hImpParErr", "B^{0}_{s} candidates;B^{0}_{s} candidate impact parameter error (cm);entries", {HistType::kTH2F, {{100, -1., 1.}, axisPt}}); + registry.add("hIPProd", "B^{0}_{s} candidates;B^{0}_{s} candidate impact parameter product;entries", {HistType::kTH2F, {{100, -0.5, 0.5}, axisPt}}); + registry.add("hInvMassDs", "B^{0}_{s} candidates;prong 0 (D^{#pm}_{s}) inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{500, 0, 5}, axisPt}}); + + registry.add("hPtGenSig", "B^{0}_{s} candidates (gen+rec);candidate #it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtRecSig", "B^{0}_{s} candidates (matched);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtRecBg", "B^{0}_{s} candidates (unmatched);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hEtaRecSig", "B^{0}_{s} candidates (matched);B^{0}_{s} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hEtaRecBg", "B^{0}_{s} candidates (unmatched);B^{0}_{s} candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hRapidityRecSig", "B^{0}_{s} candidates (matched);B^{0}_{s} candidate #it{y};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hRapidityRecBg", "B^{0}_{s} candidates (unmatched);B^{0}_{s} candidate #it{y};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hCPARecSig", "B^{0}_{s} candidates (matched);B^{0}_{s} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{220, 0., 1.1}, axisPt}}); + registry.add("hCPARecBg", "B^{0}_{s} candidates (unmatched);B^{0}_{s} candidate cosine of pointing angle;entries", {HistType::kTH2F, {{220, 0., 1.1}, axisPt}}); + registry.add("hCPAxyRecSig", "B^{0}_{s} candidates (matched);B^{0}_{s} candidate CPAxy;entries", {HistType::kTH2F, {{220, 0., 1.1}, axisPt}}); + registry.add("hCPAxyRecBg", "B^{0}_{s} candidates (unmatched);B^{0}_{s} candidate CPAxy;entries", {HistType::kTH2F, {{220, 0., 1.1}, axisPt}}); + registry.add("hMassRecSig", "B^{0}_{s} candidates (matched);inv. mass D^{#mp}_{s} #pi^{#pm} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 4.0, 7.00}, axisPt}}); + registry.add("hMassRecBg", "B^{0}_{s} candidates (unmatched);inv. mass D^{#mp}_{s} #pi^{#pm} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 4.0, 7.0}, axisPt}}); + registry.add("hDecLengthRecSig", "B^{0}_{s} candidates (matched);B^{0}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, axisPt}}); + registry.add("hDecLengthRecBg", "B^{0}_{s} candidates (unmatched);B^{0}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, axisPt}}); + registry.add("hDecLengthXYRecSig", "B^{0}_{s} candidates (matched);B^{0}_{s} candidate decay length xy (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, axisPt}}); + registry.add("hDecLengthXYRecBg", "B^{0}_{s} candidates (unmatched);B^{0}_{s} candidate decay length xy(cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, axisPt}}); + registry.add("hDecLengthNormRecSig", "B^{0}_{s} candidates (matched);B^{0}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, axisPt}}); + registry.add("hDecLengthNormRecBg", "B^{0}_{s} candidates (unmatched);B^{0}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, axisPt}}); + registry.add("hImpParProdBsRecSig", "B^{0}_{s} candidates (matched);B^{0}_{s} candidate impact parameter product ;entries", {HistType::kTH2F, {{100, -0.01, 0.01}, axisPt}}); + registry.add("hImpParProdBsRecBg", "B^{0}_{s} candidates (unmatched);B^{0}_{s} candidate impact parameter product ;entries", {HistType::kTH2F, {{100, -0.01, 0.01}, axisPt}}); + registry.add("hPtProng0RecSig", "B^{0}_{s} candidates (matched);prong 0 (D^{#pm}_{s}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, axisPt}}); + registry.add("hPtProng0RecBg", "B^{0}_{s} candidates (unmatched);prong 0 (D^{#pm}_{s}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, axisPt}}); + registry.add("hPtProng1RecSig", "B^{0}_{s} candidates (matched);prong 1 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, axisPt}}); + registry.add("hPtProng1RecBg", "B^{0}_{s} candidates (unmatched);prong 1 (#pi^{#pm}) #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, axisPt}}); + registry.add("hd0Prong0RecSig", "B^{0}_{s} candidates (matched);prong 0 (D^{#pm}_{s}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{200, -0.05, 0.05}, axisPt}}); + registry.add("hd0Prong0RecBg", "B^{0}_{s} candidates (unmatched);prong 0 (D^{#pm}_{s}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{200, -0.05, 0.05}, axisPt}}); + registry.add("hd0Prong1RecSig", "B^{0}_{s} candidates (matched);prong 1 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{200, -0.05, 0.05}, axisPt}}); + registry.add("hd0Prong1RecBg", "B^{0}_{s} candidates (unmatched);prong 1 (#pi^{#pm}) DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{200, -0.05, 0.05}, axisPt}}); + registry.add("hCPADsRecSig", "B^{0}_{s} candidates (matched);prong 0 (D^{#pm}_{s}) cosine of pointing angle;entries", {HistType::kTH2F, {{220, 0., 1.1}, axisPt}}); + registry.add("hCPADsRecBg", "B^{0}_{s} candidates (unmatched);prong 0 (D^{#pm}_{s}) cosine of pointing angle;entries", {HistType::kTH2F, {{220, 0., 1.1}, axisPt}}); + registry.add("hDecLengthDsRecSig", "B^{0}_{s} candidates (matched);D^{#pm}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, axisPt}}); + registry.add("hDecLengthDsRecBg", "B^{0}_{s} candidates (unmatched);D^{#pm}_{s} candidate decay length (cm);entries", {HistType::kTH2F, {{100, 0., 0.5}, axisPt}}); + registry.add("hChi2PCARecSig", "B^{0}_{s} candidates (matched);sum of distances of the secondary vertex to its prongs;entries", {HistType::kTH2F, {{240, -0.01, 0.1}, axisPt}}); + registry.add("hChi2PCARecBg", "B^{0}_{s} candidates (unmatched);sum of distances of the secondary vertex to its prongs;entries", {HistType::kTH2F, {{240, -0.01, 0.1}, axisPt}}); + + registry.add("hPtProng0Gen", "MC particles (generated);prong 0 (D_{s}^{#pm}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, axisPt}}); + registry.add("hPtProng1Gen", "MC particles (generated);prong 1 (#pi^{#pm}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{100, 0., 10.}, axisPt}}); + registry.add("hEtaProng0Gen", "MC particles (generated);prong 0 (D^{#pm}_{s}) #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hEtaProng1Gen", "MC particles (generated);prong 1 (#pi^{#pm}) #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hYProng0Gen", "MC particles (generated);prong 0 (D^{#pm}_{s}) #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hYProng1Gen", "MC particles (generated);prong 1 (#pi^{#pm}) #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2, 2}, axisPt}}); + registry.add("hPtGen", "MC particles (generated);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hEtaGen", "MC particles (generated);B^{0}_{s} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hYGen", "MC particles (generated);B^{0}_{s} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hPtGenWithRapidityBelowHalf", "MC particles (generated - |#it{y}^{gen}|<0.5);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hPtGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); + registry.add("hEtaGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0}_{s} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + registry.add("hYGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0}_{s} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); + + if (checkDecayTypeMc) { + constexpr uint8_t kNBinsDecayTypeMc = hf_cand_bs::DecayTypeMc::NDecayTypeMc + 1; + TString labels[kNBinsDecayTypeMc]; + labels[hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi] = "B^{0}_{s} #rightarrow (D^{#mp}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#mp}) #pi^{#pm}"; + labels[hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi] = "B^{0} #rightarrow (D^{#pm}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#pm}) #pi^{#mp}"; + labels[hf_cand_bs::DecayTypeMc::PartlyRecoDecay] = "Partly reconstructed decay channel"; + labels[hf_cand_bs::DecayTypeMc::NDecayTypeMc] = "Other decays"; + static const AxisSpec axisDecayType = {kNBinsDecayTypeMc, 0.5, kNBinsDecayTypeMc + 0.5, ""}; + registry.add("hDecayTypeMc", "DecayType", {HistType::kTH3F, {axisDecayType, axisMassBs, axisPt}}); + for (uint8_t iBin = 0; iBin < kNBinsDecayTypeMc; ++iBin) { + registry.get(HIST("hDecayTypeMc"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin]); + } + } + } + + /// Selection of Bs daughter in geometrical acceptance + /// \param etaProng is the pseudorapidity of Bs prong + /// \param ptProng is the pT of Bs prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + void process(soa::Filtered> const& candidates, + soa::Join const&, + TracksWithSel const&) + { + for (const auto& candidate : candidates) { + if (!TESTBIT(candidate.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { + continue; + } + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + + auto candDs = candidate.prong0_as>(); + + auto ptCandBs = candidate.pt(); + + registry.fill(HIST("hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), candidate.ptProng1()); + registry.fill(HIST("hPtCand"), ptCandBs); + registry.fill(HIST("hEta"), candidate.eta(), ptCandBs); + registry.fill(HIST("hRapidity"), hfHelper.yBs(candidate), ptCandBs); + registry.fill(HIST("hCPA"), candidate.cpa(), ptCandBs); + registry.fill(HIST("hMass"), hfHelper.invMassBsToDsPi(candidate), ptCandBs); + registry.fill(HIST("hDecLength"), candidate.decayLength(), ptCandBs); + registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), ptCandBs); + registry.fill(HIST("hDecLengthXY"), candidate.decayLengthXY(), ptCandBs); + registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), ptCandBs); + registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), ptCandBs); + registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), ptCandBs); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), ptCandBs); + registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandBs); + registry.fill(HIST("hIPProd"), candidate.impactParameterProduct(), ptCandBs); + registry.fill(HIST("hInvMassDs"), hfHelper.invMassDsToKKPi(candDs), ptCandBs); + } // candidate loop + } // process + + /// Bs MC analysis and fill histograms + void processMc(soa::Filtered> const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const&, + soa::Join const&) + { + // MC rec + for (const auto& candidate : candidates) { + if (!TESTBIT(candidate.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { + continue; + } + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + + auto ptCandBs = candidate.pt(); + auto candDs = candidate.prong0_as>(); + auto invMassCandBs = hfHelper.invMassBsToDsPi(candidate); + int flagMcMatchRecBs = std::abs(candidate.flagMcMatchRec()); + + if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi)) { + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), pdg::Code::kBS, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); + + registry.fill(HIST("hPtGenSig"), particleMother.pt()); + registry.fill(HIST("hPtRecSig"), ptCandBs); + registry.fill(HIST("hEtaRecSig"), candidate.eta(), ptCandBs); + registry.fill(HIST("hRapidityRecSig"), hfHelper.yBs(candidate), ptCandBs); + registry.fill(HIST("hCPARecSig"), candidate.cpa(), ptCandBs); + registry.fill(HIST("hCPAxyRecSig"), candidate.cpaXY(), ptCandBs); + registry.fill(HIST("hMassRecSig"), hfHelper.invMassBsToDsPi(candidate), ptCandBs); + registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), ptCandBs); + registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), ptCandBs); + registry.fill(HIST("hDecLengthNormRecSig"), candidate.decayLengthXYNormalised(), ptCandBs); + registry.fill(HIST("hImpParProdBsRecSig"), candidate.impactParameterProduct(), ptCandBs); + registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), ptCandBs); + registry.fill(HIST("hPtProng1RecSig"), candidate.ptProng1(), ptCandBs); + registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), ptCandBs); + registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), ptCandBs); + registry.fill(HIST("hCPADsRecSig"), candDs.cpa(), ptCandBs); + registry.fill(HIST("hDecLengthDsRecSig"), candDs.decayLength(), ptCandBs); + registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandBs); + + if (checkDecayTypeMc) { + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi, invMassCandBs, ptCandBs); + } + } else { + registry.fill(HIST("hPtRecBg"), ptCandBs); + registry.fill(HIST("hEtaRecBg"), candidate.eta(), ptCandBs); + registry.fill(HIST("hRapidityRecBg"), hfHelper.yBs(candidate), ptCandBs); + registry.fill(HIST("hCPARecBg"), candidate.cpa(), ptCandBs); + registry.fill(HIST("hCPAxyRecBg"), candidate.cpaXY(), ptCandBs); + registry.fill(HIST("hMassRecBg"), hfHelper.invMassBsToDsPi(candidate), ptCandBs); + registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), ptCandBs); + registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), ptCandBs); + registry.fill(HIST("hDecLengthNormRecBg"), candidate.decayLengthXYNormalised(), ptCandBs); + registry.fill(HIST("hImpParProdBsRecBg"), candidate.impactParameterProduct(), ptCandBs); + registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), ptCandBs); + registry.fill(HIST("hPtProng1RecBg"), candidate.ptProng1(), ptCandBs); + registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), ptCandBs); + registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), ptCandBs); + registry.fill(HIST("hCPADsRecBg"), candDs.cpa(), ptCandBs); + registry.fill(HIST("hDecLengthDsRecBg"), candDs.decayLength(), ptCandBs); + registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandBs); + + if (checkDecayTypeMc) { + if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi)) { // B0(bar) → Ds± π∓ → (K- K+ π±) π∓ + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi, invMassCandBs, ptCandBs); + } else if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::PartlyRecoDecay)) { // Partly reconstructed decay channel + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::PartlyRecoDecay, invMassCandBs, ptCandBs); + } else { + registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::NDecayTypeMc, invMassCandBs, ptCandBs); + } + } + } + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi)) { + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassBS); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + continue; + } + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(std::array{daught.px(), daught.py(), daught.pz()}, pdg->Mass(daught.pdgCode())); + counter++; + } + + registry.fill(HIST("hPtProng0Gen"), ptProngs[0], ptParticle); + registry.fill(HIST("hPtProng1Gen"), ptProngs[1], ptParticle); + registry.fill(HIST("hEtaProng0Gen"), etaProngs[0], ptParticle); + registry.fill(HIST("hEtaProng1Gen"), etaProngs[1], ptParticle); + registry.fill(HIST("hYProng0Gen"), yProngs[0], ptParticle); + registry.fill(HIST("hYProng1Gen"), yProngs[1], ptParticle); + registry.fill(HIST("hPtGen"), ptParticle); + registry.fill(HIST("hYGen"), yParticle, ptParticle); + registry.fill(HIST("hEtaGen"), particle.eta(), ptParticle); + + // generated Bs with |y|<0.5 + if (std::abs(yParticle) < 0.5) { + registry.fill(HIST("hPtGenWithRapidityBelowHalf"), ptParticle); + } + + // reject Bs daughters that are not in geometrical acceptance + if (!isProngInAcceptance(etaProngs[0], ptProngs[0]) || !isProngInAcceptance(etaProngs[1], ptProngs[1])) { + continue; + } + registry.fill(HIST("hPtGenWithProngsInAcceptance"), ptParticle); + registry.fill(HIST("hEtaGenWithProngsInAcceptance"), particle.eta(), ptParticle); + registry.fill(HIST("hYGenWithProngsInAcceptance"), yParticle, ptParticle); + } + } // gen + } // process + PROCESS_SWITCH(HfTaskBs, processMc, "Process MC", false); +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index ed9095d7b36..8ec3a905cce 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -19,14 +19,14 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; /// D0 analysis task struct HfTaskD0 { @@ -40,8 +40,17 @@ struct HfTaskD0 { Configurable selectionPid{"selectionPid", 1, "Selection Flag for reco PID candidates"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; - Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - Partition> recoFlag2Prong = aod::hf_sel_candidate_d0::isRecoHfFlag >= selectionFlagHf; + HfHelper hfHelper; + + using D0Candidates = soa::Join; + using D0CandidatesMc = soa::Join; + using D0CandidatesKF = soa::Join; + using D0CandidatesMcKF = soa::Join; + + Partition selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition selectedD0CandidatesKF = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isRecoHfFlag >= selectionFlagHf; + Partition selectedD0CandidatesMcKF = aod::hf_sel_candidate_d0::isRecoHfFlag >= selectionFlagHf; HistogramRegistry registry{ "registry", @@ -119,8 +128,16 @@ struct HfTaskD0 { {"hMassReflBkgD0bar", "2-prong candidates (matched);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{120, 1.5848, 2.1848}, {150, 0., 30.}, {20, -5., 5.}}}}, {"hMassSigBkgD0bar", "2-prong candidates (not checked);#it{m}_{inv} (GeV/#it{c}^{2}); #it{p}_{T}; #it{y}", {HistType::kTH3F, {{120, 1.5848, 2.1848}, {150, 0., 30.}, {20, -5., 5.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { + std::array doprocess{doprocessDataWithDCAFitterN, doprocessDataWithKFParticle, doprocessMcWithDCAFitterN, doprocessMcWithKFParticle}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) == 0) { + LOGP(fatal, "At least one process function should be enabled at a time."); + } + if ((doprocessDataWithDCAFitterN || doprocessMcWithDCAFitterN) && (doprocessDataWithKFParticle || doprocessMcWithKFParticle)) { + LOGP(fatal, "DCAFitterN and KFParticle can not be enabled at a time."); + } + auto vbins = (std::vector)binsPt; registry.add("hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{500, 0., 5.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassVsPhi", "2-prong candidates vs phi;inv. mass (#pi K) (GeV/#it{c}^{2});phi (rad);entries", {HistType::kTH3F, {{120, 1.5848, 2.1848}, {vbins, "#it{p}_{T} (GeV/#it{c})"}, {32, 0, o2::constants::math::TwoPI}}}); @@ -161,18 +178,25 @@ struct HfTaskD0 { registry.add("hDecLengthxyVsPtSig", "2-prong candidates;decay length xy (cm) vs #it{p}_{T} for signal;entries", {HistType::kTH2F, {{800, 0., 4.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); } - void process(soa::Join& candidates) + template + void processData(CandType const& candidates) { - for (auto& candidate : selectedD0Candidates) { - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yD0(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yD0(candidate)) > yCandRecoMax) { continue; } - auto massD0 = invMassD0ToPiK(candidate); - auto massD0bar = invMassD0barToKPi(candidate); + float massD0, massD0bar; + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + massD0 = candidate.kfGeoMassD0(); + massD0bar = candidate.kfGeoMassD0bar(); + } else { + massD0 = hfHelper.invMassD0ToPiK(candidate); + massD0bar = hfHelper.invMassD0barToKPi(candidate); + } auto ptCandidate = candidate.pt(); if (candidate.isSelD0() >= selectionFlagD0) { @@ -199,8 +223,8 @@ struct HfTaskD0 { registry.fill(HIST("hd0ErrProng0"), candidate.errorImpactParameter0(), ptCandidate); registry.fill(HIST("hd0ErrProng1"), candidate.errorImpactParameter1(), ptCandidate); registry.fill(HIST("hd0d0"), candidate.impactParameterProduct(), ptCandidate); - registry.fill(HIST("hCTS"), cosThetaStarD0(candidate), ptCandidate); - registry.fill(HIST("hCt"), ctD0(candidate), ptCandidate); + registry.fill(HIST("hCTS"), hfHelper.cosThetaStarD0(candidate), ptCandidate); + registry.fill(HIST("hCt"), hfHelper.ctD0(candidate), ptCandidate); registry.fill(HIST("hCPA"), candidate.cpa(), ptCandidate); registry.fill(HIST("hEta"), candidate.eta(), ptCandidate); registry.fill(HIST("hSelectionStatus"), candidate.isSelD0() + (candidate.isSelD0bar() * 2), ptCandidate); @@ -209,36 +233,54 @@ struct HfTaskD0 { registry.fill(HIST("hd0Prong0FinerBinning"), candidate.impactParameter0(), ptCandidate); registry.fill(HIST("hd0Prong1FinerBinning"), candidate.impactParameter1(), ptCandidate); registry.fill(HIST("hd0d0FinerBinning"), candidate.impactParameterProduct(), ptCandidate); - registry.fill(HIST("hCTSFinerBinning"), cosThetaStarD0(candidate), ptCandidate); - registry.fill(HIST("hCtFinerBinning"), ctD0(candidate), ptCandidate); + registry.fill(HIST("hCTSFinerBinning"), hfHelper.cosThetaStarD0(candidate), ptCandidate); + registry.fill(HIST("hCtFinerBinning"), hfHelper.ctD0(candidate), ptCandidate); registry.fill(HIST("hCPAFinerBinning"), candidate.cpa(), ptCandidate); registry.fill(HIST("hCPAXYFinerBinning"), candidate.cpaXY(), ptCandidate); } } + void processDataWithDCAFitterN(D0Candidates const&) + { + processData(selectedD0Candidates); + } + PROCESS_SWITCH(HfTaskD0, processDataWithDCAFitterN, "process taskD0 with DCAFitterN", true); - void processMc(soa::Join& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + void processDataWithKFParticle(D0CandidatesKF const&) + { + processData(selectedD0CandidatesKF); + } + PROCESS_SWITCH(HfTaskD0, processDataWithKFParticle, "process taskD0 with KFParticle", false); + + template + void processMc(CandType const& candidates, + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { // MC rec. - // Printf("MC Candidates: %d", candidates.size()); - for (auto& candidate : recoFlag2Prong) { - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yD0(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yD0(candidate)) > yCandRecoMax) { continue; } - auto massD0 = invMassD0ToPiK(candidate); - auto massD0bar = invMassD0barToKPi(candidate); - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::D0ToPiK) { + float massD0, massD0bar; + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + massD0 = candidate.kfGeoMassD0(); + massD0bar = candidate.kfGeoMassD0bar(); + } else { + massD0 = hfHelper.invMassD0ToPiK(candidate); + massD0bar = hfHelper.invMassD0barToKPi(candidate); + } + if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // Get the corresponding MC particle. - auto indexMother = RecoDecay::getMother(particlesMC, candidate.prong0_as().mcParticle_as>(), pdg::Code::kD0, true); - auto particleMother = particlesMC.rawIteratorAt(indexMother); - auto ptGen = particleMother.pt(); // gen. level pT - auto yGen = RecoDecay::y(array{particleMother.px(), particleMother.py(), particleMother.pz()}, RecoDecay::getMassPDG(particleMother.pdgCode())); // gen. level y - registry.fill(HIST("hPtGenSig"), ptGen); // gen. level pT + auto indexMother = RecoDecay::getMother(mcParticles, candidate.template prong0_as().template mcParticle_as>(), pdg::Code::kD0, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); + auto ptGen = particleMother.pt(); // gen. level pT + auto yGen = RecoDecay::y(std::array{particleMother.px(), particleMother.py(), particleMother.pz()}, o2::analysis::pdg::MassD0); // gen. level y + registry.fill(HIST("hPtGenSig"), ptGen); // gen. level pT auto ptRec = candidate.pt(); - auto yRec = yD0(candidate); + auto yRec = hfHelper.yD0(candidate); if (candidate.isRecoHfFlag() >= selectionFlagHf) { registry.fill(HIST("hPtVsYRecSigRecoHFFlag"), ptRec, yRec); registry.fill(HIST("hPtGenVsPtRecSig"), ptGen, ptRec); @@ -308,7 +350,7 @@ struct HfTaskD0 { auto ptCandidate = candidate.pt(); auto ptProng0 = candidate.ptProng0(); auto ptProng1 = candidate.ptProng1(); - auto rapidityCandidate = yD0(candidate); + auto rapidityCandidate = hfHelper.yD0(candidate); auto declengthCandidate = candidate.decayLength(); auto declengthxyCandidate = candidate.decayLengthXY(); auto normaliseddeclengthCandidate = candidate.decayLengthNormalised(); @@ -316,13 +358,13 @@ struct HfTaskD0 { auto d0Prong0 = candidate.impactParameter0(); auto d0Prong1 = candidate.impactParameter1(); auto d0d0Candidate = candidate.impactParameterProduct(); - auto ctsCandidate = cosThetaStarD0(candidate); - auto ctCandidate = ctD0(candidate); + auto ctsCandidate = hfHelper.cosThetaStarD0(candidate); + auto ctCandidate = hfHelper.ctD0(candidate); auto cpaCandidate = candidate.cpa(); auto cpaxyCandidate = candidate.cpaXY(); if (candidate.isSelD0() >= selectionFlagD0) { registry.fill(HIST("hMassSigBkgD0"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hPtProng0Sig"), ptProng0, rapidityCandidate); registry.fill(HIST("hPtProng1Sig"), ptProng1, rapidityCandidate); registry.fill(HIST("hDecLengthSig"), declengthCandidate, rapidityCandidate); @@ -361,32 +403,31 @@ struct HfTaskD0 { registry.fill(HIST("hCPABkg"), cpaCandidate, rapidityCandidate); registry.fill(HIST("hCPAxyBkg"), cpaxyCandidate, rapidityCandidate); registry.fill(HIST("hMassBkgD0"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassReflBkgD0"), massD0, ptCandidate, rapidityCandidate); } } } if (candidate.isSelD0bar() >= selectionFlagD0bar) { registry.fill(HIST("hMassSigBkgD0bar"), massD0bar, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassSigD0bar"), massD0bar, ptCandidate, rapidityCandidate); } else { registry.fill(HIST("hMassBkgD0bar"), massD0bar, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { registry.fill(HIST("hMassReflBkgD0bar"), massD0bar, ptCandidate, rapidityCandidate); } } } } // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::D0ToPiK) { - if (yCandGenMax >= 0. && std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > yCandGenMax) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (yCandGenMax >= 0. && std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0)) > yCandGenMax) { continue; } auto ptGen = particle.pt(); - auto yGen = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto yGen = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0); registry.fill(HIST("hPtGen"), ptGen); registry.fill(HIST("hPtVsYGen"), ptGen, yGen); if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { @@ -403,7 +444,21 @@ struct HfTaskD0 { } } - PROCESS_SWITCH(HfTaskD0, processMc, "Process MC", false); + void processMcWithDCAFitterN(D0CandidatesMc const&, + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) + { + processMc(selectedD0CandidatesMc, mcParticles, tracks); + } + PROCESS_SWITCH(HfTaskD0, processMcWithDCAFitterN, "Process MC with DCAFitterN", false); + + void processMcWithKFParticle(D0CandidatesMcKF const&, + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) + { + processMc(selectedD0CandidatesMcKF, mcParticles, tracks); + } + PROCESS_SWITCH(HfTaskD0, processMcWithKFParticle, "Process MC with KFParticle", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/Tasks/taskDplus.cxx b/PWGHF/D2H/Tasks/taskDplus.cxx index 771e4b38d60..a72ee9070f2 100644 --- a/PWGHF/D2H/Tasks/taskDplus.cxx +++ b/PWGHF/D2H/Tasks/taskDplus.cxx @@ -20,13 +20,14 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; /// D± analysis task struct HfTaskDplus { @@ -35,6 +36,8 @@ struct HfTaskDplus { Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Partition> selectedDPlusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; Partition> recoFlagDPlusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi > 0; @@ -50,7 +53,7 @@ struct HfTaskDplus { {"hEtaRecBg", "3-prong candidates (unmatched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, {"hEtaGen", "MC particles (matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMass", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{350, 1.7, 2.05}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -94,18 +97,18 @@ struct HfTaskDplus { void process(soa::Join const& candidates) { - for (auto& candidate : selectedDPlusCandidates) { + for (const auto& candidate : selectedDPlusCandidates) { // not possible in Filter since expressions do not support binary operators - if (!(candidate.hfflag() & 1 << DecayType::DplusToPiKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yDplus(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yDplus(candidate)) > yCandRecoMax) { continue; } - registry.fill(HIST("hMass"), invMassDplusToPiKPi(candidate), candidate.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt()); registry.fill(HIST("hPt"), candidate.pt()); registry.fill(HIST("hEta"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hCt"), ctDplus(candidate), candidate.pt()); + registry.fill(HIST("hCt"), hfHelper.ctDplus(candidate), candidate.pt()); registry.fill(HIST("hDecayLength"), candidate.decayLength(), candidate.pt()); registry.fill(HIST("hDecayLengthXY"), candidate.decayLengthXY(), candidate.pt()); registry.fill(HIST("hNormalisedDecayLengthXY"), candidate.decayLengthXYNormalised(), candidate.pt()); @@ -129,25 +132,25 @@ struct HfTaskDplus { } void processMc(soa::Join const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { // MC rec. - // Printf("MC Candidates: %d", candidates.size()); - for (auto& candidate : recoFlagDPlusCandidates) { + for (const auto& candidate : recoFlagDPlusCandidates) { // not possible in Filter since expressions do not support binary operators - if (!(candidate.hfflag() & 1 << DecayType::DplusToPiKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yDplus(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yDplus(candidate)) > yCandRecoMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::DplusToPiKPi) { + if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { // Get the corresponding MC particle. - auto indexMother = RecoDecay::getMother(particlesMC, candidate.prong0_as().mcParticle_as>(), pdg::Code::kDPlus, true); - auto particleMother = particlesMC.rawIteratorAt(indexMother); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong0_as().mcParticle_as>(), pdg::Code::kDPlus, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("hPtGenSig"), particleMother.pt()); // gen. level pT auto ptRec = candidate.pt(); - auto yRec = yDplus(candidate); + auto yRec = hfHelper.yDplus(candidate); registry.fill(HIST("hPtVsYRecSig_RecoSkim"), ptRec, yRec); if (TESTBIT(candidate.isSelDplusToPiKPi(), aod::SelectionStep::RecoTopol)) { registry.fill(HIST("hPtVsYRecSigRecoTopol"), ptRec, yRec); @@ -190,11 +193,10 @@ struct HfTaskDplus { } } // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::DplusToPiKPi) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { auto ptGen = particle.pt(); - auto yGen = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto yGen = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassDPlus); if (yCandGenMax >= 0. && std::abs(yGen) > yCandGenMax) { continue; } diff --git a/PWGHF/D2H/Tasks/taskDs.cxx b/PWGHF/D2H/Tasks/taskDs.cxx index 9ac4737b9dd..25a865c1aa0 100644 --- a/PWGHF/D2H/Tasks/taskDs.cxx +++ b/PWGHF/D2H/Tasks/taskDs.cxx @@ -20,13 +20,14 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; /// Ds± analysis task struct HfTaskDs { @@ -36,14 +37,19 @@ struct HfTaskDs { Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits"}; - Filter dsFlagFilter = (o2::aod::hf_track_index::hfflag & static_cast(1 << DecayType::DsToKKPi)) != static_cast(0); + HfHelper hfHelper; - using candDsData = soa::Filtered>; - using candDsMcReco = soa::Filtered>; - using candDsMcGen = soa::Join; + using CandDsData = soa::Filtered>; + using CandDsMcReco = soa::Filtered>; + using CandDsMcGen = soa::Join; - Partition selectedDsToKKPiCand = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; - Partition selectedDsToPiKKCand = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; + Filter filterDsFlag = (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi))) != static_cast(0); + + Partition selectedDsToKKPiCand = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; + Partition selectedDsToPiKKCand = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; + + Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && aod::hf_cand_3prong::flagMcDecayChanRec == decayChannel; + Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)); HistogramRegistry registry{ "registry", @@ -57,7 +63,7 @@ struct HfTaskDs { {"hEtaRecBkg", "3-prong candidates (unmatched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, {"hEtaGen", "MC particles (matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; AxisSpec ybins = {100, -5., 5, "#it{y}"}; @@ -111,7 +117,7 @@ struct HfTaskDs { auto pt = candidate.pt(); registry.fill(HIST("hPt"), pt); registry.fill(HIST("hEta"), candidate.eta(), pt); - registry.fill(HIST("hCt"), ctDs(candidate), pt); + registry.fill(HIST("hCt"), hfHelper.ctDs(candidate), pt); registry.fill(HIST("hDecayLength"), candidate.decayLength(), pt); registry.fill(HIST("hDecayLengthXY"), candidate.decayLengthXY(), pt); registry.fill(HIST("hNormalisedDecayLengthXY"), candidate.decayLengthXYNormalised(), pt); @@ -140,10 +146,10 @@ struct HfTaskDs { void fillHistoKKPi(const T1& candidate) { auto pt = candidate.pt(); - registry.fill(HIST("hMass"), invMassDsToKKPi(candidate), pt); - registry.fill(HIST("hCos3PiK"), cos3PiKDsToKKPi(candidate), pt); - registry.fill(HIST("hAbsCos3PiK"), std::abs(cos3PiKDsToKKPi(candidate)), pt); - registry.fill(HIST("hDeltaMassPhi"), deltaMassPhiDsToKKPi(candidate), pt); + registry.fill(HIST("hMass"), hfHelper.invMassDsToKKPi(candidate), pt); + registry.fill(HIST("hCos3PiK"), hfHelper.cos3PiKDsToKKPi(candidate), pt); + registry.fill(HIST("hAbsCos3PiK"), std::abs(hfHelper.cos3PiKDsToKKPi(candidate)), pt); + registry.fill(HIST("hDeltaMassPhi"), hfHelper.deltaMassPhiDsToKKPi(candidate), pt); return; } @@ -153,10 +159,10 @@ struct HfTaskDs { void fillHistoPiKK(const T1& candidate) { auto pt = candidate.pt(); - registry.fill(HIST("hMass"), invMassDsToPiKK(candidate), pt); - registry.fill(HIST("hCos3PiK"), cos3PiKDsToPiKK(candidate), pt); - registry.fill(HIST("hAbsCos3PiK"), std::abs(cos3PiKDsToPiKK(candidate)), pt); - registry.fill(HIST("hDeltaMassPhi"), deltaMassPhiDsToPiKK(candidate), pt); + registry.fill(HIST("hMass"), hfHelper.invMassDsToPiKK(candidate), pt); + registry.fill(HIST("hCos3PiK"), hfHelper.cos3PiKDsToPiKK(candidate), pt); + registry.fill(HIST("hAbsCos3PiK"), std::abs(hfHelper.cos3PiKDsToPiKK(candidate)), pt); + registry.fill(HIST("hDeltaMassPhi"), hfHelper.deltaMassPhiDsToPiKK(candidate), pt); return; } @@ -167,7 +173,7 @@ struct HfTaskDs { void fillHistoMCRec(const T1& candidate, int flag) { auto pt = candidate.pt(); // rec. level pT - auto y = yDs(candidate); + auto y = hfHelper.yDs(candidate); registry.fill(HIST("hPtRecSig"), pt); registry.fill(HIST("hCPARecSig"), candidate.cpa()); @@ -207,18 +213,18 @@ struct HfTaskDs { return; } - void process(candDsData const& candidates) + void process(CandDsData const& candidates) { - for (auto& candidate : selectedDsToKKPiCand) { - if (yCandRecoMax >= 0. && std::abs(yDs(candidate)) > yCandRecoMax) { + for (const auto& candidate : selectedDsToKKPiCand) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { continue; } fillHisto(candidate); fillHistoKKPi(candidate); } - for (auto& candidate : selectedDsToPiKKCand) { - if (yCandRecoMax >= 0. && std::abs(yDs(candidate)) > yCandRecoMax) { + for (const auto& candidate : selectedDsToPiKKCand) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { continue; } fillHisto(candidate); @@ -226,48 +232,51 @@ struct HfTaskDs { } } - void processMc(candDsMcReco const& candidates, candDsMcGen const& particlesMC, aod::BigTracksMC const&) + void processMc(CandDsMcReco const& candidates, + CandDsMcGen const& mcParticles, + aod::TracksWMc const&) { // MC rec. - for (auto& candidate : candidates) { - if (yCandRecoMax >= 0. && std::abs(yDs(candidate)) > yCandRecoMax) { + for (const auto& candidate : reconstructedCandSig) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::DsToKKPi) { - if (candidate.flagMcDecayChanRec() != decayChannel) { - continue; - } - auto prong0McPart = candidate.prong0_as().mcParticle_as(); - auto indexMother = RecoDecay::getMother(particlesMC, prong0McPart, pdg::Code::kDS, true); - auto particleMother = particlesMC.iteratorAt(indexMother); - registry.fill(HIST("hPtGenSig"), particleMother.pt()); // gen. level pT - - // KKPi - if (std::abs(prong0McPart.pdgCode()) == kKPlus) { - fillHistoMCRec(candidate, candidate.isSelDsToKKPi()); - } - // TODO: add histograms for reflections - // PiKK - if (std::abs(prong0McPart.pdgCode()) == kPiPlus) { - fillHistoMCRec(candidate, candidate.isSelDsToPiKK()); - } - // TODO: add histograms for reflections - } else { - registry.fill(HIST("hPtRecBkg"), candidate.pt()); - registry.fill(HIST("hCPARecBkg"), candidate.cpa()); - registry.fill(HIST("hEtaRecBkg"), candidate.eta()); + auto prong0McPart = candidate.prong0_as().mcParticle_as(); + auto indexMother = RecoDecay::getMother(mcParticles, prong0McPart, pdg::Code::kDS, true); + auto particleMother = mcParticles.iteratorAt(indexMother); + registry.fill(HIST("hPtGenSig"), particleMother.pt()); // gen. level pT + + // KKPi + if (candidate.isCandidateSwapped() == 0) { // 0 corresponds to KKPi + fillHistoMCRec(candidate, candidate.isSelDsToKKPi()); } + + // PiKK + if (candidate.isCandidateSwapped() == 1) { // 1 corresponds to PiKK + fillHistoMCRec(candidate, candidate.isSelDsToPiKK()); + } + } + + for (const auto& candidate : reconstructedCandBkg) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { + continue; + } + + registry.fill(HIST("hPtRecBkg"), candidate.pt()); + registry.fill(HIST("hCPARecBkg"), candidate.cpa()); + registry.fill(HIST("hEtaRecBkg"), candidate.eta()); } + // TODO: add histograms for reflections // MC gen. - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::DsToKKPi) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) { if (particle.flagMcDecayChanGen() != decayChannel) { continue; } auto pt = particle.pt(); - auto y = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto y = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassDS); if (yCandGenMax >= 0. && std::abs(y) > yCandGenMax) { continue; } diff --git a/PWGHF/D2H/Tasks/taskLb.cxx b/PWGHF/D2H/Tasks/taskLb.cxx index 62e3855c3ab..c34dc181934 100644 --- a/PWGHF/D2H/Tasks/taskLb.cxx +++ b/PWGHF/D2H/Tasks/taskLb.cxx @@ -14,10 +14,13 @@ /// /// \author Panos Christakoglou , Nikhef -#include "Common/DataModel/Centrality.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" + +#include "Common/DataModel/Centrality.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -26,10 +29,6 @@ using namespace o2; using namespace o2::aod; using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_cand_lb; -using namespace o2::analysis::hf_cuts_lb_to_lc_pi; using namespace o2::framework::expressions; void customize(std::vector& workflowOptions) @@ -47,6 +46,8 @@ struct HfTaskLb { Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lb_to_lc_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_lb::isSelLbToLcPi >= selectionFlagLb); HistogramRegistry registry{ @@ -56,7 +57,7 @@ struct HfTaskLb { {"hPtCand", "Lb candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{1000, 0., 50.}}}}, {"hCentrality", "centrality;centrality percentile;entries", {HistType::kTH1F, {{100, 0., 100.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { registry.add("hMass", "#Lambda_{b}^{0} candidates;inv. mass #Lambda_{c}^{#plus}#pi^{#minus} (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c}); centrality", {HistType::kTH3F, {{500, 0., 10.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}, {100, 0., 100.}}}); registry.add("hDecLength", "#Lambda_{b}^{0} candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 0.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -73,23 +74,26 @@ struct HfTaskLb { registry.add("hInvMassLc", "#Lambda_{b}^{0} candidates;prong0, #Lambda_{c}^{+} inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{500, 0, 5}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); } - void process(soa::Join::iterator const& collision, soa::Filtered> const& candidates, soa::Join const&, aod::BigTracks const&) + void process(soa::Join::iterator const& collision, + soa::Filtered> const& candidates, + soa::Join const&, + aod::Tracks const&) { float centrality = collision.centRun2V0M(); registry.fill(HIST("hCentrality"), centrality); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!(candidate.hfflag() & 1 << hf_cand_lb::DecayType::LbToLcPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yLb(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yLb(candidate)) > yCandRecoMax) { continue; } auto candLc = candidate.prong0_as>(); - auto candPi = candidate.prong1_as(); + auto candPi = candidate.prong1(); - registry.fill(HIST("hMass"), invMassLbToLcPi(candidate), candidate.pt(), centrality); + registry.fill(HIST("hMass"), hfHelper.invMassLbToLcPi(candidate), candidate.pt(), centrality); registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); @@ -100,13 +104,13 @@ struct HfTaskLb { registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hCPA"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEta"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hRapidity"), yLb(candidate), candidate.pt()); + registry.fill(HIST("hRapidity"), hfHelper.yLb(candidate), candidate.pt()); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter0(), candidate.pt()); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), candidate.pt()); registry.fill(HIST("hDecLenErr"), candidate.errorDecayLength(), candidate.pt()); registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), candidate.pt()); if (candPi.sign() < 0) { - registry.fill(HIST("hInvMassLc"), invMassLcToPKPi(candLc), candidate.pt()); + registry.fill(HIST("hInvMassLc"), hfHelper.invMassLcToPKPi(candLc), candidate.pt()); } } // candidate loop } // process @@ -119,6 +123,9 @@ struct HfTaskLbMc { Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lb_to_lc_pi::vecBinsPt}, "pT bin limits"}; + Service pdg; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_lb::isSelLbToLcPi >= selectionFlagLb); HistogramRegistry registry{ @@ -128,7 +135,7 @@ struct HfTaskLbMc { {"hPtGenSig", "Lb candidates (matched);candidate #it{p}_{T}^{gen.} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 10.}}}}, {"hPtGen", "MC particles (matched);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { registry.add("hEtaGen", "MC particles (matched);#Lambda_{b}^{0} candidate #it{#eta}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hYGen", "MC particles (matched);#Lambda_{b}^{0} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -177,31 +184,32 @@ struct HfTaskLbMc { } void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks, aod::HfCand3Prong const&) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks, + aod::HfCand3Prong const&) { // MC rec - for (auto& candidate : candidates) { - // Printf("(Panos) MC candidate: pT: %lf",candidate.pt()); + for (const auto& candidate : candidates) { if (!(candidate.hfflag() & 1 << hf_cand_lb::DecayType::LbToLcPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yLb(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yLb(candidate)) > yCandRecoMax) { continue; } auto candLc = candidate.prong0_as(); if (std::abs(candidate.flagMcMatchRec()) == 1 << hf_cand_lb::DecayType::LbToLcPi) { - auto indexMother = RecoDecay::getMother(particlesMC, candidate.prong1_as().mcParticle_as>(), pdg::Code::kLambdaB0, true); - auto particleMother = particlesMC.rawIteratorAt(indexMother); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), pdg::Code::kLambdaB0, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("hPtGenSig"), particleMother.pt()); registry.fill(HIST("hPtRecSig"), candidate.pt()); registry.fill(HIST("hCPARecSig"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hCPAxyRecSig"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEtaRecSig"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hRapidityRecSig"), yLb(candidate), candidate.pt()); + registry.fill(HIST("hRapidityRecSig"), hfHelper.yLb(candidate), candidate.pt()); registry.fill(HIST("hDecLengthRecSig"), candidate.decayLength(), candidate.pt()); registry.fill(HIST("hDecLengthXYRecSig"), candidate.decayLengthXY(), candidate.pt()); - registry.fill(HIST("hMassRecSig"), invMassLbToLcPi(candidate), candidate.pt()); + registry.fill(HIST("hMassRecSig"), hfHelper.invMassLbToLcPi(candidate), candidate.pt()); registry.fill(HIST("hd0Prong0RecSig"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1RecSig"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hPtProng0RecSig"), candidate.ptProng0(), candidate.pt()); @@ -217,10 +225,10 @@ struct HfTaskLbMc { registry.fill(HIST("hCPARecBg"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hCPAxyRecBg"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEtaRecBg"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hRapidityRecBg"), yLb(candidate), candidate.pt()); + registry.fill(HIST("hRapidityRecBg"), hfHelper.yLb(candidate), candidate.pt()); registry.fill(HIST("hDecLengthRecBg"), candidate.decayLength(), candidate.pt()); registry.fill(HIST("hDecLengthXYRecBg"), candidate.decayLengthXY(), candidate.pt()); - registry.fill(HIST("hMassRecBg"), invMassLbToLcPi(candidate), candidate.pt()); + registry.fill(HIST("hMassRecBg"), hfHelper.invMassLbToLcPi(candidate), candidate.pt()); registry.fill(HIST("hd0Prong0RecBg"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1RecBg"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hPtProng0RecBg"), candidate.ptProng0(), candidate.pt()); @@ -235,21 +243,20 @@ struct HfTaskLbMc { } // rec // MC gen. level - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { if (std::abs(particle.flagMcMatchGen()) == 1 << hf_cand_lb::DecayType::LbToLcPi) { - auto yParticle = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(pdg::Code::kLambdaB0)); + auto yParticle = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassLambdaB0); if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { continue; } float ptProngs[2], yProngs[2], etaProngs[2]; int counter = 0; - for (auto& daught : particle.daughters_as()) { + for (const auto& daught : particle.daughters_as()) { ptProngs[counter] = daught.pt(); etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(array{daught.px(), daught.py(), daught.pz()}, RecoDecay::getMassPDG(daught.pdgCode())); + yProngs[counter] = RecoDecay::y(std::array{daught.px(), daught.py(), daught.pz()}, pdg->Mass(daught.pdgCode())); counter++; } diff --git a/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index fccade1456c..3343ebf9663 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -17,20 +17,18 @@ /// \author Vít Kučera , CERN /// \author Annalena Kalteyer , GSI Darmstadt -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_lc_to_p_k_pi; /// Λc± → p± K∓ π± analysis task struct HfTaskLc { @@ -39,6 +37,8 @@ struct HfTaskLc { Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); HistogramRegistry registry{ @@ -84,15 +84,15 @@ struct HfTaskLc { {"MC/reconstructed/prompt/hd0RecProng2SigPrompt", "3-prong candidates (matched, prompt);prong 2 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{600, -0.4, 0.4}}}}, {"MC/reconstructed/nonprompt/hd0RecProng2SigNonPrompt", "3-prong candidates (matched, non-prompt);prong 2 DCAxy to prim. vertex (cm);entries", {HistType::kTH1F, {{600, -0.4, 0.4}}}}, /// decay length candidate - {"Data/hDecLength", "3-prong candidates;decay length (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, - {"MC/reconstructed/signal/hDecLengthRecSig", "3-prong candidates (matched);decay length (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, - {"MC/reconstructed/prompt/hDecLengthRecSigPrompt", "3-prong candidates (matched, prompt);decay length (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, - {"MC/reconstructed/nonprompt/hDecLengthRecSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, + {"Data/hDecLength", "3-prong candidates;decay length (cm);entries", {HistType::kTH1F, {{400, 0., 1.}}}}, + {"MC/reconstructed/signal/hDecLengthRecSig", "3-prong candidates (matched);decay length (cm);entries", {HistType::kTH1F, {{400, 0., 1.}}}}, + {"MC/reconstructed/prompt/hDecLengthRecSigPrompt", "3-prong candidates (matched, prompt);decay length (cm);entries", {HistType::kTH1F, {{400, 0., 1.}}}}, + {"MC/reconstructed/nonprompt/hDecLengthRecSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length (cm);entries", {HistType::kTH1F, {{400, 0., 1.}}}}, /// decay length xy candidate - {"Data/hDecLengthxy", "3-prong candidates;decay length xy (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, - {"MC/reconstructed/signal/hDecLengthxyRecSig", "3-prong candidates (matched);decay length xy (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, - {"MC/reconstructed/prompt/hDecLengthxyRecSigPrompt", "3-prong candidates (matched, prompt);decay length xy (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, - {"MC/reconstructed/nonprompt/hDecLengthxyRecSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length xy (cm);entries", {HistType::kTH1F, {{200, 0., 2.}}}}, + {"Data/hDecLengthxy", "3-prong candidates;decay length xy (cm);entries", {HistType::kTH1F, {{400, 0., 1.}}}}, + {"MC/reconstructed/signal/hDecLengthxyRecSig", "3-prong candidates (matched);decay length xy (cm);entries", {HistType::kTH1F, {{400, 0., 1.}}}}, + {"MC/reconstructed/prompt/hDecLengthxyRecSigPrompt", "3-prong candidates (matched, prompt);decay length xy (cm);entries", {HistType::kTH1F, {{400, 0., 1.}}}}, + {"MC/reconstructed/nonprompt/hDecLengthxyRecSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length xy (cm);entries", {HistType::kTH1F, {{400, 0., 1.}}}}, /// proper lifetime {"Data/hCt", "3-prong candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);entries", {HistType::kTH1F, {{100, 0., 0.2}}}}, {"MC/reconstructed/signal/hCtRecSig", "3-prong candidates (matched);proper lifetime (#Lambda_{c}) * #it{c} (cm);entries", {HistType::kTH1F, {{100, 0., 0.2}}}}, @@ -133,7 +133,7 @@ struct HfTaskLc { {"MC/generated/prompt/hPhiGenPrompt", "MC particles (matched, prompt);#it{#Phi};entries", {HistType::kTH1F, {{100, 0., 6.3}}}}, {"MC/generated/nonprompt/hPhiGenNonPrompt", "MC particles (matched, non-prompt);#it{#Phi};entries", {HistType::kTH1F, {{100, 0., 6.3}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; /// mass candidate @@ -157,16 +157,16 @@ struct HfTaskLc { registry.add("MC/reconstructed/nonprompt/hd0VsPtRecProng2SigNonPrompt", "3-prong candidates (matched, non-prompt);prong 2 DCAxy to prim. vertex (cm);entries", {HistType::kTH2F, {{600, -0.4, 0.4}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); /// decay length candidate - registry.add("Data/hDecLengthVsPt", "3-prong candidates;decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("MC/reconstructed/signal/hDecLengthVsPtRecSig", "3-prong candidates (matched);decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("MC/reconstructed/prompt/hDecLengthVsPtRecSigPrompt", "3-prong candidates (matched, prompt);decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("MC/reconstructed/nonprompt/hDecLengthVsPtRecSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length (cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/hDecLengthVsPt", "3-prong candidates;decay length (cm);entries", {HistType::kTH2F, {{400, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("MC/reconstructed/signal/hDecLengthVsPtRecSig", "3-prong candidates (matched);decay length (cm);entries", {HistType::kTH2F, {{400, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("MC/reconstructed/prompt/hDecLengthVsPtRecSigPrompt", "3-prong candidates (matched, prompt);decay length (cm);entries", {HistType::kTH2F, {{400, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("MC/reconstructed/nonprompt/hDecLengthVsPtRecSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length (cm);entries", {HistType::kTH2F, {{400, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); /// decay length xy candidate - registry.add("Data/hDecLengthxyVsPt", "3-prong candidates;decay length xy(cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("MC/reconstructed/signal/hDecLengthxyVsPtRecSig", "3-prong candidates (matched);decay length xy(cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("MC/reconstructed/prompt/hDecLengthxyVsPtRecSigPrompt", "3-prong candidates (matched, prompt);decay length xy(cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("MC/reconstructed/nonprompt/hDecLengthxyVsPtRecSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length xy(cm);entries", {HistType::kTH2F, {{200, 0., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("Data/hDecLengthxyVsPt", "3-prong candidates;decay length xy(cm);entries", {HistType::kTH2F, {{400, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("MC/reconstructed/signal/hDecLengthxyVsPtRecSig", "3-prong candidates (matched);decay length xy(cm);entries", {HistType::kTH2F, {{400, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("MC/reconstructed/prompt/hDecLengthxyVsPtRecSigPrompt", "3-prong candidates (matched, prompt);decay length xy(cm);entries", {HistType::kTH2F, {{400, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("MC/reconstructed/nonprompt/hDecLengthxyVsPtRecSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length xy(cm);entries", {HistType::kTH2F, {{400, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); /// proper lifetime registry.add("Data/hCtVsPt", "3-prong candidates;proper lifetime (#Lambda_{c}) * #it{c} (cm);entries", {HistType::kTH2F, {{100, 0., 0.2}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -236,11 +236,13 @@ struct HfTaskLc { registry.add("MC/reconstructed/nonprompt/hDecLenErrSigNonPrompt", "3-prong candidates (matched, non-prompt);decay length error (cm);entries", {HistType::kTH2F, {{100, 0., 1.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); } - void process(const o2::aod::Collision& collision, const soa::Join& tracks, soa::Filtered> const& candidates) + void process(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Filtered> const& candidates) { int nTracks = 0; if (collision.numContrib() > 1) { - for (auto const& track : tracks) { + for (const auto& track : tracks) { if (std::abs(track.eta()) > 4.0) { continue; } @@ -252,23 +254,23 @@ struct HfTaskLc { } registry.fill(HIST("Data/hMultiplicity"), nTracks); - for (auto const& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yLc(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yLc(candidate)) > yCandRecoMax) { continue; } auto pt = candidate.pt(); if (candidate.isSelLcToPKPi() >= selectionFlagLc) { - registry.fill(HIST("Data/hMass"), invMassLcToPKPi(candidate)); - registry.fill(HIST("Data/hMassVsPtVsMult"), invMassLcToPKPi(candidate), pt, nTracks); - registry.fill(HIST("Data/hMassVsPt"), invMassLcToPKPi(candidate), pt); + registry.fill(HIST("Data/hMass"), hfHelper.invMassLcToPKPi(candidate)); + registry.fill(HIST("Data/hMassVsPtVsMult"), hfHelper.invMassLcToPKPi(candidate), pt, nTracks); + registry.fill(HIST("Data/hMassVsPt"), hfHelper.invMassLcToPKPi(candidate), pt); } if (candidate.isSelLcToPiKP() >= selectionFlagLc) { - registry.fill(HIST("Data/hMass"), invMassLcToPiKP(candidate)); - registry.fill(HIST("Data/hMassVsPtVsMult"), invMassLcToPiKP(candidate), pt, nTracks); - registry.fill(HIST("Data/hMassVsPt"), invMassLcToPiKP(candidate), pt); + registry.fill(HIST("Data/hMass"), hfHelper.invMassLcToPiKP(candidate)); + registry.fill(HIST("Data/hMassVsPtVsMult"), hfHelper.invMassLcToPiKP(candidate), pt, nTracks); + registry.fill(HIST("Data/hMassVsPt"), hfHelper.invMassLcToPiKP(candidate), pt); } registry.fill(HIST("Data/hPt"), pt); registry.fill(HIST("Data/hPtProng0"), candidate.ptProng0()); @@ -284,8 +286,8 @@ struct HfTaskLc { registry.fill(HIST("Data/hDecLengthVsPt"), candidate.decayLength(), pt); registry.fill(HIST("Data/hDecLengthxy"), candidate.decayLengthXY()); registry.fill(HIST("Data/hDecLengthxyVsPt"), candidate.decayLengthXY(), pt); - registry.fill(HIST("Data/hCt"), ctLc(candidate)); - registry.fill(HIST("Data/hCtVsPt"), ctLc(candidate), pt); + registry.fill(HIST("Data/hCt"), hfHelper.ctLc(candidate)); + registry.fill(HIST("Data/hCtVsPt"), hfHelper.ctLc(candidate), pt); registry.fill(HIST("Data/hCPA"), candidate.cpa()); registry.fill(HIST("Data/hCPAVsPt"), candidate.cpa(), pt); registry.fill(HIST("Data/hCPAxy"), candidate.cpaXY()); @@ -307,34 +309,35 @@ struct HfTaskLc { /// Fills MC histograms. void processMc(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& /*tracks*/) + soa::Join const& mcParticles, + aod::TracksWMc const&) { - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { /// Select Lc - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { continue; } /// rapidity selection - if (yCandRecoMax >= 0. && std::abs(yLc(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yLc(candidate)) > yCandRecoMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::LcToPKPi) { + if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { // Get the corresponding MC particle. - auto mcParticleProng0 = candidate.prong0_as().mcParticle_as>(); + auto mcParticleProng0 = candidate.prong0_as().mcParticle_as>(); auto pdgCodeProng0 = std::abs(mcParticleProng0.pdgCode()); - auto indexMother = RecoDecay::getMother(particlesMC, mcParticleProng0, pdg::Code::kLambdaCPlus, true); - auto particleMother = particlesMC.rawIteratorAt(indexMother); + auto indexMother = RecoDecay::getMother(mcParticles, mcParticleProng0, pdg::Code::kLambdaCPlus, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("MC/generated/signal/hPtGenSig"), particleMother.pt()); // gen. level pT auto pt = candidate.pt(); /// MC reconstructed signal if ((candidate.isSelLcToPKPi() >= selectionFlagLc) && pdgCodeProng0 == kProton) { - registry.fill(HIST("MC/reconstructed/signal/hMassRecSig"), invMassLcToPKPi(candidate)); - registry.fill(HIST("MC/reconstructed/signal/hMassVsPtRecSig"), invMassLcToPKPi(candidate), pt); + registry.fill(HIST("MC/reconstructed/signal/hMassRecSig"), hfHelper.invMassLcToPKPi(candidate)); + registry.fill(HIST("MC/reconstructed/signal/hMassVsPtRecSig"), hfHelper.invMassLcToPKPi(candidate), pt); } if ((candidate.isSelLcToPiKP() >= selectionFlagLc) && pdgCodeProng0 == kPiPlus) { - registry.fill(HIST("MC/reconstructed/signal/hMassRecSig"), invMassLcToPiKP(candidate)); - registry.fill(HIST("MC/reconstructed/signal/hMassVsPtRecSig"), invMassLcToPiKP(candidate), pt); + registry.fill(HIST("MC/reconstructed/signal/hMassRecSig"), hfHelper.invMassLcToPiKP(candidate)); + registry.fill(HIST("MC/reconstructed/signal/hMassVsPtRecSig"), hfHelper.invMassLcToPiKP(candidate), pt); } registry.fill(HIST("MC/reconstructed/signal/hPtRecSig"), pt); registry.fill(HIST("MC/reconstructed/signal/hPtRecProng0Sig"), candidate.ptProng0()); @@ -351,8 +354,8 @@ struct HfTaskLc { registry.fill(HIST("MC/reconstructed/signal/hDecLengthVsPtRecSig"), candidate.decayLength(), pt); registry.fill(HIST("MC/reconstructed/signal/hDecLengthxyRecSig"), candidate.decayLengthXY()); registry.fill(HIST("MC/reconstructed/signal/hDecLengthxyVsPtRecSig"), candidate.decayLengthXY(), pt); - registry.fill(HIST("MC/reconstructed/signal/hCtRecSig"), ctLc(candidate)); - registry.fill(HIST("MC/reconstructed/signal/hCtVsPtRecSig"), ctLc(candidate), pt); + registry.fill(HIST("MC/reconstructed/signal/hCtRecSig"), hfHelper.ctLc(candidate)); + registry.fill(HIST("MC/reconstructed/signal/hCtVsPtRecSig"), hfHelper.ctLc(candidate), pt); registry.fill(HIST("MC/reconstructed/signal/hCPARecSig"), candidate.cpa()); registry.fill(HIST("MC/reconstructed/signal/hCPAVsPtRecSig"), candidate.cpa(), pt); registry.fill(HIST("MC/reconstructed/signal/hCPAxyRecSig"), candidate.cpaXY()); @@ -371,12 +374,12 @@ struct HfTaskLc { /// reconstructed signal prompt if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { if ((candidate.isSelLcToPKPi() >= selectionFlagLc) && pdgCodeProng0 == kProton) { - registry.fill(HIST("MC/reconstructed/prompt/hMassRecSigPrompt"), invMassLcToPKPi(candidate)); - registry.fill(HIST("MC/reconstructed/prompt/hMassVsPtRecSigPrompt"), invMassLcToPKPi(candidate), pt); + registry.fill(HIST("MC/reconstructed/prompt/hMassRecSigPrompt"), hfHelper.invMassLcToPKPi(candidate)); + registry.fill(HIST("MC/reconstructed/prompt/hMassVsPtRecSigPrompt"), hfHelper.invMassLcToPKPi(candidate), pt); } if ((candidate.isSelLcToPiKP() >= selectionFlagLc) && pdgCodeProng0 == kPiPlus) { - registry.fill(HIST("MC/reconstructed/prompt/hMassRecSigPrompt"), invMassLcToPiKP(candidate)); - registry.fill(HIST("MC/reconstructed/prompt/hMassVsPtRecSigPrompt"), invMassLcToPiKP(candidate), pt); + registry.fill(HIST("MC/reconstructed/prompt/hMassRecSigPrompt"), hfHelper.invMassLcToPiKP(candidate)); + registry.fill(HIST("MC/reconstructed/prompt/hMassVsPtRecSigPrompt"), hfHelper.invMassLcToPiKP(candidate), pt); } registry.fill(HIST("MC/reconstructed/prompt/hPtRecSigPrompt"), pt); registry.fill(HIST("MC/reconstructed/prompt/hPtRecProng0SigPrompt"), candidate.ptProng0()); @@ -392,8 +395,8 @@ struct HfTaskLc { registry.fill(HIST("MC/reconstructed/prompt/hDecLengthVsPtRecSigPrompt"), candidate.decayLength(), pt); registry.fill(HIST("MC/reconstructed/prompt/hDecLengthxyRecSigPrompt"), candidate.decayLengthXY()); registry.fill(HIST("MC/reconstructed/prompt/hDecLengthxyVsPtRecSigPrompt"), candidate.decayLengthXY(), pt); - registry.fill(HIST("MC/reconstructed/prompt/hCtRecSigPrompt"), ctLc(candidate)); - registry.fill(HIST("MC/reconstructed/prompt/hCtVsPtRecSigPrompt"), ctLc(candidate), pt); + registry.fill(HIST("MC/reconstructed/prompt/hCtRecSigPrompt"), hfHelper.ctLc(candidate)); + registry.fill(HIST("MC/reconstructed/prompt/hCtVsPtRecSigPrompt"), hfHelper.ctLc(candidate), pt); registry.fill(HIST("MC/reconstructed/prompt/hCPARecSigPrompt"), candidate.cpa()); registry.fill(HIST("MC/reconstructed/prompt/hCPAVsPtRecSigPrompt"), candidate.cpa(), pt); registry.fill(HIST("MC/reconstructed/prompt/hCPAxyRecSigPrompt"), candidate.cpaXY()); @@ -410,12 +413,12 @@ struct HfTaskLc { registry.fill(HIST("MC/reconstructed/prompt/hDecLenErrSigPrompt"), candidate.errorDecayLength(), pt); } else { if ((candidate.isSelLcToPKPi() >= selectionFlagLc) && pdgCodeProng0 == kProton) { - registry.fill(HIST("MC/reconstructed/nonprompt/hMassRecSigNonPrompt"), invMassLcToPKPi(candidate)); - registry.fill(HIST("MC/reconstructed/nonprompt/hMassVsPtRecSigNonPrompt"), invMassLcToPKPi(candidate), pt); + registry.fill(HIST("MC/reconstructed/nonprompt/hMassRecSigNonPrompt"), hfHelper.invMassLcToPKPi(candidate)); + registry.fill(HIST("MC/reconstructed/nonprompt/hMassVsPtRecSigNonPrompt"), hfHelper.invMassLcToPKPi(candidate), pt); } if ((candidate.isSelLcToPiKP() >= selectionFlagLc) && pdgCodeProng0 == kPiPlus) { - registry.fill(HIST("MC/reconstructed/nonprompt/hMassRecSigNonPrompt"), invMassLcToPiKP(candidate)); - registry.fill(HIST("MC/reconstructed/nonprompt/hMassVsPtRecSigNonPrompt"), invMassLcToPiKP(candidate), pt); + registry.fill(HIST("MC/reconstructed/nonprompt/hMassRecSigNonPrompt"), hfHelper.invMassLcToPiKP(candidate)); + registry.fill(HIST("MC/reconstructed/nonprompt/hMassVsPtRecSigNonPrompt"), hfHelper.invMassLcToPiKP(candidate), pt); } registry.fill(HIST("MC/reconstructed/nonprompt/hPtRecSigNonPrompt"), pt); registry.fill(HIST("MC/reconstructed/nonprompt/hPtRecProng0SigNonPrompt"), candidate.ptProng0()); @@ -431,8 +434,8 @@ struct HfTaskLc { registry.fill(HIST("MC/reconstructed/nonprompt/hDecLengthVsPtRecSigNonPrompt"), candidate.decayLength(), pt); registry.fill(HIST("MC/reconstructed/nonprompt/hDecLengthxyRecSigNonPrompt"), candidate.decayLengthXY()); registry.fill(HIST("MC/reconstructed/nonprompt/hDecLengthxyVsPtRecSigNonPrompt"), candidate.decayLengthXY(), pt); - registry.fill(HIST("MC/reconstructed/nonprompt/hCtRecSigNonPrompt"), ctLc(candidate)); - registry.fill(HIST("MC/reconstructed/nonprompt/hCtVsPtRecSigNonPrompt"), ctLc(candidate), pt); + registry.fill(HIST("MC/reconstructed/nonprompt/hCtRecSigNonPrompt"), hfHelper.ctLc(candidate)); + registry.fill(HIST("MC/reconstructed/nonprompt/hCtVsPtRecSigNonPrompt"), hfHelper.ctLc(candidate), pt); registry.fill(HIST("MC/reconstructed/nonprompt/hCPARecSigNonPrompt"), candidate.cpa()); registry.fill(HIST("MC/reconstructed/nonprompt/hCPAVsPtRecSigNonPrompt"), candidate.cpa(), pt); registry.fill(HIST("MC/reconstructed/nonprompt/hCPAxyRecSigNonPrompt"), candidate.cpaXY()); @@ -451,10 +454,9 @@ struct HfTaskLc { } } // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto const& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::LcToPKPi) { - auto yGen = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + auto yGen = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassLambdaCPlus); if (yCandGenMax >= 0. && std::abs(yGen) > yCandGenMax) { continue; } diff --git a/PWGHF/D2H/Tasks/taskLcToK0sP.cxx b/PWGHF/D2H/Tasks/taskLcToK0sP.cxx index b0095a7850c..f1a305cf2ff 100644 --- a/PWGHF/D2H/Tasks/taskLcToK0sP.cxx +++ b/PWGHF/D2H/Tasks/taskLcToK0sP.cxx @@ -15,18 +15,19 @@ /// \author Chiara Zampolli, , CERN /// Paul Buehler, , Vienna /// -/// based on taskD0.cxx, taskLc.cxx +/// \note based on taskD0.cxx, taskLc.cxx #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_casc; using namespace o2::framework::expressions; /// LcToK0sp analysis task @@ -36,8 +37,12 @@ struct HfTaskLcToK0sP { Configurable etaCandMax{"etaCandMax", -1., "max. cand. pseudorapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_k0s_p::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcToK0sP || aod::hf_sel_candidate_lc_to_k0s_p::isSelLcToK0sP >= selectionFlagLcbarToK0sP); + using TracksWPid = soa::Join; + HistogramRegistry registry{"registry"}; void init(InitContext& context) @@ -239,11 +244,10 @@ struct HfTaskLcToK0sP { } } - void - process(soa::Filtered> const& candidates, aod::BigTracksPID const&) + void process(soa::Filtered> const& candidates, + TracksWPid const&) { - // Printf("Candidates: %d", candidates.size()); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { /* // no such selection for LcK0sp for now - it is the only cascade if (!(candidate.hfflag() & 1 << D0ToPiK)) { @@ -252,14 +256,13 @@ struct HfTaskLcToK0sP { */ if (etaCandMax >= 0. && std::abs(candidate.eta()) > etaCandMax) { - // Printf("Candidate: eta rejection: %g", candidate.eta()); continue; } auto ptCand = candidate.pt(); auto eta = candidate.eta(); auto phi = candidate.phi(); - auto invMassLcToK0sP = o2::aod::hf_cand_casc::invMassLcToK0sP(candidate); + auto invMassLcToK0sP = hfHelper.invMassLcToK0sP(candidate); auto ptProng0 = candidate.ptProng0(); auto ptProng1 = candidate.ptProng1(); auto impactParameter0 = candidate.impactParameter0(); @@ -275,13 +278,13 @@ struct HfTaskLcToK0sP { auto mLambda = candidate.mLambda(); auto mAntiLambda = candidate.mAntiLambda(); auto mGamma = candidate.mGamma(); - auto ctV0K0Short = o2::aod::hf_cand_casc::ctV0K0s(candidate); - auto ctV0Lambda = o2::aod::hf_cand_casc::ctV0Lambda(candidate); + auto ctV0K0Short = hfHelper.ctV0K0s(candidate); + auto ctV0Lambda = hfHelper.ctV0Lambda(candidate); auto cpa = candidate.cpa(); auto cpaXY = candidate.cpaXY(); auto decayLength = candidate.decayLength(); auto decayLengthXY = candidate.decayLengthXY(); - auto ctLc = o2::aod::hf_cand_3prong::ctLc(candidate); + auto ctLc = hfHelper.ctLc(candidate); registry.fill(HIST("hPtCand"), ptCand); registry.fill(HIST("hEtaCand"), eta); @@ -335,7 +338,7 @@ struct HfTaskLcToK0sP { registry.fill(HIST("hCtCand"), ctLc); registry.fill(HIST("hCtCandVsPtCand"), ctLc, ptCand); - const auto& bach = candidate.prong0_as(); // bachelor track + const auto& bach = candidate.prong0_as(); // bachelor track auto tpcNSigmaPr = bach.tpcNSigmaPr(); auto pBach = bach.p(); registry.fill(HIST("hTPCNSigmaPrBach"), tpcNSigmaPr); @@ -349,21 +352,20 @@ struct HfTaskLcToK0sP { } void processMc(soa::Filtered> const& candidates, - soa::Join const& particlesMC, - aod::BigTracksMC const& tracks, aod::BigTracksPID const&) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks, + TracksWPid const&) { // MC rec. - // Printf("MC Candidates: %d", candidates.size()); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (etaCandMax >= 0. && std::abs(candidate.eta()) > etaCandMax) { - // Printf("MC Rec.: eta rejection: %g", candidate.eta()); continue; } auto ptCand = candidate.pt(); auto eta = candidate.eta(); auto phi = candidate.phi(); - auto invMassLcToK0sP = o2::aod::hf_cand_casc::invMassLcToK0sP(candidate); + auto invMassLcToK0sP = hfHelper.invMassLcToK0sP(candidate); auto ptProng0 = candidate.ptProng0(); auto ptProng1 = candidate.ptProng1(); auto impactParameter0 = candidate.impactParameter0(); @@ -379,15 +381,15 @@ struct HfTaskLcToK0sP { auto mLambda = candidate.mLambda(); auto mAntiLambda = candidate.mAntiLambda(); auto mGamma = candidate.mGamma(); - auto ctV0K0Short = o2::aod::hf_cand_casc::ctV0K0s(candidate); - auto ctV0Lambda = o2::aod::hf_cand_casc::ctV0Lambda(candidate); + auto ctV0K0Short = hfHelper.ctV0K0s(candidate); + auto ctV0Lambda = hfHelper.ctV0Lambda(candidate); auto cpa = candidate.cpa(); auto cpaXY = candidate.cpaXY(); auto decayLength = candidate.decayLength(); auto decayLengthXY = candidate.decayLengthXY(); - auto ctLc = o2::aod::hf_cand_3prong::ctLc(candidate); + auto ctLc = hfHelper.ctLc(candidate); - const auto& bach = candidate.prong0_as(); // bachelor track + const auto& bach = candidate.prong0_as(); // bachelor track auto tpcNSigmaPr = bach.tpcNSigmaPr(); auto pBach = bach.p(); @@ -512,10 +514,8 @@ struct HfTaskLcToK0sP { } } // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { if (etaCandMax >= 0. && std::abs(particle.eta()) > etaCandMax) { - // Printf("MC Gen.: eta rejection: %g", particle.eta()); continue; } diff --git a/PWGHF/D2H/Tasks/taskOmegacSt.cxx b/PWGHF/D2H/Tasks/taskOmegacSt.cxx index 522bc36b5f6..74a57253d54 100644 --- a/PWGHF/D2H/Tasks/taskOmegacSt.cxx +++ b/PWGHF/D2H/Tasks/taskOmegacSt.cxx @@ -14,13 +14,10 @@ /// /// \author Jochen Klein -#include "TDatabasePDG.h" -#include "TPDGCode.h" +#include +#include #include "CCDB/BasicCCDBManager.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "DCAFitter/DCAFitterN.h" @@ -28,12 +25,18 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/ASoA.h" +#include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGHF/Core/PDG.h" #include "PWGHF/Core/SelectorCuts.h" using namespace o2; @@ -55,10 +58,10 @@ struct HfTaskOmegacSt { Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations if chi2/chi2old > this"}; Service ccdb; + o2::vertexing::DCAFitterN<2> df2; bool bzOnly = true; - o2::vertexing::DCAFitterN<2> df2; - int runNumber; + int runNumber{0}; using TracksExt = soa::Join; @@ -108,7 +111,8 @@ struct HfTaskOmegacSt { df2.setUseAbsDCA(useAbsDCA); } - void processMc(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) + void processMc(aod::McCollision const& mcCollision, + aod::McParticles const& mcParticles) { for (const auto& mcParticle : mcParticles) { if (mcParticle.pdgCode() != kOmegaMinus) { @@ -119,15 +123,20 @@ struct HfTaskOmegacSt { std::array primaryVertexPosGen = {mcColl.posX(), mcColl.posY(), mcColl.posZ()}; std::array secondaryVertexGen = {mcParticle.vx(), mcParticle.vy(), mcParticle.vz()}; const auto decayLengthGen = RecoDecay::distance(secondaryVertexGen, primaryVertexPosGen); - registry.fill(HIST("hDecayLengthScaledMc"), decayLengthGen * RecoDecay::getMassPDG(analysis::pdg::Code::kOmegaC0) / mcParticle.mothers_first_as().p() * 1e4); + registry.fill(HIST("hDecayLengthScaledMc"), decayLengthGen * o2::analysis::pdg::MassOmegaC0 / mcParticle.mothers_first_as().p() * 1e4); } } } PROCESS_SWITCH(HfTaskOmegacSt, processMc, "Process MC", true); - void process(aod::Collision const& collision, aod::McCollisions const& mcCollisions, - aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& cascades, - aod::V0s const& v0s, TracksExt const& tracks, aod::McParticles const& mcParticles, aod::BCsWithTimestamps const&) + void process(aod::Collision const& collision, + aod::McCollisions const&, + aod::AssignedTrackedCascades const& trackedCascades, + aod::Cascades const&, + aod::V0s const&, + TracksExt const& tracks, + aod::McParticles const&, + aod::BCsWithTimestamps const&) { const auto bc = collision.bc_as(); if (runNumber != bc.runNumber()) { @@ -191,7 +200,7 @@ struct HfTaskOmegacSt { LOG(debug) << "cascade with PDG code: " << pdgCode; if (std::abs(pdgCode) == kOmegaMinus) { LOG(debug) << "found Omega, looking for pions"; - std::array masses{RecoDecay::getMassPDG(kOmegaMinus), RecoDecay::getMassPDG(kPiPlus)}; + std::array masses{o2::analysis::pdg::MassOmegaMinus, o2::analysis::pdg::MassPiPlus}; std::array, 2> momenta; std::array primaryVertexPos = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; const auto& mcColl = mother.mcCollision(); @@ -221,9 +230,9 @@ struct HfTaskOmegacSt { if (df2.process(trackParCovTrk, trackParCovPion)) { const auto& secondaryVertex = df2.getPCACandidate(); const auto decayLength = RecoDecay::distance(secondaryVertex, primaryVertexPos); - if (std::abs(RecoDecay::m(momenta, masses) - RecoDecay::getMassPDG(analysis::pdg::Code::kOmegaC0)) < 0.02) { + if (std::abs(RecoDecay::m(momenta, masses) - o2::analysis::pdg::MassOmegaC0) < 0.02) { registry.fill(HIST("hDecayLength"), decayLength * 1e4); - registry.fill(HIST("hDecayLengthScaled"), decayLength * RecoDecay::getMassPDG(analysis::pdg::Code::kOmegaC0) / RecoDecay::p(momenta[0], momenta[1]) * 1e4); + registry.fill(HIST("hDecayLengthScaled"), decayLength * o2::analysis::pdg::MassOmegaC0 / RecoDecay::p(momenta[0], momenta[1]) * 1e4); } if (mother.has_mothers()) { const auto& cand = mother.template mothers_first_as(); @@ -232,8 +241,8 @@ struct HfTaskOmegacSt { std::array secondaryVertexGen = {mother.vx(), mother.vy(), mother.vz()}; const auto decayLengthGen = RecoDecay::distance(secondaryVertexGen, primaryVertexPosGen); registry.fill(HIST("hDecayLengthId"), decayLength * 1e4); - registry.fill(HIST("hDecayLengthScaledId"), decayLength * RecoDecay::getMassPDG(analysis::pdg::Code::kOmegaC0) / RecoDecay::p(momenta[0], momenta[1]) * 1e4); - registry.fill(HIST("hDecayLengthScaledGen"), decayLengthGen * RecoDecay::getMassPDG(analysis::pdg::Code::kOmegaC0) / RecoDecay::p(momenta[0], momenta[1]) * 1e4); + registry.fill(HIST("hDecayLengthScaledId"), decayLength * o2::analysis::pdg::MassOmegaC0 / RecoDecay::p(momenta[0], momenta[1]) * 1e4); + registry.fill(HIST("hDecayLengthScaledGen"), decayLengthGen * o2::analysis::pdg::MassOmegaC0 / RecoDecay::p(momenta[0], momenta[1]) * 1e4); registry.fill(HIST("hDecayLengthGen"), decayLengthGen * 1e4); registry.fill(HIST("hDeltaDecayLength"), (decayLength - decayLengthGen) * 1e4); } diff --git a/PWGHF/D2H/Tasks/taskSigmac.cxx b/PWGHF/D2H/Tasks/taskSigmac.cxx index 0083f57a840..23c0a3ddde5 100644 --- a/PWGHF/D2H/Tasks/taskSigmac.cxx +++ b/PWGHF/D2H/Tasks/taskSigmac.cxx @@ -16,18 +16,18 @@ /// \author Mattia Faggin , University and INFN PADOVA #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_cand_sigmac; struct HfTaskSigmac { - /// One value of rapidity only /// Remember that in Run2 the distinction among GenLimAcc, GenAccMother, GenAcc was done, where: /// - GenLimAcc: Sc in |y|<0.5 @@ -38,6 +38,8 @@ struct HfTaskSigmac { /// consider the new parametrization of the fiducial acceptance (to be seen for reco signal in MC) Configurable yCandMax{"yCandMax", -1, "Sc rapidity"}; + HfHelper hfHelper; + /// analysis histograms HistogramRegistry registry{ "registry", @@ -215,12 +217,13 @@ struct HfTaskSigmac { /// @brief process function to fill the histograms needed in analysis (data) /// @param candidatesSc are the reconstructed candidate Σc0,++ /// @param - void process(const aod::HfCandSc& candidatesSc, - const RecoLc&, const aod::BigTracksExtended&) + void process(aod::HfCandSc const& candidatesSc, + RecoLc const&, + aod::Tracks const&) { /// loop over the candidate Σc0,++ - for (auto& candSc : candidatesSc) { + for (const auto& candSc : candidatesSc) { const int8_t chargeSc = candSc.charge(); // either Σc0 or Σc++ @@ -234,11 +237,11 @@ struct HfTaskSigmac { double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); - double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); + double ptSoftPi(candSc.prong1().pt()), etaSoftPi(candSc.prong1().eta()), phiSoftPi(candSc.prong1().phi()); /// candidate Λc+ → pK-π+ (and charge conjugate) within the range of M(pK-π+) chosen in the Σc0,++ builder if (isCandPKPiPiKP == 1 || isCandPKPiPiKP == 3) { - massSc = invMassScRecoLcToPKPi(candSc, candidateLc); - massLc = invMassLcToPKPi(candidateLc); + massSc = hfHelper.invMassScRecoLcToPKPi(candSc, candidateLc); + massLc = hfHelper.invMassLcToPKPi(candidateLc); deltaMass = massSc - massLc; /// fill the histograms if (chargeSc == 0) { @@ -291,8 +294,8 @@ struct HfTaskSigmac { } /// end candidate Λc+ → pK-π+ (and charge conjugate) /// candidate Λc+ → π+K-p (and charge conjugate) within the range of M(π+K-p) chosen in the Σc0,++ builder if (isCandPKPiPiKP == 2 || isCandPKPiPiKP == 3) { - massSc = invMassScRecoLcToPiKP(candSc, candidateLc); - massLc = invMassLcToPiKP(candidateLc); + massSc = hfHelper.invMassScRecoLcToPiKP(candSc, candidateLc); + massLc = hfHelper.invMassLcToPiKP(candidateLc); deltaMass = massSc - massLc; /// fill the histograms if (chargeSc == 0) { @@ -348,17 +351,18 @@ struct HfTaskSigmac { /// @brief process function to fill the histograms needed in analysis (MC) /// @param candidatesSc are the reconstructed candidate Σc0,++ with MC info - /// @param particlesMc are the generated particles with flags wheter they are Σc0,++ or not + /// @param mcParticles are the generated particles with flags wheter they are Σc0,++ or not /// @param - void processMc(const soa::Join& candidatesSc, - aod::McParticles const& particlesMc, - soa::Join const& particlesMcSc, - soa::Join const& particlesMcLc, - soa::Join const&, const aod::BigTracksMC&) + void processMc(soa::Join const& candidatesSc, + aod::McParticles const& mcParticles, + soa::Join const& mcParticlesSc, + soa::Join const& mcParticlesLc, + soa::Join const&, + aod::TracksWMc const&) { /// MC generated particles - for (auto& particle : particlesMcSc) { + for (const auto& particle : mcParticlesSc) { /// reject immediately particles different from Σc0,++ bool isSc0Gen = (std::abs(particle.flagMcMatchGen()) == (1 << aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi)); @@ -377,7 +381,7 @@ struct HfTaskSigmac { OR consider the new parametrization of the fiducial acceptance (to be seen for reco signal in MC) */ - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > yCandMax) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassSigmaC0)) > yCandMax) { continue; } @@ -398,8 +402,8 @@ struct HfTaskSigmac { int8_t channel = -1; if (std::abs(arrayDaughtersIds[0]) == pdg::Code::kLambdaCPlus) { /// daughter 0 is the Λc+, daughter 1 the soft π - auto daugLc = particlesMcLc.rawIteratorAt(arrayDaughtersIds[0]); - auto daugSoftPi = particlesMc.rawIteratorAt(arrayDaughtersIds[1]); + auto daugLc = mcParticlesLc.rawIteratorAt(arrayDaughtersIds[0]); + auto daugSoftPi = mcParticles.rawIteratorAt(arrayDaughtersIds[1]); ptGenLc = daugLc.pt(); etaGenLc = daugLc.eta(); phiGenLc = daugLc.phi(); @@ -410,8 +414,8 @@ struct HfTaskSigmac { phiGenSoftPi = daugSoftPi.phi(); } else if (std::abs(arrayDaughtersIds[0]) == kPiPlus) { /// daughter 0 is the soft π, daughter 1 the Λc+ - auto daugLc = particlesMcLc.rawIteratorAt(arrayDaughtersIds[1]); - auto daugSoftPi = particlesMc.rawIteratorAt(arrayDaughtersIds[0]); + auto daugLc = mcParticlesLc.rawIteratorAt(arrayDaughtersIds[1]); + auto daugSoftPi = mcParticles.rawIteratorAt(arrayDaughtersIds[0]); ptGenLc = daugLc.pt(); etaGenLc = daugLc.eta(); phiGenLc = daugLc.phi(); @@ -470,14 +474,14 @@ struct HfTaskSigmac { } /// end loop over generated particles /// reconstructed Σc0,++ matched to MC - for (auto& candSc : candidatesSc) { + for (const auto& candSc : candidatesSc) { /// Candidate selected as Σc0 and/or Σc++ if (!(candSc.hfflag() & 1 << aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi) && !(candSc.hfflag() & 1 << aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi)) { continue; } /// rapidity selection on Σc0,++ - if (yCandMax >= 0. && std::abs(ySc0(candSc)) > yCandMax && std::abs(yScPlusPlus(candSc)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.ySc0(candSc)) > yCandMax && std::abs(hfHelper.yScPlusPlus(candSc)) > yCandMax) { continue; } @@ -494,15 +498,15 @@ struct HfTaskSigmac { /// Reconstructed Σc0 signal if (std::abs(candSc.flagMcMatchRec()) == 1 << aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi && (chargeSc == 0)) { // Get the corresponding MC particle for Sc, found as the mother of the soft pion - auto indexMcScRec = RecoDecay::getMother(particlesMc, candSc.prong1_as().mcParticle(), pdg::Code::kSigmaC0, true); - auto particleSc = particlesMc.rawIteratorAt(indexMcScRec); + auto indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), pdg::Code::kSigmaC0, true); + auto particleSc = mcParticles.rawIteratorAt(indexMcScRec); // Get the corresponding MC particle for Lc - auto arrayDaughtersLc = array{candidateLc.prong0_as(), candidateLc.prong1_as(), candidateLc.prong2_as()}; + auto arrayDaughtersLc = std::array{candidateLc.prong0_as(), candidateLc.prong1_as(), candidateLc.prong2_as()}; int8_t sign = 0; - int indexMcLcRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersLc, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); - auto particleLc = particlesMc.rawIteratorAt(indexMcLcRec); + int indexMcLcRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, pdg::Code::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + auto particleLc = mcParticles.rawIteratorAt(indexMcLcRec); // Get the corresponding MC particle for soft pion - auto particleSoftPi = candSc.prong1_as().mcParticle(); + auto particleSoftPi = candSc.prong1_as().mcParticle(); // const int iscandidateLcpKpi = (candidateLc.isSelLcToPKPi() >= 1) && candSc.statusSpreadLcMinvPKPiFromPDG(); // Λc+ → pK-π+ and within the requested mass to build the Σc0,++ // const int iscandidateLcpiKp = (candidateLc.isSelLcToPiKP() >= 1) && candSc.statusSpreadLcMinvPiKPFromPDG(); // Λc+ → π+K-p and within the requested mass to build the Σc0,++ @@ -510,15 +514,15 @@ struct HfTaskSigmac { double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); - double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); + double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); double ptGenSc(particleSc.pt()), ptGenLc(particleLc.pt()), ptGenSoftPi(particleSoftPi.pt()); int origin = candSc.originMcRec(); auto channel = candidateLc.flagMcDecayChanRec(); /// 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π± /// candidate Λc+ → pK-π+ (and charge conjugate) within the range of M(pK-π+) chosen in the Σc0,++ builder - if ((isCandPKPiPiKP == 1 || isCandPKPiPiKP == 3) && std::abs(candidateLc.prong0_as().mcParticle().pdgCode()) == kProton) { - massSc = invMassScRecoLcToPKPi(candSc, candidateLc); - massLc = invMassLcToPKPi(candidateLc); + if ((isCandPKPiPiKP == 1 || isCandPKPiPiKP == 3) && std::abs(candidateLc.prong0_as().mcParticle().pdgCode()) == kProton) { + massSc = hfHelper.invMassScRecoLcToPKPi(candSc, candidateLc); + massLc = hfHelper.invMassLcToPKPi(candidateLc); deltaMass = massSc - massLc; /// Fill the histograms for reconstructed Σc0 signal @@ -563,9 +567,9 @@ struct HfTaskSigmac { } /// end candidate Λc+ → pK-π+ (and charge conjugate) /// candidate Λc+ → π+K-p (and charge conjugate) within the range of M(π+K-p) chosen in the Σc0,++ builder - if ((isCandPKPiPiKP == 2 || isCandPKPiPiKP == 3) && std::abs(candidateLc.prong0_as().mcParticle().pdgCode()) == kPiPlus) { - massSc = invMassScRecoLcToPiKP(candSc, candidateLc); - massLc = invMassLcToPiKP(candidateLc); + if ((isCandPKPiPiKP == 2 || isCandPKPiPiKP == 3) && std::abs(candidateLc.prong0_as().mcParticle().pdgCode()) == kPiPlus) { + massSc = hfHelper.invMassScRecoLcToPiKP(candSc, candidateLc); + massLc = hfHelper.invMassLcToPiKP(candidateLc); deltaMass = massSc - massLc; /// Fill the histograms for reconstructed Σc0 signal @@ -613,15 +617,15 @@ struct HfTaskSigmac { } else if (std::abs(candSc.flagMcMatchRec()) == 1 << aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi && (std::abs(chargeSc) == 2)) { /// Reconstructed Σc++ signal // Get the corresponding MC particle for Sc, found as the mother of the soft pion - auto indexMcScRec = RecoDecay::getMother(particlesMc, candSc.prong1_as().mcParticle(), pdg::Code::kSigmaCPlusPlus, true); - auto particleSc = particlesMc.rawIteratorAt(indexMcScRec); + auto indexMcScRec = RecoDecay::getMother(mcParticles, candSc.prong1_as().mcParticle(), pdg::Code::kSigmaCPlusPlus, true); + auto particleSc = mcParticles.rawIteratorAt(indexMcScRec); // Get the corresponding MC particle for Lc - auto arrayDaughtersLc = array{candidateLc.prong0_as(), candidateLc.prong1_as(), candidateLc.prong2_as()}; + auto arrayDaughtersLc = std::array{candidateLc.prong0_as(), candidateLc.prong1_as(), candidateLc.prong2_as()}; int8_t sign = 0; - int indexMcLcRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersLc, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); - auto particleLc = particlesMc.rawIteratorAt(indexMcLcRec); + int indexMcLcRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, pdg::Code::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + auto particleLc = mcParticles.rawIteratorAt(indexMcLcRec); // Get the corresponding MC particle for soft pion - auto particleSoftPi = candSc.prong1_as().mcParticle(); + auto particleSoftPi = candSc.prong1_as().mcParticle(); // const int iscandidateLcpKpi = (candidateLc.isSelLcToPKPi() >= 1) && candSc.statusSpreadLcMinvPKPiFromPDG(); // Λc+ → pK-π+ and within the requested mass to build the Σc0,++ // const int iscandidateLcpiKp = (candidateLc.isSelLcToPiKP() >= 1) && candSc.statusSpreadLcMinvPiKPFromPDG(); // Λc+ → π+K-p and within the requested mass to build the Σc0,++ @@ -629,15 +633,15 @@ struct HfTaskSigmac { double ptSc(candSc.pt()), ptLc(candidateLc.pt()); double etaSc(candSc.eta()), etaLc(candidateLc.eta()); double phiSc(candSc.phi()), phiLc(candidateLc.phi()); - double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); + double ptSoftPi(candSc.prong1_as().pt()), etaSoftPi(candSc.prong1_as().eta()), phiSoftPi(candSc.prong1_as().phi()); double ptGenSc(particleSc.pt()), ptGenLc(particleLc.pt()), ptGenSoftPi(particleSoftPi.pt()); int origin = candSc.originMcRec(); auto channel = candidateLc.flagMcDecayChanRec(); /// 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π± /// candidate Λc+ → pK-π+ (and charge conjugate) within the range of M(pK-π+) chosen in the Σc0,++ builder - if ((isCandPKPiPiKP == 1 || isCandPKPiPiKP == 3) && std::abs(candidateLc.prong0_as().mcParticle().pdgCode()) == kProton) { - massSc = invMassScRecoLcToPKPi(candSc, candidateLc); - massLc = invMassLcToPKPi(candidateLc); + if ((isCandPKPiPiKP == 1 || isCandPKPiPiKP == 3) && std::abs(candidateLc.prong0_as().mcParticle().pdgCode()) == kProton) { + massSc = hfHelper.invMassScRecoLcToPKPi(candSc, candidateLc); + massLc = hfHelper.invMassLcToPKPi(candidateLc); deltaMass = massSc - massLc; /// Fill the histograms for reconstructed Σc++ signal @@ -682,9 +686,9 @@ struct HfTaskSigmac { } /// end candidate Λc+ → pK-π+ (and charge conjugate) /// candidate Λc+ → π+K-p (and charge conjugate) within the range of M(π+K-p) chosen in the Σc0,++ builder - if ((isCandPKPiPiKP == 2 || isCandPKPiPiKP == 3) && std::abs(candidateLc.prong0_as().mcParticle().pdgCode()) == kPiPlus) { - massSc = invMassScRecoLcToPiKP(candSc, candidateLc); - massLc = invMassLcToPiKP(candidateLc); + if ((isCandPKPiPiKP == 2 || isCandPKPiPiKP == 3) && std::abs(candidateLc.prong0_as().mcParticle().pdgCode()) == kPiPlus) { + massSc = hfHelper.invMassScRecoLcToPiKP(candSc, candidateLc); + massLc = hfHelper.invMassLcToPiKP(candidateLc); deltaMass = massSc - massLc; /// Fill the histograms for reconstructed Σc++ signal diff --git a/PWGHF/D2H/Tasks/taskXic.cxx b/PWGHF/D2H/Tasks/taskXic.cxx index a7b33042b18..b48c9a1436e 100644 --- a/PWGHF/D2H/Tasks/taskXic.cxx +++ b/PWGHF/D2H/Tasks/taskXic.cxx @@ -21,16 +21,17 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_xic_to_p_k_pi; /// Ξc± analysis task @@ -43,9 +44,15 @@ struct HfTaskXic { Configurable dcaZTrackMax{"dcaZTrackMax", 0.0025, "max. DCAz for track"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_p_k_pi::vecBinsPt}, "pT bin limits"}; + Service pdg; + HfHelper hfHelper; + float etaMaxAcceptance = 0.8; float ptMinAcceptance = 0.1; + using TracksWPid = soa::Join; + Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic); Partition> selectedMCXicCandidates = (aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic); @@ -69,9 +76,8 @@ struct HfTaskXic { }}; - void init(o2::framework::InitContext&) + void init(InitContext&) { - AxisSpec axisPPid = {100, 0.f, 10.0f, "#it{p} (GeV/#it{c})"}; AxisSpec axisNSigmaPr = {100, -6.f, 6.f, "n#it{#sigma}_{p}"}; AxisSpec axisNSigmaPi = {100, -6.f, 6.f, "n#it{#sigma}_{#pi}"}; @@ -181,12 +187,14 @@ struct HfTaskXic { return std::abs(etaProng) <= etaMaxAcceptance && ptProng >= ptMinAcceptance; } - void process(aod::Collision const& collision, soa::Join const& tracks, soa::Filtered> const& candidates, aod::BigTracksPID const&) + void process(aod::Collision const& collision, + TracksWPid const& tracks, + soa::Filtered> const& candidates) { int nTracks = 0; if (collision.numContrib() > 1) { - for (auto const& track : tracks) { + for (const auto& track : tracks) { if (std::abs(track.eta()) > etaTrackMax) { continue; } @@ -198,23 +206,23 @@ struct HfTaskXic { } registry.fill(HIST("Data/hMultiplicity"), nTracks); // filling the histo for multiplicity - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { auto ptCandidate = candidate.pt(); - if (!(candidate.hfflag() & 1 << DecayType::XicToPKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::XicToPKPi)) { continue; } - if (yCandRecoMax >= 0. && std::abs(yXic(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yXic(candidate)) > yCandRecoMax) { continue; } if (candidate.isSelXicToPKPi() >= selectionFlagXic) { // pKpi - registry.fill(HIST("Data/hMassVsPt"), invMassXicToPKPi(candidate), ptCandidate); - registry.fill(HIST("Data/hMass"), invMassXicToPKPi(candidate)); + registry.fill(HIST("Data/hMassVsPt"), hfHelper.invMassXicToPKPi(candidate), ptCandidate); + registry.fill(HIST("Data/hMass"), hfHelper.invMassXicToPKPi(candidate)); } if (candidate.isSelXicToPiKP() >= selectionFlagXic) { // piKp - registry.fill(HIST("Data/hMassVsPt"), invMassXicToPiKP(candidate), ptCandidate); - registry.fill(HIST("Data/hMass"), invMassXicToPiKP(candidate)); + registry.fill(HIST("Data/hMassVsPt"), hfHelper.invMassXicToPiKP(candidate), ptCandidate); + registry.fill(HIST("Data/hMass"), hfHelper.invMassXicToPiKP(candidate)); } registry.fill(HIST("Data/hPt"), ptCandidate); registry.fill(HIST("Data/hEta"), candidate.eta()); @@ -229,7 +237,7 @@ struct HfTaskXic { registry.fill(HIST("Data/hd0Prong0"), candidate.impactParameter0(), ptCandidate); registry.fill(HIST("Data/hd0Prong1"), candidate.impactParameter1(), ptCandidate); registry.fill(HIST("Data/hd0Prong2"), candidate.impactParameter2(), ptCandidate); - registry.fill(HIST("Data/hCt"), ctXic(candidate), ptCandidate); + registry.fill(HIST("Data/hCt"), hfHelper.ctXic(candidate), ptCandidate); registry.fill(HIST("Data/hCPA"), candidate.cpa(), ptCandidate); registry.fill(HIST("Data/hCPAXY"), candidate.cpaXY(), ptCandidate); registry.fill(HIST("Data/hEtaVsPt"), candidate.eta(), ptCandidate); @@ -241,9 +249,9 @@ struct HfTaskXic { registry.fill(HIST("Data/hChi2PCA"), candidate.chi2PCA(), ptCandidate); // PID histos - const auto& trackProng0 = candidate.prong0_as(); // bachelor track - const auto& trackProng1 = candidate.prong1_as(); // bachelor track - const auto& trackProng2 = candidate.prong2_as(); // bachelor track + const auto& trackProng0 = candidate.prong0_as(); // bachelor track + const auto& trackProng1 = candidate.prong1_as(); // bachelor track + const auto& trackProng2 = candidate.prong2_as(); // bachelor track auto momentumProng0 = trackProng0.p(); auto momentumProng1 = trackProng1.p(); @@ -278,16 +286,16 @@ struct HfTaskXic { } // Fill MC histograms void processMc(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& /*tracks*/) + soa::Join const& mcParticles) { // MC rec. - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { // Selected Xic - if (!(candidate.hfflag() & 1 << DecayType::XicToPKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::XicToPKPi)) { continue; } // rapidity selection - if (yCandRecoMax >= 0. && std::abs(yXic(candidate)) > yCandRecoMax) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yXic(candidate)) > yCandRecoMax) { continue; } @@ -296,13 +304,13 @@ struct HfTaskXic { auto ptCandidate = candidate.pt(); if (candidate.isSelXicToPKPi() >= selectionFlagXic) { - massXicToPKPi = invMassXicToPKPi(candidate); + massXicToPKPi = hfHelper.invMassXicToPKPi(candidate); } if (candidate.isSelXicToPiKP() >= selectionFlagXic) { - massXicToPiKP = invMassXicToPiKP(candidate); // mass conjugate + massXicToPiKP = hfHelper.invMassXicToPiKP(candidate); // mass conjugate } - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::XicToPKPi) { + if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::XicToPKPi) { // Signal registry.fill(HIST("MC/reconstructed/signal/hPtRecSig"), ptCandidate); // rec. level pT @@ -323,7 +331,7 @@ struct HfTaskXic { registry.fill(HIST("MC/reconstructed/signal/hd0Prong0RecSig"), candidate.impactParameter0(), ptCandidate); registry.fill(HIST("MC/reconstructed/signal/hd0Prong1RecSig"), candidate.impactParameter1(), ptCandidate); registry.fill(HIST("MC/reconstructed/signal/hd0Prong2RecSig"), candidate.impactParameter2(), ptCandidate); - registry.fill(HIST("MC/reconstructed/signal/hCtRecSig"), ctXic(candidate), ptCandidate); + registry.fill(HIST("MC/reconstructed/signal/hCtRecSig"), hfHelper.ctXic(candidate), ptCandidate); registry.fill(HIST("MC/reconstructed/signal/hCPARecSig"), candidate.cpa(), ptCandidate); registry.fill(HIST("MC/reconstructed/signal/hCPAXYRecSig"), candidate.cpaXY(), ptCandidate); registry.fill(HIST("MC/reconstructed/signal/hEtaRecSig"), candidate.eta(), ptCandidate); @@ -351,7 +359,7 @@ struct HfTaskXic { registry.fill(HIST("MC/reconstructed/background/hd0Prong0RecBg"), candidate.impactParameter0(), ptCandidate); registry.fill(HIST("MC/reconstructed/background/hd0Prong1RecBg"), candidate.impactParameter1(), ptCandidate); registry.fill(HIST("MC/reconstructed/background/hd0Prong2RecBg"), candidate.impactParameter2(), ptCandidate); - registry.fill(HIST("MC/reconstructed/background/hCtRecBg"), ctXic(candidate), ptCandidate); + registry.fill(HIST("MC/reconstructed/background/hCtRecBg"), hfHelper.ctXic(candidate), ptCandidate); registry.fill(HIST("MC/reconstructed/background/hCPARecBg"), candidate.cpa(), ptCandidate); registry.fill(HIST("MC/reconstructed/background/hCPAXYRecBg"), candidate.cpaXY(), ptCandidate); registry.fill(HIST("MC/reconstructed/background/hEtaRecBg"), candidate.eta(), ptCandidate); @@ -361,9 +369,9 @@ struct HfTaskXic { } } // MC gen. - for (auto const& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::XicToPKPi) { - auto yParticle = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::XicToPKPi) { + auto yParticle = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassXiCPlus); if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { continue; } @@ -372,10 +380,10 @@ struct HfTaskXic { std::array yProngs; std::array etaProngs; int counter = 0; - for (auto const& daught : particle.daughters_as()) { + for (const auto& daught : particle.daughters_as()) { ptProngs[counter] = daught.pt(); etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(array{daught.px(), daught.py(), daught.pz()}, RecoDecay::getMassPDG(daught.pdgCode())); + yProngs[counter] = RecoDecay::y(std::array{daught.px(), daught.py(), daught.pz()}, pdg->Mass(daught.pdgCode())); counter++; } @@ -392,7 +400,6 @@ struct HfTaskXic { } } } - PROCESS_SWITCH(HfTaskXic, processMc, "Process MC", false); }; diff --git a/PWGHF/D2H/Tasks/taskXicc.cxx b/PWGHF/D2H/Tasks/taskXicc.cxx index 65aaea7615f..cbaeacbe541 100644 --- a/PWGHF/D2H/Tasks/taskXicc.cxx +++ b/PWGHF/D2H/Tasks/taskXicc.cxx @@ -19,14 +19,14 @@ #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_xicc; -// using namespace o2::aod::hf_cand_3prong; void customize(std::vector& workflowOptions) { @@ -42,6 +42,8 @@ struct HfTaskXicc { Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_xicc_to_p_k_pi_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_xicc::isSelXiccToPKPiPi >= selectionFlagXicc); HistogramRegistry registry{ @@ -50,7 +52,7 @@ struct HfTaskXicc { {"hPtProng0", "#Xi^{++}_{cc}-candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}}, {"hPtProng1", "#Xi^{++}_{cc}-candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMass", "#Xi^{++}_{cc} candidates;inv. mass (p K #pi #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{400, 3.2, 4.0}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -70,16 +72,15 @@ struct HfTaskXicc { } void process(soa::Filtered> const& candidates) - // void process(aod::HfCandXicc const& candidates) { - for (auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::XiccToXicPi)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_xicc::DecayType::XiccToXicPi)) { continue; } - if (yCandMax >= 0. && std::abs(yXicc(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yXicc(candidate)) > yCandMax) { continue; } - registry.fill(HIST("hMass"), invMassXiccToXicPi(candidate), candidate.pt()); // FIXME need to consider the two mass hp + registry.fill(HIST("hMass"), hfHelper.invMassXiccToXicPi(candidate), candidate.pt()); // FIXME need to consider the two mass hp registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); registry.fill(HIST("hPtProng1"), candidate.ptProng1()); @@ -88,10 +89,10 @@ struct HfTaskXicc { registry.fill(HIST("hChi2PCA"), candidate.chi2PCA(), candidate.pt()); registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), candidate.pt()); - registry.fill(HIST("hCt"), ctXicc(candidate), candidate.pt()); + registry.fill(HIST("hCt"), hfHelper.ctXicc(candidate), candidate.pt()); registry.fill(HIST("hCPA"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEta"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hY"), yXicc(candidate), candidate.pt()); + registry.fill(HIST("hY"), hfHelper.yXicc(candidate), candidate.pt()); registry.fill(HIST("hSelectionStatus"), candidate.isSelXiccToPKPiPi(), candidate.pt()); registry.fill(HIST("hImpParErr0"), candidate.errorImpactParameter0(), candidate.pt()); registry.fill(HIST("hImpParErr1"), candidate.errorImpactParameter1(), candidate.pt()); @@ -106,6 +107,8 @@ struct HfTaskXiccMc { Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_xicc_to_p_k_pi_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_xicc::isSelXiccToPKPiPi >= selectionFlagXicc); HistogramRegistry registry{ @@ -122,7 +125,7 @@ struct HfTaskXiccMc { {"hYGen", "#Xi^{++}_{cc} MC particles (matched);#it{y};entries", {HistType::kTH1F, {{250, -5., 5.}}}}, {"hPtvsEtavsYGen", "#Xi^{++}_{cc} MC particles (matched);#it{p}_{T} (GeV/#it{c});#it{#eta};#it{y}", {HistType::kTH3F, {{360, 0., 36.}, {250, -5., 5.}, {20, -5., 5.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMassVsPtRecSig", "#Xi^{++}_{cc} (rec. matched) candidates;inv. mass (p K #pi #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{400, 3.2, 4.0}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -173,29 +176,28 @@ struct HfTaskXiccMc { registry.add("hCPAVsPtVsYRecBg", "#Xi^{++}_{cc} (rec. unmatched) candidates;cosine of pointing angle; #it{p}_{T} (GeV/#it{c}); #it{y}", {HistType::kTH3F, {{2200, -1.1, 1.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}, {20, -5., 5.}}}); } - // void process(soa::Filtered> const& candidates) void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { // MC rec. - // Printf("MC Candidates: %d", candidates.size()); - for (auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::XiccToXicPi)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_xicc::DecayType::XiccToXicPi)) { continue; } - if (yCandMax >= 0. && std::abs(yXicc(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yXicc(candidate)) > yCandMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::XiccToXicPi) { + if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_xicc::DecayType::XiccToXicPi) { // Get the corresponding MC particle. - auto indexMother = RecoDecay::getMother(particlesMC, candidate.prong1_as().mcParticle_as>(), 4422, true); - auto particleXicc = particlesMC.rawIteratorAt(indexMother); - auto particleXic = particlesMC.rawIteratorAt(particleXicc.daughtersIds().front()); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), 4422, true); + auto particleXicc = mcParticles.rawIteratorAt(indexMother); + auto particleXic = mcParticles.rawIteratorAt(particleXicc.daughtersIds().front()); /* - auto daughter1 = particlesMC.rawIteratorAt(particleXicc.daughtersIds().back()); - auto p0xic = particlesMC.rawIteratorAt(particleXic.daughtersIds().front()); - auto p1xic = particlesMC.rawIteratorAt(particleXic.daughtersIds().front()+1); - auto p2xic = particlesMC.rawIteratorAt(particleXic.daughterIds().back()); + auto daughter1 = mcParticles.rawIteratorAt(particleXicc.daughtersIds().back()); + auto p0xic = mcParticles.rawIteratorAt(particleXic.daughtersIds().front()); + auto p1xic = mcParticles.rawIteratorAt(particleXic.daughtersIds().front()+1); + auto p2xic = mcParticles.rawIteratorAt(particleXic.daughterIds().back()); LOGF(info, "mother pdg %d", particleXicc.pdgCode()); LOGF(info, "Xic pdg %d", particleXic.pdgCode()); LOGF(info, "Xic prong 0 pdg %d", p0xic.pdgCode()); @@ -206,17 +208,17 @@ struct HfTaskXiccMc { registry.fill(HIST("hPtGenSig"), particleXicc.pt()); // gen. level pT registry.fill(HIST("hPtRecSig"), candidate.pt()); // rec. level pT registry.fill(HIST("hEtaRecSig"), candidate.eta()); - registry.fill(HIST("hYRecSig"), yXicc(candidate)); - registry.fill(HIST("hMassVsPtRecSig"), invMassXiccToXicPi(candidate), candidate.pt()); // FIXME need to consider the two mass hp + registry.fill(HIST("hYRecSig"), hfHelper.yXicc(candidate)); + registry.fill(HIST("hMassVsPtRecSig"), hfHelper.invMassXiccToXicPi(candidate), candidate.pt()); // FIXME need to consider the two mass hp registry.fill(HIST("hDecLengthVsPtRecSig"), candidate.decayLength(), candidate.pt()); registry.fill(HIST("hChi2PCAVsPtRecSig"), candidate.chi2PCA(), candidate.pt()); registry.fill(HIST("hCPAVsPtRecSig"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hd0Prong0VsPtRecSig"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1VsPtRecSig"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hd0d0VsPtRecSig"), candidate.impactParameterProduct(), candidate.pt()); - registry.fill(HIST("hCtVsPtRecSig"), ctXicc(candidate), candidate.pt()); + registry.fill(HIST("hCtVsPtRecSig"), hfHelper.ctXicc(candidate), candidate.pt()); registry.fill(HIST("hEtaVsPtRecSig"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hYVsPtRecSig"), yXicc(candidate), candidate.pt()); + registry.fill(HIST("hYVsPtRecSig"), hfHelper.yXicc(candidate), candidate.pt()); registry.fill(HIST("hImpParErr0VsPtRecSig"), candidate.errorImpactParameter0(), candidate.pt()); registry.fill(HIST("hImpParErr1VsPtRecSig"), candidate.errorImpactParameter1(), candidate.pt()); registry.fill(HIST("hXSecVtxPosRecGenDiffSig"), candidate.xSecondaryVertex() - particleXic.vx(), candidate.pt()); @@ -224,51 +226,50 @@ struct HfTaskXiccMc { registry.fill(HIST("hZSecVtxPosRecGenDiffSig"), candidate.zSecondaryVertex() - particleXic.vz(), candidate.pt()); registry.fill(HIST("hPtRecGenDiffSig"), candidate.pt() - particleXicc.pt(), candidate.pt()); // Check Y dependence (To be removed) - registry.fill(HIST("hMassVsPtVsYRecSig"), invMassXiccToXicPi(candidate), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hDecLengthVsPtVsYRecSig"), candidate.decayLength(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hChi2PCAVsPtVsYRecSig"), candidate.chi2PCA(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hCPAVsPtVsYRecSig"), candidate.cpa(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hd0Prong0VsPtVsYRecSig"), candidate.impactParameter0(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hd0Prong1VsPtVsYRecSig"), candidate.impactParameter1(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hCtVsPtVsYRecSig"), ctXicc(candidate), candidate.pt(), yXicc(candidate)); + registry.fill(HIST("hMassVsPtVsYRecSig"), hfHelper.invMassXiccToXicPi(candidate), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hDecLengthVsPtVsYRecSig"), candidate.decayLength(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hChi2PCAVsPtVsYRecSig"), candidate.chi2PCA(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hCPAVsPtVsYRecSig"), candidate.cpa(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hd0Prong0VsPtVsYRecSig"), candidate.impactParameter0(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hd0Prong1VsPtVsYRecSig"), candidate.impactParameter1(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hCtVsPtVsYRecSig"), hfHelper.ctXicc(candidate), candidate.pt(), hfHelper.yXicc(candidate)); } else { registry.fill(HIST("hPtRecBg"), candidate.pt()); registry.fill(HIST("hEtaRecBg"), candidate.eta()); - registry.fill(HIST("hYRecBg"), yXicc(candidate)); - registry.fill(HIST("hMassVsPtRecBg"), invMassXiccToXicPi(candidate), candidate.pt()); // FIXME need to consider the two mass hp + registry.fill(HIST("hYRecBg"), hfHelper.yXicc(candidate)); + registry.fill(HIST("hMassVsPtRecBg"), hfHelper.invMassXiccToXicPi(candidate), candidate.pt()); // FIXME need to consider the two mass hp registry.fill(HIST("hDecLengthVsPtRecBg"), candidate.decayLength(), candidate.pt()); registry.fill(HIST("hChi2PCAVsPtRecBg"), candidate.chi2PCA(), candidate.pt()); registry.fill(HIST("hCPAVsPtRecBg"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hd0Prong0VsPtRecBg"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1VsPtRecBg"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hd0d0VsPtRecBg"), candidate.impactParameterProduct(), candidate.pt()); - registry.fill(HIST("hCtVsPtRecBg"), ctXicc(candidate), candidate.pt()); + registry.fill(HIST("hCtVsPtRecBg"), hfHelper.ctXicc(candidate), candidate.pt()); registry.fill(HIST("hEtaVsPtRecBg"), candidate.eta(), candidate.pt()); - registry.fill(HIST("hYVsPtRecBg"), yXicc(candidate), candidate.pt()); + registry.fill(HIST("hYVsPtRecBg"), hfHelper.yXicc(candidate), candidate.pt()); registry.fill(HIST("hImpParErr0VsPtRecBg"), candidate.errorImpactParameter0(), candidate.pt()); registry.fill(HIST("hImpParErr1VsPtRecBg"), candidate.errorImpactParameter1(), candidate.pt()); registry.fill(HIST("hDebugMCmatching"), candidate.debugMcRec(), candidate.pt()); // Check Y dependence (To be removed) - registry.fill(HIST("hMassVsPtVsYRecBg"), invMassXiccToXicPi(candidate), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hDecLengthVsPtVsYRecBg"), candidate.decayLength(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hChi2PCAVsPtVsYRecBg"), candidate.chi2PCA(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hCPAVsPtVsYRecBg"), candidate.cpa(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hd0Prong0VsPtVsYRecBg"), candidate.impactParameter0(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hd0Prong1VsPtVsYRecBg"), candidate.impactParameter1(), candidate.pt(), yXicc(candidate)); - registry.fill(HIST("hCtVsPtVsYRecBg"), ctXicc(candidate), candidate.pt(), yXicc(candidate)); + registry.fill(HIST("hMassVsPtVsYRecBg"), hfHelper.invMassXiccToXicPi(candidate), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hDecLengthVsPtVsYRecBg"), candidate.decayLength(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hChi2PCAVsPtVsYRecBg"), candidate.chi2PCA(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hCPAVsPtVsYRecBg"), candidate.cpa(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hd0Prong0VsPtVsYRecBg"), candidate.impactParameter0(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hd0Prong1VsPtVsYRecBg"), candidate.impactParameter1(), candidate.pt(), hfHelper.yXicc(candidate)); + registry.fill(HIST("hCtVsPtVsYRecBg"), hfHelper.ctXicc(candidate), candidate.pt(), hfHelper.yXicc(candidate)); } } // end of loop over reconstructed candidates // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::XiccToXicPi) { - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > yCandMax) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_xicc::DecayType::XiccToXicPi) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassXiCCPlusPlus)) > yCandMax) { continue; } registry.fill(HIST("hPtGen"), particle.pt()); registry.fill(HIST("hEtaGen"), particle.eta()); - registry.fill(HIST("hYGen"), RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))); - registry.fill(HIST("hPtvsEtavsYGen"), particle.pt(), particle.eta(), RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))); + registry.fill(HIST("hYGen"), RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassXiCCPlusPlus)); + registry.fill(HIST("hPtvsEtavsYGen"), particle.pt(), particle.eta(), RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassXiCCPlusPlus)); } } // end of loop of MC particles } // end of process function diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 69ead7d61f5..97cc4c6e6ea 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -21,20 +21,127 @@ #include #include +#include "Framework/AnalysisDataModel.h" + #include "ALICE3/DataModel/ECAL.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisDataModel.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGHF/Core/SelectorCuts.h" - -using namespace o2::analysis; +#include "PWGHF/Core/PDG.h" namespace o2::aod { +// Table aliases + +using TracksWCov = soa::Join; +using TracksWDca = soa::Join; +using TracksWExtra = soa::Join; +using TracksWCovDca = soa::Join; +using TracksWCovExtra = soa::Join; +using TracksWDcaExtra = soa::Join; +using TracksWCovDcaExtra = soa::Join; + +using TracksWMc = soa::Join; + +using TracksPidEl = soa::Join; +using TracksPidMu = soa::Join; +using TracksPidPi = soa::Join; +using TracksPidKa = soa::Join; +using TracksPidPr = soa::Join; + +using TracksPidTinyEl = soa::Join; +using TracksPidTinyMu = soa::Join; +using TracksPidTinyPi = soa::Join; +using TracksPidTinyKa = soa::Join; +using TracksPidTinyPr = soa::Join; + +namespace pid_tpc_tof_utils +{ +/// Function to combine TPC and TOF NSigma (for ML purposes) +/// \param tpcNSigma is the (binned) NSigma separation in TPC (if tiny = true) +/// \param tofNSigma is the (binned) NSigma separation in TOF (if tiny = true) +/// \return Node containing the combined NSigma of TPC and TOF +template +o2::framework::expressions::Node combineNSigma(const T1& tpcNSigma, const T1& tofNSigma) +{ + float defaultNSigmaTolerance = .1f; + float defaultNSigma = -999.f + defaultNSigmaTolerance; // -999.f is the default value set in TPCPIDResponse.h and PIDTOF.h + + if constexpr (tiny) { + auto tpcBinWidth = 1.f * pidtpc_tiny::binning::bin_width; + auto tofBinWidth = 1.f * pidtof_tiny::binning::bin_width; + + return o2::framework::expressions::ifnode((tpcNSigma * tpcBinWidth > defaultNSigma) && (tofNSigma * tofBinWidth > defaultNSigma), o2::framework::expressions::nsqrt(.5f * tpcNSigma * tpcNSigma * tpcBinWidth * tpcBinWidth + .5f * tofNSigma * tofNSigma * tofBinWidth * tofBinWidth), // TPC and TOF + o2::framework::expressions::ifnode(tpcNSigma * tpcBinWidth > defaultNSigma, o2::framework::expressions::nabs(tpcNSigma * tpcBinWidth), // only TPC + o2::framework::expressions::ifnode(tofNSigma * tofBinWidth > defaultNSigma, o2::framework::expressions::nabs(tofNSigma * tofBinWidth), // only TOF + 1.f * tofNSigma * tofBinWidth))); // no TPC nor TOF + } + + return o2::framework::expressions::ifnode((tpcNSigma > defaultNSigma) && (tofNSigma > defaultNSigma), o2::framework::expressions::nsqrt(.5f * tpcNSigma * tpcNSigma + .5f * tofNSigma * tofNSigma), // TPC and TOF + o2::framework::expressions::ifnode(tpcNSigma > defaultNSigma, o2::framework::expressions::nabs(tpcNSigma), // only TPC + o2::framework::expressions::ifnode(tofNSigma > defaultNSigma, o2::framework::expressions::nabs(tofNSigma), // only TOF + 1.f * tofNSigma))); // no TPC nor TOF +} +} // namespace pid_tpc_tof_utils + +namespace pid_tpc_tof +{ +// Combined TPC and TOF NSigma +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaEl, tpcTofNSigmaEl, //! Combined NSigma separation with the TPC & TOF detectors for electron + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc::tpcNSigmaEl, o2::aod::pidtof::tofNSigmaEl)); +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaMu, tpcTofNSigmaMu, //! Combined NSigma separation with the TPC & TOF detectors for muon + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc::tpcNSigmaMu, o2::aod::pidtof::tofNSigmaMu)); +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaPi, tpcTofNSigmaPi, //! Combined NSigma separation with the TPC & TOF detectors for pion + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc::tpcNSigmaPi, o2::aod::pidtof::tofNSigmaPi)); +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaKa, tpcTofNSigmaKa, //! Combined NSigma separation with the TPC & TOF detectors for kaon + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc::tpcNSigmaKa, o2::aod::pidtof::tofNSigmaKa)); +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaPr, tpcTofNSigmaPr, //! Combined NSigma separation with the TPC & TOF detectors for proton + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc::tpcNSigmaPr, o2::aod::pidtof::tofNSigmaPr)); +} // namespace pid_tpc_tof + +namespace pid_tpc_tof_tiny +{ +// Combined binned TPC and TOF NSigma +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaEl, tpcTofNSigmaEl, //! Combined binned NSigma separation with the TPC & TOF detectors for electron + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc_tiny::tpcNSigmaStoreEl, o2::aod::pidtof_tiny::tofNSigmaStoreEl)); +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaMu, tpcTofNSigmaMu, //! Combined binned NSigma separation with the TPC & TOF detectors for muon + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc_tiny::tpcNSigmaStoreMu, o2::aod::pidtof_tiny::tofNSigmaStoreMu)); +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaPi, tpcTofNSigmaPi, //! Combined binned NSigma separation with the TPC & TOF detectors for pion + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc_tiny::tpcNSigmaStorePi, o2::aod::pidtof_tiny::tofNSigmaStorePi)); +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaKa, tpcTofNSigmaKa, //! Combined binned NSigma separation with the TPC & TOF detectors for kaon + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc_tiny::tpcNSigmaStoreKa, o2::aod::pidtof_tiny::tofNSigmaStoreKa)); +DECLARE_SOA_EXPRESSION_COLUMN(TpcTofNSigmaPr, tpcTofNSigmaPr, //! Combined binned NSigma separation with the TPC & TOF detectors for proton + float, pid_tpc_tof_utils::combineNSigma(o2::aod::pidtpc_tiny::tpcNSigmaStorePr, o2::aod::pidtof_tiny::tofNSigmaStorePr)); +} // namespace pid_tpc_tof_tiny + +// Extension of per particle tables +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidElExt, TracksPidEl, "PIDELEXT", //! Table of the TPC & TOF Combined NSigma for electron + pid_tpc_tof::TpcTofNSigmaEl); +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidMuExt, TracksPidMu, "PIDMUEXT", //! Table of the TPC & TOF Combined NSigma for muon + pid_tpc_tof::TpcTofNSigmaMu); +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidPiExt, TracksPidPi, "PIDPIEXT", //! Table of the TPC & TOF Combined NSigma for pion + pid_tpc_tof::TpcTofNSigmaPi); +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidKaExt, TracksPidKa, "PIDKAEXT", //! Table of the TPC & TOF Combined NSigma for kaon + pid_tpc_tof::TpcTofNSigmaKa); +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidPrExt, TracksPidPr, "PIDPREXT", //! Table of the TPC & TOF Combined NSigma for proton + pid_tpc_tof::TpcTofNSigmaPr); + +// Extension of tiny size tables +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidTinyElExt, TracksPidTinyEl, "PIDTINYELEXT", //! Table of the TPC & TOF combined binned NSigma for electron + pid_tpc_tof_tiny::TpcTofNSigmaEl); +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidTinyMuExt, TracksPidTinyMu, "PIDTINYMUEXT", //! Table of the TPC & TOF combined binned NSigma for muon + pid_tpc_tof_tiny::TpcTofNSigmaMu); +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidTinyPiExt, TracksPidTinyPi, "PIDTINYPIEXT", //! Table of the TPC & TOF combined binned NSigma for pion + pid_tpc_tof_tiny::TpcTofNSigmaPi); +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidTinyKaExt, TracksPidTinyKa, "PIDTINYKAEXT", //! Table of the TPC & TOF combined binned NSigma for kaon + pid_tpc_tof_tiny::TpcTofNSigmaKa); +DECLARE_SOA_EXTENDED_TABLE_USER(TracksPidTinyPrExt, TracksPidTinyPr, "PIDTINYPREXT", //! Table of the TPC & TOF combined binned NSigma for proton + pid_tpc_tof_tiny::TpcTofNSigmaPr); + namespace hf_sel_collision { DECLARE_SOA_COLUMN(WhyRejectColl, whyRejectColl, int); //! @@ -79,16 +186,6 @@ DECLARE_SOA_TABLE(HfPvRefitTrack, "AOD", "HFPVREFITTRACK", //! hf_pv_refit_track::PvRefitDcaXY, hf_pv_refit_track::PvRefitDcaZ); -using BigTracks = soa::Join; -using BigTracksExtended = soa::Join; -using BigTracksMC = soa::Join; -using BigTracksPID = soa::Join; -using BigTracksPIDExtended = soa::Join; - -// FIXME: this is a workaround until we get the index columns to work with joins. - namespace hf_track_index { DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! Collision index @@ -107,6 +204,8 @@ DECLARE_SOA_COLUMN(FlagDplusToPiKPi, flagDplusToPiKPi, uint8_t); //! DECLARE_SOA_COLUMN(FlagLcToPKPi, flagLcToPKPi, uint8_t); //! DECLARE_SOA_COLUMN(FlagDsToKKPi, flagDsToKKPi, uint8_t); //! DECLARE_SOA_COLUMN(FlagXicToPKPi, flagXicToPKPi, uint8_t); //! + +DECLARE_SOA_COLUMN(FlagDstarToD0Pi, flagDstarToD0Pi, uint8_t); //! } // namespace hf_track_index DECLARE_SOA_TABLE(Hf2Prongs_000, "AOD", "HF2PRONG", //! Table for HF 2 prong candidates (Run 2 converted format) @@ -175,10 +274,18 @@ namespace hf_track_index DECLARE_SOA_INDEX_COLUMN_FULL(ProngD0, prongD0, int, Hf2Prongs, ""); //! Index to a D0 prong } // namespace hf_track_index -DECLARE_SOA_TABLE(HfDstars, "AOD", "HFDSTAR", //! D* -> D0pi candidates +DECLARE_SOA_TABLE(HfDstars_000, "AOD", "HFDSTAR", //! D* -> D0pi candidates (Run 2 converted format) o2::soa::Index<>, hf_track_index::Prong0Id, hf_track_index::ProngD0Id); + +DECLARE_SOA_TABLE(HfDstars_001, "AOD", "HFDSTAR", //! D* -> D0pi candidates (Run 3 format) + o2::soa::Index<>, + hf_track_index::CollisionId, + hf_track_index::Prong0Id, + hf_track_index::ProngD0Id); + +using HfDstars = HfDstars_001; using HfDstar = HfDstars::iterator; DECLARE_SOA_TABLE(HfCutStatus2Prong, "AOD", "HFCUTSTATUS2P", //! @@ -192,7 +299,10 @@ DECLARE_SOA_TABLE(HfCutStatus3Prong, "AOD", "HFCUTSTATUS3P", //! hf_track_index::FlagDsToKKPi, hf_track_index::FlagXicToPKPi); -namespace hf_pv_refit_cand_2prong +DECLARE_SOA_TABLE(HfCutStatusDstar, "AOD", "HFCUTSTATUSDST", //! + hf_track_index::FlagDstarToD0Pi); + +namespace hf_pv_refit { DECLARE_SOA_COLUMN(PvRefitX, pvRefitX, float); //! DECLARE_SOA_COLUMN(PvRefitY, pvRefitY, float); //! @@ -203,42 +313,42 @@ DECLARE_SOA_COLUMN(PvRefitSigmaY2, pvRefitSigmaY2, float); //! DECLARE_SOA_COLUMN(PvRefitSigmaXZ, pvRefitSigmaXZ, float); //! DECLARE_SOA_COLUMN(PvRefitSigmaYZ, pvRefitSigmaYZ, float); //! DECLARE_SOA_COLUMN(PvRefitSigmaZ2, pvRefitSigmaZ2, float); //! -} // namespace hf_pv_refit_cand_2prong +} // namespace hf_pv_refit DECLARE_SOA_TABLE(HfPvRefit2Prong, "AOD", "HFPVREFIT2PRONG", //! - hf_pv_refit_cand_2prong::PvRefitX, - hf_pv_refit_cand_2prong::PvRefitY, - hf_pv_refit_cand_2prong::PvRefitZ, - hf_pv_refit_cand_2prong::PvRefitSigmaX2, - hf_pv_refit_cand_2prong::PvRefitSigmaXY, - hf_pv_refit_cand_2prong::PvRefitSigmaY2, - hf_pv_refit_cand_2prong::PvRefitSigmaXZ, - hf_pv_refit_cand_2prong::PvRefitSigmaYZ, - hf_pv_refit_cand_2prong::PvRefitSigmaZ2); - -namespace hf_pv_refit_cand_3prong -{ -DECLARE_SOA_COLUMN(PvRefitX, pvRefitX, float); //! -DECLARE_SOA_COLUMN(PvRefitY, pvRefitY, float); //! -DECLARE_SOA_COLUMN(PvRefitZ, pvRefitZ, float); //! -DECLARE_SOA_COLUMN(PvRefitSigmaX2, pvRefitSigmaX2, float); //! -DECLARE_SOA_COLUMN(PvRefitSigmaXY, pvRefitSigmaXY, float); //! -DECLARE_SOA_COLUMN(PvRefitSigmaY2, pvRefitSigmaY2, float); //! -DECLARE_SOA_COLUMN(PvRefitSigmaXZ, pvRefitSigmaXZ, float); //! -DECLARE_SOA_COLUMN(PvRefitSigmaYZ, pvRefitSigmaYZ, float); //! -DECLARE_SOA_COLUMN(PvRefitSigmaZ2, pvRefitSigmaZ2, float); //! -} // namespace hf_pv_refit_cand_3prong + hf_pv_refit::PvRefitX, + hf_pv_refit::PvRefitY, + hf_pv_refit::PvRefitZ, + hf_pv_refit::PvRefitSigmaX2, + hf_pv_refit::PvRefitSigmaXY, + hf_pv_refit::PvRefitSigmaY2, + hf_pv_refit::PvRefitSigmaXZ, + hf_pv_refit::PvRefitSigmaYZ, + hf_pv_refit::PvRefitSigmaZ2); DECLARE_SOA_TABLE(HfPvRefit3Prong, "AOD", "HFPVREFIT3PRONG", //! - hf_pv_refit_cand_3prong::PvRefitX, - hf_pv_refit_cand_3prong::PvRefitY, - hf_pv_refit_cand_3prong::PvRefitZ, - hf_pv_refit_cand_3prong::PvRefitSigmaX2, - hf_pv_refit_cand_3prong::PvRefitSigmaXY, - hf_pv_refit_cand_3prong::PvRefitSigmaY2, - hf_pv_refit_cand_3prong::PvRefitSigmaXZ, - hf_pv_refit_cand_3prong::PvRefitSigmaYZ, - hf_pv_refit_cand_3prong::PvRefitSigmaZ2); + hf_pv_refit::PvRefitX, + hf_pv_refit::PvRefitY, + hf_pv_refit::PvRefitZ, + hf_pv_refit::PvRefitSigmaX2, + hf_pv_refit::PvRefitSigmaXY, + hf_pv_refit::PvRefitSigmaY2, + hf_pv_refit::PvRefitSigmaXZ, + hf_pv_refit::PvRefitSigmaYZ, + hf_pv_refit::PvRefitSigmaZ2, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(HfPvRefitDstar, "AOD", "HFPVREFITDSTAR", //! + hf_pv_refit::PvRefitX, + hf_pv_refit::PvRefitY, + hf_pv_refit::PvRefitZ, + hf_pv_refit::PvRefitSigmaX2, + hf_pv_refit::PvRefitSigmaXY, + hf_pv_refit::PvRefitSigmaY2, + hf_pv_refit::PvRefitSigmaXZ, + hf_pv_refit::PvRefitSigmaYZ, + hf_pv_refit::PvRefitSigmaZ2, + o2::soa::Marker<2>); // general decay properties namespace hf_cand @@ -261,7 +371,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptProng0, //! DECLARE_SOA_DYNAMIC_COLUMN(Pt2Prong0, pt2Prong0, //! [](float px, float py) -> float { return RecoDecay::pt2(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(PVectorProng0, pVectorProng0, //! - [](float px, float py, float pz) -> array { return array{px, py, pz}; }); + [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); DECLARE_SOA_COLUMN(ImpactParameter0, impactParameter0, float); //! DECLARE_SOA_COLUMN(ErrorImpactParameter0, errorImpactParameter0, float); //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, //! @@ -274,7 +384,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptProng1, //! DECLARE_SOA_DYNAMIC_COLUMN(Pt2Prong1, pt2Prong1, //! [](float px, float py) -> float { return RecoDecay::pt2(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(PVectorProng1, pVectorProng1, //! - [](float px, float py, float pz) -> array { return array{px, py, pz}; }); + [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); DECLARE_SOA_COLUMN(ImpactParameter1, impactParameter1, float); //! DECLARE_SOA_COLUMN(ErrorImpactParameter1, errorImpactParameter1, float); //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, //! @@ -287,7 +397,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtProng2, ptProng2, //! DECLARE_SOA_DYNAMIC_COLUMN(Pt2Prong2, pt2Prong2, //! [](float px, float py) -> float { return RecoDecay::pt2(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(PVectorProng2, pVectorProng2, //! - [](float px, float py, float pz) -> array { return array{px, py, pz}; }); + [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); DECLARE_SOA_COLUMN(ImpactParameter2, impactParameter2, float); //! DECLARE_SOA_COLUMN(ErrorImpactParameter2, errorImpactParameter2, float); //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterNormalised2, impactParameterNormalised2, //! @@ -302,35 +412,40 @@ DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! DECLARE_SOA_DYNAMIC_COLUMN(P2, p2, //! [](float px, float py, float pz) -> float { return RecoDecay::p2(px, py, pz); }); DECLARE_SOA_DYNAMIC_COLUMN(PVector, pVector, //! - [](float px, float py, float pz) -> array { return array{px, py, pz}; }); + [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! - [](float px, float py, float pz) -> float { return RecoDecay::eta(array{px, py, pz}); }); + [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! [](float px, float py) -> float { return RecoDecay::phi(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(Y, y, //! - [](float px, float py, float pz, double m) -> float { return RecoDecay::y(array{px, py, pz}, m); }); + [](float px, float py, float pz, double m) -> float { return RecoDecay::y(std::array{px, py, pz}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(E, e, //! [](float px, float py, float pz, double m) -> float { return RecoDecay::e(px, py, pz, m); }); DECLARE_SOA_DYNAMIC_COLUMN(E2, e2, //! [](float px, float py, float pz, double m) -> float { return RecoDecay::e2(px, py, pz, m); }); DECLARE_SOA_DYNAMIC_COLUMN(DecayLength, decayLength, //! - [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { return RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}); }); + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { return RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}); }); DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthXY, decayLengthXY, //! - [](float xVtxP, float yVtxP, float xVtxS, float yVtxS) -> float { return RecoDecay::distanceXY(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}); }); + [](float xVtxP, float yVtxP, float xVtxS, float yVtxS) -> float { return RecoDecay::distanceXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}); }); DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthNormalised, decayLengthNormalised, //! - [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float err) -> float { return RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}) / err; }); + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float err) -> float { return RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}) / err; }); DECLARE_SOA_DYNAMIC_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, //! - [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float err) -> float { return RecoDecay::distanceXY(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}) / err; }); + [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float err) -> float { return RecoDecay::distanceXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}) / err; }); DECLARE_SOA_COLUMN(ErrorDecayLength, errorDecayLength, float); //! DECLARE_SOA_COLUMN(ErrorDecayLengthXY, errorDecayLengthXY, float); //! DECLARE_SOA_DYNAMIC_COLUMN(CPA, cpa, //! - [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::cpa(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}, array{px, py, pz}); }); + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::cpa(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(CPAXY, cpaXY, //! - [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float px, float py) -> float { return RecoDecay::cpaXY(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, array{px, py}); }); + [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float px, float py) -> float { return RecoDecay::cpaXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{px, py}); }); DECLARE_SOA_DYNAMIC_COLUMN(Ct, ct, //! - [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) -> float { return RecoDecay::ct(array{px, py, pz}, RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}), m); }); + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) -> float { return RecoDecay::ct(std::array{px, py, pz}, RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}), m); }); DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterXY, impactParameterXY, //! - [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::impParXY(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}, array{px, py, pz}); }); + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); }); +DECLARE_SOA_COLUMN(KfTopolChi2OverNdf, kfTopolChi2OverNdf, float); //! chi2overndf of the KFParticle topological constraint + +// method of secondary-vertex reconstruction +enum VertexerType { DCAFitter = 0, + KfParticle }; } // namespace hf_cand // specific 2-prong decay properties @@ -345,20 +460,23 @@ DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, //! [](float dca1, float dca2) -> float { return dca1 * dca2; }); DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m) -> float { return RecoDecay::m(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m) -> float { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m) -> float { return RecoDecay::m2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m) -> float { return RecoDecay::m2(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m, double mTot, int iProng) -> float { return RecoDecay::cosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m, double mTot, int iProng) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m, mTot, iProng); }); DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, //! [](float impParProng0, float impParProng1) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1); }); DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! - [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, errDlxy, array{pxM, pyM}, array{ip0, ip1}, array{errIp0, errIp1}, array{array{px0, py0}, array{px1, py1}}); }); + [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1}, std::array{errIp0, errIp1}, std::array{std::array{px0, py0}, std::array{px1, py1}}); }); // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level +// KF related properties +DECLARE_SOA_COLUMN(KfGeoMassD0, kfGeoMassD0, float); //! mass of the D0 candidate from the KFParticle geometric fit +DECLARE_SOA_COLUMN(KfGeoMassD0bar, kfGeoMassD0bar, float); //! mass of the D0bar candidate from the KFParticle geometric fit // mapping of decay types enum DecayType { D0ToPiK = 0, @@ -366,86 +484,6 @@ enum DecayType { D0ToPiK = 0, JpsiToMuMu, N2ProngDecays }; // always keep N2ProngDecays at the end -// functions for specific particles - -// D0(bar) → π± K∓ - -template -auto ctD0(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kD0)); -} - -template -auto yD0(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kD0)); -} - -template -auto eD0(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kD0)); -} - -template -auto invMassD0ToPiK(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus)}); -} - -template -auto invMassD0barToKPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); -} - -template -auto cosThetaStarD0(const T& candidate) -{ - return candidate.cosThetaStar(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus)}, RecoDecay::getMassPDG(pdg::Code::kD0), 1); -} - -template -auto cosThetaStarD0bar(const T& candidate) -{ - return candidate.cosThetaStar(array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}, RecoDecay::getMassPDG(pdg::Code::kD0), 0); -} - -// J/ψ - -template -auto ctJpsi(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kJPsi)); -} - -template -auto yJpsi(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kJPsi)); -} - -template -auto eJpsi(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kJPsi)); -} - -// J/ψ → e+ e− -template -auto invMassJpsiToEE(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kElectron), RecoDecay::getMassPDG(kElectron)}); -} -// J/ψ → μ+ μ− - -template -auto invMassJpsiToMuMu(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kMuonPlus), RecoDecay::getMassPDG(kMuonMinus)}); -} - } // namespace hf_cand_2prong // general columns @@ -510,6 +548,10 @@ DECLARE_SOA_EXTENDED_TABLE_USER(HfCand2ProngExt, HfCand2ProngBase, "HFCAND2PEXT" using HfCand2Prong = HfCand2ProngExt; +DECLARE_SOA_TABLE(HfCand2ProngKF, "AOD", "HFCAND2PKF", + hf_cand::KfTopolChi2OverNdf, + hf_cand_2prong::KfGeoMassD0, hf_cand_2prong::KfGeoMassD0bar); + // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCand2ProngMcRec, "AOD", "HFCAND2PMCREC", //! hf_cand_2prong::FlagMcMatchRec, @@ -530,13 +572,13 @@ DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! py of candidate float, 1.f * aod::hf_cand::pyProng0 + 1.f * aod::hf_cand::pyProng1); DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! pz of candidate float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1); -// DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m) { return RecoDecay::M(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); +// DECLARE_SOA_DYNAMIC_COLUMN(M, m, [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m) { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(PtV0Pos, ptV0Pos, //! pt of the positive V0 daughter [](float px, float py) { return RecoDecay::pt(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(PtV0Neg, ptV0Neg, //! pt of the negative V0 daughter [](float px, float py) { return RecoDecay::pt(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(CtV0, ctV0, //! c*t of the V0 - [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) -> float { return RecoDecay::ct(array{px, py, pz}, RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}), m); }); + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz, double m) -> float { return RecoDecay::ct(std::array{px, py, pz}, RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}), m); }); DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level @@ -544,31 +586,6 @@ DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, DECLARE_SOA_COLUMN(V0X, v0x, float); //! X position of V0 decay DECLARE_SOA_COLUMN(V0Y, v0y, float); //! Y position of V0 decay DECLARE_SOA_COLUMN(V0Z, v0z, float); //! Z position of V0 decay - -template -auto invMassLcToK0sP(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kProton), RecoDecay::getMassPDG(kK0Short)}); // first daughter is bachelor -} - -template -auto invMassGammaToEE(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kElectron), RecoDecay::getMassPDG(kElectron)}); -} - -template -auto ctV0K0s(const T& candidate) -{ - return candidate.ctV0(RecoDecay::getMassPDG(kK0Short)); -} - -template -auto ctV0Lambda(const T& candidate) -{ - return candidate.ctV0(RecoDecay::getMassPDG(kLambda0)); -} - } // namespace hf_cand_casc DECLARE_SOA_TABLE(HfCandCascBase, "AOD", "HFCANDCASCBASE", //! @@ -652,38 +669,6 @@ DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // particle origin, DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, generator level enum DecayType { BplusToD0Pi = 0 }; - -// B± → D0bar(D0) π± - -template -auto ctBplus(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kBPlus)); -} - -template -auto yBplus(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kBPlus)); -} - -template -auto eBplus(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kBPlus)); -} - -template -auto invMassBplusToD0Pi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(pdg::Code::kD0), RecoDecay::getMassPDG(kPiPlus)}); -} - -template -auto cosThetaStarBplus(const T& candidate) -{ - return candidate.cosThetaStar(array{RecoDecay::getMassPDG(pdg::Code::kD0), RecoDecay::getMassPDG(kPiPlus)}, RecoDecay::getMassPDG(pdg::Code::kBPlus), 1); -} } // namespace hf_cand_bplus // declare dedicated BPlus decay candidate table @@ -696,7 +681,6 @@ DECLARE_SOA_TABLE(HfCandBplusBase, "AOD", "HFCANDBPLUSBASE", hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, - hf_cand_bplus::Prong0Id, hf_track_index::Prong1Id, hf_track_index::HFflag, /* dynamic columns */ hf_cand_2prong::M, @@ -725,7 +709,10 @@ DECLARE_SOA_TABLE(HfCandBplusBase, "AOD", "HFCANDBPLUSBASE", DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBplusExt, HfCandBplusBase, "HFCANDBPLUSEXT", hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); -using HfCandBplus = HfCandBplusExt; +DECLARE_SOA_TABLE(HfCandBplusProngs, "AOD", "HFCANDBPPRONGS", + hf_cand_bplus::Prong0Id, hf_track_index::Prong1Id); + +using HfCandBplus = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandBplusMcRec, "AOD", "HFCANDBPMCREC", @@ -747,13 +734,13 @@ DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1 + 1.f * aod::hf_cand::pzProng2); DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array& m) -> float { return RecoDecay::m(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const std::array& m) -> float { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const array& m) -> float { return RecoDecay::m2(array{array{px0, py0, pz0}, array{px1, py1, pz1}, array{px2, py2, pz2}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, const std::array& m) -> float { return RecoDecay::m2(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, //! [](float impParProng0, float impParProng1, float impParProng2) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1, impParProng2); }); DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! - [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float ip2, float errIp2, float px0, float py0, float px1, float py1, float px2, float py2) -> float { return RecoDecay::maxNormalisedDeltaIP(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, errDlxy, array{pxM, pyM}, array{ip0, ip1, ip2}, array{errIp0, errIp1, errIp2}, array{array{px0, py0}, array{px1, py1}, array{px2, py2}}); }); + [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float ip2, float errIp2, float px0, float py0, float px1, float py1, float px2, float py2) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1, ip2}, std::array{errIp0, errIp1, errIp2}, std::array{std::array{px0, py0}, std::array{px1, py1}, std::array{px2, py2}}); }); // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level @@ -770,34 +757,6 @@ enum DecayType { DplusToPiKPi = 0, XicToPKPi, N3ProngDecays }; // always keep N3ProngDecays at the end -// functions for specific particles - -// D± → π± K∓ π± - -template -auto ctDplus(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kDPlus)); -} - -template -auto yDplus(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kDPlus)); -} - -template -auto eDplus(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kDPlus)); -} - -template -auto invMassDplusToPiKPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); -} - // Ds± → K± K∓ π± enum DecayChannelDs { @@ -805,162 +764,6 @@ enum DecayChannelDs { K0starK }; -template -auto ctDs(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kDS)); -} - -template -auto yDs(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kDS)); -} - -template -auto eDs(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kDS)); -} - -template -auto invMassDsToKKPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); -} - -template -auto invMassDsToPiKK(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kKPlus)}); -} - -template -auto deltaMassPhiDsToKKPi(const T& candidate) -{ - double invMassKKpair = RecoDecay::m(array{candidate.pVectorProng0(), candidate.pVectorProng1()}, array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kKPlus)}); - return std::abs(invMassKKpair - RecoDecay::getMassPDG(pdg::Code::kPhi)); -} - -template -auto deltaMassPhiDsToPiKK(const T& candidate) -{ - double invMassKKpair = RecoDecay::m(array{candidate.pVectorProng1(), candidate.pVectorProng2()}, array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kKPlus)}); - return std::abs(invMassKKpair - RecoDecay::getMassPDG(pdg::Code::kPhi)); -} - -/// Calculate the cosine of the angle between the pion and the opposite sign kaon in the phi rest frame -/// \param candidate Ds candidate from aod::HfCand3Prong table -/// \param option mass hypothesis considered: 0 = KKPi, 1 = PiKK -/// \return cosine of pion-kaon angle in the phi rest frame -template -auto cosPiKPhiRestFrame(const T& candidate, int option) -{ - // Ported from AliAODRecoDecayHF3Prong::CosPiKPhiRFrame - array momPi; - array momK1; - array momK2; - - if (option == 0) { // KKPi - momPi = candidate.pVectorProng2(); - momK1 = candidate.pVectorProng1(); - momK2 = candidate.pVectorProng0(); - } else { // PiKK - momPi = candidate.pVectorProng0(); - momK1 = candidate.pVectorProng1(); - momK2 = candidate.pVectorProng2(); - } - - ROOT::Math::PxPyPzMVector vecPi(momPi[0], momPi[1], momPi[2], RecoDecay::getMassPDG(kPiPlus)); - ROOT::Math::PxPyPzMVector vecK1(momK1[0], momK1[1], momK1[2], RecoDecay::getMassPDG(kKPlus)); - ROOT::Math::PxPyPzMVector vecK2(momK2[0], momK2[1], momK2[2], RecoDecay::getMassPDG(kKPlus)); - ROOT::Math::PxPyPzMVector vecPhi = vecK1 + vecK2; - - ROOT::Math::Boost boostToPhiRestFrame(vecPhi.BoostToCM()); - auto momPiPhiRestFrame = boostToPhiRestFrame(vecPi).Vect(); - auto momK1PhiRestFrame = boostToPhiRestFrame(vecK1).Vect(); - - return momPiPhiRestFrame.Dot(momK1PhiRestFrame) / std::sqrt(momPiPhiRestFrame.Mag2() * momK1PhiRestFrame.Mag2()); -} - -template -auto cos3PiKDsToKKPi(const T& candidate) -{ - auto cosPiK = cosPiKPhiRestFrame(candidate, 0); - return cosPiK * cosPiK * cosPiK; -} - -template -auto cos3PiKDsToPiKK(const T& candidate) -{ - auto cosPiK = cosPiKPhiRestFrame(candidate, 1); - return cosPiK * cosPiK * cosPiK; -} - -// Λc± → p± K∓ π± - -template -auto ctLc(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)); -} - -template -auto yLc(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)); -} - -template -auto eLc(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)); -} - -template -auto invMassLcToPKPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kProton), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); -} - -template -auto invMassLcToPiKP(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kProton)}); -} - -// Ξc± → p± K∓ π± - -template -auto ctXic(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kXiCPlus)); -} - -template -auto yXic(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kXiCPlus)); -} - -template -auto eXic(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kXiCPlus)); -} - -template -auto invMassXicToPKPi(const T& candidate) -{ - return invMassLcToPKPi(candidate); -} - -template -auto invMassXicToPiKP(const T& candidate) -{ - return invMassLcToPiKP(candidate); -} - } // namespace hf_cand_3prong // 3-prong decay candidate table @@ -1032,33 +835,21 @@ DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, //! [](float dca1, float dca2) -> float { return dca1 * dca2; }); DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m) -> float { return RecoDecay::m(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m) -> float { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m) -> float { return RecoDecay::m2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m) -> float { return RecoDecay::m2(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m, double mTot, int iProng) -> float { return RecoDecay::cosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m, double mTot, int iProng) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m, mTot, iProng); }); DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, //! [](float impParProng0, float impParProng1) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1); }); DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! - [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, errDlxy, array{pxM, pyM}, array{ip0, ip1}, array{errIp0, errIp1}, array{array{px0, py0}, array{px1, py1}}); }); + [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1}, std::array{errIp0, errIp1}, std::array{std::array{px0, py0}, std::array{px1, py1}}); }); // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level -template -auto invMassXiczeroToXiPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kXiMinus), RecoDecay::getMassPDG(kPiPlus)}); -} - -template -auto invMassOmegaczeroToOmegaPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kOmegaMinus), RecoDecay::getMassPDG(kPiPlus)}); -} - // mapping of decay types enum DecayType { XiczeroToXiPi = 0, OmegaczeroToOmegaPi, @@ -1077,27 +868,21 @@ DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProduct, impactParameterProduct, //! [](float dca1, float dca2) -> float { return dca1 * dca2; }); DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m) -> float { return RecoDecay::m(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m) -> float { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m) -> float { return RecoDecay::m2(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m) -> float { return RecoDecay::m2(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStar, cosThetaStar, //! - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m, double mTot, int iProng) -> float { return RecoDecay::cosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m, double mTot, int iProng) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m, mTot, iProng); }); DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, //! [](float impParProng0, float impParProng1) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1); }); DECLARE_SOA_DYNAMIC_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, //! - [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, errDlxy, array{pxM, pyM}, array{ip0, ip1}, array{errIp0, errIp1}, array{array{px0, py0}, array{px1, py1}}); }); + [](float xVtxP, float yVtxP, float xVtxS, float yVtxS, float errDlxy, float pxM, float pyM, float ip0, float errIp0, float ip1, float errIp1, float px0, float py0, float px1, float py1) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1}, std::array{errIp0, errIp1}, std::array{std::array{px0, py0}, std::array{px1, py1}}); }); // MC matching result: DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); //! generator level DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); //! particle origin, reconstruction level DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, generator level -template -auto invMassXicplusToXiPiPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kXiMinus), RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kPiPlus)}); -} - // mapping of decay types enum DecayType { XicplusToXiPiPi = 0, N3ProngDecays }; // always keep N3ProngDecays at the end @@ -1118,83 +903,6 @@ DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); // resonant // mapping of decay types enum DecayType { XToJpsiToEEPiPi = 0, XToJpsiToMuMuPiPi }; // move this to a dedicated cascade namespace in the future? - -// X → Jpsi π+ π- -// TODO: add pdg code for X (9920443), temporarily hardcode mass here: -float massX = 3.872; // replace this with: "RecoDecay::getMassPDG(9920443)" when pdg is added -template -auto ctX(const T& candidate) -{ - return candidate.ct(massX); -} - -template -auto yX(const T& candidate) -{ - return candidate.y(massX); -} - -template -auto eX(const T& candidate) -{ - return candidate.e(massX); -} - -template -auto invMassXToJpsiPiPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(443), RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kPiPlus)}); -} - -/// Difference between the X mass and the sum of the J/psi and di-pion masses -template -auto qX(const T& candidate) -{ - auto piVec1 = array{candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()}; - auto piVec2 = array{candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()}; - double massPi = RecoDecay::getMassPDG(kPiPlus); - - auto arrayMomenta = array{piVec1, piVec2}; - double massPiPi = RecoDecay::m(arrayMomenta, array{massPi, massPi}); - - // PDG mass, as reported in CMS paper https://arxiv.org/pdf/1302.3968.pdf - double massJpsi = RecoDecay::getMassPDG(o2::analysis::pdg::kJPsi); - - double massX = invMassXToJpsiPiPi(candidate); - return std::abs(massX - massJpsi - massPiPi); -} - -/// Angular difference between the J/psi and the pion -template -auto dRX(const T& candidate, int numPi) -{ - double etaJpsi = RecoDecay::eta(array{candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()}); - double phiJpsi = RecoDecay::phi(candidate.pxProng0(), candidate.pyProng0()); - - double etaPi, phiPi; - - if (numPi <= 1) { - etaPi = RecoDecay::eta(array{candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()}); - phiPi = RecoDecay::phi(candidate.pxProng1(), candidate.pyProng1()); - } else { - etaPi = RecoDecay::eta(array{candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()}); - phiPi = RecoDecay::phi(candidate.pxProng2(), candidate.pyProng2()); - } - - double deltaEta = etaJpsi - etaPi; - double deltaPhi = RecoDecay::constrainAngle(phiJpsi - phiPi, -o2::constants::math::PI); - - return RecoDecay::sqrtSumOfSquares(deltaEta, deltaPhi); -} - -/// Difference in pT between the two pions -template -auto balancePtPionsX(const T& candidate) -{ - double ptPi1 = RecoDecay::pt(candidate.pxProng1(), candidate.pyProng1()); - double ptPi2 = RecoDecay::pt(candidate.pxProng2(), candidate.pyProng2()); - return std::abs(ptPi1 - ptPi2) / (ptPi1 + ptPi2); -} } // namespace hf_cand_x // declare dedicated X candidate table @@ -1251,103 +959,6 @@ DECLARE_SOA_TABLE(HfCandXMcGen, "AOD", "HFCANDXMCGEN", //! hf_cand_x::OriginMcGen, hf_cand_x::FlagMcDecayChanGen); -// definition of columns and tables for D-Dbar correlation pairs -namespace hf_correlation_d_dbar -{ -DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); -DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); -DECLARE_SOA_COLUMN(PtD, ptD, float); -DECLARE_SOA_COLUMN(PtDbar, ptDbar, float); -DECLARE_SOA_COLUMN(MD, mD, float); -DECLARE_SOA_COLUMN(MDbar, mDbar, float); -DECLARE_SOA_COLUMN(SignalStatus, signalStatus, int); -} // namespace hf_correlation_d_dbar -DECLARE_SOA_TABLE(DDbarPair, "AOD", "DDBARPAIR", - aod::hf_correlation_d_dbar::DeltaPhi, - aod::hf_correlation_d_dbar::DeltaEta, - aod::hf_correlation_d_dbar::PtD, - aod::hf_correlation_d_dbar::PtDbar); -DECLARE_SOA_TABLE(DDbarRecoInfo, "AOD", "DDBARRECOINFO", - aod::hf_correlation_d_dbar::MD, - aod::hf_correlation_d_dbar::MDbar, - aod::hf_correlation_d_dbar::SignalStatus); - -// definition of columns and tables for D0-Hadron correlation pairs -namespace hf_correlation_d0_hadron -{ -DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); -DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); -DECLARE_SOA_COLUMN(PtD, ptD, float); -DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); -DECLARE_SOA_COLUMN(MD, mD, float); -DECLARE_SOA_COLUMN(MDbar, mDbar, float); -DECLARE_SOA_COLUMN(SignalStatus, signalStatus, int); -} // namespace hf_correlation_d0_hadron -DECLARE_SOA_TABLE(DHadronPair, "AOD", "DHADRONPAIR", - aod::hf_correlation_d0_hadron::DeltaPhi, - aod::hf_correlation_d0_hadron::DeltaEta, - aod::hf_correlation_d0_hadron::PtD, - aod::hf_correlation_d0_hadron::PtHadron); -DECLARE_SOA_TABLE(DHadronRecoInfo, "AOD", "DHADRONRECOINFO", - aod::hf_correlation_d0_hadron::MD, - aod::hf_correlation_d0_hadron::MDbar, - aod::hf_correlation_d0_hadron::SignalStatus); - -// definition of columns and tables for Ds-Hadron correlation pairs -namespace hf_correlation_ds_hadron -{ -DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! DeltaPhi between Ds and Hadrons -DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta between Ds and Hadrons -DECLARE_SOA_COLUMN(PtD, ptD, float); //! Transverse momentum of Ds -DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron -DECLARE_SOA_COLUMN(MD, mD, float); //! Invariant mass of Ds -DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin for the MixedEvent -DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); //! Used in MC-Rec, Ds Signal -DECLARE_SOA_COLUMN(IsPrompt, isPrompt, bool); //! Used in MC-Rec, Ds Prompt or Non-Prompt -} // namespace hf_correlation_ds_hadron -DECLARE_SOA_TABLE(DsHadronPair, "AOD", "DSHPAIR", //! Ds-Hadrons pairs Informations - aod::hf_correlation_ds_hadron::DeltaPhi, - aod::hf_correlation_ds_hadron::DeltaEta, - aod::hf_correlation_ds_hadron::PtD, - aod::hf_correlation_ds_hadron::PtHadron, - aod::hf_correlation_ds_hadron::PoolBin); - -DECLARE_SOA_TABLE(DsHadronRecoInfo, "AOD", "DSHRECOINFO", //! Ds-Hadrons pairs Reconstructed Informations - aod::hf_correlation_ds_hadron::MD, - aod::hf_correlation_ds_hadron::IsSignal); - -DECLARE_SOA_TABLE(DsHadronGenInfo, "AOD", "DSHGENINFO", //! Ds-Hadrons pairs Generated Informations - aod::hf_correlation_ds_hadron::IsPrompt); - -// definition of columns and tables for Dplus-Hadron correlation pairs -namespace hf_correlation_dplus_hadron -{ -DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! DeltaPhi between D+ and Hadrons -DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta between D+ and Hadrons -DECLARE_SOA_COLUMN(PtD, ptD, float); //! Transverse momentum of D+ -DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron -DECLARE_SOA_COLUMN(MD, mD, float); //! Invariant mass of D+ -DECLARE_SOA_COLUMN(SignalStatus, signalStatus, bool); //! Used in MC-Rec, D+ Signal -DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin of event defined using zvtx and multiplicity -} // namespace hf_correlation_dplus_hadron -DECLARE_SOA_TABLE(DplusHadronPair, "AOD", "DPLUSHPAIR", //! D+-Hadrons pairs Informations - aod::hf_correlation_dplus_hadron::DeltaPhi, - aod::hf_correlation_dplus_hadron::DeltaEta, - aod::hf_correlation_dplus_hadron::PtD, - aod::hf_correlation_dplus_hadron::PtHadron, - aod::hf_correlation_dplus_hadron::PoolBin); -DECLARE_SOA_TABLE(DplusHadronRecoInfo, "AOD", "DPLUSHRECOINFO", //! D+-Hadrons pairs Reconstructed Informations - aod::hf_correlation_dplus_hadron::MD, - aod::hf_correlation_dplus_hadron::SignalStatus); - -// Table for selection of Dmeson in a collision -namespace hf_selection_dmeson_collision -{ -DECLARE_SOA_COLUMN(DmesonSel, dmesonSel, bool); //! Selection flag for D meson in a collision -} // namespace hf_selection_dmeson_collision -DECLARE_SOA_TABLE(DmesonSelection, "AOD", "DINCOLL", // Selection of D meson in collisions - aod::hf_selection_dmeson_collision::DmesonSel); - // specific Xicc candidate properties namespace hf_cand_xicc { @@ -1360,32 +971,6 @@ DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level // mapping of decay types enum DecayType { XiccToXicPi = 0 }; // move this to a dedicated cascade namespace in the future? - -// Ξcc±± → p± K∓ π± π± - -template -auto ctXicc(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kXiCCPlusPlus)); -} - -template -auto yXicc(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kXiCCPlusPlus)); -} - -template -auto eXicc(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kXiCCPlusPlus)); -} - -template -auto invMassXiccToXicPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(pdg::Code::kXiCPlus), RecoDecay::getMassPDG(kPiPlus)}); -} } // namespace hf_cand_xicc // declare dedicated Xicc candidate table @@ -1612,30 +1197,6 @@ DECLARE_SOA_COLUMN(JpsiToMuMuMass, jpsiToMuMuMass, float); // Jpsi mass // mapping of decay types enum DecayType { ChicToJpsiToEEGamma = 0, ChicToJpsiToMuMuGamma }; // move this to a dedicated cascade namespace in the future? -// chic → Jpsi gamma -template -auto ctChic(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kChiC1)); -} - -template -auto yChic(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kChiC1)); -} - -template -auto eChic(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kChiC1)); -} -template -auto invMassChicToJpsiGamma(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(pdg::Code::kJPsi), 0.}); -} - } // namespace hf_cand_chic // declare dedicated chi_c candidate table @@ -1703,31 +1264,6 @@ DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // particle origin, DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association reconstruction level // mapping of decay types enum DecayType { LbToLcPi }; // move this to a dedicated cascade namespace in the future? - -// Λb → Λc+ π- → p K- π+ π- -// float massLb = RecoDecay::getMassPDG(pdg::Code::kLambdaB0); -template -auto ctLb(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kLambdaB0)); -} - -template -auto yLb(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kLambdaB0)); -} - -template -auto eLb(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kLambdaB0)); -} -template -auto invMassLbToLcPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus), RecoDecay::getMassPDG(kPiPlus)}); -} } // namespace hf_cand_lb // declare dedicated Lb candidate table @@ -1798,36 +1334,6 @@ enum DecayTypeMc : uint8_t { B0ToDplusPiToPiKPiPi = 0, PartlyRecoDecay, OtherDecay, NDecayTypeMc }; -// B0(B0bar) → D∓ π± -template -auto ctB0(const T& candidate) -{ - return candidate.ct(RecoDecay::getMassPDG(pdg::Code::kB0)); -} - -template -auto yB0(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kB0)); -} - -template -auto eB0(const T& candidate) -{ - return candidate.e(RecoDecay::getMassPDG(pdg::Code::kB0)); -} - -template -auto invMassB0ToDPi(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(pdg::Code::kDMinus), RecoDecay::getMassPDG(kPiPlus)}); -} - -template -auto cosThetaStarB0(const T& candidate) -{ - return candidate.cosThetaStar(array{RecoDecay::getMassPDG(pdg::Code::kDMinus), RecoDecay::getMassPDG(kPiPlus)}, RecoDecay::getMassPDG(pdg::Code::kB0), 1); -} } // namespace hf_cand_b0 // declare dedicated B0 decay candidate table @@ -1839,7 +1345,6 @@ DECLARE_SOA_TABLE(HfCandB0Base, "AOD", "HFCANDB0BASE", hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, - hf_cand_b0::Prong0Id, hf_track_index::Prong1Id, hf_track_index::HFflag, /* dynamic columns */ hf_cand_2prong::M, @@ -1868,7 +1373,10 @@ DECLARE_SOA_TABLE(HfCandB0Base, "AOD", "HFCANDB0BASE", DECLARE_SOA_EXTENDED_TABLE_USER(HfCandB0Ext, HfCandB0Base, "HFCANDB0EXT", hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); -using HfCandB0 = HfCandB0Ext; +DECLARE_SOA_TABLE(HfCandB0Prongs, "AOD", "HFCANDB0PRONGS", + hf_cand_b0::Prong0Id, hf_track_index::Prong1Id); + +using HfCandB0 = soa::Join; // table with results of reconstruction level MC matching DECLARE_SOA_TABLE(HfCandB0McRec, "AOD", "HFCANDB0MCREC", @@ -1881,6 +1389,72 @@ DECLARE_SOA_TABLE(HfCandB0McGen, "AOD", "HFCANDB0MCGEN", hf_cand_b0::FlagMcMatchGen, hf_cand_b0::OriginMcGen); +// specific Bs candidate properties +namespace hf_cand_bs +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfCand3Prong, "_0"); // Ds index +// MC matching result: +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level + +// mapping of decay types +enum DecayType { BsToDsPi }; + +enum DecayTypeMc : uint8_t { BsToDsPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → (Phi π∓) π± → (K- K+ π∓) π± + B0ToDsPiToKKPiPi, // B0(bar) → Ds± π∓ → (Phi π±) π∓ → (K- K+ π±) π∓ + PartlyRecoDecay, // 4 final state particles have another common b-hadron ancestor + NDecayTypeMc }; // counter of differentiated MC decay types + +} // namespace hf_cand_bs + +// declare dedicated Bs decay candidate table +DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", + // general columns + HFCAND_COLUMNS, + // 2-prong specific columns + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, + hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, + hf_cand_bs::Prong0Id, hf_track_index::Prong1Id, + hf_track_index::HFflag, + /* dynamic columns */ + hf_cand_2prong::M, + hf_cand_2prong::M2, + hf_cand_2prong::ImpactParameterProduct, + hf_cand_2prong::CosThetaStar, + hf_cand_2prong::ImpactParameterProngSqSum, + /* dynamic columns that use candidate momentum components */ + hf_cand::Pt, + hf_cand::Pt2, + hf_cand::P, + hf_cand::P2, + hf_cand::PVector, + hf_cand::CPA, + hf_cand::CPAXY, + hf_cand::Ct, + hf_cand::ImpactParameterXY, + hf_cand_2prong::MaxNormalisedDeltaIP, + hf_cand::Eta, + hf_cand::Phi, + hf_cand::Y, + hf_cand::E, + hf_cand::E2); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsExt, HfCandBsBase, "HFCANDBSEXT", + hf_cand_2prong::Px, hf_cand_2prong::Py, hf_cand_2prong::Pz); + +using HfCandBs = HfCandBsExt; + +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfCandBsMcRec, "AOD", "HFCANDBSMCREC", + hf_cand_bs::FlagMcMatchRec); + +// table with results of generator level MC matching +DECLARE_SOA_TABLE(HfCandBsMcGen, "AOD", "HFCANDBSMCGEN", + hf_cand_bs::FlagMcMatchGen); + // specific Σc0,++ candidate properties namespace hf_cand_sigmac { @@ -1898,34 +1472,6 @@ DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); //! particle origin, // mapping of decay types enum DecayType { Sc0ToPKPiPi = 0, ScplusplusToPKPiPi }; - -/// Σc0,++ → Λc+(→pK-π+) π-,+ -/// @brief Sc inv. mass using reco mass for Lc in pKpi and PDG mass for pion -template -auto invMassScRecoLcToPKPi(const T& candidateSc, const U& candidateLc) -{ - return candidateSc.m(array{static_cast(hf_cand_3prong::invMassLcToPKPi(candidateLc)), RecoDecay::getMassPDG(kPiPlus)}); -} - -/// @brief Sc inv. mass using reco mass for Lc in piKp and PDG mass for pion -template -auto invMassScRecoLcToPiKP(const T& candidateSc, const U& candidateLc) -{ - return candidateSc.m(array{static_cast(hf_cand_3prong::invMassLcToPiKP(candidateLc)), RecoDecay::getMassPDG(kPiPlus)}); -} - -template -auto ySc0(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kSigmaC0)); -} - -template -auto yScPlusPlus(const T& candidate) -{ - return candidate.y(RecoDecay::getMassPDG(pdg::Code::kSigmaCPlusPlus)); -} - } // namespace hf_cand_sigmac // declare dedicated Σc0,++ decay candidate table @@ -1985,6 +1531,8 @@ DECLARE_SOA_TABLE(HfCandScMcGen, "AOD", "HFCANDSCMCGEN", //! hf_cand_sigmac::FlagMcMatchGen, hf_cand_sigmac::OriginMcGen); +#undef HFCAND_COLUMNS + } // namespace o2::aod #endif // PWGHF_DATAMODEL_CANDIDATERECONSTRUCTIONTABLES_H_ diff --git a/PWGHF/DataModel/CandidateSelectionTables.h b/PWGHF/DataModel/CandidateSelectionTables.h index 6c18e187395..cce5144eda2 100644 --- a/PWGHF/DataModel/CandidateSelectionTables.h +++ b/PWGHF/DataModel/CandidateSelectionTables.h @@ -15,6 +15,8 @@ #ifndef PWGHF_DATAMODEL_CANDIDATESELECTIONTABLES_H_ #define PWGHF_DATAMODEL_CANDIDATESELECTIONTABLES_H_ +#include + #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelectorPID.h" @@ -28,6 +30,7 @@ enum SelectionStep { RecoSkims = 0, RecoTopol, RecoPID, + RecoMl, NSelectionSteps }; @@ -39,7 +42,9 @@ DECLARE_SOA_COLUMN(IsRecoHfFlag, isRecoHfFlag, int); //! DECLARE_SOA_COLUMN(IsRecoTopol, isRecoTopol, int); //! DECLARE_SOA_COLUMN(IsRecoCand, isRecoCand, int); //! DECLARE_SOA_COLUMN(IsRecoPid, isRecoPid, int); +DECLARE_SOA_COLUMN(MlProbD0, mlProbD0, std::vector); //! } // namespace hf_sel_candidate_d0 + DECLARE_SOA_TABLE(HfSelD0, "AOD", "HFSELD0", //! hf_sel_candidate_d0::IsSelD0, hf_sel_candidate_d0::IsSelD0bar, @@ -48,6 +53,9 @@ DECLARE_SOA_TABLE(HfSelD0, "AOD", "HFSELD0", //! hf_sel_candidate_d0::IsRecoCand, hf_sel_candidate_d0::IsRecoPid); +DECLARE_SOA_TABLE(HfMlD0, "AOD", "HFMLD0", //! + hf_sel_candidate_d0::MlProbD0); + namespace hf_sel_candidate_d0_parametrized_pid { DECLARE_SOA_COLUMN(IsSelD0NoPid, isSelD0NoPid, int); //! @@ -57,6 +65,7 @@ DECLARE_SOA_COLUMN(IsSelD0barNoPid, isSelD0barNoPid, int); //! DECLARE_SOA_COLUMN(IsSelD0barPerfectPid, isSelD0barPerfectPid, int); //! DECLARE_SOA_COLUMN(IsSelD0bar, isSelD0bar, int); //! } // namespace hf_sel_candidate_d0_parametrized_pid + DECLARE_SOA_TABLE(HfSelD0ParametrizedPid, "AOD", "HFSELD0P", //! hf_sel_candidate_d0_parametrized_pid::IsSelD0NoPid, hf_sel_candidate_d0_parametrized_pid::IsSelD0PerfectPid, @@ -75,6 +84,7 @@ DECLARE_SOA_COLUMN(IsSelD0RichPid, isSelD0RichPid, int); //! DECLARE_SOA_COLUMN(IsSelD0TofPlusRichPid, isSelD0TofPlusRichPid, int); //! DECLARE_SOA_COLUMN(IsSelD0barTofPlusRichPid, isSelD0barTofPlusRichPid, int); //! } // namespace hf_sel_candidate_d0_alice3_barrel + DECLARE_SOA_TABLE(HfSelD0Alice3Barrel, "AOD", "HFSELD0A3B", //! hf_sel_candidate_d0_alice3_barrel::IsSelHfFlag, hf_sel_candidate_d0_alice3_barrel::IsSelD0NoPid, @@ -90,6 +100,7 @@ DECLARE_SOA_COLUMN(IsSelHfFlag, isSelHfFlag, int); //! DECLARE_SOA_COLUMN(IsSelD0FNoPid, isSelD0FNoPid, int); //! DECLARE_SOA_COLUMN(IsSelD0FRichPid, isSelD0FRichPid, int); //! } // namespace hf_sel_candidate_d0_alice3_forward + DECLARE_SOA_TABLE(HfSelD0Alice3Forward, "AOD", "HFSELD0A3F", //! hf_sel_candidate_d0_alice3_forward::IsSelHfFlag, hf_sel_candidate_d0_alice3_forward::IsSelD0FNoPid, @@ -98,18 +109,28 @@ DECLARE_SOA_TABLE(HfSelD0Alice3Forward, "AOD", "HFSELD0A3F", //! namespace hf_sel_candidate_dplus { DECLARE_SOA_COLUMN(IsSelDplusToPiKPi, isSelDplusToPiKPi, int); //! +DECLARE_SOA_COLUMN(MlProbDplusToPiKPi, mlProbDplusToPiKPi, std::vector); //! } // namespace hf_sel_candidate_dplus + DECLARE_SOA_TABLE(HfSelDplusToPiKPi, "AOD", "HFSELDPLUS", //! hf_sel_candidate_dplus::IsSelDplusToPiKPi); +DECLARE_SOA_TABLE(HfMlDplusToPiKPi, "AOD", "HFMLDPLUS", //! + hf_sel_candidate_dplus::MlProbDplusToPiKPi); + namespace hf_sel_candidate_ds { DECLARE_SOA_COLUMN(IsSelDsToKKPi, isSelDsToKKPi, int); //! DECLARE_SOA_COLUMN(IsSelDsToPiKK, isSelDsToPiKK, int); //! +DECLARE_SOA_COLUMN(MlProbDsToKKPi, mlProbDsToKKPi, std::vector); //! } // namespace hf_sel_candidate_ds + DECLARE_SOA_TABLE(HfSelDsToKKPi, "AOD", "HFSELDS", //! hf_sel_candidate_ds::IsSelDsToKKPi, hf_sel_candidate_ds::IsSelDsToPiKK); +DECLARE_SOA_TABLE(HfMlDsToKKPi, "AOD", "HFMLDS", //! + hf_sel_candidate_ds::MlProbDsToKKPi); + namespace hf_sel_candidate_lc { DECLARE_SOA_COLUMN(IsSelLcToPKPi, isSelLcToPKPi, int); //! @@ -129,6 +150,7 @@ DECLARE_SOA_COLUMN(IsSelLcToPiKPPerfectPid, isSelLcToPiKPPerfectPid, int); DECLARE_SOA_COLUMN(IsSelLcToPiKPTofPid, isSelLcToPiKPTofPid, int); //! DECLARE_SOA_COLUMN(IsSelLcToPiKPTofPlusRichPid, isSelLcToPiKPTofPlusRichPid, int); //! } // namespace hf_sel_candidate_lc_alice3 + DECLARE_SOA_TABLE(HfSelLcAlice3, "AOD", "HFSELLCA3B", //! hf_sel_candidate_lc_alice3::IsSelLcToPKPiNoPid, hf_sel_candidate_lc_alice3::IsSelLcToPKPiPerfectPid, @@ -148,6 +170,7 @@ DECLARE_SOA_COLUMN(IsSelLcToPiKPNoPid, isSelLcToPiKPNoPid, int); //! DECLARE_SOA_COLUMN(IsSelLcToPiKPPerfectPid, isSelLcToPiKPPerfectPid, int); //! DECLARE_SOA_COLUMN(IsSelLcToPiKP, isSelLcToPiKP, int); //! } // namespace hf_sel_candidate_lc_parametrized_pid + DECLARE_SOA_TABLE(HfSelLcParametrizedPid, "AOD", "HFSELLCP", //! hf_sel_candidate_lc_parametrized_pid::IsSelLcToPKPiNoPid, hf_sel_candidate_lc_parametrized_pid::IsSelLcToPKPiPerfectPid, @@ -168,6 +191,7 @@ DECLARE_SOA_COLUMN(IsSelJpsiToEETofRich, isSelJpsiToEETofRich, int); //! DECLARE_SOA_COLUMN(IsSelJpsiToMuMuTopol, isSelJpsiToMuMuTopol, int); //! DECLARE_SOA_COLUMN(IsSelJpsiToMuMuMid, isSelJpsiToMuMuMid, int); //! } // namespace hf_sel_candidate_jpsi + DECLARE_SOA_TABLE(HfSelJpsi, "AOD", "HFSELJPSI", //! hf_sel_candidate_jpsi::IsSelJpsiToEE, hf_sel_candidate_jpsi::IsSelJpsiToMuMu, @@ -183,117 +207,34 @@ namespace hf_sel_candidate_lc_to_k0s_p { DECLARE_SOA_COLUMN(IsSelLcToK0sP, isSelLcToK0sP, int); } // namespace hf_sel_candidate_lc_to_k0s_p + DECLARE_SOA_TABLE(HfSelLcToK0sP, "AOD", "HFSELLCK0SP", //! hf_sel_candidate_lc_to_k0s_p::IsSelLcToK0sP); namespace hf_sel_candidate_b0 { DECLARE_SOA_COLUMN(IsSelB0ToDPi, isSelB0ToDPi, int); //! - -/// Apply topological cuts as defined in SelectorCuts.h -/// \param candB0 B0 candidate -/// \param cuts B0 candidate selection per pT bin" -/// \param binsPt pT bin limits -/// \return true if candidate passes all selections -template -bool selectionTopol(const T1& candB0, const T2& cuts, const T3& binsPt) -{ - auto ptCandB0 = candB0.pt(); - auto ptD = RecoDecay::pt(candB0.pxProng0(), candB0.pyProng0()); - auto ptPi = RecoDecay::pt(candB0.pxProng1(), candB0.pyProng1()); - - int pTBin = findBin(binsPt, ptCandB0); - if (pTBin == -1) { - // LOGF(info, "B0 topol selection failed at getpTBin"); - return false; - } - - // // check that the candidate pT is within the analysis range - // if (ptCandB0 < ptCandMin || ptCandB0 >= ptCandMax) { - // return false; - // } - - // B0 mass cut - if (std::abs(o2::aod::hf_cand_b0::invMassB0ToDPi(candB0) - RecoDecay::getMassPDG(o2::analysis::pdg::Code::kB0)) > cuts->get(pTBin, "m")) { - // Printf("B0 topol selection failed at mass diff check"); - return false; - } - - // pion pt - if (ptPi < cuts->get(pTBin, "pT Pi")) { - return false; - } - - // D- pt - if (ptD < cuts->get(pTBin, "pT D")) { - return false; - } - - /* - // D mass cut | already applied in candidateSelectorDplusToPiKPi.cxx - if (std::abs(o2::aod::hf_cand_3prong::invMassDplusToPiKPi(hfCandD) - RecoDecay::getMassPDG(o2::analysis::pdg::Code::kDMinus)) > cuts->get(pTBin, "DeltaMD")) { - return false; - } - */ - - // B0 Decay length - if (candB0.decayLength() < cuts->get(pTBin, "B0 decLen")) { - return false; - } - - // B0 Decay length XY - if (candB0.decayLengthXY() < cuts->get(pTBin, "B0 decLenXY")) { - return false; - } - - // B0 chi2PCA cut - if (candB0.chi2PCA() > cuts->get(pTBin, "Chi2PCA")) { - return false; - } - - // B0 CPA cut - if (candB0.cpa() < cuts->get(pTBin, "CPA")) { - return false; - } - - // d0 of pi - if (std::abs(candB0.impactParameter1()) < cuts->get(pTBin, "d0 Pi")) { - return false; - } - - // d0 of D - if (std::abs(candB0.impactParameter0()) < cuts->get(pTBin, "d0 D")) { - return false; - } - - return true; -} - -/// Apply PID selection -/// \param pidTrackPi PID status of trackPi (prong1 of B0 candidate) -/// \param acceptPIDNotApplicable switch to accept Status::PIDNotApplicable -/// \return true if prong1 of B0 candidate passes all selections -template -bool selectionPID(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) -{ - if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Status::PIDAccepted) { - return false; - } - if (acceptPIDNotApplicable && pidTrackPi == TrackSelectorPID::Status::PIDRejected) { - return false; - } - - return true; -} - } // namespace hf_sel_candidate_b0 + DECLARE_SOA_TABLE(HfSelB0ToDPi, "AOD", "HFSELB0", //! hf_sel_candidate_b0::IsSelB0ToDPi); +namespace hf_sel_candidate_bs +{ +DECLARE_SOA_COLUMN(IsSelBsToDsPi, isSelBsToDsPi, int); //! +DECLARE_SOA_COLUMN(MlProbBsToDsPi, mlProbBsToDsPi, std::vector); //! +} // namespace hf_sel_candidate_bs + +DECLARE_SOA_TABLE(HfSelBsToDsPi, "AOD", "HFSELBS", //! + hf_sel_candidate_bs::IsSelBsToDsPi); +DECLARE_SOA_TABLE(HfMlBsToDsPi, "AOD", "HFMLBS", //! + hf_sel_candidate_bs::MlProbBsToDsPi); + namespace hf_sel_candidate_bplus { DECLARE_SOA_COLUMN(IsSelBplusToD0Pi, isSelBplusToD0Pi, int); //! } // namespace hf_sel_candidate_bplus + DECLARE_SOA_TABLE(HfSelBplusToD0Pi, "AOD", "HFSELBPLUS", //! hf_sel_candidate_bplus::IsSelBplusToD0Pi); @@ -301,6 +242,7 @@ namespace hf_sel_candidate_lb { DECLARE_SOA_COLUMN(IsSelLbToLcPi, isSelLbToLcPi, int); //! } // namespace hf_sel_candidate_lb + DECLARE_SOA_TABLE(HfSelLbToLcPi, "AOD", "HFSELLB", //! hf_sel_candidate_lb::IsSelLbToLcPi); @@ -309,6 +251,7 @@ namespace hf_sel_candidate_x DECLARE_SOA_COLUMN(IsSelXToJpsiToEEPiPi, isSelXToJpsiToEEPiPi, int); //! DECLARE_SOA_COLUMN(IsSelXToJpsiToMuMuPiPi, isSelXToJpsiToMuMuPiPi, int); //! } // namespace hf_sel_candidate_x + DECLARE_SOA_TABLE(HfSelXToJpsiPiPi, "AOD", "HFSELX", //! hf_sel_candidate_x::IsSelXToJpsiToEEPiPi, hf_sel_candidate_x::IsSelXToJpsiToMuMuPiPi); @@ -317,6 +260,7 @@ namespace hf_sel_candidate_chic DECLARE_SOA_COLUMN(IsSelChicToJpsiToEEGamma, isSelChicToJpsiToEEGamma, int); //! DECLARE_SOA_COLUMN(IsSelChicToJpsiToMuMuGamma, isSelChicToJpsiToMuMuGamma, int); //! } // namespace hf_sel_candidate_chic + DECLARE_SOA_TABLE(HfSelChicToJpsiGamma, "AOD", "HFSELCHIC", //! hf_sel_candidate_chic::IsSelChicToJpsiToEEGamma, hf_sel_candidate_chic::IsSelChicToJpsiToMuMuGamma); @@ -325,6 +269,7 @@ namespace hf_sel_candidate_xic DECLARE_SOA_COLUMN(IsSelXicToPKPi, isSelXicToPKPi, int); //! DECLARE_SOA_COLUMN(IsSelXicToPiKP, isSelXicToPiKP, int); //! } // namespace hf_sel_candidate_xic + DECLARE_SOA_TABLE(HfSelXicToPKPi, "AOD", "HFSELXIC", //! hf_sel_candidate_xic::IsSelXicToPKPi, hf_sel_candidate_xic::IsSelXicToPiKP); @@ -332,6 +277,7 @@ namespace hf_sel_candidate_xicc { DECLARE_SOA_COLUMN(IsSelXiccToPKPiPi, isSelXiccToPKPiPi, int); //! } // namespace hf_sel_candidate_xicc + DECLARE_SOA_TABLE(HfSelXiccToPKPiPi, "AOD", "HFSELXICC", //! hf_sel_candidate_xicc::IsSelXiccToPKPiPi); @@ -352,14 +298,17 @@ DECLARE_SOA_COLUMN(TofNSigmaPiFromOmega, tofNSigmaPiFromOmega, float); DECLARE_SOA_COLUMN(TofNSigmaPiFromCasc, tofNSigmaPiFromCasc, float); DECLARE_SOA_COLUMN(TofNSigmaPiFromLambda, tofNSigmaPiFromLambda, float); DECLARE_SOA_COLUMN(TofNSigmaPrFromLambda, tofNSigmaPrFromLambda, float); - +DECLARE_SOA_COLUMN(PidTpcInfoStored, pidTpcInfoStored, int); +DECLARE_SOA_COLUMN(PidTofInfoStored, pidTofInfoStored, int); } // namespace hf_sel_toxipi + DECLARE_SOA_TABLE(HfSelToXiPi, "AOD", "HFSELTOXIPI", hf_sel_toxipi::StatusPidLambda, hf_sel_toxipi::StatusPidCascade, hf_sel_toxipi::StatusPidOmegac, hf_sel_toxipi::StatusInvMassLambda, hf_sel_toxipi::StatusInvMassCascade, hf_sel_toxipi::StatusInvMassOmegac, - hf_sel_toxipi::ResultSelections, + hf_sel_toxipi::ResultSelections, hf_sel_toxipi::PidTpcInfoStored, hf_sel_toxipi::PidTofInfoStored, hf_sel_toxipi::TpcNSigmaPiFromOmega, hf_sel_toxipi::TpcNSigmaPiFromCasc, hf_sel_toxipi::TpcNSigmaPiFromLambda, hf_sel_toxipi::TpcNSigmaPrFromLambda, hf_sel_toxipi::TofNSigmaPiFromOmega, hf_sel_toxipi::TofNSigmaPiFromCasc, hf_sel_toxipi::TofNSigmaPiFromLambda, hf_sel_toxipi::TofNSigmaPrFromLambda); } // namespace o2::aod + #endif // PWGHF_DATAMODEL_CANDIDATESELECTIONTABLES_H_ diff --git a/PWGHF/HFC/DataModel/CorrelationTables.h b/PWGHF/HFC/DataModel/CorrelationTables.h new file mode 100644 index 00000000000..c5654d03ecb --- /dev/null +++ b/PWGHF/HFC/DataModel/CorrelationTables.h @@ -0,0 +1,150 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file CorrelationTables.h +/// \brief Correlation table definitions. +/// \author Vít Kučera , Inha University + +#ifndef PWGHF_HFC_DATAMODEL_CORRELATIONTABLES_H_ +#define PWGHF_HFC_DATAMODEL_CORRELATIONTABLES_H_ + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +// definition of columns and tables for D-Dbar correlation pairs +namespace hf_correlation_d_dbar +{ +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); +DECLARE_SOA_COLUMN(PtD, ptD, float); +DECLARE_SOA_COLUMN(PtDbar, ptDbar, float); +DECLARE_SOA_COLUMN(MD, mD, float); +DECLARE_SOA_COLUMN(MDbar, mDbar, float); +DECLARE_SOA_COLUMN(SignalStatus, signalStatus, int); +} // namespace hf_correlation_d_dbar + +DECLARE_SOA_TABLE(DDbarPair, "AOD", "DDBARPAIR", + aod::hf_correlation_d_dbar::DeltaPhi, + aod::hf_correlation_d_dbar::DeltaEta, + aod::hf_correlation_d_dbar::PtD, + aod::hf_correlation_d_dbar::PtDbar); + +DECLARE_SOA_TABLE(DDbarRecoInfo, "AOD", "DDBARRECOINFO", + aod::hf_correlation_d_dbar::MD, + aod::hf_correlation_d_dbar::MDbar, + aod::hf_correlation_d_dbar::SignalStatus); + +// definition of columns and tables for D0-Hadron correlation pairs +namespace hf_correlation_d0_hadron +{ +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! DeltaPhi between D0 and Hadrons +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta between D0 and Hadrons +DECLARE_SOA_COLUMN(PtD, ptD, float); //! Transverse momentum of D0 +DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron +DECLARE_SOA_COLUMN(MD, mD, float); //! Invariant mass of D0 +DECLARE_SOA_COLUMN(MDbar, mDbar, float); //! Invariant mass of D0bar +DECLARE_SOA_COLUMN(SignalStatus, signalStatus, int); //! Tag for D0,D0bar +DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin for the MixedEvent + +enum ParticleTypeData { + D0Only = 1, // Identified as D0 + D0barOnly, // Identified as D0bar + D0D0barBoth, // Identified as both D0 and D0bar + D0OnlySoftPi = 11, // Identified as D0 with soft pion + D0barOnlySoftPi, // Identified as D0bar with soft pion + D0D0barBothSoftPi // Identified as both D0 and D0bar with soft pion +}; + +enum ParticleTypeMcRec { + D0Sig = 0, // D0 signal + D0Ref, // D0 reflection + D0Bg, // D0 background + D0barSig, // D0bar signal + D0barRef, // D0bar reflection + D0barBg, // D0bar background + SoftPi // pairs including soft pion +}; +} // namespace hf_correlation_d0_hadron + +DECLARE_SOA_TABLE(DHadronPair, "AOD", "DHADRONPAIR", //! D0-Hadrons pairs Informations + aod::hf_correlation_d0_hadron::DeltaPhi, + aod::hf_correlation_d0_hadron::DeltaEta, + aod::hf_correlation_d0_hadron::PtD, + aod::hf_correlation_d0_hadron::PtHadron, + aod::hf_correlation_d0_hadron::PoolBin); + +DECLARE_SOA_TABLE(DHadronRecoInfo, "AOD", "DHADRONRECOINFO", //! D0-Hadrons pairs Reconstructed Informations + aod::hf_correlation_d0_hadron::MD, + aod::hf_correlation_d0_hadron::MDbar, + aod::hf_correlation_d0_hadron::SignalStatus); + +// definition of columns and tables for Ds-Hadron correlation pairs +namespace hf_correlation_ds_hadron +{ +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! DeltaPhi between Ds and Hadrons +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta between Ds and Hadrons +DECLARE_SOA_COLUMN(PtD, ptD, float); //! Transverse momentum of Ds +DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron +DECLARE_SOA_COLUMN(MD, mD, float); //! Invariant mass of Ds +DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin for the MixedEvent +DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); //! Used in MC-Rec, Ds Signal +DECLARE_SOA_COLUMN(IsPrompt, isPrompt, bool); //! Used in MC-Rec, Ds Prompt or Non-Prompt +} // namespace hf_correlation_ds_hadron + +DECLARE_SOA_TABLE(DsHadronPair, "AOD", "DSHPAIR", //! Ds-Hadrons pairs Informations + aod::hf_correlation_ds_hadron::DeltaPhi, + aod::hf_correlation_ds_hadron::DeltaEta, + aod::hf_correlation_ds_hadron::PtD, + aod::hf_correlation_ds_hadron::PtHadron, + aod::hf_correlation_ds_hadron::PoolBin); + +DECLARE_SOA_TABLE(DsHadronRecoInfo, "AOD", "DSHRECOINFO", //! Ds-Hadrons pairs Reconstructed Informations + aod::hf_correlation_ds_hadron::MD, + aod::hf_correlation_ds_hadron::IsSignal); + +DECLARE_SOA_TABLE(DsHadronGenInfo, "AOD", "DSHGENINFO", //! Ds-Hadrons pairs Generated Informations + aod::hf_correlation_ds_hadron::IsPrompt); + +// definition of columns and tables for Dplus-Hadron correlation pairs +namespace hf_correlation_dplus_hadron +{ +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! DeltaPhi between D+ and Hadrons +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! DeltaEta between D+ and Hadrons +DECLARE_SOA_COLUMN(PtD, ptD, float); //! Transverse momentum of D+ +DECLARE_SOA_COLUMN(PtHadron, ptHadron, float); //! Transverse momentum of Hadron +DECLARE_SOA_COLUMN(MD, mD, float); //! Invariant mass of D+ +DECLARE_SOA_COLUMN(SignalStatus, signalStatus, bool); //! Used in MC-Rec, D+ Signal +DECLARE_SOA_COLUMN(PoolBin, poolBin, int); //! Pool Bin of event defined using zvtx and multiplicity +} // namespace hf_correlation_dplus_hadron + +DECLARE_SOA_TABLE(DplusHadronPair, "AOD", "DPLUSHPAIR", //! D+-Hadrons pairs Informations + aod::hf_correlation_dplus_hadron::DeltaPhi, + aod::hf_correlation_dplus_hadron::DeltaEta, + aod::hf_correlation_dplus_hadron::PtD, + aod::hf_correlation_dplus_hadron::PtHadron, + aod::hf_correlation_dplus_hadron::PoolBin); + +DECLARE_SOA_TABLE(DplusHadronRecoInfo, "AOD", "DPLUSHRECOINFO", //! D+-Hadrons pairs Reconstructed Informations + aod::hf_correlation_dplus_hadron::MD, + aod::hf_correlation_dplus_hadron::SignalStatus); + +// Table for selection of Dmeson in a collision +namespace hf_selection_dmeson_collision +{ +DECLARE_SOA_COLUMN(DmesonSel, dmesonSel, bool); //! Selection flag for D meson in a collision +} // namespace hf_selection_dmeson_collision + +DECLARE_SOA_TABLE(DmesonSelection, "AOD", "DINCOLL", // Selection of D meson in collisions + aod::hf_selection_dmeson_collision::DmesonSel); +} // namespace o2::aod + +#endif // PWGHF_HFC_DATAMODEL_CORRELATIONTABLES_H_ diff --git a/PWGHF/HFC/TableProducer/CMakeLists.txt b/PWGHF/HFC/TableProducer/CMakeLists.txt index 92824a6c34d..ff1207f3f69 100644 --- a/PWGHF/HFC/TableProducer/CMakeLists.txt +++ b/PWGHF/HFC/TableProducer/CMakeLists.txt @@ -11,35 +11,35 @@ o2physics_add_dpl_workflow(correlator-d0-d0bar SOURCES correlatorD0D0bar.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(correlator-d0-d0bar-barrel-full-pid SOURCES correlatorD0D0barBarrelFullPid.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(correlator-d0-hadrons SOURCES correlatorD0Hadrons.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(correlator-d-meson-pairs SOURCES correlatorDMesonPairs.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(correlator-dplus-dminus SOURCES correlatorDplusDminus.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(correlator-dplus-hadrons SOURCES correlatorDplusHadrons.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(correlator-ds-hadrons SOURCES correlatorDsHadrons.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx b/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx index 354d7ae273c..c3741d56d4f 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx @@ -14,22 +14,22 @@ /// /// \author Fabio Colamaria , INFN Bari -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_correlation_d_dbar; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; -using namespace o2::constants::math; /// /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies @@ -82,6 +82,8 @@ struct HfCorrelatorD0D0bar { Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits for candidate mass plots and efficiency"}; Configurable> efficiencyD{"efficiencyD", std::vector{efficiencyDmeson_v}, "Efficiency values for D0 meson"}; + HfHelper hfHelper; + Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; Partition> selectedD0candidatesMC = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; @@ -115,7 +117,7 @@ struct HfCorrelatorD0D0bar { {"hCountCCbarPerEvent", "c,cbar particles - MC gen;Number per event;entries", {HistType::kTH1F, {{20, 0., 20.}}}}, {"hCountCCbarPerEventBeforeEtaCut", "c,cbar particles - MC gen;Number per event pre #eta cut;entries", {HistType::kTH1F, {{20, 0., 20.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMass", "D0,D0bar candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -132,7 +134,9 @@ struct HfCorrelatorD0D0bar { } /// D0-D0bar correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processData(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates) + void processData(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const&) { int nTracks = 0; if (collision.numContrib() > 1) { @@ -154,15 +158,15 @@ struct HfCorrelatorD0D0bar { auto selectedD0CandidatesGrouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto& candidate1 : selectedD0CandidatesGrouped) { - if (yCandMax >= 0. && std::abs(yD0(candidate1)) > yCandMax) { + for (const auto& candidate1 : selectedD0CandidatesGrouped) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { continue; } // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate1.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } @@ -173,19 +177,19 @@ struct HfCorrelatorD0D0bar { // fill invariant mass plots and generic info from all D0/D0bar candidates if (candidate1.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hMass"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMassD0"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } if (candidate1.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hMass"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMassD0bar"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0bar"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } registry.fill(HIST("hPtCand"), candidate1.pt()); registry.fill(HIST("hPtProng0"), candidate1.ptProng0()); registry.fill(HIST("hPtProng1"), candidate1.ptProng1()); registry.fill(HIST("hEta"), candidate1.eta()); registry.fill(HIST("hPhi"), candidate1.phi()); - registry.fill(HIST("hY"), yD0(candidate1)); + registry.fill(HIST("hY"), hfHelper.yD0(candidate1)); registry.fill(HIST("hSelectionStatus"), candidate1.isSelD0bar() + (candidate1.isSelD0() * 2)); // D-Dbar correlation dedicated section @@ -193,15 +197,15 @@ struct HfCorrelatorD0D0bar { if (candidate1.isSelD0() < selectionFlagD0) { continue; } - for (auto& candidate2 : selectedD0CandidatesGrouped) { - if (!(candidate2.hfflag() & 1 << DecayType::D0ToPiK)) { // check decay channel flag for candidate2 + for (const auto& candidate2 : selectedD0CandidatesGrouped) { + if (!(candidate2.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // check decay channel flag for candidate2 continue; } if (candidate2.isSelD0bar() < selectionFlagD0bar) { // keep only D0bar candidates passing the selection continue; } // kinematic selection on D0bar candidates - if (yCandMax >= 0. && std::abs(yD0(candidate2)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate2)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { @@ -215,8 +219,8 @@ struct HfCorrelatorD0D0bar { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt()); - entryD0D0barRecoInfo(invMassD0ToPiK(candidate1), - invMassD0barToKPi(candidate2), + entryD0D0barRecoInfo(hfHelper.invMassD0ToPiK(candidate1), + hfHelper.invMassD0barToKPi(candidate2), 0); double etaCut = 0.; double ptCut = 0.; @@ -241,7 +245,9 @@ struct HfCorrelatorD0D0bar { PROCESS_SWITCH(HfCorrelatorD0D0bar, processData, "Process data", false); /// D0-D0bar correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) - void processMcRec(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates) + void processMcRec(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const&) { int nTracks = 0; if (collision.numContrib() > 1) { @@ -268,12 +274,12 @@ struct HfCorrelatorD0D0bar { bool flagD0Reflection = false; bool flagD0barSignal = false; bool flagD0barReflection = false; - for (auto& candidate1 : selectedD0CandidatesGroupedMC) { + for (const auto& candidate1 : selectedD0CandidatesGroupedMC) { // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate1.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (yCandMax >= 0. && std::abs(yD0(candidate1)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { @@ -285,33 +291,33 @@ struct HfCorrelatorD0D0bar { efficiencyWeight = 1. / efficiencyD->at(o2::analysis::findBin(binsPt, candidate1.pt())); } - if (std::abs(candidate1.flagMcMatchRec()) == 1 << DecayType::D0ToPiK) { + if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // fill per-candidate distributions from D0/D0bar true candidates registry.fill(HIST("hPtCandMCRec"), candidate1.pt()); registry.fill(HIST("hPtProng0MCRec"), candidate1.ptProng0()); registry.fill(HIST("hPtProng1MCRec"), candidate1.ptProng1()); registry.fill(HIST("hEtaMCRec"), candidate1.eta()); registry.fill(HIST("hPhiMCRec"), candidate1.phi()); - registry.fill(HIST("hYMCRec"), yD0(candidate1)); + registry.fill(HIST("hYMCRec"), hfHelper.yD0(candidate1)); registry.fill(HIST("hSelectionStatusMCRec"), candidate1.isSelD0bar() + (candidate1.isSelD0() * 2)); } // fill invariant mass plots from D0/D0bar signal and background candidates if (candidate1.isSelD0() >= selectionFlagD0) { // only reco as D0 - if (candidate1.flagMcMatchRec() == 1 << DecayType::D0ToPiK) { // also matched as D0 - registry.fill(HIST("hMassD0MCRecSig"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { - registry.fill(HIST("hMassD0MCRecRefl"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // also matched as D0 + registry.fill(HIST("hMassD0MCRecSig"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + } else if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + registry.fill(HIST("hMassD0MCRecRefl"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } else { - registry.fill(HIST("hMassD0MCRecBkg"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0MCRecBkg"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } } if (candidate1.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar - if (candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { // also matched as D0bar - registry.fill(HIST("hMassD0barMCRecSig"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == 1 << DecayType::D0ToPiK) { - registry.fill(HIST("hMassD0barMCRecRefl"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // also matched as D0bar + registry.fill(HIST("hMassD0barMCRecSig"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + } else if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + registry.fill(HIST("hMassD0barMCRecRefl"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { - registry.fill(HIST("hMassD0barMCRecBkg"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0barMCRecBkg"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } } @@ -320,18 +326,18 @@ struct HfCorrelatorD0D0bar { if (candidate1.isSelD0() < selectionFlagD0) { // discard candidates not selected as D0 in outer loop continue; } - flagD0Signal = candidate1.flagMcMatchRec() == 1 << DecayType::D0ToPiK; // flagD0Signal 'true' if candidate1 matched to D0 (particle) - flagD0Reflection = candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) - for (auto& candidate2 : selectedD0CandidatesGroupedMC) { - if (!(candidate2.hfflag() & 1 << DecayType::D0ToPiK)) { // check decay channel flag for candidate2 + flagD0Signal = candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; // flagD0Signal 'true' if candidate1 matched to D0 (particle) + flagD0Reflection = candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) + for (const auto& candidate2 : selectedD0CandidatesGroupedMC) { + if (!(candidate2.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // check decay channel flag for candidate2 continue; } if (candidate2.isSelD0bar() < selectionFlagD0bar) { // discard candidates not selected as D0bar in inner loop continue; } - flagD0barSignal = candidate2.flagMcMatchRec() == -(1 << DecayType::D0ToPiK); // flagD0barSignal 'true' if candidate2 matched to D0bar (antiparticle) - flagD0barReflection = candidate2.flagMcMatchRec() == 1 << DecayType::D0ToPiK; // flagD0barReflection 'true' if candidate2, selected as D0bar (antiparticle), is matched to D0 (particle) - if (yCandMax >= 0. && std::abs(yD0(candidate2)) > yCandMax) { + flagD0barSignal = candidate2.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0barSignal 'true' if candidate2 matched to D0bar (antiparticle) + flagD0barReflection = candidate2.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; // flagD0barReflection 'true' if candidate2, selected as D0bar (antiparticle), is matched to D0 (particle) + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate2)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { @@ -359,8 +365,8 @@ struct HfCorrelatorD0D0bar { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt()); - entryD0D0barRecoInfo(invMassD0ToPiK(candidate1), - invMassD0barToKPi(candidate2), + entryD0D0barRecoInfo(hfHelper.invMassD0ToPiK(candidate1), + hfHelper.invMassD0barToKPi(candidate2), pairSignalStatus); double etaCut = 0.; double ptCut = 0.; @@ -382,17 +388,18 @@ struct HfCorrelatorD0D0bar { PROCESS_SWITCH(HfCorrelatorD0D0bar, processMcRec, "Process MC Reco mode", true); /// D0-D0bar correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGen(aod::McCollision const& mccollision, MCParticlesPlus const& particlesMC) + void processMcGen(aod::McCollision const&, + MCParticlesPlus const& mcParticles) { int counterD0D0bar = 0; registry.fill(HIST("hMCEvtCount"), 0); // MC gen level - for (auto& particle1 : particlesMC) { + for (const auto& particle1 : mcParticles) { // check if the particle is D0 or D0bar (for general plot filling and selection, so both cases are fine) - NOTE: decay channel is not probed! if (std::abs(particle1.pdgCode()) != pdg::Code::kD0) { continue; } - double yD = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yD = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassD0); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -411,11 +418,11 @@ struct HfCorrelatorD0D0bar { continue; } registry.fill(HIST("hCountD0triggersMCGen"), 0, particle1.pt()); // to count trigger D0 (for normalisation) - for (auto& particle2 : particlesMC) { + for (const auto& particle2 : mcParticles) { if (particle2.pdgCode() != pdg::Code::kD0Bar) { // check that inner particle is D0bar continue; } - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle2.px(), particle2.py(), particle2.pz()}, RecoDecay::getMassPDG(particle2.pdgCode()))) > yCandMax) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle2.px(), particle2.py(), particle2.pz()}, o2::analysis::pdg::MassD0Bar)) > yCandMax) { continue; } if (ptCandMin >= 0. && particle2.pt() < ptCandMin) { @@ -433,7 +440,7 @@ struct HfCorrelatorD0D0bar { // fill pairs vs etaCut plot bool rightDecayChannels = false; - if ((std::abs(particle1.flagMcMatchGen()) == 1 << DecayType::D0ToPiK) && (std::abs(particle2.flagMcMatchGen()) == 1 << DecayType::D0ToPiK)) { + if ((std::abs(particle1.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) && (std::abs(particle2.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { rightDecayChannels = true; } do { @@ -446,13 +453,13 @@ struct HfCorrelatorD0D0bar { if (rightDecayChannels) { // fill with D and Dbar daughter particls acceptance checks bool candidate1DauInAcc = true; bool candidate2DauInAcc = true; - for (auto& dau : particle1.daughters_as()) { + for (const auto& dau : particle1.daughters_as()) { if (std::abs(dau.eta()) > etaCut) { candidate1DauInAcc = false; break; } } - for (auto& dau : particle2.daughters_as()) { + for (const auto& dau : particle2.daughters_as()) { if (std::abs(dau.eta()) > etaCut) { candidate2DauInAcc = false; break; @@ -473,13 +480,14 @@ struct HfCorrelatorD0D0bar { PROCESS_SWITCH(HfCorrelatorD0D0bar, processMcGen, "Process MC Gen mode", false); /// c-cbar correlator table builder - for MC gen-level analysis - void processCCbar(aod::McCollision const& mccollision, MCParticlesPlus const& particlesMC) + void processCCbar(aod::McCollision const&, + MCParticlesPlus const& mcParticles) { registry.fill(HIST("hMCEvtCount"), 0); int counterCCbar = 0, counterCCbarBeforeEtasel = 0; // loop over particles at MC gen level - for (auto& particle1 : particlesMC) { + for (const auto& particle1 : mcParticles) { if (std::abs(particle1.pdgCode()) != PDG_t::kCharm) { // search c or cbar particles continue; } @@ -489,7 +497,7 @@ struct HfCorrelatorD0D0bar { continue; } counterCCbarBeforeEtasel++; // count c or cbar (before kinematic selection) - double yC = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yC = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassCharm); if (yCandMax >= 0. && std::abs(yC) > yCandMax) { continue; } @@ -509,11 +517,11 @@ struct HfCorrelatorD0D0bar { } registry.fill(HIST("hCountCtriggersMCGen"), 0, particle1.pt()); // to count trigger c quark (for normalisation) - for (auto& particle2 : particlesMC) { + for (const auto& particle2 : mcParticles) { if (particle2.pdgCode() != PDG_t::kCharmBar) { // check that inner particle is a cbar continue; } - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle2.px(), particle2.py(), particle2.pz()}, RecoDecay::getMassPDG(particle2.pdgCode()))) > yCandMax) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle2.px(), particle2.py(), particle2.pz()}, o2::analysis::pdg::MassCharmBar)) > yCandMax) { continue; } if (ptCandMin >= 0. && particle2.pt() < ptCandMin) { diff --git a/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx b/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx index e0387970fee..ee8520fd1c2 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx @@ -14,22 +14,22 @@ /// /// \author Fabio Colamaria , INFN Bari -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_correlation_d_dbar; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; -using namespace o2::constants::math; /// /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies @@ -83,6 +83,8 @@ struct HfCorrelatorD0D0barBarrelFullPid { Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits for candidate mass plots and efficiency"}; Configurable> efficiencyD{"efficiencyD", std::vector{efficiencyDmeson_v}, "Efficiency values for D0 meson"}; + HfHelper hfHelper; + Partition> selectedD0candidates = (aod::hf_sel_candidate_d0_alice3_barrel::isSelD0TofPlusRichPid >= selectionFlagD0 || aod::hf_sel_candidate_d0_alice3_barrel::isSelD0barTofPlusRichPid >= selectionFlagD0bar); Partition> selectedD0candidatesMC = (aod::hf_sel_candidate_d0_alice3_barrel::isSelD0TofPlusRichPid >= selectionFlagD0 || aod::hf_sel_candidate_d0_alice3_barrel::isSelD0barTofPlusRichPid >= selectionFlagD0bar); @@ -116,7 +118,7 @@ struct HfCorrelatorD0D0barBarrelFullPid { {"hCountCCbarPerEvent", "c,cbar particles - MC gen;Number per event;entries", {HistType::kTH1F, {{20, 0., 20.}}}}, {"hCountCCbarPerEventBeforeEtaCut", "c,cbar particles - MC gen;Number per event pre #eta cut;entries", {HistType::kTH1F, {{20, 0., 20.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMass", "D0,D0bar candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -133,7 +135,9 @@ struct HfCorrelatorD0D0barBarrelFullPid { } /// D0-D0bar correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processData(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates) + void processData(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const&) { int nTracks = 0; if (collision.numContrib() > 1) { @@ -155,15 +159,15 @@ struct HfCorrelatorD0D0barBarrelFullPid { auto selectedD0candidatesGrouped = selectedD0candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto& candidate1 : selectedD0candidatesGrouped) { - if (yCandMax >= 0. && std::abs(yD0(candidate1)) > yCandMax) { + for (const auto& candidate1 : selectedD0candidatesGrouped) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { continue; } // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate1.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } @@ -174,19 +178,19 @@ struct HfCorrelatorD0D0barBarrelFullPid { // fill invariant mass plots and generic info from all D0/D0bar candidates if (candidate1.isSelD0TofPlusRichPid() >= selectionFlagD0) { - registry.fill(HIST("hMass"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMassD0"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } if (candidate1.isSelD0barTofPlusRichPid() >= selectionFlagD0bar) { - registry.fill(HIST("hMass"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMassD0bar"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0bar"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } registry.fill(HIST("hPtCand"), candidate1.pt()); registry.fill(HIST("hPtProng0"), candidate1.ptProng0()); registry.fill(HIST("hPtProng1"), candidate1.ptProng1()); registry.fill(HIST("hEta"), candidate1.eta()); registry.fill(HIST("hPhi"), candidate1.phi()); - registry.fill(HIST("hY"), yD0(candidate1)); + registry.fill(HIST("hY"), hfHelper.yD0(candidate1)); registry.fill(HIST("hSelectionStatus"), candidate1.isSelD0barTofPlusRichPid() + (candidate1.isSelD0TofPlusRichPid() * 2)); // D-Dbar correlation dedicated section @@ -194,15 +198,15 @@ struct HfCorrelatorD0D0barBarrelFullPid { if (candidate1.isSelD0TofPlusRichPid() < selectionFlagD0) { continue; } - for (auto& candidate2 : selectedD0candidatesGrouped) { - if (!(candidate2.hfflag() & 1 << DecayType::D0ToPiK)) { // check decay channel flag for candidate2 + for (const auto& candidate2 : selectedD0candidatesGrouped) { + if (!(candidate2.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // check decay channel flag for candidate2 continue; } if (candidate2.isSelD0barTofPlusRichPid() < selectionFlagD0bar) { // keep only D0bar candidates passing the selection continue; } // kinematic selection on D0bar candidates - if (yCandMax >= 0. && std::abs(yD0(candidate2)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate2)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { @@ -216,8 +220,8 @@ struct HfCorrelatorD0D0barBarrelFullPid { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt()); - entryD0D0barRecoInfo(invMassD0ToPiK(candidate1), - invMassD0barToKPi(candidate2), + entryD0D0barRecoInfo(hfHelper.invMassD0ToPiK(candidate1), + hfHelper.invMassD0barToKPi(candidate2), 0); double etaCut = 0.; double ptCut = 0.; @@ -242,7 +246,9 @@ struct HfCorrelatorD0D0barBarrelFullPid { PROCESS_SWITCH(HfCorrelatorD0D0barBarrelFullPid, processData, "Process data", false); /// D0-D0bar correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) - void processMcRec(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates) + void processMcRec(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const&) { int nTracks = 0; if (collision.numContrib() > 1) { @@ -269,12 +275,12 @@ struct HfCorrelatorD0D0barBarrelFullPid { bool flagD0Reflection = false; bool flagD0barSignal = false; bool flagD0barReflection = false; - for (auto& candidate1 : selectedD0candidatesGroupedMC) { + for (const auto& candidate1 : selectedD0candidatesGroupedMC) { // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate1.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (yCandMax >= 0. && std::abs(yD0(candidate1)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { @@ -286,33 +292,33 @@ struct HfCorrelatorD0D0barBarrelFullPid { efficiencyWeight = 1. / efficiencyD->at(o2::analysis::findBin(binsPt, candidate1.pt())); } - if (std::abs(candidate1.flagMcMatchRec()) == 1 << DecayType::D0ToPiK) { + if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // fill per-candidate distributions from D0/D0bar true candidates registry.fill(HIST("hPtCandMCRec"), candidate1.pt()); registry.fill(HIST("hPtProng0MCRec"), candidate1.ptProng0()); registry.fill(HIST("hPtProng1MCRec"), candidate1.ptProng1()); registry.fill(HIST("hEtaMCRec"), candidate1.eta()); registry.fill(HIST("hPhiMCRec"), candidate1.phi()); - registry.fill(HIST("hYMCRec"), yD0(candidate1)); + registry.fill(HIST("hYMCRec"), hfHelper.yD0(candidate1)); registry.fill(HIST("hSelectionStatusMCRec"), candidate1.isSelD0barTofPlusRichPid() + (candidate1.isSelD0TofPlusRichPid() * 2)); } // fill invariant mass plots from D0/D0bar signal and background candidates if (candidate1.isSelD0TofPlusRichPid() >= selectionFlagD0) { // only reco as D0 - if (candidate1.flagMcMatchRec() == 1 << DecayType::D0ToPiK) { // also matched as D0 - registry.fill(HIST("hMassD0MCRecSig"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { - registry.fill(HIST("hMassD0MCRecRefl"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // also matched as D0 + registry.fill(HIST("hMassD0MCRecSig"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + } else if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + registry.fill(HIST("hMassD0MCRecRefl"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } else { - registry.fill(HIST("hMassD0MCRecBkg"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0MCRecBkg"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } } if (candidate1.isSelD0barTofPlusRichPid() >= selectionFlagD0bar) { // only reco as D0bar - if (candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { // also matched as D0bar - registry.fill(HIST("hMassD0barMCRecSig"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == 1 << DecayType::D0ToPiK) { - registry.fill(HIST("hMassD0barMCRecRefl"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // also matched as D0bar + registry.fill(HIST("hMassD0barMCRecSig"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + } else if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + registry.fill(HIST("hMassD0barMCRecRefl"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { - registry.fill(HIST("hMassD0barMCRecBkg"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0barMCRecBkg"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } } @@ -321,18 +327,18 @@ struct HfCorrelatorD0D0barBarrelFullPid { if (candidate1.isSelD0TofPlusRichPid() < selectionFlagD0) { // discard candidates not selected as D0 in outer loop continue; } - flagD0Signal = candidate1.flagMcMatchRec() == 1 << DecayType::D0ToPiK; // flagD0Signal 'true' if candidate1 matched to D0 (particle) - flagD0Reflection = candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) - for (auto& candidate2 : selectedD0candidatesGroupedMC) { - if (!(candidate2.hfflag() & 1 << DecayType::D0ToPiK)) { // check decay channel flag for candidate2 + flagD0Signal = candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; // flagD0Signal 'true' if candidate1 matched to D0 (particle) + flagD0Reflection = candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) + for (const auto& candidate2 : selectedD0candidatesGroupedMC) { + if (!(candidate2.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // check decay channel flag for candidate2 continue; } if (candidate2.isSelD0barTofPlusRichPid() < selectionFlagD0bar) { // discard candidates not selected as D0bar in inner loop continue; } - flagD0barSignal = candidate2.flagMcMatchRec() == -(1 << DecayType::D0ToPiK); // flagD0barSignal 'true' if candidate2 matched to D0bar (antiparticle) - flagD0barReflection = candidate2.flagMcMatchRec() == 1 << DecayType::D0ToPiK; // flagD0barReflection 'true' if candidate2, selected as D0bar (antiparticle), is matched to D0 (particle) - if (yCandMax >= 0. && std::abs(yD0(candidate2)) > yCandMax) { + flagD0barSignal = candidate2.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0barSignal 'true' if candidate2 matched to D0bar (antiparticle) + flagD0barReflection = candidate2.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; // flagD0barReflection 'true' if candidate2, selected as D0bar (antiparticle), is matched to D0 (particle) + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate2)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { @@ -360,8 +366,8 @@ struct HfCorrelatorD0D0barBarrelFullPid { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt()); - entryD0D0barRecoInfo(invMassD0ToPiK(candidate1), - invMassD0barToKPi(candidate2), + entryD0D0barRecoInfo(hfHelper.invMassD0ToPiK(candidate1), + hfHelper.invMassD0barToKPi(candidate2), pairSignalStatus); double etaCut = 0.; double ptCut = 0.; @@ -383,17 +389,18 @@ struct HfCorrelatorD0D0barBarrelFullPid { PROCESS_SWITCH(HfCorrelatorD0D0barBarrelFullPid, processMcRec, "Process MC Reco mode", true); /// D0-D0bar correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGen(aod::McCollision const& mccollision, MCParticlesPlus const& particlesMC) + void processMcGen(aod::McCollision const&, + MCParticlesPlus const& mcParticles) { int counterD0D0bar = 0; registry.fill(HIST("hMCEvtCount"), 0); // MC gen level - for (auto& particle1 : particlesMC) { + for (const auto& particle1 : mcParticles) { // check if the particle is D0 or D0bar (for general plot filling and selection, so both cases are fine) - NOTE: decay channel is not probed! if (std::abs(particle1.pdgCode()) != pdg::Code::kD0) { continue; } - double yD = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yD = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassD0); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -412,11 +419,11 @@ struct HfCorrelatorD0D0barBarrelFullPid { continue; } registry.fill(HIST("hCountD0triggersMCGen"), 0, particle1.pt()); // to count trigger D0 (for normalisation) - for (auto& particle2 : particlesMC) { + for (const auto& particle2 : mcParticles) { if (particle2.pdgCode() != pdg::Code::kD0Bar) { // check that inner particle is D0bar continue; } - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle2.px(), particle2.py(), particle2.pz()}, RecoDecay::getMassPDG(particle2.pdgCode()))) > yCandMax) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle2.px(), particle2.py(), particle2.pz()}, o2::analysis::pdg::MassD0Bar)) > yCandMax) { continue; } if (ptCandMin >= 0. && particle2.pt() < ptCandMin) { @@ -434,7 +441,7 @@ struct HfCorrelatorD0D0barBarrelFullPid { // fill pairs vs etaCut plot bool rightDecayChannels = false; - if ((std::abs(particle1.flagMcMatchGen()) == 1 << DecayType::D0ToPiK) && (std::abs(particle2.flagMcMatchGen()) == 1 << DecayType::D0ToPiK)) { + if ((std::abs(particle1.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) && (std::abs(particle2.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { rightDecayChannels = true; } do { @@ -447,13 +454,13 @@ struct HfCorrelatorD0D0barBarrelFullPid { if (rightDecayChannels) { // fill with D and Dbar daughter particls acceptance checks bool candidate1DauInAcc = true; bool candidate2DauInAcc = true; - for (auto& dau : particle1.daughters_as()) { + for (const auto& dau : particle1.daughters_as()) { if (std::abs(dau.eta()) > etaCut) { candidate1DauInAcc = false; break; } } - for (auto& dau : particle2.daughters_as()) { + for (const auto& dau : particle2.daughters_as()) { if (std::abs(dau.eta()) > etaCut) { candidate2DauInAcc = false; break; @@ -474,13 +481,14 @@ struct HfCorrelatorD0D0barBarrelFullPid { PROCESS_SWITCH(HfCorrelatorD0D0barBarrelFullPid, processMcGen, "Process MC Gen mode", false); /// c-cbar correlator table builder - for MC gen-level analysis - void processCCbar(aod::McCollision const& mccollision, MCParticlesPlus const& particlesMC) + void processCCbar(aod::McCollision const&, + MCParticlesPlus const& mcParticles) { registry.fill(HIST("hMCEvtCount"), 0); int counterCCbar = 0, counterCCbarBeforeEtasel = 0; // loop over particles at MC gen level - for (auto& particle1 : particlesMC) { + for (const auto& particle1 : mcParticles) { if (std::abs(particle1.pdgCode()) != PDG_t::kCharm) { // search c or cbar particles continue; } @@ -490,7 +498,7 @@ struct HfCorrelatorD0D0barBarrelFullPid { continue; } counterCCbarBeforeEtasel++; // count c or cbar (before kinematic selection) - double yC = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yC = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassCharm); if (yCandMax >= 0. && std::abs(yC) > yCandMax) { continue; } @@ -510,11 +518,11 @@ struct HfCorrelatorD0D0barBarrelFullPid { } registry.fill(HIST("hCountCtriggersMCGen"), 0, particle1.pt()); // to count trigger c quark (for normalisation) - for (auto& particle2 : particlesMC) { + for (const auto& particle2 : mcParticles) { if (particle2.pdgCode() != PDG_t::kCharmBar) { // check that inner particle is a cbar continue; } - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle2.px(), particle2.py(), particle2.pz()}, RecoDecay::getMassPDG(particle2.pdgCode()))) > yCandMax) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle2.px(), particle2.py(), particle2.pz()}, o2::analysis::pdg::MassCharmBar)) > yCandMax) { continue; } if (ptCandMin >= 0. && particle2.pt() < ptCandMin) { diff --git a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx index 0a3c9ac1333..d8b0b82d874 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx @@ -15,30 +15,31 @@ /// \author Samrangy Sadhu , INFN Bari /// \author Swapnesh Santosh Khade , IIT Indore -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_correlation_d0_hadron; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; -using namespace o2::constants::math; /// /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies /// -double getDeltaPhi(double phiD, double phiDbar) +double getDeltaPhi(double phiHadron, double phiD) { - return RecoDecay::constrainAngle(phiDbar - phiD, -o2::constants::math::PIHalf); + return RecoDecay::constrainAngle(phiHadron - phiD, -o2::constants::math::PIHalf); } const int nPtBinsMassAndEfficiency = o2::analysis::hf_cuts_d0_to_pi_k::nBinsPt; @@ -58,35 +59,149 @@ const double yAxisMax = 5.; const int ptDAxisNBins = 180; const double ptDAxisMin = 0.; const double ptDAxisMax = 36.; -const double massD0 = RecoDecay::getMassPDG(pdg::Code::kD0); -const double softPiMass = 0.14543; // pion mass + Q-value of the D*->D0pi decay -auto massPi = RecoDecay::getMassPDG(kPiPlus); -auto massK = RecoDecay::getMassPDG(kKPlus); -struct HfCorrelatorD0Hadrons { +// definition of ME variables and new types +std::vector zBins{VARIABLE_WIDTH, -10.0, -2.5, 2.5, 10.0}; +std::vector multBins{VARIABLE_WIDTH, 0., 200., 500.0, 5000.}; +std::vector multBinsMcGen{VARIABLE_WIDTH, 0., 20., 50.0, 500.}; // In MCGen multiplicity is defined by counting primaries +using BinningType = ColumnBinningPolicy>; +BinningType corrBinning{{zBins, multBins}, true}; + +using SelectedCollisions = soa::Filtered>; +using SelectedTracks = soa::Filtered; +using SelectedCandidatesData = soa::Filtered>; +using SelectedCandidatesMcRec = soa::Filtered>; +using SelectedCollisionsMcGen = soa::Filtered>; +using SelectedTracksMcGen = soa::Filtered; + +// Code to select collisions with at least one D0 +struct HfCorrelatorD0HadronsSelection { SliceCache cache; + + Produces d0Sel; + + Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; + Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; + Configurable yCandMax{"yCandMax", 4.0, "max. cand. rapidity"}; + Configurable ptCandMin{"ptCandMin", -1., "min. cand. pT"}; + + HfHelper hfHelper; + Preslice perCol = aod::hf_cand::collisionId; + Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition> selectedD0candidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + + void processD0SelectionData(aod::Collision const& collision, + soa::Join const& candidates) + { + bool isD0Found = 0; + if (selectedD0Candidates.size() > 0) { + auto selectedD0CandidatesGrouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + + for (const auto& candidate1 : selectedD0CandidatesGrouped) { + // check decay channel flag for candidate1 + if (!TESTBIT(candidate1.hfflag(), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + continue; + } + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate1)) > yCandMax) { + continue; + } + if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { + continue; + } + isD0Found = 1; + } + } + d0Sel(isD0Found); + } + PROCESS_SWITCH(HfCorrelatorD0HadronsSelection, processD0SelectionData, "Process D0 Selection Data", false); + + void processD0SelectionMcRec(aod::Collision const& collision, + soa::Join const& candidates) + { + bool isD0Found = 0; + if (selectedD0candidatesMc.size() > 0) { + auto selectedD0CandidatesGroupedMc = selectedD0candidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + for (const auto& candidate1 : selectedD0CandidatesGroupedMc) { + // check decay channel flag for candidate1 + if (!TESTBIT(candidate1.hfflag(), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + continue; + } + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate1)) > yCandMax) { + continue; + } + if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { + continue; + } + isD0Found = 1; + } + } + d0Sel(isD0Found); + } + PROCESS_SWITCH(HfCorrelatorD0HadronsSelection, processD0SelectionMcRec, "Process D0 Selection MCRec", true); + + void processD0SelectionMcGen(aod::McCollision const& mcCollision, + aod::McParticles const& mcParticles) + { + bool isD0Found = 0; + for (const auto& particle1 : mcParticles) { + if (std::abs(particle1.pdgCode()) != pdg::Code::kD0) { + continue; + } + double yD = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassD0); + if (yCandMax >= 0. && std::abs(yD) > yCandMax) { + continue; + } + if (ptCandMin >= 0. && particle1.pt() < ptCandMin) { + continue; + } + isD0Found = 1; + } + d0Sel(isD0Found); + } + PROCESS_SWITCH(HfCorrelatorD0HadronsSelection, processD0SelectionMcGen, "Process D0 Selection MCGen", false); +}; + +struct HfCorrelatorD0Hadrons { + SliceCache cache; Produces entryD0HadronPair; Produces entryD0HadronRecoInfo; Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; - Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; - Configurable etaTrackMax{"etaTrackMax", 4., "max. eta of tracks"}; - Configurable dcaXYTrackMax{"dcaXYTrackMax", 0.0025, "max. DCAxy of tracks"}; - Configurable dcaZTrackMax{"dcaZTrackMax", 0.0025, "max. DCAz of tracks"}; - Configurable ptCandMin{"ptCandMin", -1., "min. cand. pT"}; - Configurable ptTrackMin{"ptTrackMin", -1., "min. track pT"}; + Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 4., "max. eta of tracks"}; + Configurable dcaXYTrackMax{"dcaXYTrackMax", 0.0025, "max. DCAxy of tracks"}; + Configurable dcaZTrackMax{"dcaZTrackMax", 0.0025, "max. DCAz of tracks"}; + Configurable ptCandMin{"ptCandMin", -1., "min. cand. pT"}; + Configurable ptTrackMin{"ptTrackMin", -1., "min. track pT"}; Configurable> bins{"ptBinsForMassAndEfficiency", std::vector{o2::analysis::hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits for candidate mass plots and efficiency"}; Configurable> efficiencyDmeson{"efficiencyDmeson", std::vector{vecEfficiencyDmeson}, "Efficiency values for D0 meson"}; Configurable applyEfficiency{"efficiencyFlagD", 1, "Flag for applying D-meson efficiency weights"}; - Configurable multMin{"multMin", 0., "minimum multiplicity accepted"}; - Configurable multMax{"multMax", 10000., "maximum multiplicity accepted"}; - Configurable ptSoftPionMax{"ptSoftPionMax", 3 * 800. * pow(10., -6.), "max. pT cut for soft pion identification"}; + Configurable multMin{"multMin", 0., "minimum multiplicity accepted"}; + Configurable multMax{"multMax", 10000., "maximum multiplicity accepted"}; + Configurable ptSoftPionMax{"ptSoftPionMax", 3 * 800. * pow(10., -6.), "max. pT cut for soft pion identification"}; + + HfHelper hfHelper; + + double massD0{0.}; + double massPi{0.}; + double massK{0.}; + double softPiMass = 0.14543; // pion mass + Q-value of the D*->D0pi decay + + Preslice perCol = aod::hf_cand::collisionId; Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - Partition> selectedD0candidatesMC = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + Partition> selectedD0candidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; + + // Filters for ME + Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; + Filter trackFilter = (aod::track::eta > static_cast(-etaTrackMax)) && (aod::track::eta < static_cast(etaTrackMax)) && (aod::track::pt > static_cast(ptTrackMin)) && (aod::track::dcaXY > static_cast(-dcaXYTrackMax)) && (aod::track::dcaXY < static_cast(dcaXYTrackMax)) && + (aod::track::dcaZ > static_cast(-dcaZTrackMax)) && (aod::track::dcaZ < static_cast(dcaZTrackMax)); + Filter d0Filter = (aod::hf_sel_candidate_d0::isSelD0 >= 1) || (aod::hf_sel_candidate_d0::isSelD0bar >= 1); + Filter collisionFilterGen = aod::hf_selection_dmeson_collision::dmesonSel == true; + Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == static_cast(pdg::Code::kD0) || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); HistogramRegistry registry{ "registry", @@ -104,6 +219,7 @@ struct HfCorrelatorD0Hadrons { {"hPtProng0Rec", "D0,D0bar candidates - MC reco;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisNBins, ptDAxisMin, ptDAxisMax}}}}, {"hPtProng1Rec", "D0,D0bar candidates - MC reco;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{ptDAxisNBins, ptDAxisMin, ptDAxisMax}}}}, {"hSelectionStatusRec", "D0,D0bar candidates - MC reco;selection status;entries", {HistType::kTH1F, {{4, -0.5, 3.5}}}}, + {"hSignalStatusMERec", "Signal Status - MC reco ME;candidate sidnalStatus;entries", {HistType::kTH1F, {{200, 0, 200}}}}, {"hEtaRec", "D0,D0bar candidates - MC reco;candidate #it{#eta};entries", {HistType::kTH1F, {{yAxisNBins, yAxisMin, yAxisMax}}}}, {"hPhiRec", "D0,D0bar candidates - MC reco;candidate #it{#varphi};entries", {HistType::kTH1F, {{phiAxisNBins, phiAxisMin, phiAxisMax}}}}, {"hYRec", "D0,D0bar candidates - MC reco;candidate #it{y};entries", {HistType::kTH1F, {{yAxisNBins, yAxisMin, yAxisMax}}}}, @@ -114,10 +230,18 @@ struct HfCorrelatorD0Hadrons { {"hYGen", "D0,D0bar candidates - MC gen;candidate #it{y};entries", {HistType::kTH1F, {{yAxisNBins, yAxisMin, yAxisMax}}}}, {"hTrackCounter", "soft pion counter - Data", {HistType::kTH1F, {{5, 0., 5.}}}}, {"hTrackCounterRec", "soft pion counter - MC rec", {HistType::kTH1F, {{5, 0., 5.}}}}, - {"hTrackCounterGen", "soft pion counter - MC gen", {HistType::kTH1F, {{5, 0., 5.}}}}}}; + {"hTrackCounterGen", "soft pion counter - MC gen", {HistType::kTH1F, {{5, 0., 5.}}}}, + {"hMultV0M", "multiplicity;multiplicity;entries", {HistType::kTH1F, {{10000, 0., 10000.}}}}, + {"hZvtx", "z vertex;z vertex;entries", {HistType::kTH1F, {{200, -20., 20.}}}}, + {"hD0Bin", "D0 selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}}, + {"hTracksBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { + massD0 = o2::analysis::pdg::MassD0; + massPi = o2::analysis::pdg::MassPiPlus; + massK = o2::analysis::pdg::MassKPlus; + auto vbins = (std::vector)bins; registry.add("hMass", "D0,D0bar candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisNBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMass1D", "D0,D0bar candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{massAxisNBins, massAxisMin, massAxisMax}}}); @@ -138,17 +262,18 @@ struct HfCorrelatorD0Hadrons { registry.add("hCountD0TriggersGen", "D0 trigger particles - MC gen;;N of trigger D0", {HistType::kTH2F, {{1, -0.5, 0.5}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); } - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // ============================================================================= Process starts for Data ================================================================================== - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // ======= Process starts for Data, Same event ============ /// D0-h correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processData(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates) + void processData(soa::Join::iterator const& collision, + aod::TracksWDca const& tracks, + soa::Join const& candidates) { // protection against empty tables to be sliced if (selectedD0Candidates.size() == 0) { return; } + int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFV0M())); int nTracks = 0; if (collision.numContrib() > 1) { for (const auto& track : tracks) { @@ -169,15 +294,15 @@ struct HfCorrelatorD0Hadrons { auto selectedD0CandidatesGrouped = selectedD0Candidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto const& candidate1 : selectedD0CandidatesGrouped) { - if (yCandMax >= 0. && std::abs(yD0(candidate1)) > yCandMax) { + for (const auto& candidate1 : selectedD0CandidatesGrouped) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { continue; } // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!TESTBIT(candidate1.hfflag(), aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } @@ -192,14 +317,14 @@ struct HfCorrelatorD0Hadrons { } // ========================== Fill mass histo ================================ if (candidate1.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hMass"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMass1D"), invMassD0ToPiK(candidate1), efficiencyWeight); - registry.fill(HIST("hMassD01D"), invMassD0ToPiK(candidate1), efficiencyWeight); + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass1D"), hfHelper.invMassD0ToPiK(candidate1), efficiencyWeight); + registry.fill(HIST("hMassD01D"), hfHelper.invMassD0ToPiK(candidate1), efficiencyWeight); } if (candidate1.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hMass"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMass1D"), invMassD0barToKPi(candidate1), efficiencyWeight); - registry.fill(HIST("hMassD0bar1D"), invMassD0barToKPi(candidate1), efficiencyWeight); + registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass1D"), hfHelper.invMassD0barToKPi(candidate1), efficiencyWeight); + registry.fill(HIST("hMassD0bar1D"), hfHelper.invMassD0barToKPi(candidate1), efficiencyWeight); } // ========================== Fill general histos ================================ registry.fill(HIST("hPtCand"), candidate1.pt()); @@ -207,10 +332,11 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hPtProng1"), candidate1.ptProng1()); registry.fill(HIST("hEta"), candidate1.eta()); registry.fill(HIST("hPhi"), candidate1.phi()); - registry.fill(HIST("hY"), yD0(candidate1)); + registry.fill(HIST("hY"), hfHelper.yD0(candidate1)); registry.fill(HIST("hSelectionStatus"), candidate1.isSelD0bar() + (candidate1.isSelD0() * 2)); + registry.fill(HIST("hD0Bin"), poolBin); - // ================================================================================= D-h correlation dedicated section ===================================================== + // ============ D-h correlation dedicated section ================================== // ========================== track loop starts here ================================ for (const auto& track : tracks) { @@ -224,42 +350,43 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hTrackCounter"), 2); // fill no. of tracks before soft pion removal - // ===== soft pion removal =================================================== + // ========== soft pion removal =================================================== double invMassDstar1 = 0., invMassDstar2 = 0.; - bool isSoftpiD0 = false, isSoftpiD0bar = false; + bool isSoftPiD0 = false, isSoftPiD0bar = false; auto pSum2 = RecoDecay::p2(candidate1.px() + track.px(), candidate1.py() + track.py(), candidate1.pz() + track.pz()); auto ePion = track.energy(massPi); invMassDstar1 = std::sqrt((ePiK + ePion) * (ePiK + ePion) - pSum2); invMassDstar2 = std::sqrt((eKPi + ePion) * (eKPi + ePion) - pSum2); if (candidate1.isSelD0() >= selectionFlagD0) { - if ((std::abs(invMassDstar1 - invMassD0ToPiK(candidate1)) - softPiMass) < ptSoftPionMax) { - isSoftpiD0 = true; + if ((std::abs(invMassDstar1 - hfHelper.invMassD0ToPiK(candidate1)) - softPiMass) < ptSoftPionMax) { + isSoftPiD0 = true; continue; } } if (candidate1.isSelD0bar() >= selectionFlagD0bar) { - if ((std::abs(invMassDstar2 - invMassD0barToKPi(candidate1)) - softPiMass) < ptSoftPionMax) { - isSoftpiD0bar = true; + if ((std::abs(invMassDstar2 - hfHelper.invMassD0barToKPi(candidate1)) - softPiMass) < ptSoftPionMax) { + isSoftPiD0bar = true; continue; } } registry.fill(HIST("hTrackCounter"), 3); // fill no. of tracks after soft pion removal int signalStatus = 0; - if ((candidate1.isSelD0() >= selectionFlagD0) && (isSoftpiD0 == false)) { - signalStatus += 1; + if ((candidate1.isSelD0() >= selectionFlagD0) && !isSoftPiD0) { + signalStatus += aod::hf_correlation_d0_hadron::ParticleTypeData::D0Only; } - if ((candidate1.isSelD0bar() >= selectionFlagD0bar) && (isSoftpiD0bar == false)) { - signalStatus += 2; + if ((candidate1.isSelD0bar() >= selectionFlagD0bar) && !isSoftPiD0bar) { + signalStatus += aod::hf_correlation_d0_hadron::ParticleTypeData::D0barOnly; } entryD0HadronPair(getDeltaPhi(track.phi(), candidate1.phi()), track.eta() - candidate1.eta(), candidate1.pt(), - track.pt()); - entryD0HadronRecoInfo(invMassD0ToPiK(candidate1), invMassD0barToKPi(candidate1), signalStatus); + track.pt(), + poolBin); + entryD0HadronRecoInfo(hfHelper.invMassD0ToPiK(candidate1), hfHelper.invMassD0barToKPi(candidate1), signalStatus); } // end inner loop (tracks) @@ -267,16 +394,17 @@ struct HfCorrelatorD0Hadrons { } PROCESS_SWITCH(HfCorrelatorD0Hadrons, processData, "Process data", false); - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // ============================================================================= Process starts for MCRec ================================================================================== - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // ================ Process starts for MCRec, same event ======================== - void processMcRec(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates) + void processMcRec(soa::Join::iterator const& collision, + aod::TracksWDca const& tracks, + soa::Join const& candidates) { // protection against empty tables to be sliced - if (selectedD0candidatesMC.size() == 0) { + if (selectedD0candidatesMc.size() == 0) { return; } + int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFV0M())); int nTracks = 0; if (collision.numContrib() > 1) { for (const auto& track : tracks) { @@ -295,17 +423,17 @@ struct HfCorrelatorD0Hadrons { } registry.fill(HIST("hMultiplicity"), nTracks); - auto selectedD0CandidatesGroupedMC = selectedD0candidatesMC->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + auto selectedD0CandidatesGroupedMc = selectedD0candidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); // MC reco level bool flagD0 = false; bool flagD0bar = false; - for (auto const& candidate1 : selectedD0CandidatesGroupedMC) { + for (const auto& candidate1 : selectedD0CandidatesGroupedMc) { // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!TESTBIT(candidate1.hfflag(), aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (yCandMax >= 0. && std::abs(yD0(candidate1)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { @@ -317,44 +445,44 @@ struct HfCorrelatorD0Hadrons { efficiencyWeight = 1. / efficiencyDmeson->at(o2::analysis::findBin(bins, candidate1.pt())); } - if (std::abs(candidate1.flagMcMatchRec()) == 1 << DecayType::D0ToPiK) { + if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // fill per-candidate distributions from D0/D0bar true candidates registry.fill(HIST("hPtCandRec"), candidate1.pt()); registry.fill(HIST("hPtProng0Rec"), candidate1.ptProng0()); registry.fill(HIST("hPtProng1Rec"), candidate1.ptProng1()); registry.fill(HIST("hEtaRec"), candidate1.eta()); registry.fill(HIST("hPhiRec"), candidate1.phi()); - registry.fill(HIST("hYRec"), yD0(candidate1)); + registry.fill(HIST("hYRec"), hfHelper.yD0(candidate1)); registry.fill(HIST("hSelectionStatusRec"), candidate1.isSelD0bar() + (candidate1.isSelD0() * 2)); } // fill invariant mass plots from D0/D0bar signal and background candidates if (candidate1.isSelD0() >= selectionFlagD0) { // only reco as D0 - if (candidate1.flagMcMatchRec() == 1 << DecayType::D0ToPiK) { // also matched as D0 - registry.fill(HIST("hMassD0RecSig"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { - registry.fill(HIST("hMassD0RecRef"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // also matched as D0 + registry.fill(HIST("hMassD0RecSig"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + } else if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + registry.fill(HIST("hMassD0RecRef"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } else { - registry.fill(HIST("hMassD0RecBg"), invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0RecBg"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } } if (candidate1.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar - if (candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK)) { // also matched as D0bar - registry.fill(HIST("hMassD0barRecSig"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == 1 << DecayType::D0ToPiK) { - registry.fill(HIST("hMassD0barRecRef"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // also matched as D0bar + registry.fill(HIST("hMassD0barRecSig"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + } else if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + registry.fill(HIST("hMassD0barRecRef"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { - registry.fill(HIST("hMassD0barRecBg"), invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0barRecBg"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } } - // ========================== Define parameters for soft pion removal ================================ + // ===================== Define parameters for soft pion removal ======================== auto ePiK = RecoDecay::e(candidate1.pVectorProng0(), massPi) + RecoDecay::e(candidate1.pVectorProng1(), massK); auto eKPi = RecoDecay::e(candidate1.pVectorProng0(), massK) + RecoDecay::e(candidate1.pVectorProng1(), massPi); - // D0-h correlation dedicated section + // ============== D-h correlation dedicated section ==================================== - flagD0 = candidate1.flagMcMatchRec() == (1 << DecayType::D0ToPiK); // flagD0Signal 'true' if candidate1 matched to D0 (particle) - flagD0bar = candidate1.flagMcMatchRec() == -(1 << DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) + flagD0 = candidate1.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Signal 'true' if candidate1 matched to D0 (particle) + flagD0bar = candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) // ========== track loop starts here ======================== @@ -377,22 +505,22 @@ struct HfCorrelatorD0Hadrons { // ===== soft pion removal =================================================== double invMassDstar1 = 0, invMassDstar2 = 0; - bool isSoftpiD0 = false, isSoftpiD0bar = false; + bool isSoftPiD0 = false, isSoftPiD0bar = false; auto pSum2 = RecoDecay::p2(candidate1.px() + track.px(), candidate1.py() + track.py(), candidate1.pz() + track.pz()); auto ePion = track.energy(massPi); invMassDstar1 = std::sqrt((ePiK + ePion) * (ePiK + ePion) - pSum2); invMassDstar2 = std::sqrt((eKPi + ePion) * (eKPi + ePion) - pSum2); if (candidate1.isSelD0() >= selectionFlagD0) { - if ((std::abs(invMassDstar1 - invMassD0ToPiK(candidate1)) - softPiMass) < ptSoftPionMax) { - isSoftpiD0 = true; + if ((std::abs(invMassDstar1 - hfHelper.invMassD0ToPiK(candidate1)) - softPiMass) < ptSoftPionMax) { + isSoftPiD0 = true; continue; } } if (candidate1.isSelD0bar() >= selectionFlagD0bar) { - if ((std::abs(invMassDstar2 - invMassD0barToKPi(candidate1)) - softPiMass) < ptSoftPionMax) { - isSoftpiD0bar = true; + if ((std::abs(invMassDstar2 - hfHelper.invMassD0barToKPi(candidate1)) - softPiMass) < ptSoftPionMax) { + isSoftPiD0bar = true; continue; } } @@ -400,53 +528,53 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hTrackCounterRec"), 3); // fill no. of tracks after soft pion removal int signalStatus = 0; - if ((flagD0 == true) && (candidate1.isSelD0() >= selectionFlagD0) && (isSoftpiD0 == false)) { - signalStatus += 1; + if (flagD0 && (candidate1.isSelD0() >= selectionFlagD0) && !isSoftPiD0) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0Sig); } // signal case D0 - if ((flagD0bar == true) && (candidate1.isSelD0() >= selectionFlagD0) && (isSoftpiD0 == false)) { - signalStatus += 2; + if (flagD0bar && (candidate1.isSelD0() >= selectionFlagD0) && !isSoftPiD0) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0Ref); } // reflection case D0 - if ((flagD0 == false) && (flagD0bar == false) && (candidate1.isSelD0() >= selectionFlagD0) && (isSoftpiD0 == false)) { - signalStatus += 4; + if (!flagD0 && !flagD0bar && (candidate1.isSelD0() >= selectionFlagD0) && !isSoftPiD0) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0Bg); } // background case D0 - if ((flagD0bar == true) && (candidate1.isSelD0bar() >= selectionFlagD0bar) && (isSoftpiD0bar == false)) { - signalStatus += 8; + if (flagD0bar && (candidate1.isSelD0bar() >= selectionFlagD0bar) && !isSoftPiD0bar) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0barSig); } // signal case D0bar - if ((flagD0 == true) && (candidate1.isSelD0bar() >= selectionFlagD0bar) && (isSoftpiD0bar == false)) { - signalStatus += 16; + if (flagD0 && (candidate1.isSelD0bar() >= selectionFlagD0bar) && !isSoftPiD0bar) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0barRef); } // reflection case D0bar - if ((flagD0 == false) && (flagD0bar == false) && (candidate1.isSelD0bar() >= selectionFlagD0bar) && (isSoftpiD0bar == false)) { - signalStatus += 32; + if (!flagD0 && !flagD0bar && (candidate1.isSelD0bar() >= selectionFlagD0bar) && !isSoftPiD0bar) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0barBg); } // background case D0bar entryD0HadronPair(getDeltaPhi(track.phi(), candidate1.phi()), track.eta() - candidate1.eta(), candidate1.pt(), - track.pt()); - entryD0HadronRecoInfo(invMassD0ToPiK(candidate1), invMassD0barToKPi(candidate1), signalStatus); + track.pt(), + poolBin); + entryD0HadronRecoInfo(hfHelper.invMassD0ToPiK(candidate1), hfHelper.invMassD0barToKPi(candidate1), signalStatus); } // end inner loop (Tracks) - - } // end of outer loop (D0) + } // end of outer loop (D0) + registry.fill(HIST("hZvtx"), collision.posZ()); + registry.fill(HIST("hMultV0M"), collision.multFV0M()); } PROCESS_SWITCH(HfCorrelatorD0Hadrons, processMcRec, "Process MC Reco mode", true); - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // ============================================================================= Process starts for MCGen ================================================================================== - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // ================= Process starts for MCGen, same event =================== - void processMcGen(aod::McCollision const& mccollision, soa::Join const& particlesMC) + void processMcGen(aod::McCollision const& mcCollision, + soa::Join const& mcParticles) { - registry.fill(HIST("hEvtCountGen"), 0); // MC gen level - for (auto const& particle1 : particlesMC) { + for (const auto& particle1 : mcParticles) { // check if the particle is D0 or D0bar (for general plot filling and selection, so both cases are fine) - NOTE: decay channel is not probed! if (std::abs(particle1.pdgCode()) != pdg::Code::kD0) { continue; } - double yD = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yD = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassD0); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -458,14 +586,14 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hPhiGen"), particle1.phi()); registry.fill(HIST("hYGen"), yD); - // D-h correlation dedicated section + // =============== D-h correlation dedicated section ===================== if (std::abs(particle1.pdgCode()) != pdg::Code::kD0) { // just checking the particle PDG, not the decay channel (differently from Reco: you have a BR factor btw such levels!) continue; } registry.fill(HIST("hCountD0TriggersGen"), 0, particle1.pt()); // to count trigger D0 (for normalisation) - for (auto const& particle2 : particlesMC) { + for (const auto& particle2 : mcParticles) { registry.fill(HIST("hTrackCounterGen"), 1); // total no. of tracks if (std::abs(particle2.eta()) > etaTrackMax) { continue; @@ -481,28 +609,268 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hTrackCounterGen"), 2); // fill before soft pi removal // method used: indexMother = -1 by default if the mother doesn't match with given PID of the mother. We find mother of pion if it is D* and mother of D0 if it is D*. If they are both positive and they both match each other, then it is detected as a soft pion - auto indexMotherPi = RecoDecay::getMother(particlesMC, particle2, pdg::Code::kDStar, true, nullptr, 1); // last arguement 1 is written to consider immediate decay mother only - auto indexMotherD0 = RecoDecay::getMother(particlesMC, particle1, pdg::Code::kDStar, true, nullptr, 1); + auto indexMotherPi = RecoDecay::getMother(mcParticles, particle2, pdg::Code::kDStar, true, nullptr, 1); // last arguement 1 is written to consider immediate decay mother only + auto indexMotherD0 = RecoDecay::getMother(mcParticles, particle1, pdg::Code::kDStar, true, nullptr, 1); if (std::abs(particle2.pdgCode()) == kPiPlus && indexMotherPi >= 0 && indexMotherD0 >= 0 && indexMotherPi == indexMotherD0) continue; registry.fill(HIST("hTrackCounterGen"), 3); // fill after soft pion removal + + auto getTracksSize = [&mcParticles](aod::McCollision const& collision) { + int nTracks = 0; + for (const auto& track : mcParticles) { + if (track.isPhysicalPrimary() && std::abs(track.eta()) < 1.0) { + nTracks++; + } + } + return nTracks; + }; + using BinningTypeMcGen = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getTracksSize)>; + BinningTypeMcGen corrBinningMcGen{{getTracksSize}, {zBins, multBinsMcGen}, true}; + int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), getTracksSize(mcCollision))); + entryD0HadronPair(getDeltaPhi(particle2.phi(), particle1.phi()), particle2.eta() - particle1.eta(), particle1.pt(), - particle2.pt()); - entryD0HadronRecoInfo(massD0, - massD0, - 0); // dummy info - } // end inner loop - - } // end outer loop + particle2.pt(), + poolBin); + entryD0HadronRecoInfo(massD0, massD0, 0); // dummy info + } // end inner loop (Tracks) + } // end outer loop (D0) } PROCESS_SWITCH(HfCorrelatorD0Hadrons, processMcGen, "Process MC Gen mode", false); + + // ====================== Implement Event mixing on Data =================================== + + void processDataMixedEvent(SelectedCollisions const& collisions, + SelectedCandidatesData const& candidates, + SelectedTracks const& tracks) + { + auto tracksTuple = std::make_tuple(candidates, tracks); + Pair pairData{corrBinning, 5, -1, collisions, tracksTuple, &cache}; + + for (const auto& [c1, tracks1, c2, tracks2] : pairData) { + // LOGF(info, "Mixed event collisions: Index = (%d, %d), tracks Size: (%d, %d), Z Vertex: (%f, %f), Pool Bin: (%d, %d)", c1.globalIndex(), c2.globalIndex(), tracks1.size(), tracks2.size(), c1.posZ(), c2.posZ(), corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFV0M())),corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M()))); // For debug + int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M())); + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + + if (yCandMax >= 0. && std::abs(hfHelper.yD0(t1)) > yCandMax) { + continue; + } + + // soft pion removal, signal status 1,3 for D0 and 2,3 for D0bar (SoftPi removed), signal status 11,13 for D0 and 12.13 for D0bar (only SoftPi) + auto ePiK = RecoDecay::e(t1.pVectorProng0(), massPi) + RecoDecay::e(t1.pVectorProng1(), massK); + auto eKPi = RecoDecay::e(t1.pVectorProng0(), massK) + RecoDecay::e(t1.pVectorProng1(), massPi); + double invMassDstar1 = 0., invMassDstar2 = 0.; + bool isSoftPiD0 = false, isSoftPiD0bar = false; + auto pSum2 = RecoDecay::p2(t1.px() + t2.px(), t1.py() + t2.py(), t1.pz() + t2.pz()); + auto ePion = t2.energy(massPi); + invMassDstar1 = std::sqrt((ePiK + ePion) * (ePiK + ePion) - pSum2); + invMassDstar2 = std::sqrt((eKPi + ePion) * (eKPi + ePion) - pSum2); + + if (t1.isSelD0() >= selectionFlagD0) { + if ((std::abs(invMassDstar1 - hfHelper.invMassD0ToPiK(t1)) - softPiMass) < ptSoftPionMax) { + isSoftPiD0 = true; + } + } + + if (t1.isSelD0bar() >= selectionFlagD0bar) { + if ((std::abs(invMassDstar2 - hfHelper.invMassD0barToKPi(t1)) - softPiMass) < ptSoftPionMax) { + isSoftPiD0bar = true; + } + } + + int signalStatus = 0; + if (t1.isSelD0() >= selectionFlagD0) { + if (!isSoftPiD0) { + signalStatus += aod::hf_correlation_d0_hadron::ParticleTypeData::D0Only; + } else { + signalStatus += aod::hf_correlation_d0_hadron::ParticleTypeData::D0OnlySoftPi; + } + } + if (t1.isSelD0bar() >= selectionFlagD0bar) { + if (!isSoftPiD0bar) { + signalStatus += aod::hf_correlation_d0_hadron::ParticleTypeData::D0barOnly; + } else { + signalStatus += aod::hf_correlation_d0_hadron::ParticleTypeData::D0barOnlySoftPi; + } + } + + entryD0HadronPair(getDeltaPhi(t1.phi(), t2.phi()), t1.eta() - t2.eta(), t1.pt(), t2.pt(), poolBin); + entryD0HadronRecoInfo(hfHelper.invMassD0ToPiK(t1), hfHelper.invMassD0barToKPi(t1), signalStatus); + } + } + } + PROCESS_SWITCH(HfCorrelatorD0Hadrons, processDataMixedEvent, "Process data mixed event", false); + + // ====================== Implement Event mixing on McRec =================================== + + void processMcRecMixedEvent(SelectedCollisions const& collisions, + SelectedCandidatesMcRec const& candidates, + SelectedTracks const& tracks) + { + auto tracksTuple = std::make_tuple(candidates, tracks); + Pair pairMcRec{corrBinning, 5, -1, collisions, tracksTuple, &cache}; + bool flagD0 = false; + bool flagD0bar = false; + for (const auto& [c1, tracks1, c2, tracks2] : pairMcRec) { + int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M())); + + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + + if (yCandMax >= 0. && std::abs(hfHelper.yD0(t1)) > yCandMax) { + continue; + } + + // soft pion removal + auto ePiK = RecoDecay::e(t1.pVectorProng0(), massPi) + RecoDecay::e(t1.pVectorProng1(), massK); + auto eKPi = RecoDecay::e(t1.pVectorProng0(), massK) + RecoDecay::e(t1.pVectorProng1(), massPi); + double invMassDstar1 = 0., invMassDstar2 = 0.; + bool isSoftPiD0 = false, isSoftPiD0bar = false; + auto pSum2 = RecoDecay::p2(t1.px() + t2.px(), t1.py() + t2.py(), t1.pz() + t2.pz()); + auto ePion = t2.energy(massPi); + invMassDstar1 = std::sqrt((ePiK + ePion) * (ePiK + ePion) - pSum2); + invMassDstar2 = std::sqrt((eKPi + ePion) * (eKPi + ePion) - pSum2); + + if (t1.isSelD0() >= selectionFlagD0) { + if ((std::abs(invMassDstar1 - hfHelper.invMassD0ToPiK(t1)) - softPiMass) < ptSoftPionMax) { + isSoftPiD0 = true; + } + } + + if (t1.isSelD0bar() >= selectionFlagD0bar) { + if ((std::abs(invMassDstar2 - hfHelper.invMassD0barToKPi(t1)) - softPiMass) < ptSoftPionMax) { + isSoftPiD0bar = true; + } + } + + flagD0 = t1.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Signal 'true' if candidate1 matched to D0 (particle) + flagD0bar = t1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) + int signalStatus = 0; + + if (flagD0 && (t1.isSelD0() >= selectionFlagD0)) { + if (!isSoftPiD0) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0Sig); // signalStatus += 1; + } else { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::SoftPi); // signalStatus += 64; + } + } // signal case D0 + + if (flagD0bar && (t1.isSelD0() >= selectionFlagD0)) { + if (!isSoftPiD0) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0Ref); // signalStatus += 2; + } else { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::SoftPi); // signalStatus += 64; + } + } // reflection case D0 + + if (!flagD0 && !flagD0bar && (t1.isSelD0() >= selectionFlagD0)) { + if (!isSoftPiD0) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0Bg); // signalStatus += 4; + } else { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::SoftPi); + } + } // background case D0 + + if (flagD0bar && (t1.isSelD0bar() >= selectionFlagD0bar)) { + if (!isSoftPiD0bar) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0barSig); // signalStatus += 8; + } else { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::SoftPi); + } + } // signal case D0bar + + if (flagD0 && (t1.isSelD0bar() >= selectionFlagD0bar)) { + if (!isSoftPiD0bar) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0barRef); // signalStatus += 16; + } else { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::SoftPi); + } + } // reflection case D0bar + + if (!flagD0 && !flagD0bar && (t1.isSelD0bar() >= selectionFlagD0bar)) { + if (!isSoftPiD0bar) { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::D0barBg); // signalStatus += 32; + } else { + SETBIT(signalStatus, aod::hf_correlation_d0_hadron::ParticleTypeMcRec::SoftPi); + } + } // background case D0bar + + registry.fill(HIST("hSignalStatusMERec"), signalStatus); + entryD0HadronPair(getDeltaPhi(t1.phi(), t2.phi()), t1.eta() - t2.eta(), t1.pt(), t2.pt(), poolBin); + entryD0HadronRecoInfo(hfHelper.invMassD0ToPiK(t1), hfHelper.invMassD0barToKPi(t1), signalStatus); + } + } + } + PROCESS_SWITCH(HfCorrelatorD0Hadrons, processMcRecMixedEvent, "Process Mixed Event MCRec", false); + + // ====================== Implement Event mixing on McGen =================================== + + void processMcGenMixedEvent(SelectedCollisionsMcGen const& collisions, + SelectedTracksMcGen const& mcParticles) + { + + auto getTracksSize = [&mcParticles, this](SelectedCollisionsMcGen::iterator const& collision) { + int nTracks = 0; + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, collision.globalIndex(), this->cache); + for (const auto& track : associatedTracks) { + if (track.isPhysicalPrimary() && std::abs(track.eta()) < 1.0) { + nTracks++; + } + } + return nTracks; + }; + + using BinningTypeMcGen = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getTracksSize)>; + BinningTypeMcGen corrBinningMcGen{{getTracksSize}, {zBins, multBins}, true}; + + auto tracksTuple = std::make_tuple(mcParticles, mcParticles); + Pair pairMcGen{corrBinningMcGen, 5, -1, collisions, tracksTuple, &cache}; + + for (const auto& [c1, tracks1, c2, tracks2] : pairMcGen) { + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + + // Check track t1 is D0 + if (std::abs(t1.pdgCode()) != pdg::Code::kD0) { + continue; + } + + double yD = RecoDecay::y(std::array{t1.px(), t1.py(), t1.pz()}, o2::analysis::pdg::MassD0); + if (yCandMax >= 0. && std::abs(yD) > yCandMax) { + continue; + } + if (ptCandMin >= 0. && t1.pt() < ptCandMin) { + continue; + } + + if (std::abs(t2.eta()) > etaTrackMax) { + continue; + } + if (t2.pt() < ptTrackMin) { + continue; + } + + // ==============================soft pion removal================================ + // method used: indexMother = -1 by default if the mother doesn't match with given PID of the mother. We find mother of pion if it is D* and mother of D0 if it is D*. If they are both positive and they both match each other, then it is detected as a soft pion + + auto indexMotherPi = RecoDecay::getMother(mcParticles, t2, pdg::Code::kDStar, true, nullptr, 1); // last arguement 1 is written to consider immediate decay mother only + auto indexMotherD0 = RecoDecay::getMother(mcParticles, t1, pdg::Code::kDStar, true, nullptr, 1); + if (std::abs(t2.pdgCode()) == kPiPlus && indexMotherPi >= 0 && indexMotherD0 >= 0 && indexMotherPi == indexMotherD0) { + continue; + } + int poolBin = corrBinningMcGen.getBin(std::make_tuple(c2.posZ(), getTracksSize(c2))); + entryD0HadronPair(getDeltaPhi(t2.phi(), t1.phi()), t2.eta() - t1.eta(), t1.pt(), t2.pt(), poolBin); + entryD0HadronRecoInfo(massD0, massD0, 0); // dummy info + } + } + } + PROCESS_SWITCH(HfCorrelatorD0Hadrons, processMcGenMixedEvent, "Process Mixed Event MCGen", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index 4cdfbf2bd59..16209d40c32 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -15,23 +15,22 @@ /// \author Fabio Colamaria , INFN Bari /// \author Andrea Tavira García , IJCLab Orsay -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/DMesonPairsTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::constants::math; /// /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies @@ -95,6 +94,8 @@ struct HfCorrelatorDMesonPairs { Configurable multMax{"multMax", 10000., "maximum multiplicity accepted"}; Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits for candidate mass plots"}; + HfHelper hfHelper; + Partition> selectedD0Candidates = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; Partition> selectedD0CandidatesMc = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; @@ -138,7 +139,7 @@ struct HfCorrelatorDMesonPairs { {"hMatchedMcGen", "D Meson pair candidates - MC gen;MC Matched;entries", hTH1Matched}, {"hOriginMcGen", "D Meson pair candidates - MC gen;prompt vs. non-prompt;entries", hTH1Origin}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; constexpr int kNBinsSelStatus = 6; @@ -189,14 +190,14 @@ struct HfCorrelatorDMesonPairs { if (!(TESTBIT(candidate.hfflag(), o2::aod::hf_cand_2prong::DecayType::D0ToPiK))) { return false; } - if (yCandMax >= 0. && std::abs(candidate.y(RecoDecay::getMassPDG(pdg::Code::kD0))) > yCandMax) { + if (yCandMax >= 0. && std::abs(candidate.y(o2::analysis::pdg::MassD0)) > yCandMax) { return false; } } else { if (!(TESTBIT(candidate.hfflag(), o2::aod::hf_cand_3prong::DecayType::DplusToPiKPi))) { return false; } - if (yCandMax >= 0. && std::abs(candidate.y(RecoDecay::getMassPDG(pdg::Code::kDPlus))) > yCandMax) { + if (yCandMax >= 0. && std::abs(candidate.y(o2::analysis::pdg::MassDPlus)) > yCandMax) { return false; } } @@ -234,9 +235,9 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hEtaMcRec"), candidate.eta()); registry.fill(HIST("hPhiMcRec"), candidate.phi()); if (isD0) { - registry.fill(HIST("hYMcRec"), candidate.y(RecoDecay::getMassPDG(pdg::Code::kD0))); + registry.fill(HIST("hYMcRec"), candidate.y(o2::analysis::pdg::MassD0)); } else { - registry.fill(HIST("hYMcRec"), candidate.y(RecoDecay::getMassPDG(pdg::Code::kDPlus))); + registry.fill(HIST("hYMcRec"), candidate.y(o2::analysis::pdg::MassDPlus)); } } else { registry.fill(HIST("hPtCand"), candidate.pt()); @@ -245,9 +246,9 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hEta"), candidate.eta()); registry.fill(HIST("hPhi"), candidate.phi()); if (isD0) { - registry.fill(HIST("hY"), candidate.y(RecoDecay::getMassPDG(pdg::Code::kD0))); + registry.fill(HIST("hY"), candidate.y(o2::analysis::pdg::MassD0)); } else { - registry.fill(HIST("hY"), candidate.y(RecoDecay::getMassPDG(pdg::Code::kDPlus))); + registry.fill(HIST("hY"), candidate.y(o2::analysis::pdg::MassDPlus)); } } } @@ -324,15 +325,17 @@ struct HfCorrelatorDMesonPairs { // Common code to analyse D0's and D+'s at Gen level. template - void analyseMcGen(const T& particlesMc) + void analyseMcGen(const T& mcParticles) { registry.fill(HIST("hMcEvtCount"), 0); - for (const auto& particle1 : particlesMc) { + for (const auto& particle1 : mcParticles) { // check if the particle is D0, D0bar, DPlus or DMinus (for general plot filling and selection, so both cases are fine) - NOTE: decay channel is not probed! - if (std::abs(particle1.pdgCode()) != pdg::Code::kD0 && std::abs(particle1.pdgCode()) != pdg::Code::kDPlus) { + auto pdgCode = std::abs(particle1.pdgCode()); + if (pdgCode != pdg::Code::kD0 && pdgCode != pdg::Code::kDPlus) { continue; } - double yD = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + auto massD = pdgCode == pdg::Code::kD0 ? o2::analysis::pdg::MassD0 : o2::analysis::pdg::MassDPlus; + double yD = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, massD); if (!kinematicCutsGen(particle1)) { continue; } @@ -351,7 +354,7 @@ struct HfCorrelatorDMesonPairs { int8_t matchedGen1 = particle1.flagMcMatchGen(); registry.fill(HIST("hMatchedMcGen"), matchedGen1); - for (const auto& particle2 : particlesMc) { + for (const auto& particle2 : mcParticles) { // Candidate sign attribution. auto candidateType2 = assignCandidateTypeGen(particle2); if (!kinematicCutsGen(particle2)) { @@ -371,8 +374,8 @@ struct HfCorrelatorDMesonPairs { particle2.pt(), particle1.y(), particle2.y(), - RecoDecay::getMassPDG(pdg::Code::kD0), - RecoDecay::getMassPDG(pdg::Code::kD0), + o2::analysis::pdg::MassD0, + o2::analysis::pdg::MassD0, candidateType1, candidateType2, 2); @@ -388,8 +391,8 @@ struct HfCorrelatorDMesonPairs { particle2.pt(), particle1.y(), particle2.y(), - RecoDecay::getMassPDG(pdg::Code::kDPlus), - RecoDecay::getMassPDG(pdg::Code::kDPlus), + o2::analysis::pdg::MassDPlus, + o2::analysis::pdg::MassDPlus, candidateType1, candidateType2, 2); @@ -403,7 +406,9 @@ struct HfCorrelatorDMesonPairs { } /// D0(bar)-D0(bar) correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processDataD0(aod::Collision const& collision, soa::Join& tracks, soa::Join const&) + void processDataD0(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const&) { // protection against empty tables to be sliced if (selectedD0Candidates.size() <= 1) { @@ -417,7 +422,7 @@ struct HfCorrelatorDMesonPairs { continue; } - registry.fill(HIST("hMass"), invMassD0ToPiK(candidate1), candidate1.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution. for (const auto& candidate2 : selectedD0CandidatesGrouped) { @@ -435,10 +440,10 @@ struct HfCorrelatorDMesonPairs { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt(), - yD0(candidate1), - yD0(candidate2), - invMassD0ToPiK(candidate1), - invMassD0barToKPi(candidate2), + hfHelper.yD0(candidate1), + hfHelper.yD0(candidate2), + hfHelper.invMassD0ToPiK(candidate1), + hfHelper.invMassD0barToKPi(candidate2), candidateType1, candidateType2, 0); @@ -448,7 +453,9 @@ struct HfCorrelatorDMesonPairs { PROCESS_SWITCH(HfCorrelatorDMesonPairs, processDataD0, "Process data D0", true); /// D0(bar)-D0(bar) correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) - void processMcRecD0(aod::Collision const& collision, soa::Join& tracks, soa::Join const&) + void processMcRecD0(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const&) { // protection against empty tables to be sliced if (selectedD0CandidatesMc.size() <= 1) { @@ -464,7 +471,7 @@ struct HfCorrelatorDMesonPairs { fillInfoHists(candidate1, true, true); } - registry.fill(HIST("hMass"), invMassD0ToPiK(candidate1), candidate1.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); auto candidateType1 = assignCandidateTypeD0(candidate1); // Candidate type attribution int8_t origin1 = 0, matchedRec1 = 0; @@ -500,10 +507,10 @@ struct HfCorrelatorDMesonPairs { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt(), - yD0(candidate1), - yD0(candidate2), - invMassD0ToPiK(candidate1), - invMassD0barToKPi(candidate2), + hfHelper.yD0(candidate1), + hfHelper.yD0(candidate2), + hfHelper.invMassD0ToPiK(candidate1), + hfHelper.invMassD0barToKPi(candidate2), candidateType1, candidateType2, 1); @@ -518,15 +525,18 @@ struct HfCorrelatorDMesonPairs { PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcRecD0, "Process D0 Mc Reco mode", false); /// D0(bar)-D0(bar) correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGenD0(aod::McCollision const&, McParticlesPlus2Prong const& particlesMc) + void processMcGenD0(aod::McCollision const&, + McParticlesPlus2Prong const& mcParticles) { - analyseMcGen(particlesMc); + analyseMcGen(mcParticles); } PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcGenD0, "Process D0 Mc Gen mode", false); /// Dplus(minus)-Dplus(minus) correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processDataDPlus(aod::Collision const& collision, soa::Join& tracks, soa::Join const&, aod::BigTracks const&) + void processDataDPlus(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const&) { // protection against empty tables to be sliced if (selectedDPlusCandidates.size() <= 1) { @@ -540,14 +550,14 @@ struct HfCorrelatorDMesonPairs { } int outerParticleSign = 1; // Dplus - auto outerSecondTrack = candidate1.prong1_as(); + auto outerSecondTrack = candidate1.prong1(); if (outerSecondTrack.sign() == 1) { outerParticleSign = -1; // Dminus (second daughter track is positive) } auto candidateType1 = assignCandidateTypeDPlus(candidate1, outerParticleSign); fillInfoHists(candidate1, false, false); - registry.fill(HIST("hMass"), invMassDplusToPiKPi(candidate1), candidate1.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt()); for (const auto& candidate2 : selectedDPlusCandidatesGrouped) { if (!kinematicCuts(candidate2)) { @@ -559,7 +569,7 @@ struct HfCorrelatorDMesonPairs { } int innerParticleSign = 1; // Dplus - auto innerSecondTrack = candidate2.prong1_as(); + auto innerSecondTrack = candidate2.prong1(); if (innerSecondTrack.sign() == 1) { innerParticleSign = -1; // Dminus (second daughter track is positive) } @@ -570,10 +580,10 @@ struct HfCorrelatorDMesonPairs { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt(), - yDplus(candidate1), - yDplus(candidate2), - invMassDplusToPiKPi(candidate1), - invMassDplusToPiKPi(candidate2), + hfHelper.yDplus(candidate1), + hfHelper.yDplus(candidate2), + hfHelper.invMassDplusToPiKPi(candidate1), + hfHelper.invMassDplusToPiKPi(candidate2), candidateType1, candidateType2, 0); @@ -584,7 +594,9 @@ struct HfCorrelatorDMesonPairs { PROCESS_SWITCH(HfCorrelatorDMesonPairs, processDataDPlus, "Process Data DPlus", false); /// Dplus(minus)-Dplus(minus) correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) - void processMcRecDPlus(aod::Collision const& collision, soa::Join& tracks, soa::Join const&, aod::BigTracks const&) + void processMcRecDPlus(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const&) { // protection against empty tables to be sliced if (selectedDPlusCandidatesMc.size() <= 1) { @@ -598,13 +610,13 @@ struct HfCorrelatorDMesonPairs { } int outerParticleSign = 1; // Dplus - auto outerSecondTrack = candidate1.prong1_as(); + auto outerSecondTrack = candidate1.prong1(); if (outerSecondTrack.sign() == 1) { outerParticleSign = -1; // Dminus (second daughter track is positive) } auto candidateType1 = assignCandidateTypeDPlus(candidate1, outerParticleSign); - registry.fill(HIST("hMass"), invMassDplusToPiKPi(candidate1), candidate1.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt()); int8_t origin1 = 0, matchedRec1 = 0; if (!(TESTBIT(candidateType1, TrueD) && TESTBIT(candidateType1, TrueDbar))) { // if our event is not bkg @@ -626,7 +638,7 @@ struct HfCorrelatorDMesonPairs { } int innerParticleSign = 1; // Dplus - auto innerSecondTrack = candidate2.prong1_as(); + auto innerSecondTrack = candidate2.prong1(); if (innerSecondTrack.sign() == 1) { innerParticleSign = -1; // Dminus (second daughter track is positive) } @@ -645,10 +657,10 @@ struct HfCorrelatorDMesonPairs { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt(), - yDplus(candidate1), - yDplus(candidate2), - invMassDplusToPiKPi(candidate1), - invMassDplusToPiKPi(candidate2), + hfHelper.yDplus(candidate1), + hfHelper.yDplus(candidate2), + hfHelper.invMassDplusToPiKPi(candidate1), + hfHelper.invMassDplusToPiKPi(candidate2), candidateType1, candidateType2, 1); @@ -663,9 +675,10 @@ struct HfCorrelatorDMesonPairs { PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcRecDPlus, "Process DPlus Mc Reco", false); /// Dplus(minus)-Dplus(minus) correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGenDPlus(aod::McCollision const&, McParticlesPlus3Prong const& particlesMc) + void processMcGenDPlus(aod::McCollision const&, + McParticlesPlus3Prong const& mcParticles) { - analyseMcGen(particlesMc); + analyseMcGen(mcParticles); } PROCESS_SWITCH(HfCorrelatorDMesonPairs, processMcGenDPlus, "Process DPlus Mc Gen mode", false); diff --git a/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx b/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx index e6a13505024..72ff78a8e8b 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx @@ -14,22 +14,22 @@ /// /// \author Fabio Colamaria , INFN Bari -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_correlation_d_dbar; -using namespace o2::analysis::hf_cuts_dplus_to_pi_k_pi; -using namespace o2::constants::math; /// /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies @@ -64,13 +64,10 @@ const int ptDAxisBins = 180; const double ptDAxisMin = 0.; const double ptDAxisMax = 36.; -using MCParticlesPlus2Prong = soa::Join; -using MCParticlesPlus3Prong = soa::Join; +using McParticlesPlus2Prong = soa::Join; +using McParticlesPlus3Prong = soa::Join; struct HfCorrelatorDplusDminus { - SliceCache cache; - Preslice perCol = aod::hf_cand::collisionId; - Produces entryDplusDminusPair; Produces entryDplusDminusRecoInfo; @@ -83,6 +80,11 @@ struct HfCorrelatorDplusDminus { Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots and efficiency"}; Configurable> efficiencyD{"efficiencyD", std::vector{efficiencyDmeson_v}, "Efficiency values for Dplus meson"}; + HfHelper hfHelper; + SliceCache cache; + + Preslice perCol = aod::hf_cand::collisionId; + Partition> selectedDPlusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; Partition> selectedDPlusCandidatesMC = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; @@ -118,7 +120,7 @@ struct HfCorrelatorDplusDminus { {"hCountCCbarPerEvent", "c,cbar particles - MC gen;Number per event;entries", {HistType::kTH1F, {{20, 0., 20.}}}}, {"hCountCCbarPerEventBeforeEtaCut", "c,cbar particles - MC gen;Number per event pre #eta cut;entries", {HistType::kTH1F, {{20, 0., 20.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMass", "Dplus,Dminus candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -133,7 +135,9 @@ struct HfCorrelatorDplusDminus { } /// Dplus-Dminus correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processData(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates, aod::BigTracks const& bigtracks) + void processData(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const& candidates) { int nTracks = 0; if (collision.numContrib() > 1) { @@ -155,15 +159,15 @@ struct HfCorrelatorDplusDminus { auto selectedDPlusCandidatesGrouped = selectedDPlusCandidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto& candidate1 : selectedDPlusCandidatesGrouped) { - if (yCandMax >= 0. && std::abs(yDplus(candidate1)) > yCandMax) { + for (const auto& candidate1 : selectedDPlusCandidatesGrouped) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { continue; } // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::DplusToPiKPi)) { // probably dummy since already selected? not sure... + if (!(candidate1.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { // probably dummy since already selected? not sure... continue; } @@ -173,18 +177,18 @@ struct HfCorrelatorDplusDminus { } int outerParticleSign = 1; // Dplus - auto outerSecondTrack = candidate1.prong1_as(); + auto outerSecondTrack = candidate1.prong1_as(); if (outerSecondTrack.sign() == 1) { outerParticleSign = -1; // Dminus (second daughter track is positive) } // fill invariant mass plots and generic info from all Dplus/Dminus candidates if (outerParticleSign == 1) { - registry.fill(HIST("hMass"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMassDplus"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDplus"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { - registry.fill(HIST("hMass"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMassDminus"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDminus"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); } registry.fill(HIST("hPtCand"), candidate1.pt()); registry.fill(HIST("hPtProng0"), candidate1.ptProng0()); @@ -192,7 +196,7 @@ struct HfCorrelatorDplusDminus { registry.fill(HIST("hPtProng2"), candidate1.ptProng2()); registry.fill(HIST("hEta"), candidate1.eta()); registry.fill(HIST("hPhi"), candidate1.phi()); - registry.fill(HIST("hY"), yDplus(candidate1)); + registry.fill(HIST("hY"), hfHelper.yDplus(candidate1)); registry.fill(HIST("hSelectionStatus"), candidate1.isSelDplusToPiKPi()); // D-Dbar correlation dedicated section @@ -200,16 +204,16 @@ struct HfCorrelatorDplusDminus { if (outerParticleSign != 1) { continue; } - for (auto& candidate2 : selectedDPlusCandidatesGrouped) { + for (const auto& candidate2 : selectedDPlusCandidatesGrouped) { // check decay channel flag for candidate2 - if (!(candidate2.hfflag() & 1 << DecayType::DplusToPiKPi)) { // probably dummy since already selected? not sure... + if (!(candidate2.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { // probably dummy since already selected? not sure... continue; } - auto innerSecondTrack = candidate2.prong1_as(); + auto innerSecondTrack = candidate2.prong1_as(); if (innerSecondTrack.sign() != 1) { // keep only Dminus (with second daughter track positive) continue; } - if (yCandMax >= 0. && std::abs(yDplus(candidate2)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate2)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { @@ -219,8 +223,8 @@ struct HfCorrelatorDplusDminus { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt()); - entryDplusDminusRecoInfo(invMassDplusToPiKPi(candidate1), - invMassDplusToPiKPi(candidate2), + entryDplusDminusRecoInfo(hfHelper.invMassDplusToPiKPi(candidate1), + hfHelper.invMassDplusToPiKPi(candidate2), 0); double etaCut = 0.; double ptCut = 0.; @@ -237,11 +241,12 @@ struct HfCorrelatorDplusDminus { } // end inner loop (Dminus) } // end outer loop (Dplus) } - PROCESS_SWITCH(HfCorrelatorDplusDminus, processData, "Process data", false); /// Dplus-Dminus correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) - void processMcRec(aod::Collision const& collision, soa::Join& tracks, soa::Join const& candidates, aod::BigTracks const& bigtracks) + void processMcRec(aod::Collision const& collision, + aod::TracksWDca const& tracks, + soa::Join const& candidates) { int nTracks = 0; if (collision.numContrib() > 1) { @@ -266,12 +271,12 @@ struct HfCorrelatorDplusDminus { // MC reco level bool flagDplusSignal = false; bool flagDminusSignal = false; - for (auto& candidate1 : selectedDPlusCandidatesGroupedMC) { + for (const auto& candidate1 : selectedDPlusCandidatesGroupedMC) { // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::DplusToPiKPi)) { + if (!(candidate1.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { continue; } - if (yCandMax >= 0. && std::abs(yDplus(candidate1)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { @@ -284,16 +289,16 @@ struct HfCorrelatorDplusDminus { } int outerParticleSign = 1; // Dplus - auto outerSecondTrack = candidate1.prong1_as(); + auto outerSecondTrack = candidate1.prong1_as(); if (outerSecondTrack.sign() == 1) { outerParticleSign = -1; // Dminus (second daughter track is positive) } - if (std::abs(candidate1.flagMcMatchRec()) == 1 << DecayType::DplusToPiKPi) { + if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { // fill invariant mass plots and per-candidate distributions from Dplus/Dminus signal candidates if (outerParticleSign == 1) { // reco and matched as Dplus - registry.fill(HIST("hMassDplusMCRecSig"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDplusMCRecSig"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { // reco and matched as Dminus - registry.fill(HIST("hMassDminusMCRecSig"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDminusMCRecSig"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); } registry.fill(HIST("hPtCandMCRec"), candidate1.pt()); registry.fill(HIST("hPtProng0MCRec"), candidate1.ptProng0()); @@ -301,14 +306,14 @@ struct HfCorrelatorDplusDminus { registry.fill(HIST("hPtProng2MCRec"), candidate1.ptProng2()); registry.fill(HIST("hEtaMCRec"), candidate1.eta()); registry.fill(HIST("hPhiMCRec"), candidate1.phi()); - registry.fill(HIST("hYMCRec"), yDplus(candidate1)); + registry.fill(HIST("hYMCRec"), hfHelper.yDplus(candidate1)); registry.fill(HIST("hSelectionStatusMCRec"), candidate1.isSelDplusToPiKPi()); } else { // fill invariant mass plots from Dplus/Dminus background candidates if (outerParticleSign == 1) { // reco as Dplus - registry.fill(HIST("hMassDplusMCRecBkg"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDplusMCRecBkg"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { // matched as Dminus - registry.fill(HIST("hMassDminusMCRecBkg"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDminusMCRecBkg"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); } } @@ -316,17 +321,17 @@ struct HfCorrelatorDplusDminus { if (outerParticleSign == -1) { continue; // reject Dminus in outer loop } - flagDplusSignal = std::abs(candidate1.flagMcMatchRec()) == 1 << DecayType::DplusToPiKPi; // flagDplusSignal 'true' if candidate1 matched to Dplus - for (auto& candidate2 : selectedDPlusCandidatesGroupedMC) { - if (!(candidate2.hfflag() & 1 << DecayType::DplusToPiKPi)) { // check decay channel flag for candidate2 + flagDplusSignal = std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; // flagDplusSignal 'true' if candidate1 matched to Dplus + for (const auto& candidate2 : selectedDPlusCandidatesGroupedMC) { + if (!(candidate2.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { // check decay channel flag for candidate2 continue; } - auto innerSecondTrack = candidate2.prong1_as(); + auto innerSecondTrack = candidate2.prong1_as(); if (innerSecondTrack.sign() != 1) { // keep only Dminus (with second daughter track positive) continue; } - flagDminusSignal = std::abs(candidate2.flagMcMatchRec()) == 1 << DecayType::DplusToPiKPi; // flagDminusSignal 'true' if candidate2 matched to Dminus - if (yCandMax >= 0. && std::abs(yDplus(candidate2)) > yCandMax) { + flagDminusSignal = std::abs(candidate2.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; // flagDminusSignal 'true' if candidate2 matched to Dminus + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate2)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate2.pt() < ptCandMin) { @@ -344,8 +349,8 @@ struct HfCorrelatorDplusDminus { candidate2.eta() - candidate1.eta(), candidate1.pt(), candidate2.pt()); - entryDplusDminusRecoInfo(invMassDplusToPiKPi(candidate1), - invMassDplusToPiKPi(candidate2), + entryDplusDminusRecoInfo(hfHelper.invMassDplusToPiKPi(candidate1), + hfHelper.invMassDplusToPiKPi(candidate2), pairSignalStatus); double etaCut = 0.; double ptCut = 0.; @@ -363,21 +368,21 @@ struct HfCorrelatorDplusDminus { } // end outer loop } - PROCESS_SWITCH(HfCorrelatorDplusDminus, processMcRec, "Process MC Reco mode", true); /// Dplus-Dminus correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGen(aod::McCollision const& mccollision, MCParticlesPlus3Prong const& particlesMC) + void processMcGen(aod::McCollision const& mcCollision, + McParticlesPlus3Prong const& mcParticles) { int counterDplusDminus = 0; registry.fill(HIST("hMCEvtCount"), 0); // MC gen level - for (auto& particle1 : particlesMC) { + for (const auto& particle1 : mcParticles) { // check if the particle is Dplus or Dminus (for general plot filling and selection, so both cases are fine) - NOTE: decay channel is not probed! if (std::abs(particle1.pdgCode()) != pdg::Code::kDPlus) { continue; } - double yD = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yD = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassDPlus); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -396,11 +401,11 @@ struct HfCorrelatorDplusDminus { continue; } registry.fill(HIST("hCountDplustriggersMCGen"), 0, particle1.pt()); // to count trigger Dplus (for normalisation) - for (auto& particle2 : particlesMC) { + for (const auto& particle2 : mcParticles) { if (particle2.pdgCode() != -pdg::Code::kDPlus) { // check that inner particle is a Dminus continue; } - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle2.px(), particle2.py(), particle2.pz()}, RecoDecay::getMassPDG(particle2.pdgCode()))) > yCandMax) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle2.px(), particle2.py(), particle2.pz()}, o2::analysis::pdg::MassDPlus)) > yCandMax) { continue; } if (ptCandMin >= 0. && particle2.pt() < ptCandMin) { @@ -410,15 +415,15 @@ struct HfCorrelatorDplusDminus { particle2.eta() - particle1.eta(), particle1.pt(), particle2.pt()); - entryDplusDminusRecoInfo(1.869, - 1.869, + entryDplusDminusRecoInfo(o2::analysis::pdg::MassDPlus, + o2::analysis::pdg::MassDPlus, 8); // Dummy double etaCut = 0.; double ptCut = 0.; // fill pairs vs etaCut plot bool rightDecayChannels = false; - if ((std::abs(particle1.flagMcMatchGen()) == 1 << DecayType::DplusToPiKPi) && (std::abs(particle2.flagMcMatchGen()) == 1 << DecayType::DplusToPiKPi)) { + if ((std::abs(particle1.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) && (std::abs(particle2.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { rightDecayChannels = true; } do { @@ -431,13 +436,13 @@ struct HfCorrelatorDplusDminus { if (rightDecayChannels) { // fill with D and Dbar daughter particls acceptance checks bool candidate1DauInAcc = true; bool candidate2DauInAcc = true; - for (auto& dau : particle1.daughters_as()) { + for (const auto& dau : particle1.daughters_as()) { if (std::abs(dau.eta()) > etaCut) { candidate1DauInAcc = false; break; } } - for (auto& dau : particle2.daughters_as()) { + for (const auto& dau : particle2.daughters_as()) { if (std::abs(dau.eta()) > etaCut) { candidate2DauInAcc = false; break; @@ -454,27 +459,27 @@ struct HfCorrelatorDplusDminus { } // end outer loop registry.fill(HIST("hCountDplusDminusPerEvent"), counterDplusDminus); } - PROCESS_SWITCH(HfCorrelatorDplusDminus, processMcGen, "Process MC Gen mode", false); /// c-cbar correlator table builder - for MC gen-level analysis - void processCCbar(aod::McCollision const& mccollision, MCParticlesPlus2Prong const& particlesMC) + void processCCbar(aod::McCollision const& mcCollision, + McParticlesPlus2Prong const& mcParticles) { registry.fill(HIST("hMCEvtCount"), 0); int counterCCbar = 0, counterCCbarBeforeEtasel = 0; // loop over particles at MC gen level - for (auto& particle1 : particlesMC) { + for (const auto& particle1 : mcParticles) { if (std::abs(particle1.pdgCode()) != PDG_t::kCharm) { // search c or cbar particles continue; } - int partMothPDG = particle1.mothers_as().front().pdgCode(); + int partMothPDG = particle1.mothers_as().front().pdgCode(); // check whether mothers of quark c/cbar are still '4'/'-4' particles - in that case the c/cbar quark comes from its own fragmentation, skip it if (partMothPDG == particle1.pdgCode()) { continue; } counterCCbarBeforeEtasel++; // count c or cbar (before kinematic selection) - double yC = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yC = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassCharm); if (yCandMax >= 0. && std::abs(yC) > yCandMax) { continue; } @@ -494,18 +499,18 @@ struct HfCorrelatorDplusDminus { } registry.fill(HIST("hCountCtriggersMCGen"), 0, particle1.pt()); // to count trigger c quark (for normalisation) - for (auto& particle2 : particlesMC) { + for (const auto& particle2 : mcParticles) { if (particle2.pdgCode() != PDG_t::kCharmBar) { continue; } - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle2.px(), particle2.py(), particle2.pz()}, RecoDecay::getMassPDG(particle2.pdgCode()))) > yCandMax) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle2.px(), particle2.py(), particle2.pz()}, o2::analysis::pdg::MassCharmBar)) > yCandMax) { continue; } if (ptCandMin >= 0. && particle2.pt() < ptCandMin) { continue; } // check whether mothers of quark cbar (from associated loop) are still '-4' particles - in that case the cbar quark comes from its own fragmentation, skip it - if (particle2.mothers_as().front().pdgCode() == PDG_t::kCharmBar) { + if (particle2.mothers_as().front().pdgCode() == PDG_t::kCharmBar) { continue; } entryDplusDminusPair(getDeltaPhi(particle2.phi(), particle1.phi()), @@ -520,7 +525,6 @@ struct HfCorrelatorDplusDminus { registry.fill(HIST("hCountCCbarPerEvent"), counterCCbar); registry.fill(HIST("hCountCCbarPerEventBeforeEtaCut"), counterCCbarBeforeEtasel); } - PROCESS_SWITCH(HfCorrelatorDplusDminus, processCCbar, "Process c-cbar pairs", false); }; diff --git a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx index 5d1d5d9efbc..28aa06a3b01 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx @@ -12,25 +12,25 @@ /// \file correlatorDplusHadrons.cxx /// \author Shyam Kumar +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + #include "Common/Core/TrackSelection.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_correlation_dplus_hadron; -using namespace o2::analysis::hf_cuts_dplus_to_pi_k_pi; -using namespace o2::constants::math; /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies @@ -41,8 +41,7 @@ double getDeltaPhi(double phiD, double phiHadron) /// definition of variables for Dplus hadron pairs (in data-like, MC-reco and MC-kine tasks) const int npTBinsMassAndEfficiency = o2::analysis::hf_cuts_dplus_to_pi_k_pi::nBinsPt; -const double efficiencyDmesonDefault[npTBinsMassAndEfficiency] = {}; -auto efficiencyDmeson_v = std::vector{efficiencyDmesonDefault, efficiencyDmesonDefault + npTBinsMassAndEfficiency}; +std::vector efficiencyDmeson(npTBinsMassAndEfficiency + 1); // histogram binning definition const int massAxisBins = 350; @@ -67,23 +66,27 @@ BinningType corrBinning{{zBins, multBins}, true}; // Code to select a Dmeson in a collision struct HfDplusSelection { - SliceCache cache; Produces dplusSel; - Configurable selectionFlagDplus{"selectionFlagDplus", 1, "Selection Flag for Dplus"}; + + Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for Dplus"}; // 7 corresponds to topo+PID cuts Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; + HfHelper hfHelper; + SliceCache cache; + Partition> selectedDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Partition> recoFlagDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition> selectedDplusCandidatesMc = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - void processDplusSelectionData(aod::Collision const& collision, soa::Join const& candidates) + void processDplusSelectionData(aod::Collision const& collision, + soa::Join const& candidates) { bool isDplusFound = 0; if (selectedDplusCandidates.size() > 0) { auto selectedDplusCandidatesGrouped = selectedDplusCandidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto const& candidate1 : selectedDplusCandidatesGrouped) { - if (yCandMax >= 0. && std::abs(yDplus(candidate1)) > yCandMax) { + for (const auto& candidate1 : selectedDplusCandidatesGrouped) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { @@ -97,17 +100,18 @@ struct HfDplusSelection { } PROCESS_SWITCH(HfDplusSelection, processDplusSelectionData, "Process Dplus Selection Data", false); - void processDplusSelectionMcRec(aod::Collision const& collision, soa::Join const& candidates) + void processDplusSelectionMcRec(aod::Collision const& collision, + soa::Join const& candidates) { bool isDplusFound = 0; - if (recoFlagDplusCandidates.size() > 0) { - auto selectedDplusCandidatesGroupedMc = recoFlagDplusCandidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto const& candidate1 : selectedDplusCandidatesGroupedMc) { + if (selectedDplusCandidatesMc.size() > 0) { + auto selectedDplusCandidatesMcGrouped = selectedDplusCandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + for (const auto& candidate1 : selectedDplusCandidatesMcGrouped) { // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::DplusToPiKPi)) { + if (!(candidate1.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { continue; } - if (yCandMax >= 0. && std::abs(yDplus(candidate1)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { @@ -121,14 +125,15 @@ struct HfDplusSelection { } PROCESS_SWITCH(HfDplusSelection, processDplusSelectionMcRec, "Process Dplus Selection MCRec", false); - void processDplusSelectionMcGen(aod::McCollision const& mcCollision, aod::McParticles const& particlesMc) + void processDplusSelectionMcGen(aod::McCollision const& mcCollision, + aod::McParticles const& mcParticles) { bool isDplusFound = 0; - for (auto const& particle1 : particlesMc) { + for (const auto& particle1 : mcParticles) { if (std::abs(particle1.pdgCode()) != pdg::Code::kDPlus) { continue; } - double yD = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yD = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassDPlus); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -145,12 +150,10 @@ struct HfDplusSelection { /// Dplus-Hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) struct HfCorrelatorDplusHadrons { - SliceCache cache; - Preslice perCol = aod::hf_cand::collisionId; - Produces entryDplusHadronPair; Produces entryDplusHadronRecoInfo; - Configurable selectionFlagDplus{"selectionFlagDplus", 1, "Selection Flag for Dplus"}; + + Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for Dplus"}; // 7 corresponds to topo+PID cuts Configurable applyEfficiency{"applyEfficiency", 1, "Flag for applying D-meson efficiency weights"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; @@ -162,10 +165,31 @@ struct HfCorrelatorDplusHadrons { Configurable multMin{"multMin", 0., "minimum multiplicity accepted"}; Configurable multMax{"multMax", 10000., "maximum multiplicity accepted"}; Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots and efficiency"}; - Configurable> efficiencyD{"efficiencyD", std::vector{efficiencyDmeson_v}, "Efficiency values for Dplus meson"}; + Configurable> efficiencyD{"efficiencyD", std::vector{efficiencyDmeson}, "Efficiency values for Dplus meson"}; + + HfHelper hfHelper; + SliceCache cache; + + // Event Mixing for the Data Mode + using MySelCollisions = soa::Filtered>; + using MyTracks = soa::Filtered; + using MyCandidatesData = soa::Filtered>; + // Event Mixing for the MCRec Mode + using MyCandidatesMcRec = soa::Filtered>; + // Event Mixing for the MCGen Mode + using McCollisionsSel = soa::Filtered>; + using McParticlesSel = soa::Filtered; + + Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; + Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); + Filter dplusFilter = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= 1; + Filter collisionFilterGen = aod::hf_selection_dmeson_collision::dmesonSel == true; + Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == 411 || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); + + Preslice perCol = aod::hf_cand::collisionId; Partition> selectedDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; - Partition> recoFlagDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Partition> selectedDplusCandidatesMc = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; HistogramRegistry registry{ "registry", @@ -198,7 +222,7 @@ struct HfCorrelatorDplusHadrons { {"hDplusBin", "Dplus selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}}, {"hTracksBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMassDplus_2D", "Dplus candidates;inv. mass (K^{-}#pi^{+}#pi^{+}) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -210,7 +234,9 @@ struct HfCorrelatorDplusHadrons { } /// Dplus-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processData(soa::Join::iterator const& collision, soa::Join& tracks, soa::Join const& candidates) + void processData(soa::Join::iterator const& collision, + aod::TracksWDca const& tracks, + soa::Join const& candidates) { if (selectedDplusCandidates.size() > 0) { int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFV0M())); @@ -236,8 +262,8 @@ struct HfCorrelatorDplusHadrons { auto selectedDplusCandidatesGrouped = selectedDplusCandidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto const& candidate1 : selectedDplusCandidatesGrouped) { - if (yCandMax >= 0. && std::abs(yDplus(candidate1)) > yCandMax) { + for (const auto& candidate1 : selectedDplusCandidatesGrouped) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { @@ -247,7 +273,7 @@ struct HfCorrelatorDplusHadrons { continue; } // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::DplusToPiKPi)) { + if (!(candidate1.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { continue; } double efficiencyWeight = 1.; @@ -255,15 +281,15 @@ struct HfCorrelatorDplusHadrons { efficiencyWeight = 1. / efficiencyD->at(o2::analysis::findBin(binsPt, candidate1.pt())); } // fill invariant mass plots and generic info from all Dplus candidates - registry.fill(HIST("hMassDplus_2D"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); - registry.fill(HIST("hMassDplusData"), invMassDplusToPiKPi(candidate1), efficiencyWeight); + registry.fill(HIST("hMassDplus_2D"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDplusData"), hfHelper.invMassDplusToPiKPi(candidate1), efficiencyWeight); registry.fill(HIST("hPtCand"), candidate1.pt()); registry.fill(HIST("hPtProng0"), candidate1.ptProng0()); registry.fill(HIST("hPtProng1"), candidate1.ptProng1()); registry.fill(HIST("hPtProng2"), candidate1.ptProng2()); registry.fill(HIST("hEta"), candidate1.eta()); registry.fill(HIST("hPhi"), RecoDecay::constrainAngle(candidate1.phi(), -o2::constants::math::PIHalf)); - registry.fill(HIST("hY"), yDplus(candidate1)); + registry.fill(HIST("hY"), hfHelper.yDplus(candidate1)); registry.fill(HIST("hSelectionStatus"), candidate1.isSelDplusToPiKPi()); registry.fill(HIST("hDplusBin"), poolBin); // Dplus-Hadron correlation dedicated section @@ -286,20 +312,21 @@ struct HfCorrelatorDplusHadrons { track.eta() - candidate1.eta(), candidate1.pt(), track.pt(), poolBin); - entryDplusHadronRecoInfo(invMassDplusToPiKPi(candidate1), 0); + entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(candidate1), 0); } // Hadron Tracks loop } // end outer Dplus loop registry.fill(HIST("hZvtx"), collision.posZ()); registry.fill(HIST("hMultV0M"), collision.multFV0M()); } } - PROCESS_SWITCH(HfCorrelatorDplusHadrons, processData, "Process data", false); /// Dplus-Hadron correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) - void processMcRec(soa::Join::iterator const& collision, soa::Join& tracks, soa::Join const& candidates) + void processMcRec(soa::Join::iterator const& collision, + aod::TracksWDca const& tracks, + soa::Join const& candidates) { - if (recoFlagDplusCandidates.size() > 0) { + if (selectedDplusCandidatesMc.size() > 0) { int poolBin = corrBinning.getBin(std::make_tuple(collision.posZ(), collision.multFV0M())); int nTracks = 0; if (collision.numContrib() > 1) { @@ -320,15 +347,15 @@ struct HfCorrelatorDplusHadrons { } registry.fill(HIST("hMultiplicity"), nTracks); - auto selectedDplusCandidatesGroupedMc = recoFlagDplusCandidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + auto selectedDplusCandidatesMcGrouped = selectedDplusCandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); // MC reco level bool flagDplusSignal = false; - for (auto const& candidate1 : selectedDplusCandidatesGroupedMc) { + for (const auto& candidate1 : selectedDplusCandidatesMcGrouped) { // check decay channel flag for candidate1 - if (!(candidate1.hfflag() & 1 << DecayType::DplusToPiKPi)) { + if (!(candidate1.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { continue; } - if (yCandMax >= 0. && std::abs(yDplus(candidate1)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(candidate1)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate1.pt() < ptCandMin) { @@ -342,7 +369,7 @@ struct HfCorrelatorDplusHadrons { efficiencyWeight = 1. / efficiencyD->at(o2::analysis::findBin(binsPt, candidate1.pt())); } - if (std::abs(candidate1.flagMcMatchRec()) == 1 << DecayType::DplusToPiKPi) { + if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { // fill per-candidate distributions from Dplus true candidates registry.fill(HIST("hPtCandMCRec"), candidate1.pt()); registry.fill(HIST("hPtProng0MCRec"), candidate1.ptProng0()); @@ -350,20 +377,20 @@ struct HfCorrelatorDplusHadrons { registry.fill(HIST("hPtProng2MCRec"), candidate1.ptProng2()); registry.fill(HIST("hEtaMCRec"), candidate1.eta()); registry.fill(HIST("hPhiMCRec"), RecoDecay::constrainAngle(candidate1.phi(), -o2::constants::math::PIHalf)); - registry.fill(HIST("hYMCRec"), yDplus(candidate1)); + registry.fill(HIST("hYMCRec"), hfHelper.yDplus(candidate1)); registry.fill(HIST("hSelectionStatusMCRec"), candidate1.isSelDplusToPiKPi()); } // fill invariant mass plots from Dplus signal and background candidates - registry.fill(HIST("hMassDplusMCRec"), invMassDplusToPiKPi(candidate1), efficiencyWeight); - if (std::abs(candidate1.flagMcMatchRec()) == 1 << DecayType::DplusToPiKPi) { // also matched as Dplus - registry.fill(HIST("hMassDplusMCRecSig"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDplusMCRec"), hfHelper.invMassDplusToPiKPi(candidate1), efficiencyWeight); + if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi) { // also matched as Dplus + registry.fill(HIST("hMassDplusMCRecSig"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { - registry.fill(HIST("hMassDplusMCRecBkg"), invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassDplusMCRecBkg"), hfHelper.invMassDplusToPiKPi(candidate1), candidate1.pt(), efficiencyWeight); } registry.fill(HIST("hDplusBin"), poolBin); // Dplus-Hadron correlation dedicated section // if the candidate is selected as Dplus, search for Hadron and evaluate correlations - flagDplusSignal = candidate1.flagMcMatchRec() == 1 << DecayType::DplusToPiKPi; + flagDplusSignal = candidate1.flagMcMatchRec() == 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; for (const auto& track : tracks) { if (std::abs(track.eta()) > etaTrackMax) { continue; @@ -382,7 +409,7 @@ struct HfCorrelatorDplusHadrons { track.eta() - candidate1.eta(), candidate1.pt(), track.pt(), poolBin); - entryDplusHadronRecoInfo(invMassDplusToPiKPi(candidate1), flagDplusSignal); + entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(candidate1), flagDplusSignal); } // end inner loop (Tracks) } // end outer Dplus loop @@ -390,17 +417,18 @@ struct HfCorrelatorDplusHadrons { registry.fill(HIST("hMultV0M"), collision.multFV0M()); } } - PROCESS_SWITCH(HfCorrelatorDplusHadrons, processMcRec, "Process MC Reco mode", true); + /// Dplus-Hadron correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGen(aod::McCollision const& mcCollision, aod::McParticles const& particlesMc) + void processMcGen(aod::McCollision const& mcCollision, + aod::McParticles const& mcParticles) { int counterDplusHadron = 0; registry.fill(HIST("hMCEvtCount"), 0); - auto getTracksSize = [&particlesMc](aod::McCollision const& collision) { + auto getTracksSize = [&mcParticles](aod::McCollision const& collision) { int nTracks = 0; - for (auto const& track : particlesMc) { + for (const auto& track : mcParticles) { if (track.isPhysicalPrimary() && std::abs(track.eta()) < 1.0) { nTracks++; } @@ -411,12 +439,12 @@ struct HfCorrelatorDplusHadrons { BinningTypeMCGen corrBinningMcGen{{getTracksSize}, {zBins, multBinsMcGen}, true}; // MC gen level - for (auto const& particle1 : particlesMc) { + for (const auto& particle1 : mcParticles) { // check if the particle is Dplus (for general plot filling and selection, so both cases are fine) - NOTE: decay channel is not probed! if (std::abs(particle1.pdgCode()) != pdg::Code::kDPlus) { continue; } - double yD = RecoDecay::y(array{particle1.px(), particle1.py(), particle1.pz()}, RecoDecay::getMassPDG(particle1.pdgCode())); + double yD = RecoDecay::y(std::array{particle1.px(), particle1.py(), particle1.pz()}, o2::analysis::pdg::MassDPlus); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -434,11 +462,11 @@ struct HfCorrelatorDplusHadrons { continue; } registry.fill(HIST("hcountDplustriggersMCGen"), 0, particle1.pt()); // to count trigger Dplus for normalisation) - for (auto const& particle2 : particlesMc) { + for (const auto& particle2 : mcParticles) { // Check Mother of particle 2 bool flagMotherFound = false; - for (auto& m : particle2.mothers_as()) { + for (const auto& m : particle2.mothers_as()) { if (m.globalIndex() == particle1.globalIndex()) { flagMotherFound = true; break; @@ -471,75 +499,57 @@ struct HfCorrelatorDplusHadrons { } PROCESS_SWITCH(HfCorrelatorDplusHadrons, processMcGen, "Process MC Gen mode", false); - // Event Mixing for the Data Mode - using myCollisions = soa::Join; - using fullTracks = soa::Join; - using mySelCollisions = soa::Filtered; - using myTracks = soa::Filtered; - using myCandidatesData = soa::Filtered>; - - Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; - Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); - Filter dplusfilter = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= 1; - - void processDataMixedEvent(mySelCollisions& collisions, myCandidatesData& candidates, myTracks& tracks) + void processDataMixedEvent(MySelCollisions const& collisions, + MyCandidatesData const& candidates, + MyTracks const& tracks) { auto tracksTuple = std::make_tuple(candidates, tracks); - Pair pairData{corrBinning, 5, -1, collisions, tracksTuple, &cache}; + Pair pairData{corrBinning, 5, -1, collisions, tracksTuple, &cache}; - for (auto& [c1, tracks1, c2, tracks2] : pairData) { + for (const auto& [c1, tracks1, c2, tracks2] : pairData) { // LOGF(info, "Mixed event collisions: Index = (%d, %d), tracks Size: (%d, %d), Z Vertex: (%f, %f), Pool Bin: (%d, %d)", c1.globalIndex(), c2.globalIndex(), tracks1.size(), tracks2.size(), c1.posZ(), c2.posZ(), corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFV0M())),corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M()))); // For debug int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M())); - for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (yCandMax >= 0. && std::abs(yDplus(t1)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(t1)) > yCandMax) { continue; } entryDplusHadronPair(getDeltaPhi(t1.phi(), t2.phi()), t1.eta() - t2.eta(), t1.pt(), t2.pt(), poolBin); - entryDplusHadronRecoInfo(invMassDplusToPiKPi(t1), 0); + entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(t1), 0); } } } PROCESS_SWITCH(HfCorrelatorDplusHadrons, processDataMixedEvent, "Process Mixed Event Data", false); - // Event Mixing for the MCRec Mode - using myCandidatesMcRec = soa::Filtered>; - - void processMcRecMixedEvent(mySelCollisions& collisions, myCandidatesMcRec& candidates, myTracks& tracks) + void processMcRecMixedEvent(MySelCollisions const& collisions, + MyCandidatesMcRec const& candidates, + MyTracks const& tracks) { auto tracksTuple = std::make_tuple(candidates, tracks); - Pair pairMcRec{corrBinning, 5, -1, collisions, tracksTuple, &cache}; + Pair pairMcRec{corrBinning, 5, -1, collisions, tracksTuple, &cache}; - for (auto& [c1, tracks1, c2, tracks2] : pairMcRec) { + for (const auto& [c1, tracks1, c2, tracks2] : pairMcRec) { int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M())); - for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (yCandMax >= 0. && std::abs(yDplus(t1)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDplus(t1)) > yCandMax) { continue; } entryDplusHadronPair(getDeltaPhi(t1.phi(), t2.phi()), t1.eta() - t2.eta(), t1.pt(), t2.pt(), poolBin); - entryDplusHadronRecoInfo(invMassDplusToPiKPi(t1), 0); + entryDplusHadronRecoInfo(hfHelper.invMassDplusToPiKPi(t1), 0); } } } PROCESS_SWITCH(HfCorrelatorDplusHadrons, processMcRecMixedEvent, "Process Mixed Event MCRec", false); - // Event Mixing for the MCGen Mode - using myCollisionsMcGen = soa::Join; - using fullTracksMcGen = aod::McParticles; - using mySelCollisionsMcGen = soa::Filtered; - using myTracksMcGen = soa::Filtered; - - Filter collisionFilterGen = aod::hf_selection_dmeson_collision::dmesonSel == true; - Filter particlesFilter = nabs(aod::mcparticle::pdgCode) == 411 || ((aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary); - - void processMcGenMixedEvent(mySelCollisionsMcGen& collisions, myTracksMcGen& particlesMc) + void processMcGenMixedEvent(McCollisionsSel const& collisions, + McParticlesSel const& mcParticles) { - auto getTracksSize = [&particlesMc, this](mySelCollisionsMcGen::iterator const& collision) { + auto getTracksSize = [&mcParticles, this](McCollisionsSel::iterator const& collision) { int nTracks = 0; - auto associatedTracks = particlesMc.sliceByCached(o2::aod::mcparticle::mcCollisionId, collision.globalIndex(), this->cache); - for (auto const& track : associatedTracks) { + auto associatedTracks = mcParticles.sliceByCached(o2::aod::mcparticle::mcCollisionId, collision.globalIndex(), this->cache); + for (const auto& track : associatedTracks) { if (track.isPhysicalPrimary() && std::abs(track.eta()) < 1.0) { nTracks++; } @@ -550,18 +560,18 @@ struct HfCorrelatorDplusHadrons { using BinningTypeMcGen = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getTracksSize)>; BinningTypeMcGen corrBinningMcGen{{getTracksSize}, {zBins, multBins}, true}; - auto tracksTuple = std::make_tuple(particlesMc, particlesMc); - Pair pairMcGen{corrBinningMcGen, 5, -1, collisions, tracksTuple, &cache}; + auto tracksTuple = std::make_tuple(mcParticles, mcParticles); + Pair pairMcGen{corrBinningMcGen, 5, -1, collisions, tracksTuple, &cache}; - for (auto& [c1, tracks1, c2, tracks2] : pairMcGen) { - for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + for (const auto& [c1, tracks1, c2, tracks2] : pairMcGen) { + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { // Check track t1 is Dplus if (std::abs(t1.pdgCode()) != pdg::Code::kDPlus) { continue; } - double yD = RecoDecay::y(array{t1.px(), t1.py(), t1.pz()}, RecoDecay::getMassPDG(t1.pdgCode())); + double yD = RecoDecay::y(std::array{t1.px(), t1.py(), t1.pz()}, o2::analysis::pdg::MassDPlus); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 24093e596ac..a4c4dc7821c 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -14,26 +14,25 @@ /// \author Grazia Luparello /// \author Samuele Cattaruzzi +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + #include "Common/Core/TrackSelection.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_correlation_ds_hadron; -using namespace o2::aod::hf_selection_dmeson_collision; -using namespace o2::analysis::hf_cuts_ds_to_k_k_pi; -using namespace o2::constants::math; /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies double getDeltaPhi(double phiD, double phiHadron) @@ -60,40 +59,43 @@ AxisSpec axisMultiplicity = {1000, 0., 10000., "Multiplicity"}; AxisSpec axisPoolBin = {9, 0., 9., "PoolBin"}; // binning type -// std::vector zBins{VARIABLE_WIDTH, -10.0, -2.5, 2.5, 10.0}; -std::vector zBins{VARIABLE_WIDTH, -10.0, 10.0}; -// std::vector multBins{VARIABLE_WIDTH, 0., 200., 500.0, 5000.}; -std::vector multBins{VARIABLE_WIDTH, 0., 500.0, 5000.}; +std::vector zBins{VARIABLE_WIDTH, -10.0, -2.5, 2.5, 10.0}; +// std::vector zBins{VARIABLE_WIDTH, -10.0, 10.0}; +std::vector multBins{VARIABLE_WIDTH, 0., 500.0, 5000., 10000.}; +// std::vector multBins{VARIABLE_WIDTH, 0., 500.0, 5000.}; std::vector multBinsMcGen{VARIABLE_WIDTH, 0., 20., 50.0, 500.}; // In MCGen multiplicity is defined by counting primaries using BinningType = ColumnBinningPolicy>; BinningType corrBinning{{zBins, multBins}, true}; /// Code to select collisions with at least one Ds meson struct HfCorrelatorDsHadronsSelCollision { - SliceCache cache; Produces collisionsWithSelDs; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; - Filter dsFlagFilter = (o2::aod::hf_track_index::hfflag & static_cast(1 << DecayType::DsToKKPi)) != static_cast(0); // filter in HfCand3Prong + SliceCache cache; + HfHelper hfHelper; using CandDsData = soa::Filtered>; using CandDsMcReco = soa::Filtered>; using CandDsMcGen = soa::Join; - Partition selectedDsAllCand = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; - Partition recoFlagDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; + Filter dsFilter = (o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DsToKKPi)) != static_cast(0); // filter in HfCand3Prong + + Partition selectedDsCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; + Partition selectedDsCandidatesMc = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; /// Code to select collisions with at least one Ds meson - for real data and data-like analysis - void processDsSelCollisionsData(aod::Collision const& collision, CandDsData const& candidates) + void processDsSelCollisionsData(aod::Collision const& collision, + CandDsData const& candidates) { bool isDsFound = false; - if (selectedDsAllCand.size() > 0) { - auto selectedDsAllCandGrouped = selectedDsAllCand->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto const& candidate : selectedDsAllCandGrouped) { - if (yCandMax >= 0. && std::abs(yDs(candidate)) > yCandMax) { + if (selectedDsCandidates.size() > 0) { + auto selectedDsAllCandGrouped = selectedDsCandidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + for (const auto& candidate : selectedDsAllCandGrouped) { + if (yCandMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { @@ -108,13 +110,14 @@ struct HfCorrelatorDsHadronsSelCollision { PROCESS_SWITCH(HfCorrelatorDsHadronsSelCollision, processDsSelCollisionsData, "Process Ds Collision Selection Data", true); /// Code to select collisions with at least one Ds meson - for MC reco-level analysis - void processDsSelCollisionsMcRec(aod::Collision const& collision, CandDsMcReco const& candidates) + void processDsSelCollisionsMcRec(aod::Collision const& collision, + CandDsMcReco const& candidates) { bool isDsFound = false; - if (recoFlagDsCandidates.size() > 0) { - auto selectedDsCandidatesGroupedMc = recoFlagDsCandidates->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); - for (auto const& candidate : selectedDsCandidatesGroupedMc) { - if (yCandMax >= 0. && std::abs(yDs(candidate)) > yCandMax) { + if (selectedDsCandidatesMc.size() > 0) { + auto selectedDsCandidatesGroupedMc = selectedDsCandidatesMc->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + for (const auto& candidate : selectedDsCandidatesGroupedMc) { + if (yCandMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { @@ -129,14 +132,15 @@ struct HfCorrelatorDsHadronsSelCollision { PROCESS_SWITCH(HfCorrelatorDsHadronsSelCollision, processDsSelCollisionsMcRec, "Process Ds Collision Selection MCRec", false); /// Code to select collisions with at least one Ds meson - for MC gen-level analysis - void processDsSelCollisionsMcGen(aod::McCollision const& mccollision, CandDsMcGen const& particlesMc) + void processDsSelCollisionsMcGen(aod::McCollision const& mcCollision, + CandDsMcGen const& mcParticles) { bool isDsFound = false; - for (auto const& particle : particlesMc) { + for (const auto& particle : mcParticles) { if (std::abs(particle.pdgCode()) != pdg::Code::kDS) { continue; } - double yD = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + double yD = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassDS); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -153,19 +157,19 @@ struct HfCorrelatorDsHadronsSelCollision { /// Ds-Hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) struct HfCorrelatorDsHadrons { - SliceCache cache; - Preslice perCol = aod::hf_cand::collisionId; Produces entryDsHadronPair; Produces entryDsHadronRecoInfo; Produces entryDsHadronGenInfo; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; + Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; Configurable applyEfficiency{"applyEfficiency", true, "Flag for applying D-meson efficiency weights"}; Configurable yCandMax{"yCandMax", 0.8, "max. cand. rapidity"}; Configurable etaTrackMax{"etaTrackMax", 0.8, "max. eta of tracks"}; Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCA_xy of tracks"}; Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCA_z of tracks"}; Configurable ptCandMin{"ptCandMin", 1., "min. cand. pT"}; + Configurable ptCandMax{"ptCandMax", 50., "max. cand pT"}; Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; Configurable ptTrackMax{"ptTrackMax", 50., "max. track pT"}; Configurable multMin{"multMin", 0., "minimum multiplicity accepted"}; @@ -173,16 +177,21 @@ struct HfCorrelatorDsHadrons { Configurable> binsPt{"binsPt", std::vector{o2::analysis::hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots and efficiency"}; Configurable> efficiencyD{"efficiencyD", std::vector{vecEfficiencyDmeson}, "Efficiency values for Ds meson"}; - Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; - Filter flagDsFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << DecayType::DsToKKPi)) != static_cast(0)) && (aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs); - Filter trackFilter = (aod::track::eta < std::abs(etaTrackMax)) && (aod::track::pt > ptTrackMin) && (aod::track::dcaXY < std::abs(dcaXYTrackMax)) && (aod::track::dcaZ < std::abs(dcaZTrackMax)); + HfHelper hfHelper; + SliceCache cache; using SelCollisionsWithDs = soa::Filtered>; // collisionFilter applied using SelCollisionsWithDsMc = soa::Filtered>; // collisionFilter applied using CandDsData = soa::Filtered>; // flagDsFilter applied using CandDsMcReco = soa::Filtered>; // flagDsFilter applied using CandDsMcGen = soa::Join; // flagDsFilter applied - using MyTracksData = soa::Filtered>; // trackFilter applied + using MyTracksData = soa::Filtered; // trackFilter applied + + Filter collisionFilter = aod::hf_selection_dmeson_collision::dmesonSel == true; + Filter flagDsFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::DsToKKPi)) != static_cast(0)) && (aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs); + Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (aod::track::pt > ptTrackMin) && (aod::track::pt < ptTrackMax) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); + + Preslice perCol = aod::hf_cand::collisionId; HistogramRegistry registry{ "registry", @@ -193,7 +202,11 @@ struct HfCorrelatorDsHadrons { {"hSelectionStatusDsToKKPi", "Ds,Hadron candidates;selection status;entries", {HistType::kTH1F, {{8, -0.5, 7.5}}}}, {"hSelectionStatusDsToPiKK", "Ds,Hadron candidates;selection status;entries", {HistType::kTH1F, {{8, -0.5, 7.5}}}}, {"hEta", "Ds,Hadron candidates", {HistType::kTH1F, {axisEta}}}, + {"hEtaVsPtCand", "Ds,Hadron candidates", {HistType::kTH2F, {{axisEta}, {axisPtD}}}}, + {"hEtaVsPtPartAssoc", "Particles associated", {HistType::kTH2F, {{axisEta}, {axisPtD}}}}, {"hPhi", "Ds,Hadron candidates", {HistType::kTH1F, {axisPhi}}}, + {"hPhiVsPtCand", "Ds,Hadron candidates", {HistType::kTH2F, {{axisPhi}, {axisPtD}}}}, + {"hPhiVsPtPartAssoc", "Particles associated", {HistType::kTH2F, {{axisPhi}, {axisPtD}}}}, {"hY", "Ds,Hadron candidates", {HistType::kTH1F, {axisY}}}, {"hPtCandMcRecSig", "Ds,Hadron candidates - MC Reco", {HistType::kTH1F, {axisPtD}}}, {"hPtCandMcRecSigPrompt", "Ds,Hadron candidates Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}}, @@ -234,7 +247,7 @@ struct HfCorrelatorDsHadrons { {"hDsPoolBin", "Ds selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {axisPoolBin}}}, {"hTracksPoolBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {axisPoolBin}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMassDsVsPt", "Ds candidates", {HistType::kTH2F, {{axisMassD}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -256,8 +269,10 @@ struct HfCorrelatorDsHadrons { registry.fill(HIST("hPtProng1"), candidate.ptProng1()); registry.fill(HIST("hPtProng2"), candidate.ptProng2()); registry.fill(HIST("hEta"), candidate.eta()); + registry.fill(HIST("hEtaVsPtCand"), candidate.eta(), candidate.pt()); registry.fill(HIST("hPhi"), RecoDecay::constrainAngle(candidate.phi(), -o2::constants::math::PIHalf)); - registry.fill(HIST("hY"), yDs(candidate)); + registry.fill(HIST("hPhiVsPtCand"), RecoDecay::constrainAngle(candidate.phi(), -o2::constants::math::PIHalf), candidate.pt()); + registry.fill(HIST("hY"), hfHelper.yDs(candidate)); } /// Fill histograms of quantities for the KKPi daugther-mass hypothesis for data @@ -266,8 +281,8 @@ struct HfCorrelatorDsHadrons { template void fillHistoKKPi(const T1& candidate, double efficiencyWeight) { - registry.fill(HIST("hMassDsVsPt"), invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); - registry.fill(HIST("hMassDsData"), invMassDsToKKPi(candidate), efficiencyWeight); + registry.fill(HIST("hMassDsVsPt"), hfHelper.invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsData"), hfHelper.invMassDsToKKPi(candidate), efficiencyWeight); registry.fill(HIST("hSelectionStatusDsToKKPi"), candidate.isSelDsToKKPi()); } @@ -277,8 +292,8 @@ struct HfCorrelatorDsHadrons { template void fillHistoPiKK(const T1& candidate, double efficiencyWeight) { - registry.fill(HIST("hMassDsVsPt"), invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); - registry.fill(HIST("hMassDsData"), invMassDsToPiKK(candidate), efficiencyWeight); + registry.fill(HIST("hMassDsVsPt"), hfHelper.invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsData"), hfHelper.invMassDsToPiKK(candidate), efficiencyWeight); registry.fill(HIST("hSelectionStatusDsToPiKK"), candidate.isSelDsToPiKK()); } @@ -294,7 +309,7 @@ struct HfCorrelatorDsHadrons { registry.fill(HIST("hPtProng2McRecSig"), candidate.ptProng2()); registry.fill(HIST("hEtaMcRecSig"), candidate.eta()); registry.fill(HIST("hPhiMcRecSig"), RecoDecay::constrainAngle(candidate.phi(), -o2::constants::math::PIHalf)); - registry.fill(HIST("hYMcRecSig"), yDs(candidate)); + registry.fill(HIST("hYMcRecSig"), hfHelper.yDs(candidate)); // prompt and non-prompt division if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { @@ -317,7 +332,7 @@ struct HfCorrelatorDsHadrons { registry.fill(HIST("hPtProng2McRecBkg"), candidate.ptProng2()); registry.fill(HIST("hEtaMcRecBkg"), candidate.eta()); registry.fill(HIST("hPhiMcRecBkg"), RecoDecay::constrainAngle(candidate.phi(), -o2::constants::math::PIHalf)); - registry.fill(HIST("hYMcRecBkg"), yDs(candidate)); + registry.fill(HIST("hYMcRecBkg"), hfHelper.yDs(candidate)); } /// Fill histograms of quantities for the Ds signal for MC reco-level @@ -341,9 +356,11 @@ struct HfCorrelatorDsHadrons { } /// Ds-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processData(SelCollisionsWithDs::iterator const& collision, CandDsData const& candidates, MyTracksData const& tracks) + void processData(SelCollisionsWithDs::iterator const& collision, + CandDsData const& candidates, + MyTracksData const& tracks) { - // if (selectedDsAllCand.size() > 0) { + // if (selectedDsCandidates.size() > 0) { if (candidates.size() > 0) { registry.fill(HIST("hZVtx"), collision.posZ()); registry.fill(HIST("hMultV0M"), collision.multFV0M()); @@ -366,13 +383,13 @@ struct HfCorrelatorDsHadrons { // Ds fill histograms and Ds-Hadron correlation for DsToKKPi for (const auto& candidate : candidates) { - if (yCandMax >= 0. && std::abs(yDs(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { continue; } - if (candidate.pt() > ptTrackMax) { + if (candidate.pt() > ptCandMax) { continue; } double efficiencyWeight = 1.; @@ -392,13 +409,15 @@ struct HfCorrelatorDsHadrons { if ((candidate.prong0Id() == track.globalIndex()) || (candidate.prong1Id() == track.globalIndex()) || (candidate.prong2Id() == track.globalIndex())) { continue; } + registry.fill(HIST("hEtaVsPtPartAssoc"), track.eta(), candidate.pt()); + registry.fill(HIST("hPhiVsPtPartAssoc"), RecoDecay::constrainAngle(track.phi(), -o2::constants::math::PIHalf), candidate.pt()); if (candidate.isSelDsToKKPi() >= selectionFlagDs) { entryDsHadronPair(getDeltaPhi(track.phi(), candidate.phi()), track.eta() - candidate.eta(), candidate.pt(), track.pt(), poolBin); - entryDsHadronRecoInfo(invMassDsToKKPi(candidate), false); + entryDsHadronRecoInfo(hfHelper.invMassDsToKKPi(candidate), false); entryDsHadronGenInfo(false); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { entryDsHadronPair(getDeltaPhi(track.phi(), candidate.phi()), @@ -406,7 +425,7 @@ struct HfCorrelatorDsHadrons { candidate.pt(), track.pt(), poolBin); - entryDsHadronRecoInfo(invMassDsToPiKK(candidate), false); + entryDsHadronRecoInfo(hfHelper.invMassDsToPiKK(candidate), false); entryDsHadronGenInfo(false); } } @@ -416,7 +435,9 @@ struct HfCorrelatorDsHadrons { PROCESS_SWITCH(HfCorrelatorDsHadrons, processData, "Process data", true); /// Ds-Hadron correlation pair builder - for MC reco-level analysis (candidates matched to true signal only, but also the various bkg sources are studied) - void processMcRec(SelCollisionsWithDs::iterator const& collision, CandDsMcReco const& candidates, MyTracksData const& tracks) + void processMcRec(SelCollisionsWithDs::iterator const& collision, + CandDsMcReco const& candidates, + MyTracksData const& tracks) { if (candidates.size() > 0) { registry.fill(HIST("hZVtx"), collision.posZ()); @@ -449,15 +470,15 @@ struct HfCorrelatorDsHadrons { // prompt and non-prompt division isDsPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; // Ds Signal - isDsSignal = std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::DsToKKPi; + isDsSignal = std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi; - if (yCandMax >= 0. && std::abs(yDs(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { continue; } - if (candidate.pt() >= ptTrackMax) { + if (candidate.pt() >= ptCandMax) { continue; } double efficiencyWeight = 1.; @@ -468,28 +489,28 @@ struct HfCorrelatorDsHadrons { fillHistoMcRecSig(candidate, multiplicityV0M); // DsToKKPi and DsToPiKK division if (candidate.isSelDsToKKPi() >= selectionFlagDs) { - registry.fill(HIST("hMassDsMCRec"), invMassDsToKKPi(candidate), efficiencyWeight); - registry.fill(HIST("hMassDsMCRecSig"), invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); - registry.fill(HIST("hMassDsVsPtMCRec"), invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsMCRec"), hfHelper.invMassDsToKKPi(candidate), efficiencyWeight); + registry.fill(HIST("hMassDsMCRecSig"), hfHelper.invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsVsPtMCRec"), hfHelper.invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); registry.fill(HIST("hSelectionStatusMcRec"), candidate.isSelDsToKKPi()); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { - registry.fill(HIST("hMassDsMCRec"), invMassDsToPiKK(candidate), efficiencyWeight); - registry.fill(HIST("hMassDsMCRecSig"), invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); - registry.fill(HIST("hMassDsVsPtMCRec"), invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsMCRec"), hfHelper.invMassDsToPiKK(candidate), efficiencyWeight); + registry.fill(HIST("hMassDsMCRecSig"), hfHelper.invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsVsPtMCRec"), hfHelper.invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); registry.fill(HIST("hSelectionStatusMcRec"), candidate.isSelDsToPiKK()); } } else { fillHistoMcRecBkg(candidate); // DsToKKPi and DsToPiKK division if (candidate.isSelDsToKKPi() >= selectionFlagDs) { - registry.fill(HIST("hMassDsMCRec"), invMassDsToKKPi(candidate), efficiencyWeight); - registry.fill(HIST("hMassDsMCRecBkg"), invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); - registry.fill(HIST("hMassDsVsPtMCRec"), invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsMCRec"), hfHelper.invMassDsToKKPi(candidate), efficiencyWeight); + registry.fill(HIST("hMassDsMCRecBkg"), hfHelper.invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsVsPtMCRec"), hfHelper.invMassDsToKKPi(candidate), candidate.pt(), efficiencyWeight); registry.fill(HIST("hSelectionStatusMcRec"), candidate.isSelDsToKKPi()); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { - registry.fill(HIST("hMassDsMCRec"), invMassDsToPiKK(candidate), efficiencyWeight); - registry.fill(HIST("hMassDsMCRecBkg"), invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); - registry.fill(HIST("hMassDsVsPtMCRec"), invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsMCRec"), hfHelper.invMassDsToPiKK(candidate), efficiencyWeight); + registry.fill(HIST("hMassDsMCRecBkg"), hfHelper.invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); + registry.fill(HIST("hMassDsVsPtMCRec"), hfHelper.invMassDsToPiKK(candidate), candidate.pt(), efficiencyWeight); registry.fill(HIST("hSelectionStatusMcRec"), candidate.isSelDsToPiKK()); } } @@ -509,7 +530,7 @@ struct HfCorrelatorDsHadrons { candidate.pt(), track.pt(), poolBin); - entryDsHadronRecoInfo(invMassDsToKKPi(candidate), isDsSignal); + entryDsHadronRecoInfo(hfHelper.invMassDsToKKPi(candidate), isDsSignal); entryDsHadronGenInfo(isDsPrompt); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { entryDsHadronPair(getDeltaPhi(track.phi(), candidate.phi()), @@ -517,7 +538,7 @@ struct HfCorrelatorDsHadrons { candidate.pt(), track.pt(), poolBin); - entryDsHadronRecoInfo(invMassDsToPiKK(candidate), isDsSignal); + entryDsHadronRecoInfo(hfHelper.invMassDsToPiKK(candidate), isDsSignal); entryDsHadronGenInfo(isDsPrompt); } } @@ -527,21 +548,24 @@ struct HfCorrelatorDsHadrons { PROCESS_SWITCH(HfCorrelatorDsHadrons, processMcRec, "Process MC Reco mode", false); /// Ds-Hadron correlation - for calculating efficiencies using MC reco-level analysis - void processMcEfficiencies(CandDsMcReco const& candidates, CandDsMcGen const& particlesMc, MyTracksData const& tracksData, aod::BigTracksMC const&) + void processMcEfficiencies(CandDsMcReco const& candidates, + CandDsMcGen const& mcParticles, + MyTracksData const& tracksData, + aod::TracksWMc const&) { // MC rec. - for (auto& candidate : candidates) { - if (yCandMax >= 0. && std::abs(yDs(candidate)) > yCandMax) { + for (const auto& candidate : candidates) { + if (yCandMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { continue; } - if (candidate.pt() > ptTrackMax) { + if (candidate.pt() > ptCandMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::DsToKKPi) { - auto prong0McPart = candidate.prong0_as().mcParticle_as(); + if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) { + auto prong0McPart = candidate.prong0_as().mcParticle_as(); // DsToKKPi and DsToPiKK division if ((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) { fillHistoMcRecSig(candidate, 0.); @@ -571,13 +595,13 @@ struct HfCorrelatorDsHadrons { } // MC gen level for Ds meson reconstruction's efficiency - for (auto const& particle : particlesMc) { + for (const auto& particle : mcParticles) { // check if the particle is Ds if (std::abs(particle.pdgCode()) != pdg::Code::kDS) { continue; } - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::DsToKKPi) { - double yD = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) { + double yD = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassDS); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -589,7 +613,7 @@ struct HfCorrelatorDsHadrons { } // MC gen level for particles associated reconstruction's efficiency - for (auto const& particleAssoc : particlesMc) { + for (const auto& particleAssoc : mcParticles) { if (std::abs(particleAssoc.eta()) > etaTrackMax) { continue; } @@ -605,14 +629,15 @@ struct HfCorrelatorDsHadrons { PROCESS_SWITCH(HfCorrelatorDsHadrons, processMcEfficiencies, "Process MC for calculating efficiencies", false); /// Ds-Hadron correlation pair builder - for MC gen-level analysis (no filter/selection, only true signal) - void processMcGen(SelCollisionsWithDsMc::iterator const& mccollision, CandDsMcGen const& particlesMc) + void processMcGen(SelCollisionsWithDsMc::iterator const& mcCollision, + CandDsMcGen const& mcParticles) { int counterDsHadron = 0; registry.fill(HIST("hMcEvtCount"), 0); - auto getTracksSize = [&particlesMc](SelCollisionsWithDsMc::iterator const& mccollision) { + auto getTracksSize = [&mcParticles](SelCollisionsWithDsMc::iterator const& mcCollision) { int nTracks = 0; - for (auto& track : particlesMc) { + for (const auto& track : mcParticles) { if (track.isPhysicalPrimary() && std::abs(track.eta()) < 1.0) { nTracks++; } @@ -621,18 +646,18 @@ struct HfCorrelatorDsHadrons { }; using BinningTypeMcGen = FlexibleBinningPolicy, aod::mccollision::PosZ, decltype(getTracksSize)>; BinningTypeMcGen corrBinningMcGen{{getTracksSize}, {zBins, multBinsMcGen}, true}; - int poolBin = corrBinningMcGen.getBin(std::make_tuple(mccollision.posZ(), getTracksSize(mccollision))); + int poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), getTracksSize(mcCollision))); registry.fill(HIST("hCollisionPoolBin"), poolBin); bool isDsPrompt = false; // MC gen level - for (auto const& particle : particlesMc) { + for (const auto& particle : mcParticles) { // check if the particle is Ds if (std::abs(particle.pdgCode()) != pdg::Code::kDS) { continue; } - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::DsToKKPi) { - double yD = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) { + double yD = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassDS); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; } @@ -645,7 +670,7 @@ struct HfCorrelatorDsHadrons { isDsPrompt = particle.originMcGen() == RecoDecay::OriginType::Prompt; // Ds Hadron correlation dedicated section - for (auto const& particleAssoc : particlesMc) { + for (const auto& particleAssoc : mcParticles) { if (std::abs(particleAssoc.eta()) > etaTrackMax) { continue; } @@ -662,7 +687,7 @@ struct HfCorrelatorDsHadrons { particle.pt(), particleAssoc.pt(), poolBin); - entryDsHadronRecoInfo(RecoDecay::getMassPDG(particle.pdgCode()), true); + entryDsHadronRecoInfo(o2::analysis::pdg::MassDS, true); entryDsHadronGenInfo(isDsPrompt); } } @@ -672,7 +697,9 @@ struct HfCorrelatorDsHadrons { PROCESS_SWITCH(HfCorrelatorDsHadrons, processMcGen, "Process MC Gen mode", false); // Event Mixing - void processDataME(soa::Join& collisions, CandDsData& candidates, MyTracksData& tracks) + void processDataME(soa::Join const& collisions, + CandDsData const& candidates, + MyTracksData const& tracks) { if (candidates.size() == 0) { return; @@ -682,43 +709,43 @@ struct HfCorrelatorDsHadrons { } auto tracksTuple = std::make_tuple(candidates, tracks); - Pair, CandDsData, MyTracksData, BinningType> pairData{corrBinning, 5, -1, collisions, tracksTuple, &cache}; + Pair, CandDsData, MyTracksData, BinningType> pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; - for (auto& [c1, tracks1, c2, tracks2] : pairData) { + for (const auto& [c1, tracks1, c2, tracks2] : pairData) { if (tracks1.size() == 0) { continue; } - LOGF(info, "Mixed event collisions: Index = (%d, %d), tracks Size: (%d, %d), Z Vertex: (%f, %f), Pool Bin: (%d, %d)", c1.globalIndex(), c2.globalIndex(), tracks1.size(), tracks2.size(), c1.posZ(), c2.posZ(), corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFV0M())), corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M()))); + // LOGF(info, "Mixed event collisions: Index = (%d, %d), tracks Size: (%d, %d), Z Vertex: (%f, %f), Pool Bin: (%d, %d)", c1.globalIndex(), c2.globalIndex(), tracks1.size(), tracks2.size(), c1.posZ(), c2.posZ(), corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFV0M())), corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M()))); int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M())); int poolBinDs = corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFV0M())); registry.fill(HIST("hTracksPoolBin"), poolBin); registry.fill(HIST("hDsPoolBin"), poolBinDs); - for (auto& [cand, pAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (!(cand.hfflag() & 1 << DecayType::DsToKKPi)) { + for (const auto& [cand, pAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (!(cand.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DsToKKPi)) { continue; } - if (yCandMax >= 0. && std::abs(yDs(cand)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDs(cand)) > yCandMax) { continue; } // DsToKKPi and DsToPiKK division if (cand.isSelDsToKKPi() >= selectionFlagDs) { - LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d), track event: (%d, %d), KKPi", cand.index(), pAssoc.index(), c1.index(), c2.index(), cand.collision().index(), pAssoc.collision().index()); - entryDsHadronPair(getDeltaPhi(cand.phi(), pAssoc.phi()), - cand.eta() - pAssoc.eta(), + // LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d), track event: (%d, %d), KKPi", cand.index(), pAssoc.index(), c1.index(), c2.index(), cand.collision().index(), pAssoc.collision().index()); + entryDsHadronPair(getDeltaPhi(pAssoc.phi(), cand.phi()), + pAssoc.eta() - cand.eta(), cand.pt(), pAssoc.pt(), poolBin); - entryDsHadronRecoInfo(invMassDsToKKPi(cand), false); + entryDsHadronRecoInfo(hfHelper.invMassDsToKKPi(cand), false); entryDsHadronGenInfo(false); } else if (cand.isSelDsToPiKK() >= selectionFlagDs) { - LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d), track event: (%d, %d), PiKK", cand.index(), pAssoc.index(), c1.index(), c2.index(), cand.collision().index(), pAssoc.collision().index()); - entryDsHadronPair(getDeltaPhi(cand.phi(), pAssoc.phi()), - cand.eta() - pAssoc.eta(), + // LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d), track event: (%d, %d), PiKK", cand.index(), pAssoc.index(), c1.index(), c2.index(), cand.collision().index(), pAssoc.collision().index()); + entryDsHadronPair(getDeltaPhi(pAssoc.phi(), cand.phi()), + pAssoc.eta() - cand.eta(), cand.pt(), pAssoc.pt(), poolBin); - entryDsHadronRecoInfo(invMassDsToPiKK(cand), false); + entryDsHadronRecoInfo(hfHelper.invMassDsToPiKK(cand), false); entryDsHadronGenInfo(false); } } @@ -726,19 +753,21 @@ struct HfCorrelatorDsHadrons { } PROCESS_SWITCH(HfCorrelatorDsHadrons, processDataME, "Process Mixed Event Data", false); - void processMcRecME(SelCollisionsWithDs& collisions, CandDsMcReco& candidates, MyTracksData& tracks) + void processMcRecME(SelCollisionsWithDs const& collisions, + CandDsMcReco const& candidates, + MyTracksData const& tracks) { - for (auto& candidate : candidates) { - if (yCandMax >= 0. && std::abs(yDs(candidate)) > yCandMax) { + for (const auto& candidate : candidates) { + if (yCandMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandMax) { continue; } if (ptCandMin >= 0. && candidate.pt() < ptCandMin) { continue; } - if (candidate.pt() > ptTrackMax) { + if (candidate.pt() > ptCandMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::DsToKKPi) { + if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi) { // DsToKKPi and DsToPiKK division if (candidate.isSelDsToKKPi() >= selectionFlagDs) { fillHistoMcRecSig(candidate, 0.); @@ -752,40 +781,40 @@ struct HfCorrelatorDsHadrons { } } auto tracksTuple = std::make_tuple(candidates, tracks); - Pair pairMcRec{corrBinning, 5, -1, collisions, tracksTuple, &cache}; + Pair pairMcRec{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; bool isDsPrompt = false; bool isDsSignal = false; - for (auto& [c1, tracks1, c2, tracks2] : pairMcRec) { + for (const auto& [c1, tracks1, c2, tracks2] : pairMcRec) { int poolBin = corrBinning.getBin(std::make_tuple(c2.posZ(), c2.multFV0M())); int poolBinDs = corrBinning.getBin(std::make_tuple(c1.posZ(), c1.multFV0M())); registry.fill(HIST("hTracksPoolBin"), poolBin); registry.fill(HIST("hDsPoolBin"), poolBinDs); - for (auto& [candidate, pAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + for (const auto& [candidate, pAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - if (yCandMax >= 0. && std::abs(yDs(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandMax) { continue; } // prompt and non-prompt division isDsPrompt = candidate.originMcRec() == RecoDecay::OriginType::Prompt; // Ds Signal - isDsSignal = std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::DsToKKPi; + isDsSignal = std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::DsToKKPi; // DsToKKPi and DsToPiKK division if (candidate.isSelDsToKKPi() >= selectionFlagDs) { - entryDsHadronPair(getDeltaPhi(candidate.phi(), pAssoc.phi()), - candidate.eta() - pAssoc.eta(), + entryDsHadronPair(getDeltaPhi(pAssoc.phi(), candidate.phi()), + pAssoc.eta() - candidate.eta(), candidate.pt(), pAssoc.pt(), poolBin); - entryDsHadronRecoInfo(invMassDsToKKPi(candidate), isDsSignal); + entryDsHadronRecoInfo(hfHelper.invMassDsToKKPi(candidate), isDsSignal); entryDsHadronGenInfo(isDsPrompt); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { - entryDsHadronPair(getDeltaPhi(candidate.phi(), pAssoc.phi()), - candidate.eta() - pAssoc.eta(), + entryDsHadronPair(getDeltaPhi(pAssoc.phi(), candidate.phi()), + pAssoc.eta() - candidate.eta(), candidate.pt(), pAssoc.pt(), poolBin); - entryDsHadronRecoInfo(invMassDsToPiKK(candidate), isDsSignal); + entryDsHadronRecoInfo(hfHelper.invMassDsToPiKK(candidate), isDsSignal); entryDsHadronGenInfo(isDsPrompt); } } diff --git a/PWGHF/HFC/Tasks/CMakeLists.txt b/PWGHF/HFC/Tasks/CMakeLists.txt index 8d4469cf244..d205d4b4578 100644 --- a/PWGHF/HFC/Tasks/CMakeLists.txt +++ b/PWGHF/HFC/Tasks/CMakeLists.txt @@ -11,32 +11,32 @@ o2physics_add_dpl_workflow(task-correlation-d0-hadrons SOURCES taskCorrelationD0Hadrons.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-correlation-d-dbar SOURCES taskCorrelationDDbar.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-correlation-d-meson-pairs SOURCES taskCorrelationDMesonPairs.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-correlation-dplus-hadrons SOURCES taskCorrelationDplusHadrons.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-correlation-ds-hadrons SOURCES taskCorrelationDsHadrons.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-flow SOURCES taskFlow.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGCFCore COMPONENT_NAME Analysis) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/PWGCF/Core) diff --git a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx index 0a14cef0a34..8b23113b392 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx @@ -22,36 +22,19 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; using namespace o2::aod::hf_correlation_d0_hadron; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; -using namespace o2::constants::math; namespace o2::aod { using DHadronPairFull = soa::Join; } // namespace o2::aod -/// -/// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies -/// -double getDeltaPhi(double phiD, double phiDbar) -{ - return RecoDecay::constrainAngle(phiDbar - phiD, -o2::constants::math::PIHalf); -} - -/// -/// Returns phi of candidate/particle evaluated from x and y components of segment connecting primary and secondary vertices -/// -double evaluatePhiByVertex(double xVertex1, double xVertex2, double yVertex1, double yVertex2) -{ - return RecoDecay::phi(xVertex2 - xVertex1, yVertex2 - yVertex1); -} - // string definitions, used for histogram axis labels const TString stringPtD = "#it{p}_{T}^{D} (GeV/#it{c});"; const TString stringPtHadron = "#it{p}_{T}^{Hadron} (GeV/#it{c});"; @@ -60,21 +43,28 @@ const TString stringDeltaPhi = "#it{#varphi}^{Hadron}-#it{#varphi}^{D} (rad);"; const TString stringDHadron = "D,Hadron candidates "; const TString stringSignal = "signal region;"; const TString stringSideband = "sidebands;"; -const TString stringMCParticles = "MC gen - D,Hadron particles;"; -const TString stringMCReco = "MC reco - D,Hadron candidates "; +const TString stringMcParticles = "MC gen - D,Hadron particles;"; +const TString stringMcReco = "MC reco - D,Hadron candidates "; + +// histogram axes definition +AxisSpec axisDeltaEta = {100, -2., 2., ""}; +AxisSpec axisDeltaPhi = {64, -o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf, ""}; +AxisSpec axisPtD = {10, 0., 10., ""}; +AxisSpec axisPtHadron = {11, 0., 11., ""}; +AxisSpec axisPoolBin = {9, 0., 9., ""}; // definition of vectors for standard ptbin and invariant mass configurables const int nPtBinsCorrelations = 8; const double pTBinsCorrelations[nPtBinsCorrelations + 1] = {0., 2., 4., 6., 8., 12., 16., 24., 99.}; auto vecPtBinsCorrelations = std::vector{pTBinsCorrelations, pTBinsCorrelations + nPtBinsCorrelations + 1}; -const double signalRegionInnerDefault[nPtBinsCorrelations] = {1.810, 1.810, 1.810, 1.810, 1.810, 1.810, 1.810, 1.810}; -const double signalRegionOuterDefault[nPtBinsCorrelations] = {1.922, 1.922, 1.922, 1.922, 1.922, 1.922, 1.922, 1.922}; -const double sidebandLeftInnerDefault[nPtBinsCorrelations] = {1.642, 1.642, 1.642, 1.642, 1.642, 1.642, 1.642, 1.642}; -const double sidebandLeftOuterDefault[nPtBinsCorrelations] = {1.754, 1.754, 1.754, 1.754, 1.754, 1.754, 1.754, 1.754}; +const double signalRegionLeftDefault[nPtBinsCorrelations] = {1.810, 1.810, 1.810, 1.810, 1.810, 1.810, 1.810, 1.810}; +const double signalRegionRightDefault[nPtBinsCorrelations] = {1.922, 1.922, 1.922, 1.922, 1.922, 1.922, 1.922, 1.922}; +const double sidebandLeftInnerDefault[nPtBinsCorrelations] = {1.754, 1.754, 1.754, 1.754, 1.754, 1.754, 1.754, 1.754}; +const double sidebandLeftOuterDefault[nPtBinsCorrelations] = {1.642, 1.642, 1.642, 1.642, 1.642, 1.642, 1.642, 1.642}; const double sidebandRightInnerDefault[nPtBinsCorrelations] = {1.978, 1.978, 1.978, 1.978, 1.978, 1.978, 1.978, 1.978}; const double sidebandRightOuterDefault[nPtBinsCorrelations] = {2.090, 2.090, 2.090, 2.090, 2.090, 2.090, 2.090, 2.090}; -auto vecSignalRegionInner = std::vector{signalRegionInnerDefault, signalRegionInnerDefault + nPtBinsCorrelations}; -auto vecSignalRegionOuter = std::vector{signalRegionOuterDefault, signalRegionOuterDefault + nPtBinsCorrelations}; +auto vecsignalRegionLeft = std::vector{signalRegionLeftDefault, signalRegionLeftDefault + nPtBinsCorrelations}; +auto vecsignalRegionRight = std::vector{signalRegionRightDefault, signalRegionRightDefault + nPtBinsCorrelations}; auto vecSidebandLeftInner = std::vector{sidebandLeftInnerDefault, sidebandLeftInnerDefault + nPtBinsCorrelations}; auto vecSidebandLeftOuter = std::vector{sidebandLeftOuterDefault, sidebandLeftOuterDefault + nPtBinsCorrelations}; auto vecSidebandRightInner = std::vector{sidebandRightInnerDefault, sidebandRightInnerDefault + nPtBinsCorrelations}; @@ -83,12 +73,6 @@ const int nPtBinsEfficiency = o2::analysis::hf_cuts_d0_to_pi_k::nBinsPt; const double efficiencyDmesonDefault[nPtBinsEfficiency] = {}; auto vecEfficiencyDmeson = std::vector{efficiencyDmesonDefault, efficiencyDmesonDefault + nPtBinsEfficiency}; const double ptHadronMax = 10.0; -const int nPhiBinsCorrelations = 64; -const double phiMinCorrelations = -o2::constants::math::PIHalf; -const double phiMaxCorrelations = 3. * o2::constants::math::PIHalf; -const int nEtaBinsCorrelations = 40; -const double etaMinCorrelations = -2.; -const double etaMaxCorrelations = 2.; struct HfTaskCorrelationD0Hadrons { @@ -97,8 +81,8 @@ struct HfTaskCorrelationD0Hadrons { // pT bins for effiencies: same as above Configurable> binsEfficiency{"ptBinsForEfficiency", std::vector{o2::analysis::hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits for efficiency"}; // signal and sideband region edges, to be defined via json file (initialised to empty) - Configurable> signalRegionInner{"signalRegionInner", std::vector{vecSignalRegionInner}, "Inner values of signal region vs pT"}; - Configurable> signalRegionOuter{"signalRegionOuter", std::vector{vecSignalRegionOuter}, "Outer values of signal region vs pT"}; + Configurable> signalRegionLeft{"signalRegionLeft", std::vector{vecsignalRegionLeft}, "Inner values of signal region vs pT"}; + Configurable> signalRegionRight{"signalRegionRight", std::vector{vecsignalRegionRight}, "Outer values of signal region vs pT"}; Configurable> sidebandLeftInner{"sidebandLeftInner", std::vector{vecSidebandLeftInner}, "Inner values of left sideband vs pT"}; Configurable> sidebandLeftOuter{"sidebandLeftOuter", std::vector{vecSidebandLeftOuter}, "Outer values of left sideband vs pT"}; Configurable> sidebandRightInner{"sidebandRightInner", std::vector{vecSidebandRightInner}, "Inner values of right sideband vs pT"}; @@ -108,52 +92,82 @@ struct HfTaskCorrelationD0Hadrons { HistogramRegistry registry{ "registry", - {{"hDeltaEtaPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}}, - {"hCorrel2DPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hCorrel2DVsPtSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, // note: axes 3 and 4 (the pT) are updated in the init() - {"hDeltaEtaPtIntSidebands", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}}, - {"hCorrel2DPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hCorrel2DVsPtSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, // note: axes 3 and 4 (the pT) are updated in the init() - {"hCorrel2DVsPtRecSig", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, - {"hCorrel2DVsPtRecBg", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, + {{"hDeltaEtaPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DPtIntSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hCorrel2DVsPtSignalRegion", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, // note: axes 3 and 4 (the pT) are updated in the init() + {"hDeltaEtaPtIntSignalRegionSoftPi", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSignalRegionSoftPi", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DPtIntSignalRegionSoftPi", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hCorrel2DVsPtSignalRegionSoftPi", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, // note: axes 3 and 4 (the pT) are updated in the init() + {"hDeltaEtaPtIntSidebands", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DPtIntSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hCorrel2DVsPtSidebands", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, // note: axes 3 and 4 (the pT) are updated in the init() + {"hDeltaEtaPtIntSidebandsSoftPi", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSidebandsSoftPi", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DPtIntSidebandsSoftPi", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hCorrel2DVsPtSidebandsSoftPi", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, // note: axes 3 and 4 (the pT) are updated in the init() + {"hCorrel2DVsPtRecSig", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DVsPtRecBg", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, // correlation histograms for MCRec for signal only - {"hCorrel2DVsPtSignalRegionRecSig", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, - {"hCorrel2DPtIntSignalRegionRecSig", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hDeltaEtaPtIntSignalRegionRecSig", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntSignalRegionRecSig", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}}, - {"hCorrel2DVsPtSidebandsRecSig", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, - {"hCorrel2DPtIntSidebandsRecSig", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hDeltaEtaPtIntSidebandsRecSig", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntSidebandsRecSig", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}}, + {"hCorrel2DVsPtSignalRegionRecSig", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DVsPtSignalRegionSoftPiRecSig", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSignalRegionRecSig", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hCorrel2DPtIntSignalRegionSoftPiRecSig", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSignalRegionRecSig", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaEtaPtIntSignalRegionSoftPiRecSig", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSignalRegionRecSig", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hDeltaPhiPtIntSignalRegionSoftPiRecSig", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DVsPtSidebandsRecSig", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DVsPtSidebandsSoftPiRecSig", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSidebandsRecSig", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hCorrel2DPtIntSidebandsSoftPiRecSig", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSidebandsRecSig", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaEtaPtIntSidebandsSoftPiRecSig", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSidebandsRecSig", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hDeltaPhiPtIntSidebandsSoftPiRecSig", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, // correlation histograms for MCRec for reflection candidates only - {"hCorrel2DVsPtSignalRegionRecRef", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, - {"hCorrel2DPtIntSignalRegionRecRef", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hDeltaEtaPtIntSignalRegionRecRef", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntSignalRegionRecRef", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}}, - {"hCorrel2DVsPtSidebandsRecRef", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, - {"hCorrel2DPtIntSidebandsRecRef", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hDeltaEtaPtIntSidebandsRecRef", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntSidebandsRecRef", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}}, + {"hCorrel2DVsPtSignalRegionRecRef", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSignalRegionRecRef", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSignalRegionRecRef", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSignalRegionRecRef", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DVsPtSidebandsRecRef", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSidebandsRecRef", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSidebandsRecRef", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSidebandsRecRef", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DVsPtSignalRegionSoftPiRecRef", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSignalRegionSoftPiRecRef", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSignalRegionSoftPiRecRef", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSignalRegionSoftPiRecRef", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DVsPtSidebandsSoftPiRecRef", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSidebandsSoftPiRecRef", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSidebandsSoftPiRecRef", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSidebandsSoftPiRecRef", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, // correlation histograms for MCRec for background candidates only - {"hCorrel2DVsPtSignalRegionRecBg", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, - {"hCorrel2DPtIntSignalRegionRecBg", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hDeltaEtaPtIntSignalRegionRecBg", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntSignalRegionRecBg", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}}, - {"hCorrel2DVsPtSidebandsRecBg", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, - {"hCorrel2DPtIntSidebandsRecBg", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hDeltaEtaPtIntSidebandsRecBg", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntSidebandsRecBg", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}}, + {"hCorrel2DVsPtSignalRegionRecBg", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSignalRegionRecBg", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSignalRegionRecBg", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSignalRegionRecBg", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DVsPtSidebandsRecBg", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSidebandsRecBg", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSidebandsRecBg", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSidebandsRecBg", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DVsPtSignalRegionSoftPiRecBg", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSignalRegionSoftPiRecBg", stringDHadron + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSignalRegionSoftPiRecBg", stringDHadron + stringSignal + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSignalRegionSoftPiRecBg", stringDHadron + stringSignal + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, + {"hCorrel2DVsPtSidebandsSoftPiRecBg", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, + {"hCorrel2DPtIntSidebandsSoftPiRecBg", stringDHadron + stringSideband + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntSidebandsSoftPiRecBg", stringDHadron + stringSideband + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntSidebandsSoftPiRecBg", stringDHadron + stringSideband + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}, // correlation histograms for MCGen - {"hCorrel2DVsPtGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + stringPtD + "entries", {HistType::kTHnSparseD, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {nEtaBinsCorrelations, etaMinCorrelations, etaMaxCorrelations}, {10, 0., 10.}, {11, 0., 11.}}}}, // note: axes 3 and 4 (the pT) are updated in the init(), - {"hCorrel2DPtIntGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}, {200, -10., 10.}}}}, - {"hDeltaEtaPtIntGen", stringMCParticles + stringDeltaEta + "entries", {HistType::kTH1F, {{200, -10., 10.}}}}, - {"hDeltaPhiPtIntGen", stringMCParticles + stringDeltaPhi + "entries", {HistType::kTH1F, {{nPhiBinsCorrelations, phiMinCorrelations, phiMaxCorrelations}}}} + {"hCorrel2DVsPtGen", stringMcParticles + stringDeltaPhi + stringDeltaEta + stringPtD + "entries", {HistType::kTHnSparseD, {{axisDeltaPhi}, {axisDeltaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, // note: axes 3 and 4 (the pT) are updated in the init(), + {"hCorrel2DPtIntGen", stringMcParticles + stringDeltaPhi + stringDeltaEta + "entries", {HistType::kTH2F, {{axisDeltaPhi}, {axisDeltaEta}}}}, + {"hDeltaEtaPtIntGen", stringMcParticles + stringDeltaEta + "entries", {HistType::kTH1F, {axisDeltaEta}}}, + {"hDeltaPhiPtIntGen", stringMcParticles + stringDeltaPhi + "entries", {HistType::kTH1F, {axisDeltaPhi}}}}}; - }}; - - void init(o2::framework::InitContext&) + void init(InitContext&) { int nBinsPtAxis = binsCorrelations->size() - 1; const double* valuesPtAxis = binsCorrelations->data(); @@ -161,18 +175,34 @@ struct HfTaskCorrelationD0Hadrons { registry.get(HIST("hCorrel2DVsPtSidebands"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtSignalRegion"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSidebands"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSignalRegionSoftPi"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtSidebandsSoftPi"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtSignalRegionSoftPi"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandsSoftPi"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSignalRegionRecSig"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtSignalRegionSoftPiRecSig"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtSidebandsRecSig"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtSidebandsSoftPiRecSig"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtSignalRegionRecSig"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSignalRegionSoftPiRecSig"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSidebandsRecSig"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandsSoftPiRecSig"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSignalRegionRecRef"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtSidebandsRecRef"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtSignalRegionRecRef"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSidebandsRecRef"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSignalRegionSoftPiRecRef"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtSidebandsSoftPiRecRef"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtSignalRegionSoftPiRecRef"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandsSoftPiRecRef"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSignalRegionRecBg"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtSidebandsRecBg"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtSignalRegionRecBg"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtSidebandsRecBg"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSignalRegionSoftPiRecBg"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtSidebandsSoftPiRecBg"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtSignalRegionSoftPiRecBg"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtSidebandsSoftPiRecBg"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtRecSig"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtRecSig"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtRecBg"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); @@ -185,7 +215,7 @@ struct HfTaskCorrelationD0Hadrons { /// Works on both USL and LS analyses pair tables void processData(aod::DHadronPairFull const& pairEntries) { - for (auto const& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -196,6 +226,7 @@ struct HfTaskCorrelationD0Hadrons { int signalStatus = pairEntry.signalStatus(); int effBinD = o2::analysis::findBin(binsEfficiency, ptD); int ptBinD = o2::analysis::findBin(binsCorrelations, ptD); + int poolBin = pairEntry.poolBin(); // reject entries outside pT ranges of interest if (ptBinD < 0 || effBinD < 0) { @@ -215,48 +246,84 @@ struct HfTaskCorrelationD0Hadrons { continue; } // check if correlation entry belongs to signal region, sidebands or is outside both, and fill correlation plots - if ((massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) && ((signalStatus == 1) || (signalStatus == 3))) { + if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && ((signalStatus == ParticleTypeData::D0Only) || (signalStatus == ParticleTypeData::D0D0barBoth))) { // in signal region - registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegion"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegion"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegion"), deltaPhi, efficiencyWeight); } - if ((massDbar > signalRegionInner->at(ptBinD) && massDbar < signalRegionOuter->at(ptBinD)) && (signalStatus >= 2)) { + if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && ((signalStatus == ParticleTypeData::D0OnlySoftPi) || (signalStatus >= ParticleTypeData::D0D0barBothSoftPi))) { + // in signal region, fills for soft pion only in ME + registry.fill(HIST("hCorrel2DVsPtSignalRegionSoftPi"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSignalRegionSoftPi"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSignalRegionSoftPi"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSignalRegionSoftPi"), deltaPhi, efficiencyWeight); + } + + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && ((signalStatus == ParticleTypeData::D0barOnly) || (signalStatus == ParticleTypeData::D0D0barBoth))) { // in signal region - registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegion"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegion"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegion"), deltaPhi, efficiencyWeight); } + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && (signalStatus >= ParticleTypeData::D0barOnlySoftPi)) { + // in signal region, fills for soft pion only in ME + registry.fill(HIST("hCorrel2DVsPtSignalRegionSoftPi"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSignalRegionSoftPi"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSignalRegionSoftPi"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSignalRegionSoftPi"), deltaPhi, efficiencyWeight); + } + if (((massD > sidebandLeftOuter->at(ptBinD) && massD < sidebandLeftInner->at(ptBinD)) || (massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD))) && - ((signalStatus == 1) || (signalStatus == 3))) { + ((signalStatus == ParticleTypeData::D0Only) || (signalStatus == ParticleTypeData::D0D0barBoth))) { // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebands"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebands"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSidebands"), deltaPhi, efficiencyWeight); } + if (((massD > sidebandLeftOuter->at(ptBinD) && massD < sidebandLeftInner->at(ptBinD)) || + (massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD))) && + ((signalStatus == ParticleTypeData::D0OnlySoftPi) || (signalStatus >= ParticleTypeData::D0D0barBothSoftPi))) { + // in sideband region, fills for soft pion only in ME + registry.fill(HIST("hCorrel2DVsPtSidebandsSoftPi"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSidebandsSoftPi"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandsSoftPi"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandsSoftPi"), deltaPhi, efficiencyWeight); + } + if (((massDbar > sidebandLeftOuter->at(ptBinD) && massDbar < sidebandLeftInner->at(ptBinD)) || (massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD))) && - (signalStatus >= 2)) { + ((signalStatus == ParticleTypeData::D0barOnly) || (signalStatus == ParticleTypeData::D0D0barBoth))) { // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebands"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebands"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSidebands"), deltaPhi, efficiencyWeight); } + + if (((massDbar > sidebandLeftOuter->at(ptBinD) && massDbar < sidebandLeftInner->at(ptBinD)) || + (massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD))) && + (signalStatus >= ParticleTypeData::D0barOnlySoftPi)) { + // in sideband region, fills for soft pion only in ME + registry.fill(HIST("hCorrel2DVsPtSidebandsSoftPi"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSidebandsSoftPi"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandsSoftPi"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandsSoftPi"), deltaPhi, efficiencyWeight); + } } } PROCESS_SWITCH(HfTaskCorrelationD0Hadrons, processData, "Process data", false); void processMcRec(aod::DHadronPairFull const& pairEntries) { - for (auto const& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -265,8 +332,8 @@ struct HfTaskCorrelationD0Hadrons { double massD = pairEntry.mD(); double massDbar = pairEntry.mDbar(); int signalStatus = pairEntry.signalStatus(); - int ptBinD = o2::analysis::findBin(binsCorrelations, ptD); + int poolBin = pairEntry.poolBin(); double efficiencyWeight = 1.; if (applyEfficiency) { @@ -284,27 +351,35 @@ struct HfTaskCorrelationD0Hadrons { // check if correlation entry belongs to signal region, sidebands or is outside both, and fill correlation plots // ---------------------- Fill plots for signal case, D0 ->1, D0bar ->8 --------------------------------------------- - if ((massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) && (signalStatus == 1)) { - // in signal region - registry.fill(HIST("hCorrel2DVsPtSignalRegionRecSig"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && (TESTBIT(signalStatus, ParticleTypeMcRec::D0Sig))) { + // in signal region, tests bit ParticleTypeMcRec::D0Sig, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSignalRegionRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionRecSig"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionRecSig"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionRecSig"), deltaPhi, efficiencyWeight); } - if ((massDbar > signalRegionInner->at(ptBinD) && massDbar < signalRegionOuter->at(ptBinD)) && (signalStatus == 8)) { - // in signal region - registry.fill(HIST("hCorrel2DVsPtSignalRegionRecSig"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && (TESTBIT(signalStatus, ParticleTypeMcRec::D0barSig))) { + // in signal region, tests bit ParticleTypeMcRec::D0barSig, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSignalRegionRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionRecSig"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionRecSig"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionRecSig"), deltaPhi, efficiencyWeight); } + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && (signalStatus >= BIT(ParticleTypeMcRec::SoftPi))) { + // in signal region, fills for soft pion only for event mixing, tests bit at least ParticleTypeMcRec::SoftPi + registry.fill(HIST("hCorrel2DVsPtSignalRegionSoftPiRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSignalRegionSoftPiRecSig"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSignalRegionSoftPiRecSig"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSignalRegionSoftPiRecSig"), deltaPhi, efficiencyWeight); + } + if ((((massD > sidebandLeftOuter->at(ptBinD)) && (massD < sidebandLeftInner->at(ptBinD))) || ((massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD)))) && - (signalStatus == 1)) { - // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebandsRecSig"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + ((TESTBIT(signalStatus, ParticleTypeMcRec::D0Sig)))) { + // in sideband region, tests bit ParticleTypeMcRec::D0Sig, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSidebandsRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebandsRecSig"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebandsRecSig"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSidebandsRecSig"), deltaPhi, efficiencyWeight); @@ -312,36 +387,54 @@ struct HfTaskCorrelationD0Hadrons { if ((((massDbar > sidebandLeftOuter->at(ptBinD)) && (massDbar < sidebandLeftInner->at(ptBinD))) || ((massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD)))) && - (signalStatus == 8)) { - // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebandsRecSig"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + (TESTBIT(signalStatus, ParticleTypeMcRec::D0barSig))) { + // in sideband region, tests bit ParticleTypeMcRec::D0barSig, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSidebandsRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebandsRecSig"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebandsRecSig"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSidebandsRecSig"), deltaPhi, efficiencyWeight); } + if ((((massDbar > sidebandLeftOuter->at(ptBinD)) && (massDbar < sidebandLeftInner->at(ptBinD))) || + ((massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD)))) && + (signalStatus >= BIT(ParticleTypeMcRec::SoftPi))) { + // in sideband region, fills for soft pion only for event mixing, tests bit at least ParticleTypeMcRec::SoftPi + registry.fill(HIST("hCorrel2DVsPtSidebandsSoftPiRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSidebandsSoftPiRecSig"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandsSoftPiRecSig"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandsSoftPiRecSig"), deltaPhi, efficiencyWeight); + } + // ---------------------- Fill plots for reflection case, D0 ->2, D0bar ->16 --------------------------------------------- - if ((massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) && (signalStatus == 2)) { - // in signal region + if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && TESTBIT(signalStatus, ParticleTypeMcRec::D0Ref)) { + // in signal region, SE-> softpi removed, ME-> inclusive registry.fill(HIST("hCorrel2DVsPtSignalRegionRecRef"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionRecRef"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionRecRef"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionRecRef"), deltaPhi, efficiencyWeight); } - if ((massDbar > signalRegionInner->at(ptBinD) && massDbar < signalRegionOuter->at(ptBinD)) && (signalStatus == 16)) { - // in signal region - registry.fill(HIST("hCorrel2DVsPtSignalRegionRecRef"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && TESTBIT(signalStatus, ParticleTypeMcRec::D0barRef)) { + // in signal region, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSignalRegionRecRef"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionRecRef"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionRecRef"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionRecRef"), deltaPhi, efficiencyWeight); } + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && (signalStatus >= BIT(ParticleTypeMcRec::SoftPi))) { + // in signal region, fills for soft pion only for event mixing, tests bit at least ParticleTypeMcRec::SoftPi + registry.fill(HIST("hCorrel2DVsPtSignalRegionSoftPiRecRef"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSignalRegionSoftPiRecRef"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSignalRegionSoftPiRecRef"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSignalRegionSoftPiRecRef"), deltaPhi, efficiencyWeight); + } + if ((((massD > sidebandLeftOuter->at(ptBinD)) && (massD < sidebandLeftInner->at(ptBinD))) || ((massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD)))) && - (signalStatus == 2)) { - // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebandsRecRef"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + TESTBIT(signalStatus, ParticleTypeMcRec::D0Ref)) { + // in sideband region, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSidebandsRecRef"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebandsRecRef"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebandsRecRef"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSidebandsRecRef"), deltaPhi, efficiencyWeight); @@ -349,36 +442,54 @@ struct HfTaskCorrelationD0Hadrons { if ((((massDbar > sidebandLeftOuter->at(ptBinD)) && (massDbar < sidebandLeftInner->at(ptBinD))) || ((massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD)))) && - (signalStatus == 16)) { - // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebandsRecRef"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + TESTBIT(signalStatus, ParticleTypeMcRec::D0barRef)) { + // in sideband region, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSidebandsRecRef"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebandsRecRef"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebandsRecRef"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSidebandsRecRef"), deltaPhi, efficiencyWeight); } + if ((((massDbar > sidebandLeftOuter->at(ptBinD)) && (massDbar < sidebandLeftInner->at(ptBinD))) || + ((massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD)))) && + (signalStatus >= BIT(ParticleTypeMcRec::SoftPi))) { + // in sideband region, fills for soft pion only for event mixing, tests bit at least ParticleTypeMcRec::SoftPi + registry.fill(HIST("hCorrel2DVsPtSidebandsSoftPiRecRef"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSidebandsSoftPiRecRef"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandsSoftPiRecRef"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandsSoftPiRecRef"), deltaPhi, efficiencyWeight); + } + // ---------------------- Fill plots for background case, D0 ->4, D0bar ->32 --------------------------------------------- - if ((massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) && (signalStatus == 4)) { - // in signal region - registry.fill(HIST("hCorrel2DVsPtSignalRegionRecBg"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && TESTBIT(signalStatus, ParticleTypeMcRec::D0Bg)) { + // in signal region, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSignalRegionRecBg"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionRecBg"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionRecBg"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionRecBg"), deltaPhi, efficiencyWeight); } - if ((massDbar > signalRegionInner->at(ptBinD) && massDbar < signalRegionOuter->at(ptBinD)) && (signalStatus == 32)) { - // in signal region - registry.fill(HIST("hCorrel2DVsPtSignalRegionRecBg"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && TESTBIT(signalStatus, ParticleTypeMcRec::D0barBg)) { + // in signal region, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSignalRegionRecBg"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionRecBg"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionRecBg"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionRecBg"), deltaPhi, efficiencyWeight); } + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && (signalStatus >= BIT(ParticleTypeMcRec::SoftPi))) { + // in signal region, fills for soft pion only for event mixing, tests bit at least ParticleTypeMcRec::SoftPi + registry.fill(HIST("hCorrel2DVsPtSignalRegionSoftPiRecBg"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSignalRegionSoftPiRecBg"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSignalRegionSoftPiRecBg"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSignalRegionSoftPiRecBg"), deltaPhi, efficiencyWeight); + } + if ((((massD > sidebandLeftOuter->at(ptBinD)) && (massD < sidebandLeftInner->at(ptBinD))) || ((massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD)))) && - (signalStatus == 4)) { - // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebandsRecBg"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + TESTBIT(signalStatus, ParticleTypeMcRec::D0Bg)) { + // in sideband region, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSidebandsRecBg"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebandsRecBg"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebandsRecBg"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSidebandsRecBg"), deltaPhi, efficiencyWeight); @@ -386,13 +497,23 @@ struct HfTaskCorrelationD0Hadrons { if ((((massDbar > sidebandLeftOuter->at(ptBinD)) && (massDbar < sidebandLeftInner->at(ptBinD))) || ((massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD)))) && - (signalStatus == 32)) { - // in sideband region - registry.fill(HIST("hCorrel2DVsPtSidebandsRecBg"), deltaPhi, deltaEta, ptD, ptHadron, efficiencyWeight); + TESTBIT(signalStatus, ParticleTypeMcRec::D0barBg)) { + // in sideband region, SE-> softpi removed, ME-> inclusive + registry.fill(HIST("hCorrel2DVsPtSidebandsRecBg"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebandsRecBg"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSidebandsRecBg"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSidebandsRecBg"), deltaPhi, efficiencyWeight); } + + if ((((massDbar > sidebandLeftOuter->at(ptBinD)) && (massDbar < sidebandLeftInner->at(ptBinD))) || + ((massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD)))) && + (signalStatus >= BIT(ParticleTypeMcRec::SoftPi))) { + // in sideband region, fills for soft pion only for event mixing, tests bit at least ParticleTypeMcRec::SoftPi + registry.fill(HIST("hCorrel2DVsPtSidebandsSoftPiRecBg"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DPtIntSidebandsSoftPiRecBg"), deltaPhi, deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaEtaPtIntSidebandsSoftPiRecBg"), deltaEta, efficiencyWeight); + registry.fill(HIST("hDeltaPhiPtIntSidebandsSoftPiRecBg"), deltaPhi, efficiencyWeight); + } } } PROCESS_SWITCH(HfTaskCorrelationD0Hadrons, processMcRec, "Process MC Reco mode", true); @@ -400,12 +521,13 @@ struct HfTaskCorrelationD0Hadrons { /// D-Hadron correlation pair filling task, from pair tables - for MC gen-level analysis (no filter/selection, only true signal) void processMcGen(aod::DHadronPairFull const& pairEntries) { - for (auto const& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); double ptD = pairEntry.ptD(); double ptHadron = pairEntry.ptHadron(); + int poolBin = pairEntry.poolBin(); // reject entries outside pT ranges of interest if (o2::analysis::findBin(binsCorrelations, ptD) < 0) { continue; @@ -414,7 +536,7 @@ struct HfTaskCorrelationD0Hadrons { ptHadron = ptHadronMax + 0.5; } - registry.fill(HIST("hCorrel2DVsPtGen"), deltaPhi, deltaEta, ptD, ptHadron); + registry.fill(HIST("hCorrel2DVsPtGen"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); registry.fill(HIST("hCorrel2DPtIntGen"), deltaPhi, deltaEta); registry.fill(HIST("hDeltaEtaPtIntGen"), deltaEta); registry.fill(HIST("hDeltaPhiPtIntGen"), deltaPhi); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx b/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx index 64a2991fbec..3172d8e6e22 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx @@ -20,14 +20,12 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_correlation_d_dbar; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; -using namespace o2::constants::math; namespace o2::aod { @@ -158,7 +156,7 @@ struct HfTaskCorrelationDDbar { {"hDeltaPtDDbarMCGen", stringMCParticles + stringDeltaPt + "entries", {HistType::kTH1F, {{144, -36., 36.}}}}, {"hDeltaPtMaxMinMCGen", stringMCParticles + stringDeltaPtMaxMin + "entries", {HistType::kTH1F, {{72, 0., 36.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { // redefinition of pT axes for THnSparse holding correlation entries int nBinspTaxis = binsPtCorrelations->size() - 1; @@ -234,7 +232,7 @@ struct HfTaskCorrelationDDbar { /// Works on both USL and LS analyses pair tables void processData(aod::DDbarPairFull const& pairEntries) { - for (auto& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { //define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -282,7 +280,7 @@ struct HfTaskCorrelationDDbar { registry.fill(HIST("hDeltaPtDDbarSidebands"), ptDbar - ptD, efficiencyWeight); registry.fill(HIST("hDeltaPtMaxMinSidebands"), std::abs(ptDbar - ptD), efficiencyWeight); } - } //end loop + } // end loop } PROCESS_SWITCH(HfTaskCorrelationDDbar, processData, "Process data", false); @@ -291,7 +289,7 @@ struct HfTaskCorrelationDDbar { /// Works on both USL and LS analyses pair tables void processMcRec(aod::DDbarPairFull const& pairEntries) { - for (auto& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { //define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -429,7 +427,7 @@ struct HfTaskCorrelationDDbar { break; } } - } //end loop + } // end loop } PROCESS_SWITCH(HfTaskCorrelationDDbar, processMcRec, "Process MC Reco mode", true); @@ -438,7 +436,7 @@ struct HfTaskCorrelationDDbar { /// Works on both USL and LS analyses pair tables (and if tables are filled with quark pairs as well) void processMcGen(aod::DDbarPair const& pairEntries) { - for (auto& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { //define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -456,7 +454,7 @@ struct HfTaskCorrelationDDbar { registry.fill(HIST("hDeltaPhiPtIntMCGen"), deltaPhi); registry.fill(HIST("hDeltaPtDDbarMCGen"), ptDbar - ptD); registry.fill(HIST("hDeltaPtMaxMinMCGen"), std::abs(ptDbar - ptD)); - } //end loop + } // end loop } PROCESS_SWITCH(HfTaskCorrelationDDbar, processMcGen, "Process MC Gen mode", false); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx b/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx index 5d7c8f65545..c6a319fecfc 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx @@ -21,15 +21,12 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/DMesonPairsTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; -using namespace o2::constants::math; namespace o2::aod { @@ -77,18 +74,20 @@ double evaluatePhiByVertex(double xVertex1, double xVertex2, double yVertex1, do } // string definitions, used for histogram axis labels -const TString stringPtD = "#it{p}_{T}^{D} (GeV/#it{c});"; -const TString stringPtDbar = "#it{p}_{T}^{Dbar} (GeV/#it{c});"; -const TString stringDeltaPt = "#it{p}_{T}^{Dbar}-#it{p}_{T}^{D} (GeV/#it{c});"; +const TString stringPtD = "#it{p}_{T}^{D_{1}} (GeV/#it{c});"; +const TString stringPtDbar = "#it{p}_{T}^{D_{2}} (GeV/#it{c});"; +const TString stringDeltaPt = "#it{p}_{T}^{D_{2}}-#it{p}_{T}^{D_{1}} (GeV/#it{c});"; const TString stringDeltaPtMaxMin = "#it{p}_{T}^{max}-#it{p}_{T}^{min} (GeV/#it{c});"; -const TString stringDeltaEta = "#it{#eta}^{Dbar}-#it{#eta}^{D};"; -const TString stringDeltaY = "#it{y}^{Dbar}-#it{y}^{D};"; -const TString stringDeltaPhi = "#it{#varphi}^{Dbar}-#it{#varphi}^{D} (rad);"; -const TString stringDDbar = "D,Dbar candidates "; +const TString stringDeltaEta = "#it{#eta}^{D_{2}}-#it{#eta}^{D_{1}};"; +const TString stringDeltaY = "#it{y}^{D_{2}}-#it{y}^{D_{1}};"; +const TString stringDeltaPhi = "#it{#varphi}^{D_{2}}-#it{#varphi}^{D_{1}} (rad);"; +const TString stringDDbar = "D meson pair candidates "; const TString stringSignal = "signal region;"; const TString stringSideband = "sidebands;"; -const TString stringMCParticles = "MC gen - D,Dbar particles;"; -const TString stringMCReco = "MC reco - D,Dbar candidates "; +const TString stringMCParticles = "MC gen - D meson pair particles;"; +const TString stringMCReco = "MC reco - D meson pair candidates "; +const TString stringMassD = "inv. mass D_{1} (GeV/#it{c}^{2});"; +const TString stringMassDbar = "inv. mass D_{2} (GeV/#it{c}^{2});"; // definition of vectors for standard ptbin and invariant mass configurables const int nPtBinsCorrelations = 8; @@ -108,6 +107,8 @@ auto vecSidebandRightInner = std::vector{sidebandRightInnerDefault, side auto vecSidebandRightOuter = std::vector{sidebandRightOuterDefault, sidebandRightOuterDefault + nPtBinsCorrelations}; struct HfTaskCorrelationDMesonPairs { + // Enable histograms with finer pT and y binning + Configurable enableFinerBinning{"enableFinerBinning", false, "Enable histograms with finer pT and y binning"}; // pT ranges for correlation plots: the default values are those embedded in hf_cuts_d0_to_pi_k (i.e. the mass pT bins), but can be redefined via json files Configurable> binsPtCorrelations{"binsPtCorrelations", std::vector{vecPtBinsCorrelations}, "pT bin limits for correlation plots"}; // signal and sideband region edges, to be defined via json file (initialised to empty) @@ -127,6 +128,7 @@ struct HfTaskCorrelationDMesonPairs { HistogramConfigSpec hTH1DeltaPtMaxMin{HistType::kTH1F, {{72, 0., 36.}}}; HistogramConfigSpec hTH1Phi{HistType::kTH1F, {{64, -o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf}}}; HistogramConfigSpec hTH2CorrelPt{HistType::kTH2F, {{64, -o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf}, {200, -10., 10.}}}; + HistogramConfigSpec hTHnMass2DCorrPairsFinerBinning{HistType::kTHnSparseD, {{200, 1.6, 2.1}, {200, 1.6, 2.1}, {60, 1., 6.}, {60, 1., 6.}, {160, -0.8, 0.8}, {160, -0.8, 0.8}}}; HistogramRegistry registry{ "registry", @@ -146,18 +148,18 @@ struct HfTaskCorrelationDMesonPairs { {"hCorrel2DVsPtSidebands", stringDDbar + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtDbar + "entries", hTHnCorrel2DVsPt}, {"hDeltaPtDDbarSidebands", stringDDbar + stringSideband + stringDeltaPt + "entries", hTH1DeltaPtDDbar}, {"hDeltaPtMaxMinSidebands", stringDDbar + stringSideband + stringDeltaPtMaxMin + "entries", hTH1DeltaPtMaxMin}, - {"hMass2DCorrelationPairsMCRecBkgBkg", stringDDbar + "2D BkgBkg - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, - {"hMass2DCorrelationPairsMCRecBkgRef", stringDDbar + "2D BkgRef - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, - {"hMass2DCorrelationPairsMCRecBkgSig", stringDDbar + "2D BkgSig - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, - {"hMass2DCorrelationPairsMCRecRefBkg", stringDDbar + "2D RefBkg - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, - {"hMass2DCorrelationPairsMCRecRefRef", stringDDbar + "2D RefRef - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, - {"hMass2DCorrelationPairsMCRecRefSig", stringDDbar + "2D RefSig - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, - {"hMass2DCorrelationPairsMCRecSigBkg", stringDDbar + "2D SigBkg - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, - {"hMass2DCorrelationPairsMCRecSigRef", stringDDbar + "2D SigRef - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, - {"hMass2DCorrelationPairsMCRecSigSig", stringDDbar + "2D SigSig - MC reco;inv. mass D (GeV/#it{c}^{2});inv. mass Dbar (GeV/#it{c}^{2});" + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecBkgBkg", stringDDbar + "2D BkgBkg - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecBkgRef", stringDDbar + "2D BkgRef - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecBkgSig", stringDDbar + "2D BkgSig - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecRefBkg", stringDDbar + "2D RefBkg - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecRefRef", stringDDbar + "2D RefRef - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecRefSig", stringDDbar + "2D RefSig - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecSigBkg", stringDDbar + "2D SigBkg - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecSigRef", stringDDbar + "2D SigRef - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, + {"hMass2DCorrelationPairsMCRecSigSig", stringDDbar + "2D SigSig - MC reco;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairs}, {"hDeltaEtaPtIntSignalRegionMCRec", stringMCReco + stringSignal + stringDeltaEta + "entries", hTH1Y}, {"hDeltaPhiPtIntSignalRegionMCRec", stringMCReco + stringSignal + stringDeltaPhi + "entries", hTH1Phi}, - {"hDeltaYPtIntSignalRegionMCRec", stringMCReco + stringSignal + stringDeltaEta + "entries", hTH1Y}, + {"hDeltaYPtIntSignalRegionMCRec", stringMCReco + stringSignal + stringDeltaY + "entries", hTH1Y}, {"hCorrel2DPtIntSignalRegionMCRec", stringMCReco + stringSignal + stringDeltaPhi + stringDeltaEta + "entries", hTH2CorrelPt}, {"hDeltaPtDDbarSignalRegionMCRec", stringMCReco + stringSignal + stringDeltaPt + "entries", hTH1DeltaPtDDbar}, {"hDeltaPtMaxMinSignalRegionMCRec", stringMCReco + stringSignal + stringDeltaPtMaxMin + "entries", hTH1DeltaPtMaxMin}, @@ -185,19 +187,42 @@ struct HfTaskCorrelationDMesonPairs { {"hCorrel2DVsPtSidebandsMCRecSigRef", stringMCReco + "SigRef" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtDbar + "entries", hTHnCorrel2DVsPt}, {"hCorrel2DVsPtSidebandsMCRecSigSig", stringMCReco + "SigSig" + stringSideband + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtDbar + "entries", hTHnCorrel2DVsPt}, {"hDeltaEtaPtIntMCGen", stringMCParticles + stringDeltaEta + "entries", hTH1Y}, - {"hDeltaYPtIntMCGen", stringMCParticles + stringDeltaEta + "entries", hTH1Y}, + {"hDeltaYPtIntMCGen", stringMCParticles + stringDeltaY + "entries", hTH1Y}, {"hDeltaPhiPtIntMCGen", stringMCParticles + stringDeltaPhi + "entries", hTH1Phi}, {"hCorrel2DPtIntMCGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + "entries", hTH2CorrelPt}, {"hCorrel2DVsPtMCGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtDbar + "entries", hTHnCorrel2DVsPt}, {"hDeltaPtDDbarMCGen", stringMCParticles + stringDeltaPt + "entries", hTH1DeltaPtDDbar}, {"hDeltaPtMaxMinMCGen", stringMCParticles + stringDeltaPtMaxMin + "entries", hTH1DeltaPtMaxMin}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { // redefinition of pT axes for THnSparse holding correlation entries int nBinspTaxis = binsPtCorrelations->size() - 1; const double* valuespTaxis = binsPtCorrelations->data(); + if (enableFinerBinning) { + registry.add("hMass2DCorrelationPairsFinerBinning", stringDDbar + "2D Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecBkgBkgFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecBkgRefFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecBkgSigFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecRefBkgFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecRefRefFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecRefSigFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecSigBkgFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecSigRefFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.add("hMass2DCorrelationPairsMCRecSigSigFinerBinning", stringDDbar + "2D BkgBkg - MC reco Finer Binning;" + stringMassD + stringMassDbar + stringPtD + stringPtDbar + "entries", hTHnMass2DCorrPairsFinerBinning); + registry.get(HIST("hMass2DCorrelationPairsFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecBkgBkgFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecBkgRefFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecBkgSigFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecRefBkgFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecRefRefFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecRefSigFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecSigBkgFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecSigRefFinerBinning"))->Sumw2(); + registry.get(HIST("hMass2DCorrelationPairsMCRecSigSigFinerBinning"))->Sumw2(); + } + for (int i = 2; i <= 3; i++) { registry.get(HIST("hMass2DCorrelationPairs"))->GetAxis(i)->Set(nBinspTaxis, valuespTaxis); registry.get(HIST("hCorrel2DVsPtSignalRegion"))->GetAxis(i)->Set(nBinspTaxis, valuespTaxis); @@ -382,10 +407,19 @@ struct HfTaskCorrelationDMesonPairs { // fill 2D invariant mass plots if (pairType == DD && (TESTBIT(pairEntry.candidateType1(), SelectedD) && TESTBIT(pairEntry.candidateType2(), SelectedD))) { registry.fill(HIST("hMass2DCorrelationPairs"), massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + if (enableFinerBinning) { + registry.fill(HIST("hMass2DCorrelationPairsFinerBinning"), massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + } } else if (pairType == DDbar && ((TESTBIT(pairEntry.candidateType1(), SelectedD) && TESTBIT(pairEntry.candidateType2(), SelectedDbar)) || (TESTBIT(pairEntry.candidateType1(), SelectedDbar) && TESTBIT(pairEntry.candidateType2(), SelectedD)))) { registry.fill(HIST("hMass2DCorrelationPairs"), massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + if (enableFinerBinning) { + registry.fill(HIST("hMass2DCorrelationPairsFinerBinning"), massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + } } else if (pairType == DbarDbar && (TESTBIT(pairEntry.candidateType1(), SelectedDbar) && TESTBIT(pairEntry.candidateType2(), SelectedDbar))) { registry.fill(HIST("hMass2DCorrelationPairs"), massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + if (enableFinerBinning) { + registry.fill(HIST("hMass2DCorrelationPairsFinerBinning"), massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + } } // reject entries outside pT ranges of interest @@ -440,6 +474,10 @@ struct HfTaskCorrelationDMesonPairs { {registry.get(HIST("hCorrel2DVsPtSidebandsMCRecRefSig")), registry.get(HIST("hCorrel2DVsPtSidebandsMCRecRefRef")), registry.get(HIST("hCorrel2DVsPtSidebandsMCRecRefBkg"))}, {registry.get(HIST("hCorrel2DVsPtSidebandsMCRecBkgSig")), registry.get(HIST("hCorrel2DVsPtSidebandsMCRecBkgRef")), registry.get(HIST("hCorrel2DVsPtSidebandsMCRecBkgBkg"))}}; + std::shared_ptr hMassCorrArrayFinerBinning[3][3] = {{registry.get(HIST("hMass2DCorrelationPairsMCRecSigSigFinerBinning")), registry.get(HIST("hMass2DCorrelationPairsMCRecSigRefFinerBinning")), registry.get(HIST("hMass2DCorrelationPairsMCRecSigBkgFinerBinning"))}, + {registry.get(HIST("hMass2DCorrelationPairsMCRecRefSigFinerBinning")), registry.get(HIST("hMass2DCorrelationPairsMCRecRefRefFinerBinning")), registry.get(HIST("hMass2DCorrelationPairsMCRecRefBkgFinerBinning"))}, + {registry.get(HIST("hMass2DCorrelationPairsMCRecBkgSigFinerBinning")), registry.get(HIST("hMass2DCorrelationPairsMCRecBkgRefFinerBinning")), registry.get(HIST("hMass2DCorrelationPairsMCRecBkgBkgFinerBinning"))}}; + for (const auto& pairEntry : pairEntries) { if (pairEntry.dataType() != 1) { // Assure that we only analyse Mc reco elements continue; @@ -469,13 +507,23 @@ struct HfTaskCorrelationDMesonPairs { switch (pairType) { case DD: // D0 D0 fillMassCorrHists(hMassCorrArray, dMesonCand1, dMesonCand2, massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + if (enableFinerBinning) { + fillMassCorrHists(hMassCorrArrayFinerBinning, dMesonCand1, dMesonCand2, massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + } break; case DDbar: // D0 D0bar fillMassCorrHists(hMassCorrArray, dMesonCand1, dMesonBarCand2, massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); fillMassCorrHists(hMassCorrArray, dMesonBarCand1, dMesonCand2, massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + if (enableFinerBinning) { + fillMassCorrHists(hMassCorrArrayFinerBinning, dMesonCand1, dMesonBarCand2, massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + fillMassCorrHists(hMassCorrArrayFinerBinning, dMesonBarCand1, dMesonCand2, massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + } break; case DbarDbar: // D0bar D0bar fillMassCorrHists(hMassCorrArray, dMesonBarCand1, dMesonBarCand2, massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + if (enableFinerBinning) { + fillMassCorrHists(hMassCorrArrayFinerBinning, dMesonBarCand1, dMesonBarCand2, massCand1, massCand2, ptCand1, ptCand2, yCand1, yCand2); + } break; } diff --git a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx index 61f5092d555..2d76eb36913 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx @@ -18,14 +18,12 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_correlation_dplus_hadron; -using namespace o2::analysis::hf_cuts_dplus_to_pi_k_pi; -using namespace o2::constants::math; namespace o2::aod { @@ -75,8 +73,7 @@ auto sidebandLeftOuter_v = std::vector{sidebandLeftOuterDefault, sideban auto sidebandRightInner_v = std::vector{sidebandRightInnerDefault, sidebandRightInnerDefault + npTBinsCorrelations}; auto sidebandRightOuter_v = std::vector{sidebandRightOuterDefault, sidebandRightOuterDefault + npTBinsCorrelations}; const int npTBinsEfficiency = o2::analysis::hf_cuts_dplus_to_pi_k_pi::nBinsPt; -const double efficiencyDmesonDefault[npTBinsEfficiency] = {}; -auto efficiencyDmeson_v = std::vector{efficiencyDmesonDefault, efficiencyDmesonDefault + npTBinsEfficiency}; +std::vector efficiencyDmeson(npTBinsEfficiency + 1); /// Dplus-Hadron correlation pair filling task, from pair tables - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) struct HfTaskCorrelationDplusHadrons { @@ -91,7 +88,7 @@ struct HfTaskCorrelationDplusHadrons { Configurable> sidebandLeftOuter{"sidebandLeftOuter", std::vector{sidebandLeftOuter_v}, "Outer values of left sideband vs pT"}; Configurable> sidebandRightInner{"sidebandRightInner", std::vector{sidebandRightInner_v}, "Inner values of right sideband vs pT"}; Configurable> sidebandRightOuter{"sidebandRightOuter", std::vector{sidebandRightOuter_v}, "Outer values of right sideband vs pT"}; - Configurable> efficiencyD{"efficiencyD", std::vector{efficiencyDmeson_v}, "Efficiency values for D meson specie under study"}; + Configurable> efficiencyD{"efficiencyD", std::vector{efficiencyDmeson}, "Efficiency values for D meson specie under study"}; HistogramRegistry registry{ "registry", @@ -120,7 +117,7 @@ struct HfTaskCorrelationDplusHadrons { {"hCorrel2DVsPtMCGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + stringPtD + "entries", {HistType::kTHnSparseD, {{64, -o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf}, {40, -2., 2.}, {10, 0., 10.}, {11, 0., 11.}, {9, 0., 9.}}}}, // note: axes 3 and 4 (the pT) are updated in the init() }}; - void init(o2::framework::InitContext&) + void init(InitContext&) { // redefinition of pT axes for THnSparse holding correlation entries int nBinspTaxis = binsPtCorrelations->size() - 1; @@ -144,7 +141,7 @@ struct HfTaskCorrelationDplusHadrons { void processData(aod::DplusHadronPairFull const& pairEntries) { - for (auto& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -191,7 +188,7 @@ struct HfTaskCorrelationDplusHadrons { /// D-Hadron correlation pair filling task, from pair tables - for MC reco-level analysis (candidates matched to true signal only, but also bkg sources are studied) void processMcRec(aod::DplusHadronPairFull const& pairEntries) { - for (auto& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -244,7 +241,7 @@ struct HfTaskCorrelationDplusHadrons { /// D-Hadron correlation pair filling task, from pair tables - for MC gen-level analysis (no filter/selection, only true signal) void processMcGen(aod::DplusHadronPair const& pairEntries) { - for (auto& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index 62aa05bdebb..0c5d4e0e3f2 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -20,14 +20,12 @@ #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_correlation_ds_hadron; -using namespace o2::analysis::hf_cuts_ds_to_k_k_pi; -using namespace o2::constants::math; /// Returns deltaPhi value in range [-pi/2., 3.*pi/2], typically used for correlation studies double getDeltaPhi(double phiD, double phiHadron) @@ -55,7 +53,7 @@ const TString stringMCParticles = "MC gen - D,Hadron particles;"; const TString stringMCReco = "MC reco - D,Hadron candidates "; // histogram axes definition -AxisSpec axisDetlaEta = {200, -4., 4., ""}; +AxisSpec axisDetlaEta = {100, -2., 2., ""}; AxisSpec axisDetlaPhi = {64, -o2::constants::math::PIHalf, 3. * o2::constants::math::PIHalf, ""}; AxisSpec axisPtD = {10, 0., 10., ""}; AxisSpec axisPtHadron = {11, 0., 11., ""}; @@ -124,7 +122,7 @@ struct HfTaskCorrelationDsHadrons { {"hCorrel2DVsPtMcGen", stringMCParticles + stringDeltaPhi + stringDeltaEta + stringPtD + stringPoolBin + "entries", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisPoolBin}}}}, // note: axes 3 and 4 (the pT) are updated in the init() {"hCorrel2DVsPtMcGenPromptDivision", stringMCParticles + stringDeltaPhi + stringDeltaEta + stringPtD + stringPtHadron + stringDsPrompt + stringPoolBin + "entries", {HistType::kTHnSparseD, {{axisDetlaPhi}, {axisDetlaEta}, {axisPtD}, {axisPtHadron}, {axisDsPrompt}, {axisPoolBin}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { // redefinition of pT axes for THnSparse holding correlation entries int nBinsPtAxis = binsPtCorrelations->size() - 1; @@ -144,11 +142,13 @@ struct HfTaskCorrelationDsHadrons { registry.get(HIST("hCorrel2DVsPtBkgMcRec"))->Sumw2(); registry.get(HIST("hCorrel2DVsPtMcGen"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); registry.get(HIST("hCorrel2DVsPtMcGen"))->Sumw2(); + registry.get(HIST("hCorrel2DVsPtMcGenPromptDivision"))->GetAxis(2)->Set(nBinsPtAxis, valuesPtAxis); + registry.get(HIST("hCorrel2DVsPtMcGenPromptDivision"))->Sumw2(); } void processData(DsHadronPairFull const& pairEntries) { - for (auto const& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -189,7 +189,7 @@ struct HfTaskCorrelationDsHadrons { /// D-Hadron correlation pair filling task, from pair tables - for MC reco-level analysis (candidates matched to true signal only, but also bkg sources are studied) void processMcRec(DsHadronPairFull const& pairEntries) { - for (auto const& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); @@ -241,7 +241,7 @@ struct HfTaskCorrelationDsHadrons { /// D-Hadron correlation pair filling task, from pair tables - for MC gen-level analysis (no filter/selection, only true signal) void processMcGen(DsHadronPairFull const& pairEntries) { - for (auto const& pairEntry : pairEntries) { + for (const auto& pairEntry : pairEntries) { // define variables for widely used quantities double deltaPhi = pairEntry.deltaPhi(); double deltaEta = pairEntry.deltaEta(); diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index 3c4e6201c3c..6cb685f25ca 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -13,17 +13,11 @@ /// \author Katarina Krizkova Gajdosova , CERN /// \author Maja Kabus , CERN -#include - #include #include #include #include "CCDB/BasicCCDBManager.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" #include "DataFormatsParameters/GRPObject.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" @@ -34,24 +28,25 @@ #include "Framework/StepTHn.h" #include "ReconstructionDataFormats/GlobalTrackID.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/MathConstants.h" + #include "PWGCF/Core/CorrelationContainer.h" #include "PWGCF/Core/PairCuts.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; +using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace constants::math; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; struct HfTaskFlow { - SliceCache cache; - Preslice perCol = aod::track::collisionId; - // configurables for processing options Configurable processRun2{"processRun2", false, "Flag to run on Run 2 data"}; Configurable processRun3{"processRun3", true, "Flag to run on Run 3 data"}; @@ -68,21 +63,25 @@ struct HfTaskFlow { Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + SliceCache cache; + + using MyCollisions = soa::Filtered>; + using MyTracks = soa::Filtered>; + using HfCandidatesSel = soa::Filtered>; + // Collision filters // FIXME: The filter is applied also on the candidates! Beware! Filter collisionVtxZFilter = nabs(aod::collision::posZ) < zVertexMax; - using aodCollisions = soa::Filtered>; - // Charged track filters Filter trackFilter = (nabs(aod::track::eta) < etaTrackAssocMax) && (aod::track::pt > ptTrackAssocMin) && requireGlobalTrackWoPtEtaInFilter(); - using aodTracks = soa::Filtered>; - // HF candidate filter // TODO: use Partition instead of filter Filter candidateFilter = aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar; - using hfCandidates = soa::Filtered>; + + Preslice perCol = aod::track::collisionId; // configurables for containers ConfigurableAxis axisVertex{"axisVertex", {14, -7, 7}, "vertex axis for histograms"}; @@ -110,7 +109,7 @@ struct HfTaskFlow { // ========================= // init() // ========================= - void init(o2::framework::InitContext&) + void init(InitContext&) { // EVENT HISTOGRAMS constexpr int kNBinsEvents = 3; @@ -207,7 +206,7 @@ struct HfTaskFlow { // FIXME: Some collisions are rejected here, what causes (part of) differences with the D0 task // --------------- template - bool isCollisionSelected(TCollision collision, bool fillHistograms = false) + bool isCollisionSelected(TCollision const& collision, bool fillHistograms = false) { if (processRun2 == true) { // Run 2: trigger selection for data case @@ -240,10 +239,10 @@ struct HfTaskFlow { } template - void fillQA(float multiplicity, TTracks tracks) + void fillQA(float multiplicity, TTracks const& tracks) { int Ntracks = 0; - for (auto& track1 : tracks) { + for (const auto& track1 : tracks) { Ntracks++; registry.fill(HIST("hPt"), track1.pt()); registry.fill(HIST("hEta"), track1.eta()); @@ -255,13 +254,13 @@ struct HfTaskFlow { } template - void fillMixingQA(float multiplicity, float vz, TTracks tracks) + void fillMixingQA(float multiplicity, float vz, TTracks const& tracks) { registry.fill(HIST("hMultiplicityMixing"), multiplicity); registry.fill(HIST("hVtxZMixing"), vz); int Ntracks = 0; - for (auto& track1 : tracks) { + for (const auto& track1 : tracks) { Ntracks++; registry.fill(HIST("hPtMixing"), track1.pt()); registry.fill(HIST("hEtaMixing"), track1.eta()); @@ -271,13 +270,13 @@ struct HfTaskFlow { } template - void fillHFMixingQA(float multiplicity, float vz, TTracks tracks) + void fillHFMixingQA(float multiplicity, float vz, TTracks const& tracks) { registry.fill(HIST("hMultiplicityHFMixing"), multiplicity); registry.fill(HIST("hVtxZHFMixing"), vz); int Ntracks = 0; - for (auto& track1 : tracks) { + for (const auto& track1 : tracks) { Ntracks++; registry.fill(HIST("hPtHFMixing"), track1.pt()); registry.fill(HIST("hEtaHFMixing"), track1.eta()); @@ -287,9 +286,9 @@ struct HfTaskFlow { } template - void fillMFTQA(float multiplicity, TTracks tracks) + void fillMFTQA(float multiplicity, TTracks const& tracks) { - for (auto& track1 : tracks) { + for (const auto& track1 : tracks) { registry.fill(HIST("hEtaMFT"), track1.eta()); float phi = track1.phi(); o2::math_utils::bringTo02Pi(phi); @@ -300,12 +299,12 @@ struct HfTaskFlow { // TODO: Check how to put this into a Filter template - bool isAcceptedCandidate(TTrack candidate) + bool isAcceptedCandidate(TTrack const& candidate) { - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { return false; } - if (yCandMax >= 0. && std::abs(yD0(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate)) > yCandMax) { return false; } return true; @@ -313,18 +312,18 @@ struct HfTaskFlow { // TODO: Note: we do not need all these plots since they are in D0 and Lc task -> remove it after we are sure this works template - void fillCandidateQA(TTracks candidates) + void fillCandidateQA(TTracks const& candidates) { - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { if (!isAcceptedCandidate(candidate)) { continue; } if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hMass"), invMassD0ToPiK(candidate), candidate.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate), candidate.pt()); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hMass"), invMassD0barToKPi(candidate), candidate.pt()); + registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate), candidate.pt()); } registry.fill(HIST("hPtCand"), candidate.pt()); @@ -335,8 +334,8 @@ struct HfTaskFlow { registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hd0d0"), candidate.impactParameterProduct(), candidate.pt()); - registry.fill(HIST("hCTS"), cosThetaStarD0(candidate), candidate.pt()); - registry.fill(HIST("hCt"), ctD0(candidate), candidate.pt()); + registry.fill(HIST("hCTS"), hfHelper.cosThetaStarD0(candidate), candidate.pt()); + registry.fill(HIST("hCt"), hfHelper.ctD0(candidate), candidate.pt()); registry.fill(HIST("hCPA"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEtaCand"), candidate.eta(), candidate.pt()); registry.fill(HIST("hSelectionStatus"), candidate.isSelD0() + (candidate.isSelD0bar() * 2), candidate.pt()); @@ -348,12 +347,12 @@ struct HfTaskFlow { } template - void fillCorrelations(TTarget target, TTracksTrig tracks1, TTracksAssoc tracks2, float multiplicity, float posZ) + void fillCorrelations(TTarget target, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, float multiplicity, float posZ) { auto triggerWeight = 1; auto associatedWeight = 1; - for (auto& track1 : tracks1) { + for (const auto& track1 : tracks1) { float eta1 = track1.eta(); float pt1 = track1.pt(); @@ -366,13 +365,13 @@ struct HfTaskFlow { // Note: this is needed only in case of HF-hadron correlations bool fillingHFcontainer = false; double invmass = 0; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { // TODO: Check how to put this into a Filter if (!isAcceptedCandidate(track1)) { continue; } fillingHFcontainer = true; - invmass = invMassD0ToPiK(track1); + invmass = hfHelper.invMassD0ToPiK(track1); } // fill single-track distributions @@ -382,7 +381,7 @@ struct HfTaskFlow { target->getTriggerHist()->Fill(CorrelationContainer::kCFStepReconstructed, pt1, multiplicity, posZ, invmass, triggerWeight); } - for (auto& track2 : tracks2) { + for (const auto& track2 : tracks2) { // case of h-h correlations where the two types of tracks are the same // this avoids autocorrelations and double counting of particle pairs @@ -394,7 +393,7 @@ struct HfTaskFlow { // in case of HF-h correlations, remove candidate daughters from the pool of associated hadrons // with which the candidate is being correlated - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { if ((track1.prong0Id() == track2.globalIndex()) || (track1.prong1Id() == track2.globalIndex())) { continue; } @@ -428,15 +427,15 @@ struct HfTaskFlow { } template - void mixCollisions(aodCollisions& collisions, TTracksTrig& tracks1, TTracksAssoc& tracks2, TLambda getPartsSize, OutputObj& corrContainer) + void mixCollisions(MyCollisions const& collisions, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, TLambda getPartsSize, OutputObj& corrContainer) { using BinningType = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getPartsSize)>; BinningType binningWithTracksSize{{getPartsSize}, {axisVertex, axisMultiplicity}, true}; auto tracksTuple = std::make_tuple(tracks1, tracks2); - Pair pair{binningWithTracksSize, nMixedEvents, -1, collisions, tracksTuple, &cache}; + Pair pair{binningWithTracksSize, nMixedEvents, -1, collisions, tracksTuple, &cache}; - for (auto& [collision1, tracks1, collision2, tracks2] : pair) { + for (const auto& [collision1, tracks1, collision2, tracks2] : pair) { if (!(isCollisionSelected(collision1, false))) { continue; @@ -451,7 +450,7 @@ struct HfTaskFlow { const auto multiplicity = tracks2.size(); // get multiplicity of charged hadrons, which is used for slicing in mixing const auto vz = collision1.posZ(); - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { registry.fill(HIST("hEventCountHFMixing"), bin); fillHFMixingQA(multiplicity, vz, tracks1); } else { @@ -467,8 +466,8 @@ struct HfTaskFlow { // ===================================== // process same event correlations: h-h case // ===================================== - void processSameTpcTpcHH(aodCollisions::iterator const& collision, - aodTracks const& tracks) + void processSameTpcTpcHH(MyCollisions::iterator const& collision, + MyTracks const& tracks) { if (!(isCollisionSelected(collision, true))) { return; @@ -496,9 +495,9 @@ struct HfTaskFlow { // ===================================== // process same event correlations: HF-h case // ===================================== - void processSameHfHadrons(aodCollisions::iterator const& collision, - aodTracks const& tracks, - hfCandidates const& candidates) + void processSameHfHadrons(MyCollisions::iterator const& collision, + MyTracks const& tracks, + HfCandidatesSel const& candidates) { if (!(isCollisionSelected(collision, false))) { return; @@ -515,8 +514,8 @@ struct HfTaskFlow { // ===================================== // process same event correlations: h-MFT case // ===================================== - void processSameTpcMftHH(aodCollisions::iterator const& collision, - aodTracks const& tracks, + void processSameTpcMftHH(MyCollisions::iterator const& collision, + MyTracks const& tracks, aod::MFTTracks const& mfttracks) { if (!(isCollisionSelected(collision, false))) { @@ -535,11 +534,11 @@ struct HfTaskFlow { // ===================================== // process mixed event correlations: h-h case // ===================================== - void processMixedTpcTpcHH(aodCollisions& collisions, - aodTracks& tracks) + void processMixedTpcTpcHH(MyCollisions const& collisions, + MyTracks const& tracks) { // we want to group collisions based on charged-track multiplicity - auto getTracksSize = [&tracks, this](aodCollisions::iterator const& col) { + auto getTracksSize = [&tracks, this](MyCollisions::iterator const& col) { auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, col.globalIndex(), this->cache); // it's cached, so slicing/grouping happens only once auto size = associatedTracks.size(); return size; @@ -552,12 +551,12 @@ struct HfTaskFlow { // ===================================== // process mixed event correlations: h-h case // ===================================== - void processMixedHfHadrons(aodCollisions& collisions, - aodTracks& tracks, - hfCandidates& candidates) + void processMixedHfHadrons(MyCollisions const& collisions, + MyTracks const& tracks, + HfCandidatesSel const& candidates) { // we want to group collisions based on charged-track multiplicity - auto getTracksSize = [&tracks, this](aodCollisions::iterator const& col) { + auto getTracksSize = [&tracks, this](MyCollisions::iterator const& col) { auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, col.globalIndex(), this->cache); auto size = associatedTracks.size(); return size; @@ -570,6 +569,5 @@ struct HfTaskFlow { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGHF/HFL/Tasks/CMakeLists.txt b/PWGHF/HFL/Tasks/CMakeLists.txt index 20b02301f65..1e1596f32f9 100644 --- a/PWGHF/HFL/Tasks/CMakeLists.txt +++ b/PWGHF/HFL/Tasks/CMakeLists.txt @@ -11,15 +11,15 @@ o2physics_add_dpl_workflow(task-muon-charm-beauty-separation SOURCES taskMuonCharmBeautySeparation.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-single-muon SOURCES taskSingleMuon.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-single-muon-source SOURCES taskSingleMuonSource.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx b/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx index 2cd682893e5..cc2637cedc3 100644 --- a/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx +++ b/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx @@ -14,12 +14,13 @@ /// \brief Task to estimate HF->mu in the forward direction and use DCA observable to separate b-> mu, c-> mu. /// \author Shreyasi Acharya , LPC, France -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/TrackFwd.h" +#include "Common/DataModel/TrackSelectionTables.h" + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -27,7 +28,7 @@ using namespace o2::framework::expressions; struct HfTaskMuonCharmBeautySeparation { HistogramRegistry registry{"registry"}; - void init(o2::framework::InitContext&) + void init(InitContext&) { AxisSpec trackTypeAxis = {6, -0.5, 5.5, "Track Type"}; AxisSpec ptRecoAxis = {1500, 0, 15, "#it{p}_{T}_{Reco}"}; @@ -50,7 +51,8 @@ struct HfTaskMuonCharmBeautySeparation { registry.add("hForwardMultiplicity", "Multiplicity in forward direction", {HistType::kTH1F, {{20, 0, 20}}}); } - void process(aod::Collisions::iterator const& collision, soa::Join const& tracks) + void process(aod::Collisions::iterator const& collision, + soa::Join const& tracks) { auto pt = 0.; auto dcax = 0.; @@ -63,7 +65,7 @@ struct HfTaskMuonCharmBeautySeparation { registry.fill(HIST("hZvtx"), zvtx); - for (auto const& muon : tracks) { + for (const auto& muon : tracks) { registry.fill(HIST("hTrackType"), muon.trackType()); if (muon.has_collision()) { if (muon.trackType() == 0) { diff --git a/PWGHF/HFL/Tasks/taskSingleMuon.cxx b/PWGHF/HFL/Tasks/taskSingleMuon.cxx index f191c64ddc5..19852117023 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuon.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuon.cxx @@ -13,9 +13,6 @@ /// \brief Task used to extract the observables on single muons needed for the HF-muon analysis. /// \author Maolin Zhang , CCNU -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" @@ -23,6 +20,10 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/TrackFwd.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + using namespace o2; using namespace o2::aod; using namespace o2::framework; @@ -132,16 +133,18 @@ struct HfTaskSingleMuon { const auto charge(muon.sign()); const auto chi2(muon.chi2MatchMCHMFT()); - auto trkMFT = muon.template matchMFTTrack_as(); - if (reduceAmbMft && trkMFT.has_ambMftTrack()) { - continue; - } - if (reduceOrphMft && (!reduceAmbMft) && trkMFT.has_ambMftTrack()) { - continue; + if (muon.has_matchMFTTrack()) { + auto trkMFT = muon.template matchMFTTrack_as(); + if (reduceAmbMft && trkMFT.has_ambMftTrack()) { + continue; + } + if (reduceOrphMft && (!reduceAmbMft) && trkMFT.has_ambMftTrack()) { + continue; + } } // histograms before the acceptance cuts registry.fill(HIST("hMuBeforeCuts"), pt, eta, dcaXY, pDca, charge, chi2); - if (muon.matchMCHTrackId() > 0) { + if (muon.has_matchMCHTrack()) { auto muonType3 = muon.template matchMCHTrack_as(); registry.fill(HIST("h3DeltaPtBeforeCuts"), pt, eta, muonType3.pt() - pt); } @@ -164,7 +167,7 @@ struct HfTaskSingleMuon { // histograms after acceptance cuts registry.fill(HIST("hMuAfterCuts"), pt, eta, dcaXY, pDca, charge, chi2); registry.fill(HIST("h2DCA"), muon.fwdDcaX(), muon.fwdDcaY()); - if (muon.matchMCHTrackId() > 0) { + if (muon.has_matchMCHTrack()) { auto muonType3 = muon.template matchMCHTrack_as(); registry.fill(HIST("h3DeltaPtAfterCuts"), pt, eta, muonType3.pt() - pt); } @@ -189,16 +192,18 @@ struct HfTaskSingleMuon { const auto charge(muon.sign()); const auto chi2(muon.chi2MatchMCHMFT()); - auto trkMFT = muon.template matchMFTTrack_as(); - if (reduceAmbMft && trkMFT.has_ambMftTrack()) { - continue; - } - if (reduceOrphMft && (!reduceAmbMft) && trkMFT.has_ambMftTrack()) { - continue; + if (muon.has_matchMFTTrack()) { + auto trkMFT = muon.template matchMFTTrack_as(); + if (reduceAmbMft && trkMFT.has_ambMftTrack()) { + continue; + } + if (reduceOrphMft && (!reduceAmbMft) && trkMFT.has_ambMftTrack()) { + continue; + } } // histograms before the acceptance cuts registry.fill(HIST("hMuBeforeCuts"), pt, eta, dcaXY, pDca, charge, chi2); - if (muon.matchMCHTrackId() > 0) { + if (muon.has_matchMCHTrack()) { auto muonType3 = muon.template matchMCHTrack_as(); registry.fill(HIST("h3DeltaPtBeforeCuts"), pt, eta, muonType3.pt() - pt); } @@ -220,7 +225,7 @@ struct HfTaskSingleMuon { // histograms after acceptance cuts registry.fill(HIST("hMuAfterCuts"), pt, eta, dcaXY, pDca, charge, chi2); registry.fill(HIST("h2DCA"), muon.fwdDcaX(), muon.fwdDcaY()); - if (muon.matchMCHTrackId() > 0) { + if (muon.has_matchMCHTrack()) { auto muonType3 = muon.template matchMCHTrack_as(); registry.fill(HIST("h3DeltaPtAfterCuts"), pt, eta, muonType3.pt() - pt); } @@ -234,11 +239,16 @@ struct HfTaskSingleMuon { } } - void processMuon(soa::Filtered::iterator const& collision, MFTTracksExtra const& tracksMFT, MyMuons const& muons) + void processMuon(soa::Filtered::iterator const& collision, + MFTTracksExtra const& tracksMFT, + MyMuons const& muons) { runMuonSel(collision, tracksMFT, muons); } - void processMuonMc(soa::Filtered::iterator const& collision, MFTTracksExtra const& tracksMFT, soa::Filtered const& muons, aod::McParticles const& mc) + void processMuonMc(soa::Filtered::iterator const& collision, + MFTTracksExtra const& tracksMFT, + soa::Filtered const& muons, + aod::McParticles const& mc) { runMuonSelMc(collision, tracksMFT, muons, mc); } diff --git a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx index e668ca05aff..25cae11144b 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx @@ -13,14 +13,10 @@ // \brief Task used to seperate single muons source in Monte Carlo simulation. // \author Maolin Zhang , CCNU -#include "TDatabasePDG.h" -#include "TMath.h" -#include "TPDGCode.h" -#include "TString.h" +#include +#include +#include -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" @@ -28,6 +24,10 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/TrackFwd.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + using namespace o2; using namespace o2::aod; using namespace o2::framework; @@ -87,16 +87,20 @@ struct HfTaskSingleMuonSource { "Hadron", "Unidentified"}; + AxisSpec axisColNumber{1, 0., 1., "Selected collisions"}; AxisSpec axisDCA{5000, 0., 5., "DCA (cm)"}; AxisSpec axisChi2{500, 0., 100., "#chi^{2} of MCH-MFT matching"}; AxisSpec axisPt{200, 0., 100., "#it{p}_{T,reco} (GeV/#it{c})"}; + AxisSpec axisEta{250, -5., 0., "#it{#eta}"}; HistogramConfigSpec h2PtDCA{HistType::kTH2F, {axisPt, axisDCA}}; HistogramConfigSpec h2PtChi2{HistType::kTH2F, {axisPt, axisChi2}}; + HistogramConfigSpec h2PtEta{HistType::kTH2F, {axisPt, axisEta}}; - for (auto const& src : muonSources) { + for (const auto& src : muonSources) { registry.add(Form("h2%sPtDCA", src.Data()), "", h2PtDCA); registry.add(Form("h2%sPtChi2", src.Data()), "", h2PtChi2); + registry.add(Form("h2%sPtEta", src.Data()), "", h2PtEta); } } @@ -146,7 +150,7 @@ struct HfTaskSingleMuonSource { continue; } // compute the flavor of constituent quark - const int flv(pdgRem / TMath::Power(10, static_cast(TMath::Log10(pdgRem)))); + const int flv(pdgRem / std::pow(10, static_cast(std::log10(pdgRem)))); if (flv > 6) { // no more than 6 flavors continue; @@ -179,31 +183,31 @@ struct HfTaskSingleMuonSource { // this muon comes from beauty decay and does not have light flavor parent bool isBeautyMu(const uint8_t& mask) { - return (isMuon(mask) && TESTBIT(mask, HasBeautyParent) && (!TESTBIT(mask, HasLightParent))); + return (isMuon(mask) && TESTBIT(mask, HasBeautyParent) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, HasQuarkoniumParent))); } // this muon comes directly from beauty decay bool isBeautyDecayMu(const uint8_t& mask) { - return (isBeautyMu(mask) && (!TESTBIT(mask, HasCharmParent))); + return (isBeautyMu(mask) && (!TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasQuarkoniumParent)))); } // this muon comes from non-prompt charm decay and does not have light flavor parent bool isNonpromptCharmMu(const uint8_t& mask) { - return (isBeautyMu(mask) && TESTBIT(mask, HasCharmParent)); + return (isBeautyMu(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasQuarkoniumParent))); } // this muon comes from prompt charm decay and does not have light flavor parent bool isPromptCharmMu(const uint8_t& mask) { - return (isMuon(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasLightParent))); + return (isMuon(mask) && TESTBIT(mask, HasCharmParent) && (!TESTBIT(mask, HasBeautyParent)) && (!TESTBIT(mask, HasLightParent)) && (!TESTBIT(mask, HasQuarkoniumParent))); } // this muon comes from light flavor quark decay bool isLightDecayMu(const uint8_t& mask) { - return (isMuon(mask) && TESTBIT(mask, HasLightParent) && (!TESTBIT(mask, IsSecondary))); + return (isMuon(mask) && TESTBIT(mask, HasLightParent) && (!TESTBIT(mask, IsSecondary)) && (!TESTBIT(mask, HasQuarkoniumParent))); } // this muon comes from transport @@ -228,7 +232,7 @@ struct HfTaskSingleMuonSource { void fillHistograms(const McMuons::iterator& muon) { const auto mask(getMask(muon)); - const auto pt(muon.pt()), chi2(muon.chi2MatchMCHMFT()); + const auto pt(muon.pt()), chi2(muon.chi2MatchMCHMFT()), eta(muon.eta()); const auto dca(RecoDecay::sqrtSumOfSquares(muon.fwdDcaX(), muon.fwdDcaY())); singleMuonSource(pt, dca, mask); @@ -236,28 +240,37 @@ struct HfTaskSingleMuonSource { if (isBeautyDecayMu(mask)) { registry.fill(HIST("h2BeautyDecayMuPtDCA"), pt, dca); registry.fill(HIST("h2BeautyDecayMuPtChi2"), pt, chi2); + registry.fill(HIST("h2BeautyDecayMuPtEta"), pt, eta); } else if (isNonpromptCharmMu(mask)) { registry.fill(HIST("h2NonpromptCharmMuPtDCA"), pt, dca); registry.fill(HIST("h2NonpromptCharmMuPtChi2"), pt, chi2); + registry.fill(HIST("h2NonpromptCharmMuPtEta"), pt, eta); } else if (isPromptCharmMu(mask)) { registry.fill(HIST("h2PromptCharmMuPtDCA"), pt, dca); registry.fill(HIST("h2PromptCharmMuPtChi2"), pt, chi2); + registry.fill(HIST("h2PromptCharmMuPtEta"), pt, eta); } else if (isLightDecayMu(mask)) { registry.fill(HIST("h2LightDecayMuPtDCA"), pt, dca); registry.fill(HIST("h2LightDecayMuPtChi2"), pt, chi2); + registry.fill(HIST("h2LightDecayMuPtEta"), pt, eta); } else if (isSecondaryMu(mask)) { registry.fill(HIST("h2SecondaryMuPtDCA"), pt, dca); registry.fill(HIST("h2SecondaryMuPtChi2"), pt, chi2); + registry.fill(HIST("h2SecondaryMuPtEta"), pt, eta); } else if (isHadron(mask)) { registry.fill(HIST("h2HadronPtDCA"), pt, dca); registry.fill(HIST("h2HadronPtChi2"), pt, chi2); + registry.fill(HIST("h2HadronPtEta"), pt, eta); } else if (isUnidentified(mask)) { registry.fill(HIST("h2UnidentifiedPtDCA"), pt, dca); registry.fill(HIST("h2UnidentifiedPtChi2"), pt, chi2); + registry.fill(HIST("h2UnidentifiedPtEta"), pt, eta); } } - void process(MyCollisions::iterator const& collision, McMuons const& muons, aod::McParticles const&) + void process(MyCollisions::iterator const& collision, + McMuons const& muons, + aod::McParticles const&) { // event selections if (!collision.sel8()) { diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 788c4da3a00..00ba1b27388 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -13,166 +13,198 @@ o2physics_add_dpl_workflow(track-index-skim-creator SOURCES trackIndexSkimCreator.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsVertexing O2::DCAFitter O2Physics::AnalysisCCDB + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing O2::DCAFitter O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(refit-pv-dummy SOURCES refitPvDummy.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) # Candidate creators o2physics_add_dpl_workflow(candidate-creator-2prong SOURCES candidateCreator2Prong.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-3prong SOURCES candidateCreator3Prong.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-b0 SOURCES candidateCreatorB0.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-bplus SOURCES candidateCreatorBplus.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(candidate-creator-bs + SOURCES candidateCreatorBs.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-cascade SOURCES candidateCreatorCascade.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-dstar SOURCES candidateCreatorDstar.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-lb SOURCES candidateCreatorLb.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-sigmac0plusplus SOURCES candidateCreatorSigmac0plusplus.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-to-xi-pi SOURCES candidateCreatorToXiPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-xicc SOURCES candidateCreatorXicc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DCAFitter + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) # Candidate selectors o2physics_add_dpl_workflow(candidate-selector-b0-to-d-pi SOURCES candidateSelectorB0ToDPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-bplus-to-d0-pi SOURCES candidateSelectorBplusToD0Pi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(candidate-selector-bs-to-ds-pi + SOURCES candidateSelectorBsToDsPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-d0 SOURCES candidateSelectorD0.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-dplus-to-pi-k-pi SOURCES candidateSelectorDplusToPiKPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-ds-to-k-k-pi SOURCES candidateSelectorDsToKKPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-lb-to-lc-pi SOURCES candidateSelectorLbToLcPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-lc SOURCES candidateSelectorLc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-lc-ml SOURCES candidateSelectorLcMl.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::CCDB ONNXRuntime::ONNXRuntime O2Physics::MLCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-lc-to-k0s-p SOURCES candidateSelectorLcToK0sP.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-to-xi-pi SOURCES candidateSelectorToXiPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-xic-to-p-k-pi SOURCES candidateSelectorXicToPKPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-selector-xicc-to-p-k-pi-pi SOURCES candidateSelectorXiccToPKPiPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) # Tree creators +o2physics_add_dpl_workflow(tree-creator-b0-to-d-pi + SOURCES treeCreatorB0ToDPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(tree-creator-bplus-to-d0-pi SOURCES treeCreatorBplusToD0Pi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(tree-creator-bs-to-ds-pi + SOURCES treeCreatorBsToDsPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-d0-to-k-pi SOURCES treeCreatorD0ToKPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-dplus-to-pi-k-pi SOURCES treeCreatorDplusToPiKPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(tree-creator-ds-to-k-k-pi + SOURCES treeCreatorDsToKKPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-lb-to-lc-pi SOURCES treeCreatorLbToLcPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-lc-to-k0s-p SOURCES treeCreatorLcToK0sP.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-lc-to-p-k-pi SOURCES treeCreatorLcToPKPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-to-xi-pi SOURCES treeCreatorToXiPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(tree-creator-xic-to-p-k-pi + SOURCES treeCreatorXicToPKPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(tree-creator-xicc-to-p-k-pi-pi SOURCES treeCreatorXiccToPKPiPi.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + + diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index 83c01d76716..aa409749763 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -14,28 +14,41 @@ /// /// \author Gian Michele Innocenti , CERN /// \author Vít Kučera , CERN +/// \author Pengzhong Lu , GSI Darmstadt, USTC + +#ifndef HomogeneousField +#define HomogeneousField +#endif + +#include +#include +#include +#include +#include -#include "Common/Core/trackUtilities.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" +#include "Common/Core/trackUtilities.h" +#include "Tools/KFparticle/KFUtilities.h" + #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" using namespace o2; -using namespace o2::framework; -using namespace o2::aod::hf_cand; +using namespace o2::analysis; using namespace o2::aod::hf_cand_2prong; +using namespace o2::framework; /// Reconstruction of heavy-flavour 2-prong decay candidates struct HfCandidateCreator2Prong { Produces rowCandidateBase; + Produces rowCandidateKF; // vertexing - Configurable doPvRefit{"doPvRefit", false, "do PV refit excluding the candidate daughters, if contributors"}; - // Configurable bz{"bz", 5., "magnetic field"}; + Configurable constrainKfToPv{"constrainKfToPv", true, "constraint KFParticle to PV"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; @@ -54,15 +67,14 @@ struct HfCandidateCreator2Prong { Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; - int runNumber; + int runNumber{0}; float toMicrometers = 10000.; // from cm to µm - - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massK = RecoDecay::getMassPDG(kKPlus); + double massPi{0.}; + double massK{0.}; double massPiK{0.}; double massKPi{0.}; - double bz = 0.; + double bz{0.}; OutputObj hMass2{TH1F("hMass2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; OutputObj hCovPVXX{TH1F("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", 100, 0., 1.e-4)}; @@ -75,9 +87,24 @@ struct HfCandidateCreator2Prong { OutputObj hCovSVZZ{TH1F("hCovSVZZ", "2-prong candidates;ZZ element of cov. matrix of sec. vtx. position (cm^{2});entries", 100, 0., 0.2)}; OutputObj hDcaXYProngs{TH2F("hDcaXYProngs", "DCAxy of 2-prong candidates;#it{p}_{T} (GeV/#it{c};#it{d}_{xy}) (#mum);entries", 100, 0., 20., 200, -500., 500.)}; OutputObj hDcaZProngs{TH2F("hDcaZProngs", "DCAz of 2-prong candidates;#it{p}_{T} (GeV/#it{c};#it{d}_{z}) (#mum);entries", 100, 0., 20., 200, -500., 500.)}; + OutputObj hVertexerType{TH1F("hVertexerType", "Use KF or DCAFitterN;Vertexer type;entries", 2, -0.5, 1.5)}; // See o2::aod::hf_cand::VertexerType void init(InitContext const&) { + std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN}; + std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle}; + if ((std::accumulate(doprocessDF.begin(), doprocessDF.end(), 0) + std::accumulate(doprocessKF.begin(), doprocessKF.end(), 0)) != 1) { + LOGP(fatal, "Only one process function can be enabled at a time."); + } + if (std::accumulate(doprocessDF.begin(), doprocessDF.end(), 0) == 1) { + hVertexerType->Fill(aod::hf_cand::VertexerType::DCAFitter); + } + if (std::accumulate(doprocessKF.begin(), doprocessKF.end(), 0) == 1) { + hVertexerType->Fill(aod::hf_cand::VertexerType::KfParticle); + } + + massPi = o2::analysis::pdg::MassPiPlus; + massK = o2::analysis::pdg::MassKPlus; ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -85,10 +112,11 @@ struct HfCandidateCreator2Prong { runNumber = 0; } - void process(aod::Collisions const& collisions, - soa::Join const& rowsTrackIndexProng2, - aod::BigTracks const& tracks, - aod::BCsWithTimestamps const& bcWithTimeStamps) + template + void runCreator2ProngWithDCAFitterN(aod::Collisions const& collisions, + CandType const& rowsTrackIndexProng2, + TTracks const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) { // 2-prong vertex fitter o2::vertexing::DCAFitterN<2> df; @@ -103,8 +131,8 @@ struct HfCandidateCreator2Prong { // loop over pairs of track indices for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { - auto track0 = rowTrackIndexProng2.prong0_as(); - auto track1 = rowTrackIndexProng2.prong1_as(); + auto track0 = rowTrackIndexProng2.template prong0_as(); + auto track1 = rowTrackIndexProng2.template prong1_as(); auto trackParVarPos1 = getTrackParCov(track0); auto trackParVarNeg1 = getTrackParCov(track1); auto collision = rowTrackIndexProng2.collision(); @@ -112,7 +140,7 @@ struct HfCandidateCreator2Prong { /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, /// but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); @@ -138,8 +166,8 @@ struct HfCandidateCreator2Prong { auto trackParVar1 = df.getTrack(1); // get track momenta - array pvec0; - array pvec1; + std::array pvec0; + std::array pvec1; trackParVar0.getPxPyPzGlo(pvec0); trackParVar1.getPxPyPzGlo(pvec1); @@ -147,7 +175,7 @@ struct HfCandidateCreator2Prong { // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); auto covMatrixPV = primaryVertex.getCov(); - if (doPvRefit) { + if constexpr (doPvRefit) { /// use PV refit /// Using it in the rowCandidateBase all dynamic columns shall take it into account // coordinates @@ -178,7 +206,7 @@ struct HfCandidateCreator2Prong { // get uncertainty of the decay length double phi, theta; - getPointDirection(array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); @@ -198,14 +226,174 @@ struct HfCandidateCreator2Prong { // fill histograms if (fillHistograms) { // calculate invariant masses - auto arrayMomenta = array{pvec0, pvec1}; - massPiK = RecoDecay::m(arrayMomenta, array{massPi, massK}); - massKPi = RecoDecay::m(arrayMomenta, array{massK, massPi}); + auto arrayMomenta = std::array{pvec0, pvec1}; + massPiK = RecoDecay::m(arrayMomenta, std::array{massPi, massK}); + massKPi = RecoDecay::m(arrayMomenta, std::array{massK, massPi}); hMass2->Fill(massPiK); hMass2->Fill(massKPi); } } } + + template + void runCreator2ProngWithKFParticle(aod::Collisions const& collisions, + CandType const& rowsTrackIndexProng2, + TTracks const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) + { + + for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { + auto track0 = rowTrackIndexProng2.template prong0_as(); + auto track1 = rowTrackIndexProng2.template prong1_as(); + auto collision = rowTrackIndexProng2.collision(); + + /// Set the magnetic field from ccdb. + /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, + /// but this is not true when running on Run2 data/MC already converted into AO2Ds. + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + // df.setBz(bz); /// put it outside the 'if'! Otherwise we have a difference wrt bz Configurable (< 1 permille) in Run2 conv. data + // df.print(); + } + float covMatrixPV[6]; + + KFParticle::SetField(bz); + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + + if constexpr (doPvRefit) { + /// use PV refit + /// Using it in the rowCandidateBase all dynamic columns shall take it into account + // coordinates + kfpVertex.SetXYZ(rowTrackIndexProng2.pvRefitX(), rowTrackIndexProng2.pvRefitY(), rowTrackIndexProng2.pvRefitZ()); + // covariance matrix + kfpVertex.SetCovarianceMatrix(rowTrackIndexProng2.pvRefitSigmaX2(), rowTrackIndexProng2.pvRefitSigmaXY(), rowTrackIndexProng2.pvRefitSigmaY2(), rowTrackIndexProng2.pvRefitSigmaXZ(), rowTrackIndexProng2.pvRefitSigmaYZ(), rowTrackIndexProng2.pvRefitSigmaZ2()); + } + kfpVertex.GetCovarianceMatrix(covMatrixPV); + KFParticle KFPV(kfpVertex); + hCovPVXX->Fill(covMatrixPV[0]); + hCovPVYY->Fill(covMatrixPV[2]); + hCovPVXZ->Fill(covMatrixPV[3]); + hCovPVZZ->Fill(covMatrixPV[5]); + + KFPTrack kfpTrack0 = createKFPTrackFromTrack(track0); + KFPTrack kfpTrack1 = createKFPTrackFromTrack(track1); + + KFParticle kfPosPion(kfpTrack0, kPiPlus); + KFParticle kfNegPion(kfpTrack1, kPiPlus); + KFParticle kfPosKaon(kfpTrack0, kKPlus); + KFParticle kfNegKaon(kfpTrack1, kKPlus); + + float impactParameter0XY = 0., errImpactParameter0XY = 0., impactParameter1XY = 0., errImpactParameter1XY = 0.; + if (!kfPosPion.GetDistanceFromVertexXY(KFPV, impactParameter0XY, errImpactParameter0XY)) { + hDcaXYProngs->Fill(track0.pt(), impactParameter0XY * toMicrometers); + hDcaZProngs->Fill(track0.pt(), std::sqrt(kfPosPion.GetDistanceFromVertex(KFPV) * kfPosPion.GetDistanceFromVertex(KFPV) - impactParameter0XY * impactParameter0XY) * toMicrometers); + } else { + hDcaXYProngs->Fill(track0.pt(), -999.); + hDcaZProngs->Fill(track0.pt(), -999.); + } + if (!kfNegPion.GetDistanceFromVertexXY(KFPV, impactParameter1XY, errImpactParameter1XY)) { + hDcaXYProngs->Fill(track1.pt(), impactParameter1XY * toMicrometers); + hDcaZProngs->Fill(track1.pt(), std::sqrt(kfNegPion.GetDistanceFromVertex(KFPV) * kfNegPion.GetDistanceFromVertex(KFPV) - impactParameter1XY * impactParameter1XY) * toMicrometers); + } else { + hDcaXYProngs->Fill(track1.pt(), -999.); + hDcaZProngs->Fill(track1.pt(), -999.); + } + + KFParticle kfCandD0; + const KFParticle* kfDaughtersD0[2] = {&kfPosPion, &kfNegKaon}; + kfCandD0.SetConstructMethod(2); + kfCandD0.Construct(kfDaughtersD0, 2); + KFParticle kfCandD0bar; + const KFParticle* kfDaughtersD0bar[2] = {&kfNegPion, &kfPosKaon}; + kfCandD0bar.SetConstructMethod(2); + kfCandD0bar.Construct(kfDaughtersD0bar, 2); + + auto massD0 = kfCandD0.GetMass(); + auto massD0bar = kfCandD0bar.GetMass(); + + hCovSVXX->Fill(kfCandD0.Covariance(0, 0)); + hCovSVYY->Fill(kfCandD0.Covariance(1, 1)); + hCovSVXZ->Fill(kfCandD0.Covariance(2, 0)); + hCovSVZZ->Fill(kfCandD0.Covariance(2, 2)); + auto covMatrixSV = kfCandD0.CovarianceMatrix(); + + double phi, theta; + getPointDirection(std::array{KFPV.GetX(), KFPV.GetY(), KFPV.GetZ()}, std::array{kfCandD0.GetX(), kfCandD0.GetY(), kfCandD0.GetZ()}, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixSV, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixSV, phi, 0.)); + + float topolChi2PerNdfD0 = -999.; + KFParticle kfCandD0Topol2PV; + if (constrainKfToPv) { + kfCandD0Topol2PV = kfCandD0; + kfCandD0Topol2PV.SetProductionVertex(KFPV); + topolChi2PerNdfD0 = kfCandD0Topol2PV.GetChi2() / kfCandD0Topol2PV.GetNDF(); + } + + // fill candidate table rows + rowCandidateBase(collision.globalIndex(), + KFPV.GetX(), KFPV.GetY(), KFPV.GetZ(), + kfCandD0.GetX(), kfCandD0.GetY(), kfCandD0.GetZ(), + errorDecayLength, errorDecayLengthXY, // TODO: much different from the DCAFitterN one + kfCandD0.GetChi2() / kfCandD0.GetNDF(), // TODO: to make sure it should be chi2 only or chi2/ndf, much different from the DCAFitterN one + kfPosPion.GetPx(), kfPosPion.GetPy(), kfPosPion.GetPz(), + kfNegKaon.GetPx(), kfNegKaon.GetPy(), kfNegKaon.GetPz(), + impactParameter0XY, impactParameter1XY, + errImpactParameter0XY, errImpactParameter1XY, + rowTrackIndexProng2.prong0Id(), rowTrackIndexProng2.prong1Id(), + rowTrackIndexProng2.hfflag()); + rowCandidateKF(topolChi2PerNdfD0, + massD0, massD0bar); + + // fill histograms + if (fillHistograms) { + hMass2->Fill(massD0); + hMass2->Fill(massD0bar); + } + } + } + + void processPvRefitWithDCAFitterN(aod::Collisions const& collisions, + soa::Join const& rowsTrackIndexProng2, + aod::TracksWCov const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) + { + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + + PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterN, "Run candidate creator with PV refit", false); + + void processNoPvRefitWithDCAFitterN(aod::Collisions const& collisions, + aod::Hf2Prongs const& rowsTrackIndexProng2, + aod::TracksWCov const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) + { + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + + PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterN, "Run candidate creator without PV refit", true); + + void processPvRefitWithKFParticle(aod::Collisions const& collisions, + soa::Join const& rowsTrackIndexProng2, + soa::Join const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) + { + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticle, "Run candidate creator with PV refit", false); + + void processNoPvRefitWithKFParticle(aod::Collisions const& collisions, + aod::Hf2Prongs const& rowsTrackIndexProng2, + soa::Join const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) + { + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticle, "Run candidate creator without PV refit", false); }; /// Extends the base table with expression columns. @@ -217,8 +405,8 @@ struct HfCandidateCreator2ProngExpressions { void init(InitContext const&) {} /// Performs MC matching. - void processMc(aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC) + void processMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles) { rowCandidateProng2->bindExternalIndices(&tracks); @@ -229,23 +417,20 @@ struct HfCandidateCreator2ProngExpressions { // Match reconstructed candidates. // Spawned table can be used directly - for (auto& candidate : *rowCandidateProng2) { - // Printf("New rec. candidate"); + for (const auto& candidate : *rowCandidateProng2) { flag = 0; origin = 0; - auto arrayDaughters = array{candidate.prong0_as(), candidate.prong1_as()}; + auto arrayDaughters = std::array{candidate.prong0_as(), candidate.prong1_as()}; // D0(bar) → π± K∓ - // Printf("Checking D0(bar) → π± K∓"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kD0, array{+kPiPlus, -kKPlus}, true, &sign); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign); if (indexRec > -1) { flag = sign * (1 << DecayType::D0ToPiK); } // J/ψ → e+ e− if (flag == 0) { - // Printf("Checking J/ψ → e+ e−"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kJPsi, array{+kElectron, -kElectron}, true); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kJPsi, std::array{+kElectron, -kElectron}, true); if (indexRec > -1) { flag = 1 << DecayType::JpsiToEE; } @@ -253,8 +438,7 @@ struct HfCandidateCreator2ProngExpressions { // J/ψ → μ+ μ− if (flag == 0) { - // Printf("Checking J/ψ → μ+ μ−"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kJPsi, array{+kMuonPlus, -kMuonPlus}, true); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true); if (indexRec > -1) { flag = 1 << DecayType::JpsiToMuMu; } @@ -262,44 +446,40 @@ struct HfCandidateCreator2ProngExpressions { // Check whether the particle is non-prompt (from a b quark). if (flag != 0) { - auto particle = particlesMC.rawIteratorAt(indexRec); - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchRec(flag, origin); } // Match generated particles. - for (auto& particle : particlesMC) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = 0; origin = 0; // D0(bar) → π± K∓ - // Printf("Checking D0(bar) → π± K∓"); - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kD0, array{+kPiPlus, -kKPlus}, true, &sign)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) { flag = sign * (1 << DecayType::D0ToPiK); } // J/ψ → e+ e− if (flag == 0) { - // Printf("Checking J/ψ → e+ e−"); - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kJPsi, array{+kElectron, -kElectron}, true)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kJPsi, std::array{+kElectron, -kElectron}, true)) { flag = 1 << DecayType::JpsiToEE; } } // J/ψ → μ+ μ− if (flag == 0) { - // Printf("Checking J/ψ → μ+ μ−"); - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kJPsi, array{+kMuonPlus, -kMuonPlus}, true)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { flag = 1 << DecayType::JpsiToMuMu; } } // Check whether the particle is non-prompt (from a b quark). if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchGen(flag, origin); diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index 3f1b5744f63..8b843ef67cd 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -15,27 +15,26 @@ /// /// \author Vít Kučera , CERN -#include "Common/Core/trackUtilities.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" +#include "Common/Core/trackUtilities.h" + #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" using namespace o2; -using namespace o2::framework; -using namespace o2::aod::hf_cand; +using namespace o2::analysis; using namespace o2::aod::hf_cand_3prong; +using namespace o2::framework; /// Reconstruction of heavy-flavour 3-prong decay candidates struct HfCandidateCreator3Prong { Produces rowCandidateBase; // vertexing - Configurable doPvRefit{"doPvRefit", false, "do PV refit excluding the candidate daughters, if contributors"}; - // Configurable bz{"bz", 5., "magnetic field"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; @@ -54,14 +53,13 @@ struct HfCandidateCreator3Prong { Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; - int runNumber; + int runNumber{0}; float toMicrometers = 10000.; // from cm to µm - - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massK = RecoDecay::getMassPDG(kKPlus); + double massPi{0.}; + double massK{0.}; double massPiKPi{0.}; - double bz = 0.; + double bz{0.}; OutputObj hMass3{TH1F("hMass3", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", 500, 1.6, 2.1)}; OutputObj hCovPVXX{TH1F("hCovPVXX", "3-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", 100, 0., 1.e-4)}; @@ -77,6 +75,12 @@ struct HfCandidateCreator3Prong { void init(InitContext const&) { + if (doprocessPvRefit && doprocessNoPvRefit) { + LOGP(fatal, "Only one process function between processPvRefit and processNoPvRefit can be enabled at a time."); + } + + massPi = o2::analysis::pdg::MassPiPlus; + massK = o2::analysis::pdg::MassKPlus; ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -84,10 +88,11 @@ struct HfCandidateCreator3Prong { runNumber = 0; } - void process(aod::Collisions const& collisions, - soa::Join const& rowsTrackIndexProng3, - aod::BigTracks const& tracks, - aod::BCsWithTimestamps const& bcWithTimeStamps) + template + void runCreator3Prong(aod::Collisions const& collisions, + Cand const& rowsTrackIndexProng3, + aod::TracksWCov const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) { // 3-prong vertex fitter o2::vertexing::DCAFitterN<3> df; @@ -102,9 +107,9 @@ struct HfCandidateCreator3Prong { // loop over triplets of track indices for (const auto& rowTrackIndexProng3 : rowsTrackIndexProng3) { - auto track0 = rowTrackIndexProng3.prong0_as(); - auto track1 = rowTrackIndexProng3.prong1_as(); - auto track2 = rowTrackIndexProng3.prong2_as(); + auto track0 = rowTrackIndexProng3.template prong0_as(); + auto track1 = rowTrackIndexProng3.template prong1_as(); + auto track2 = rowTrackIndexProng3.template prong2_as(); auto trackParVar0 = getTrackParCov(track0); auto trackParVar1 = getTrackParCov(track1); auto trackParVar2 = getTrackParCov(track2); @@ -113,7 +118,7 @@ struct HfCandidateCreator3Prong { /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, /// but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); @@ -140,9 +145,9 @@ struct HfCandidateCreator3Prong { trackParVar2 = df.getTrack(2); // get track momenta - array pvec0; - array pvec1; - array pvec2; + std::array pvec0; + std::array pvec1; + std::array pvec2; trackParVar0.getPxPyPzGlo(pvec0); trackParVar1.getPxPyPzGlo(pvec1); trackParVar2.getPxPyPzGlo(pvec2); @@ -151,7 +156,7 @@ struct HfCandidateCreator3Prong { // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); auto covMatrixPV = primaryVertex.getCov(); - if (doPvRefit) { + if constexpr (doPvRefit) { /// use PV refit /// Using it in the rowCandidateBase all dynamic columns shall take it into account // coordinates @@ -186,7 +191,7 @@ struct HfCandidateCreator3Prong { // get uncertainty of the decay length double phi, theta; - getPointDirection(array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); @@ -207,12 +212,32 @@ struct HfCandidateCreator3Prong { // fill histograms if (fillHistograms) { // calculate invariant mass - auto arrayMomenta = array{pvec0, pvec1, pvec2}; - massPiKPi = RecoDecay::m(std::move(arrayMomenta), array{massPi, massK, massPi}); + auto arrayMomenta = std::array{pvec0, pvec1, pvec2}; + massPiKPi = RecoDecay::m(std::move(arrayMomenta), std::array{massPi, massK, massPi}); hMass3->Fill(massPiKPi); } } } + + void processPvRefit(aod::Collisions const& collisions, + soa::Join const& rowsTrackIndexProng3, + aod::TracksWCov const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) + { + runCreator3Prong(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + + PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefit, "Run candidate creator with PV refit", false); + + void processNoPvRefit(aod::Collisions const& collisions, + aod::Hf3Prongs const& rowsTrackIndexProng3, + aod::TracksWCov const& tracks, + aod::BCsWithTimestamps const& bcWithTimeStamps) + { + runCreator3Prong(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + + PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefit, "Run candidate creator without PV refit", true); }; /// Extends the base table with expression columns. @@ -224,8 +249,8 @@ struct HfCandidateCreator3ProngExpressions { void init(InitContext const&) {} /// Performs MC matching. - void processMc(aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC) + void processMc(aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles) { rowCandidateProng3->bindExternalIndices(&tracks); @@ -237,43 +262,40 @@ struct HfCandidateCreator3ProngExpressions { int8_t channel = 0; std::vector arrDaughIndex; std::array arrPDGDaugh; - std::array arrPDGResonant1 = {kProton, 313}; // Λc± → p± K* - std::array arrPDGResonant2 = {2224, kKPlus}; // Λc± → Δ(1232)±± K∓ - std::array arrPDGResonant3 = {3124, kPiPlus}; // Λc± → Λ(1520) π± + std::array arrPDGResonant1 = {kProton, 313}; // Λc± → p± K* + std::array arrPDGResonant2 = {2224, kKPlus}; // Λc± → Δ(1232)±± K∓ + std::array arrPDGResonant3 = {3124, kPiPlus}; // Λc± → Λ(1520) π± std::array arrPDGResonantDsPhiPi = {333, kPiPlus}; // Ds± → Phi π± std::array arrPDGResonantDsKstarK = {313, kKPlus}; // Ds± → K*(892)0bar K± // Match reconstructed candidates. // Spawned table can be used directly - for (auto& candidate : *rowCandidateProng3) { - // Printf("New rec. candidate"); + for (const auto& candidate : *rowCandidateProng3) { flag = 0; origin = 0; swapping = 0; channel = 0; arrDaughIndex.clear(); - auto arrayDaughters = array{candidate.prong0_as(), candidate.prong1_as(), candidate.prong2_as()}; + auto arrayDaughters = std::array{candidate.prong0_as(), candidate.prong1_as(), candidate.prong2_as()}; // D± → π± K∓ π± - // Printf("Checking D± → π± K∓ π±"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kDPlus, array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); if (indexRec > -1) { flag = sign * (1 << DecayType::DplusToPiKPi); } // Ds± → K± K∓ π± if (flag == 0) { - // Printf("Checking Ds± → K± K∓ π±"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kDS, array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); if (indexRec > -1) { flag = sign * (1 << DecayType::DsToKKPi); if (arrayDaughters[0].has_mcParticle()) { swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); } - RecoDecay::getDaughters(particlesMC.rawIteratorAt(indexRec), &arrDaughIndex, array{0}, 1); + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); if (arrDaughIndex.size() == 2) { for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { - auto daughI = particlesMC.rawIteratorAt(arrDaughIndex[iProng]); + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); } if ((arrPDGDaugh[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDsPhiPi[0])) { @@ -287,19 +309,18 @@ struct HfCandidateCreator3ProngExpressions { // Λc± → p± K∓ π± if (flag == 0) { - // Printf("Checking Λc± → p± K∓ π±"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); if (indexRec > -1) { flag = sign * (1 << DecayType::LcToPKPi); - // Printf("Flagging the different Λc± → p± K∓ π± decay channels"); + // Flagging the different Λc± → p± K∓ π± decay channels if (arrayDaughters[0].has_mcParticle()) { swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); } - RecoDecay::getDaughters(particlesMC.rawIteratorAt(indexRec), &arrDaughIndex, array{0}, 1); + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); if (arrDaughIndex.size() == 2) { for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { - auto daughI = particlesMC.rawIteratorAt(arrDaughIndex[iProng]); + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); } if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { @@ -315,8 +336,7 @@ struct HfCandidateCreator3ProngExpressions { // Ξc± → p± K∓ π± if (flag == 0) { - // Printf("Checking Ξc± → p± K∓ π±"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kXiCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); if (indexRec > -1) { flag = sign * (1 << DecayType::XicToPKPi); } @@ -324,36 +344,33 @@ struct HfCandidateCreator3ProngExpressions { // Check whether the particle is non-prompt (from a b quark). if (flag != 0) { - auto particle = particlesMC.rawIteratorAt(indexRec); - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchRec(flag, origin, swapping, channel); } // Match generated particles. - for (auto& particle : particlesMC) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = 0; origin = 0; channel = 0; arrDaughIndex.clear(); // D± → π± K∓ π± - // Printf("Checking D± → π± K∓ π±"); - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kDPlus, array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { flag = sign * (1 << DecayType::DplusToPiKPi); } // Ds± → K± K∓ π± if (flag == 0) { - // Printf("Checking Ds± → K± K∓ π±"); - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kDS, array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { flag = sign * (1 << DecayType::DsToKKPi); - RecoDecay::getDaughters(particle, &arrDaughIndex, array{0}, 1); + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); if (arrDaughIndex.size() == 2) { for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { - auto daughJ = particlesMC.rawIteratorAt(arrDaughIndex[jProng]); + auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); } if ((arrPDGDaugh[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDsPhiPi[0])) { @@ -367,15 +384,14 @@ struct HfCandidateCreator3ProngExpressions { // Λc± → p± K∓ π± if (flag == 0) { - // Printf("Checking Λc± → p± K∓ π±"); - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { flag = sign * (1 << DecayType::LcToPKPi); - // Printf("Flagging the different Λc± → p± K∓ π± decay channels"); - RecoDecay::getDaughters(particle, &arrDaughIndex, array{0}, 1); + // Flagging the different Λc± → p± K∓ π± decay channels + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); if (arrDaughIndex.size() == 2) { for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { - auto daughJ = particlesMC.rawIteratorAt(arrDaughIndex[jProng]); + auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); } if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { @@ -391,15 +407,14 @@ struct HfCandidateCreator3ProngExpressions { // Ξc± → p± K∓ π± if (flag == 0) { - // Printf("Checking Ξc± → p± K∓ π±"); - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kXiCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { flag = sign * (1 << DecayType::XicToPKPi); } } // Check whether the particle is non-prompt (from a b quark). if (flag != 0) { - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchGen(flag, origin, channel); diff --git a/PWGHF/TableProducer/candidateCreatorB0.cxx b/PWGHF/TableProducer/candidateCreatorB0.cxx index 9d0fef73726..4177584d33d 100644 --- a/PWGHF/TableProducer/candidateCreatorB0.cxx +++ b/PWGHF/TableProducer/candidateCreatorB0.cxx @@ -15,30 +15,30 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" using namespace o2; +using namespace o2::analysis; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_cand_b0; // from CandidateReconstructionTables.h using namespace o2::framework::expressions; /// Reconstruction of B0 candidates struct HfCandidateCreatorB0 { Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in CandidateReconstructionTables.h // vertexing // Configurable bz{"bz", 5., "magnetic field"}; @@ -63,23 +63,30 @@ struct HfCandidateCreatorB0 { Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + HfHelper hfHelper; Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber; - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massD = RecoDecay::getMassPDG(pdg::Code::kDMinus); - double massB0 = RecoDecay::getMassPDG(pdg::Code::kB0); - double massDPi{0.}; + double massPi{0.}; + double massD{0.}; + double massB0{0.}; + double invMass2DPiMin{0.}; + double invMass2DPiMax{0.}; double bz{0.}; - using TracksWithSel = soa::Join; + // Fitter for B vertex (2-prong vertex filter) + o2::vertexing::DCAFitterN<2> df2; + // Fitter to redo D-vertex to get extrapolated daughter tracks (3-prong vertex filter) + o2::vertexing::DCAFitterN<3> df3; - Filter filterSelectCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagD); + using TracksWithSel = soa::Join; using CandsDFiltered = soa::Filtered>; - Preslice candsDPerCollision = aod::track_association::collisionId; + Filter filterSelectCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagD); + + Preslice candsDPerCollision = aod::track_association::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; OutputObj hMassDToPiKPi{TH1F("hMassDToPiKPi", "D^{#minus} candidates;inv. mass (p^{#minus} K^{#plus} #pi^{#minus}) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; @@ -92,11 +99,37 @@ struct HfCandidateCreatorB0 { void init(InitContext const&) { + // Initialise fitter for B vertex (2-prong vertex filter) + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + + // Initial fitter to redo D-vertex to get extrapolated daughter tracks (3-prong vertex filter) + df3.setPropagateToPCA(propagateToPCA); + df3.setMaxR(maxR); + df3.setMaxDZIni(maxDZIni); + df3.setMinParamChange(minParamChange); + df3.setMinRelChi2Change(minRelChi2Change); + df3.setUseAbsDCA(useAbsDCA); + df3.setWeightedFinalPCA(useWeightedFinalPCA); + + // Configure CCDB access ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); runNumber = 0; + + // invariant-mass window cut + massPi = o2::analysis::pdg::MassPiPlus; + massD = o2::analysis::pdg::MassDMinus; + massB0 = o2::analysis::pdg::MassB0; + invMass2DPiMin = (massB0 - invMassWindowB0) * (massB0 - invMassWindowB0); + invMass2DPiMax = (massB0 + invMassWindowB0) * (massB0 + invMassWindowB0); } /// Single-track cuts for pions on dcaXY @@ -125,27 +158,6 @@ struct HfCandidateCreatorB0 { TracksWithSel const&, aod::BCsWithTimestamps const&) { - // Initialise fitter for B vertex (2-prong vertex filter) - o2::vertexing::DCAFitterN<2> df2; - // df2.setBz(bz); - df2.setPropagateToPCA(propagateToPCA); - df2.setMaxR(maxR); - df2.setMaxDZIni(maxDZIni); - df2.setMinParamChange(minParamChange); - df2.setMinRelChi2Change(minRelChi2Change); - df2.setUseAbsDCA(useAbsDCA); - df2.setWeightedFinalPCA(useWeightedFinalPCA); - - // Initial fitter to redo D-vertex to get extrapolated daughter tracks (3-prong vertex filter) - o2::vertexing::DCAFitterN<3> df3; - // df3.setBz(bz); - df3.setPropagateToPCA(propagateToPCA); - df3.setMaxR(maxR); - df3.setMaxDZIni(maxDZIni); - df3.setMinParamChange(minParamChange); - df3.setMinRelChi2Change(minRelChi2Change); - df3.setUseAbsDCA(useAbsDCA); - df3.setWeightedFinalPCA(useWeightedFinalPCA); static int ncol = 0; @@ -175,7 +187,7 @@ struct HfCandidateCreatorB0 { auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); for (const auto& candD : candsDThisColl) { // start loop over filtered D candidates indices as associated to this collision in candidateCreator3Prong.cxx - hMassDToPiKPi->Fill(invMassDplusToPiKPi(candD), candD.pt()); + hMassDToPiKPi->Fill(hfHelper.invMassDplusToPiKPi(candD), candD.pt()); hPtD->Fill(candD.pt()); hCPAD->Fill(candD.cpa()); @@ -226,12 +238,10 @@ struct HfCandidateCreatorB0 { df3.getTrack(2).getPxPyPzGlo(pVec2); // D∓ → π∓ K± π∓ - array pVecPiK = RecoDecay::pVec(pVec0, pVec1); - array pVecD = RecoDecay::pVec(pVec0, pVec1, pVec2); - auto trackParCovPiK = o2::dataformats::V0(df3.getPCACandidatePos(), pVecPiK, df3.calcPCACovMatrixFlat(), - trackParCov0, trackParCov1, {0, 0}, {0, 0}); - auto trackParCovD = o2::dataformats::V0(df3.getPCACandidatePos(), pVecD, df3.calcPCACovMatrixFlat(), - trackParCovPiK, trackParCov2, {0, 0}, {0, 0}); + std::array pVecPiK = RecoDecay::pVec(pVec0, pVec1); + std::array pVecD = RecoDecay::pVec(pVec0, pVec1, pVec2); + auto trackParCovPiK = o2::dataformats::V0(df3.getPCACandidatePos(), pVecPiK, df3.calcPCACovMatrixFlat(), trackParCov0, trackParCov1); + auto trackParCovD = o2::dataformats::V0(df3.getPCACandidatePos(), pVecD, df3.calcPCACovMatrixFlat(), trackParCovPiK, trackParCov2); int indexTrack0 = track0.globalIndex(); int indexTrack1 = track1.globalIndex(); @@ -261,7 +271,7 @@ struct HfCandidateCreatorB0 { } hPtPion->Fill(trackPion.pt()); - array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; + std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; auto trackParCovPi = getTrackParCov(trackPion); // --------------------------------- @@ -283,12 +293,12 @@ struct HfCandidateCreatorB0 { df2.getTrack(0).getPxPyPzGlo(pVecD); // momentum of D at the B0 vertex df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the B0 vertex - // calculate invariant mass and apply selection - massDPi = RecoDecay::m(array{pVecD, pVecPion}, array{massD, massPi}); - if (std::abs(massDPi - massB0) > invMassWindowB0) { + // calculate invariant mass square and apply selection + auto invMass2DPi = RecoDecay::m2(std::array{pVecD, pVecPion}, std::array{massD, massPi}); + if ((invMass2DPi < invMass2DPiMin) || (invMass2DPi > invMass2DPiMax)) { continue; } - hMassB0ToDPi->Fill(massDPi); + hMassB0ToDPi->Fill(std::sqrt(invMass2DPi)); // compute impact parameters of D and Pi o2::dataformats::DCA dcaD; @@ -299,7 +309,7 @@ struct HfCandidateCreatorB0 { // get uncertainty of the decay length double phi, theta; // getPointDirection modifies phi and theta - getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB0, phi, theta); + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexB0, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); @@ -315,8 +325,9 @@ struct HfCandidateCreatorB0 { pVecPion[0], pVecPion[1], pVecPion[2], dcaD.getY(), dcaPion.getY(), std::sqrt(dcaD.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2()), - candD.globalIndex(), trackPion.globalIndex(), hfFlag); + + rowCandidateProngs(candD.globalIndex(), trackPion.globalIndex()); } // pi loop } // D loop } // collision loop @@ -332,11 +343,10 @@ struct HfCandidateCreatorB0Expressions { void init(InitContext const&) {} void processMc(aod::HfCand3Prong const& dplus, - aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMc) + aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::HfCandB0Prongs const& candsB0) { - rowCandidateB0->bindExternalIndices(&tracks); - rowCandidateB0->bindExternalIndices(&dplus); int indexRec = -1; int8_t sign = 0; @@ -345,28 +355,24 @@ struct HfCandidateCreatorB0Expressions { int8_t debug = 0; // Match reconstructed candidates. - // Spawned table can be used directly - for (auto const& candidate : *rowCandidateB0) { - // Printf("New rec. candidate"); + for (const auto& candidate : candsB0) { flag = 0; origin = 0; debug = 0; auto candD = candidate.prong0(); - auto arrayDaughtersB0 = array{candD.prong0_as(), - candD.prong1_as(), - candD.prong2_as(), - candidate.prong1_as()}; - auto arrayDaughtersD = array{candD.prong0_as(), - candD.prong1_as(), - candD.prong2_as()}; + auto arrayDaughtersB0 = std::array{candD.prong0_as(), + candD.prong1_as(), + candD.prong2_as(), + candidate.prong1_as()}; + auto arrayDaughtersD = std::array{candD.prong0_as(), + candD.prong1_as(), + candD.prong2_as()}; // B0 → D- π+ → (π- K+ π-) π+ - // Printf("Checking B0 → D- π+"); - indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersB0, pdg::Code::kB0, array{-kPiPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersB0, pdg::Code::kB0, std::array{-kPiPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); if (indexRec > -1) { // D- → π- K+ π- - // Printf("Checking D- → π- K+ π-"); - indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersD, pdg::Code::kDMinus, array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersD, pdg::Code::kDMinus, std::array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign, 2); if (indexRec > -1) { flag = sign * BIT(hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); } else { @@ -377,10 +383,10 @@ struct HfCandidateCreatorB0Expressions { // B0 → Ds- π+ → (K- K+ π-) π+ if (!flag) { - indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersB0, pdg::Code::kB0, array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersB0, pdg::Code::kB0, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); if (indexRec > -1) { // Ds- → K- K+ π- - indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughtersD, -pdg::Code::kDS, array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersD, -pdg::Code::kDS, std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); if (indexRec > -1) { flag = sign * BIT(hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi); } @@ -398,10 +404,10 @@ struct HfCandidateCreatorB0Expressions { std::array bHadronMotherHypos = {pdg::Code::kB0, pdg::Code::kBS, pdg::Code::kLambdaB0}; for (const auto& bHadronMotherHypo : bHadronMotherHypos) { - int index0Mother = RecoDecay::getMother(particlesMc, particleProng0, bHadronMotherHypo, true); - int index1Mother = RecoDecay::getMother(particlesMc, particleProng1, bHadronMotherHypo, true); - int index2Mother = RecoDecay::getMother(particlesMc, particleProng2, bHadronMotherHypo, true); - int index3Mother = RecoDecay::getMother(particlesMc, particleProng3, bHadronMotherHypo, true); + int index0Mother = RecoDecay::getMother(mcParticles, particleProng0, bHadronMotherHypo, true); + int index1Mother = RecoDecay::getMother(mcParticles, particleProng1, bHadronMotherHypo, true); + int index2Mother = RecoDecay::getMother(mcParticles, particleProng2, bHadronMotherHypo, true); + int index3Mother = RecoDecay::getMother(mcParticles, particleProng3, bHadronMotherHypo, true); // look for common b-hadron ancestor if (index0Mother > -1 && index1Mother > -1 && index2Mother > -1 && index3Mother > -1) { @@ -417,16 +423,14 @@ struct HfCandidateCreatorB0Expressions { } // rec // Match generated particles. - for (auto const& particle : particlesMc) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = 0; origin = 0; // B0 → D- π+ - if (RecoDecay::isMatchedMCGen(particlesMc, particle, pdg::Code::kB0, array{-static_cast(pdg::Code::kDPlus), +kPiPlus}, true)) { - // Match D- -> π- K+ π- - auto candDMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); - // Printf("Checking D- -> π- K+ π-"); - if (RecoDecay::isMatchedMCGen(particlesMc, candDMC, -static_cast(pdg::Code::kDPlus), array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kB0, std::array{-static_cast(pdg::Code::kDPlus), +kPiPlus}, true)) { + // D- → π- K+ π- + auto candDMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, candDMC, -static_cast(pdg::Code::kDPlus), std::array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign)) { flag = sign * BIT(hf_cand_b0::DecayType::B0ToDPi); } } diff --git a/PWGHF/TableProducer/candidateCreatorBplus.cxx b/PWGHF/TableProducer/candidateCreatorBplus.cxx index 632ae14ecfa..ced6eac6fcc 100644 --- a/PWGHF/TableProducer/candidateCreatorBplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorBplus.cxx @@ -18,30 +18,30 @@ /// \author Deepa Thomas , UT Austin /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" using namespace o2; +using namespace o2::analysis; +using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_cand_bplus; /// Reconstruction of B± → D0bar(D0) π± → (K± π∓) π± struct HfCandidateCreatorBplus { - Produces rowCandidateBase; + Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateProngs; // table defined in CandidateReconstructionTables.h // vertexing parameters // Configurable bz{"bz", 5., "magnetic field"}; @@ -69,19 +69,27 @@ struct HfCandidateCreatorBplus { Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + HfHelper hfHelper; Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber; - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massD0 = RecoDecay::getMassPDG(pdg::Code::kD0); - double massBplus = RecoDecay::getMassPDG(pdg::Code::kBPlus); - double massD0Pi = 0.; - double bz = 0.; + double massPi{0.}; + double massD0{0.}; + double massBplus{0.}; + double invMass2D0PiMin{0.}; + double invMass2D0PiMax{0.}; + double bz{0.}; + + // Fitter for B vertex + o2::vertexing::DCAFitterN<2> dfB; + // Fitter to redo D-vertex to get extrapolated daughter tracks + o2::vertexing::DCAFitterN<2> df; - using TracksWithSel = soa::Join; + using TracksWithSel = soa::Join; using CandsDFiltered = soa::Filtered>; + Filter filterSelectCandidates = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar); Preslice candsDPerCollision = aod::track_association::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; @@ -94,11 +102,35 @@ struct HfCandidateCreatorBplus { void init(InitContext const&) { + // Initialise fitter for B vertex + dfB.setPropagateToPCA(propagateToPCA); + dfB.setMaxR(maxR); + dfB.setMinParamChange(minParamChange); + dfB.setMinRelChi2Change(minRelChi2Change); + dfB.setUseAbsDCA(true); + dfB.setWeightedFinalPCA(useWeightedFinalPCA); + + // Initial fitter to redo D-vertex to get extrapolated daughter tracks + df.setPropagateToPCA(propagateToPCA); + df.setMaxR(maxR); + df.setMinParamChange(minParamChange); + df.setMinRelChi2Change(minRelChi2Change); + df.setUseAbsDCA(useAbsDCA); + df.setWeightedFinalPCA(useWeightedFinalPCA); + + // Configure CCDB access ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); runNumber = 0; + + // invariant-mass window cut + massPi = o2::analysis::pdg::MassPiPlus; + massD0 = o2::analysis::pdg::MassD0; + massBplus = o2::analysis::pdg::MassBPlus; + invMass2D0PiMin = (massBplus - invMassWindowBplus) * (massBplus - invMassWindowBplus); + invMass2D0PiMax = (massBplus + invMassWindowBplus) * (massBplus + invMassWindowBplus); } /// Single-track cuts for pions on dcaXY @@ -128,24 +160,6 @@ struct HfCandidateCreatorBplus { aod::BCsWithTimestamps const&) { - // Initialise fitter for B vertex - o2::vertexing::DCAFitterN<2> dfB; - dfB.setPropagateToPCA(propagateToPCA); - dfB.setMaxR(maxR); - dfB.setMinParamChange(minParamChange); - dfB.setMinRelChi2Change(minRelChi2Change); - dfB.setUseAbsDCA(true); - dfB.setWeightedFinalPCA(useWeightedFinalPCA); - - // Initial fitter to redo D-vertex to get extrapolated daughter tracks - o2::vertexing::DCAFitterN<2> df; - df.setPropagateToPCA(propagateToPCA); - df.setMaxR(maxR); - df.setMinParamChange(minParamChange); - df.setMinRelChi2Change(minRelChi2Change); - df.setUseAbsDCA(useAbsDCA); - df.setWeightedFinalPCA(useWeightedFinalPCA); - static int nCol = 0; for (const auto& collision : collisions) { @@ -178,11 +192,11 @@ struct HfCandidateCreatorBplus { if (!TESTBIT(candD0.hfflag(), aod::hf_cand_2prong::DecayType::D0ToPiK)) { continue; } - if (yCandMax >= 0. && std::abs(yD0(candD0)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yD0(candD0)) > yCandMax) { continue; } - hRapidityD0->Fill(yD0(candD0)); + hRapidityD0->Fill(hfHelper.yD0(candD0)); // track0 <-> pi, track1 <-> K auto prong0 = candD0.prong0_as(); @@ -216,10 +230,10 @@ struct HfCandidateCreatorBplus { df.getTrack(0).getPxPyPzGlo(pVec0); df.getTrack(1).getPxPyPzGlo(pVec1); // Get D0 momentum - array pVecD = RecoDecay::pVec(pVec0, pVec1); + std::array pVecD = RecoDecay::pVec(pVec0, pVec1); // build a D0 neutral track - auto trackD0 = o2::dataformats::V0(vertexD0, pVecD, df.calcPCACovMatrixFlat(), trackParCovProng0, trackParCovProng1, {0, 0}, {0, 0}); + auto trackD0 = o2::dataformats::V0(vertexD0, pVecD, df.calcPCACovMatrixFlat(), trackParCovProng0, trackParCovProng1); int indexTrack0 = prong0.globalIndex(); int indexTrack1 = prong1.globalIndex(); @@ -237,7 +251,7 @@ struct HfCandidateCreatorBplus { // Select D0pi- and D0(bar)pi+ pairs only if (!((candD0.isSelD0() >= selectionFlagD0 && trackPion.sign() < 0) || (candD0.isSelD0bar() >= selectionFlagD0bar && trackPion.sign() > 0))) { - // Printf("D0: %d, D0bar%d, sign: %d", candD0.isSelD0(), candD0.isSelD0bar(), track.sign()); + // LOGF(debug, "D0: %d, D0bar%d, sign: %d", candD0.isSelD0(), candD0.isSelD0bar(), track.sign()); continue; } @@ -288,18 +302,18 @@ struct HfCandidateCreatorBplus { // get uncertainty of the decay length double phi, theta; - getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secVertexBplus, phi, theta); + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secVertexBplus, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); - int hfFlag = 1 << hf_cand_bplus::DecayType::BplusToD0Pi; + int hfFlag = BIT(hf_cand_bplus::DecayType::BplusToD0Pi); - // calculate invariant mass and fill the Invariant Mass control plot - massD0Pi = RecoDecay::m(array{pVecD0, pVecBach}, array{massD0, massPi}); - if (std::abs(massD0Pi - massBplus) > invMassWindowBplus) { + // compute invariant mass square and apply selection + auto invMass2D0Pi = RecoDecay::m2(std::array{pVecD0, pVecBach}, std::array{massD0, massPi}); + if ((invMass2D0Pi < invMass2D0PiMin) || (invMass2D0Pi > invMass2D0PiMax)) { continue; } - hMassBplusToD0Pi->Fill(massD0Pi); + hMassBplusToD0Pi->Fill(std::sqrt(invMass2D0Pi)); // fill candidate table rows rowCandidateBase(collision.globalIndex(), @@ -311,8 +325,9 @@ struct HfCandidateCreatorBplus { pVecBach[0], pVecBach[1], pVecBach[2], impactParameter0.getY(), impactParameter1.getY(), std::sqrt(impactParameter0.getSigmaY2()), std::sqrt(impactParameter1.getSigmaY2()), - candD0.globalIndex(), trackPion.globalIndex(), // index D0 and bachelor hfFlag); + + rowCandidateProngs(candD0.globalIndex(), trackPion.globalIndex()); // index D0 and bachelor } // track loop } // D0 cand loop } // collision @@ -328,11 +343,10 @@ struct HfCandidateCreatorBplusExpressions { void init(InitContext const&) {} void processMc(aod::HfCand2Prong const& dzero, - aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC) + aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles, + aod::HfCandBplusProngs const& candsBplus) { - rowCandidateBPlus->bindExternalIndices(&tracks); - rowCandidateBPlus->bindExternalIndices(&dzero); int indexRec = -1, indexRecD0 = -1; int8_t signB = 0, signD0 = 0; @@ -342,19 +356,17 @@ struct HfCandidateCreatorBplusExpressions { // Match reconstructed candidates. // Spawned table can be used directly - for (auto const& candidate : *rowCandidateBPlus) { - // Printf("New rec. candidate"); + for (const auto& candidate : candsBplus) { flag = 0; origin = 0; - auto candDaughterD0 = candidate.prong0_as(); - auto arrayDaughtersD0 = array{candDaughterD0.prong0_as(), candDaughterD0.prong1_as()}; - auto arrayDaughters = array{candidate.prong1_as(), candDaughterD0.prong0_as(), candDaughterD0.prong1_as()}; + auto candDaughterD0 = candidate.prong0(); + auto arrayDaughtersD0 = std::array{candDaughterD0.prong0_as(), candDaughterD0.prong1_as()}; + auto arrayDaughters = std::array{candidate.prong1_as(), candDaughterD0.prong0_as(), candDaughterD0.prong1_as()}; // B± → D0bar(D0) π± → (K± π∓) π± - // Printf("Checking B± → D0(bar) π±"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kBPlus, array{+kPiPlus, +kKPlus, -kPiPlus}, true, &signB, 2); - indexRecD0 = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersD0, pdg::Code::kD0, array{-kKPlus, +kPiPlus}, true, &signD0, 1); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kBPlus, std::array{+kPiPlus, +kKPlus, -kPiPlus}, true, &signB, 2); + indexRecD0 = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersD0, -pdg::Code::kD0, std::array{+kKPlus, -kPiPlus}, true, &signD0, 1); if (indexRecD0 > -1 && indexRec > -1) { flag = signB * (1 << hf_cand_bplus::DecayType::BplusToD0Pi); @@ -363,8 +375,7 @@ struct HfCandidateCreatorBplusExpressions { } // Match generated particles. - for (auto& particle : particlesMC) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = 0; origin = 0; signB = 0; @@ -372,15 +383,13 @@ struct HfCandidateCreatorBplusExpressions { int indexGenD0 = -1; // B± → D0bar(D0) π± → (K± π∓) π± - // Printf("Checking B± → D0(bar) π±"); std::vector arrayDaughterB; - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kBPlus, array{-kD0pdg, +kPiPlus}, true, &signB, 1, &arrayDaughterB)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kBPlus, std::array{-kD0pdg, +kPiPlus}, true, &signB, 1, &arrayDaughterB)) { // D0(bar) → π± K∓ - // Printf("Checking D0(bar) → π± K∓"); for (auto iD : arrayDaughterB) { - auto candDaughterMC = particlesMC.rawIteratorAt(iD); + auto candDaughterMC = mcParticles.rawIteratorAt(iD); if (std::abs(candDaughterMC.pdgCode()) == kD0pdg) { - indexGenD0 = RecoDecay::isMatchedMCGen(particlesMC, candDaughterMC, pdg::Code::kD0, array{-kKPlus, +kPiPlus}, true, &signD0, 1); + indexGenD0 = RecoDecay::isMatchedMCGen(mcParticles, candDaughterMC, pdg::Code::kD0, std::array{-kKPlus, +kPiPlus}, true, &signD0, 1); } } if (indexGenD0 > -1) { diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx new file mode 100644 index 00000000000..6f7454d0ae0 --- /dev/null +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -0,0 +1,483 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file candidateCreatorBs.cxx +/// \brief Reconstruction of Bs candidates +/// \note Adapted from candidateCreatorB0.cxx +/// +/// \author Phil Stahlhut + +#include "DCAFitter/DCAFitterN.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/V0.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" + +using namespace o2; +using namespace o2::analysis; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; + +/// Reconstruction of Bs candidates +struct HfCandidateCreatorBs { + Produces rowCandidateBase; // table defined in CandidateReconstructionTables.h + + // vertexing + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; + Configurable useAbsDCADs{"useAbsDCADs", false, "Minimise abs. distance rather than chi2 for 3-prong Ds vertex"}; + Configurable useAbsDCABs{"useAbsDCABs", true, "Minimise abs. distance rather than chi2 for 2-prong Bs vertex"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + Configurable maxR{"maxR", 4., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any Bs is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + // selection + Configurable usePionIsGlobalTrackWoDCA{"usePionIsGlobalTrackWoDCA", true, "check isGlobalTrackWoDCA status for pions, for Run3 studies"}; + Configurable ptPionMin{"ptPionMin", 0.5, "minimum pion pT threshold (GeV/c)"}; + Configurable> binsPtPion{"binsPtPion", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for pion DCA XY pT-dependent cut"}; + Configurable> cutsTrackPionDCA{"cutsTrackPionDCA", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for pions"}; + Configurable invMassWindowBs{"invMassWindowBs", 0.3, "invariant-mass window for Bs candidates"}; + Configurable selectionFlagDs{"selectionFlagDs", 1, "Selection Flag for Ds"}; + // magnetic field setting from CCDB + Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + + HfHelper hfHelper; + Service ccdb; + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + + int runNumber{0}; + double massPi{0.}; + double massDs{0.}; + double massBs{0.}; + double massDsPi{0.}; + double bz{0.}; + + using TracksWithSel = soa::Join; + using CandsDsFiltered = soa::Filtered>; + + Filter filterSelectCandidates = (aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs); + + Preslice candsDsPerCollision = aod::track_association::collisionId; + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + + OutputObj hMassDsToKKPi{TH1F("hMassDsToKKPi", "D_{s} candidates;inv. mass (K K #pi) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; + OutputObj hPtDs{TH1F("hPtDs", "D_{s} candidates;D_{s} candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj hPtPion{TH1F("hPtPion", "#pi candidates;#pi candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)}; + OutputObj hCPADs{TH1F("hCPADs", "D_{s} candidates;D_{s} cosine of pointing angle;entries", 110, -1.1, 1.1)}; + OutputObj hMassBsToDsPi{TH1F("hMassBsToDsPi", "2-prong candidates;inv. mass (B_{s} #rightarrow D_{s}#pi #rightarrow KK#pi#pi) (GeV/#it{c}^{2});entries", 500, 3., 8.)}; + OutputObj hCovPVXX{TH1F("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", 100, 0., 1.e-4)}; + OutputObj hCovSVXX{TH1F("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", 100, 0., 0.2)}; + + void init(InitContext const&) + { + massPi = o2::analysis::pdg::MassPiPlus; + massDs = o2::analysis::pdg::MassDSBar; + massBs = o2::analysis::pdg::MassBS; + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); + runNumber = 0; + } + + /// Single-track cuts for pions on dcaXY + /// \param track is a track + /// \return true if track passes all cuts + template + bool isSelectedTrackDCA(const T& track) + { + auto pTBinTrack = findBin(binsPtPion, track.pt()); + if (pTBinTrack == -1) { + return false; + } + + if (std::abs(track.dcaXY()) < cutsTrackPionDCA->get(pTBinTrack, "min_dcaxytoprimary")) { + return false; // minimum DCAxy + } + if (std::abs(track.dcaXY()) > cutsTrackPionDCA->get(pTBinTrack, "max_dcaxytoprimary")) { + return false; // maximum DCAxy + } + return true; + } + + void process(aod::Collisions const& collisions, + CandsDsFiltered const& candsDs, + aod::TrackAssoc const& trackIndices, + TracksWithSel const&, + aod::BCsWithTimestamps const&) + { + // Initialise fitter for Bs vertex (2-prong vertex filter) + o2::vertexing::DCAFitterN<2> df2; + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCABs); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + + // Initialise fitter to redo Ds-vertex to get extrapolated daughter tracks (3-prong vertex filter) + o2::vertexing::DCAFitterN<3> df3; + df3.setPropagateToPCA(propagateToPCA); + df3.setMaxR(maxR); + df3.setMaxDZIni(maxDZIni); + df3.setMinParamChange(minParamChange); + df3.setMinRelChi2Change(minRelChi2Change); + df3.setUseAbsDCA(useAbsDCADs); + df3.setWeightedFinalPCA(useWeightedFinalPCA); + + for (const auto& collision : collisions) { + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + + /// Set the magnetic field from ccdb. + /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, + /// but this is not true when running on Run2 data/MC already converted into AO2Ds. + auto bc = collision.bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + } + df2.setBz(bz); + df3.setBz(bz); + + auto thisCollId = collision.globalIndex(); + auto candsDsThisColl = candsDs.sliceBy(candsDsPerCollision, thisCollId); + + for (const auto& candDs : candsDsThisColl) { // start loop over filtered Ds candidates indices as associated to this collision in candidateCreator3Prong.cxx + + // track0 <-> K, track1 <-> K, track2 <-> pi + auto track0 = candDs.prong0_as(); + auto track1 = candDs.prong1_as(); + auto track2 = candDs.prong2_as(); + auto trackParCov0 = getTrackParCov(track0); + auto trackParCov1 = getTrackParCov(track1); + auto trackParCov2 = getTrackParCov(track2); + + std::array pVec0 = {track0.px(), track0.py(), track0.pz()}; + std::array pVec1 = {track1.px(), track1.py(), track1.pz()}; + std::array pVec2 = {track2.px(), track2.py(), track2.pz()}; + + auto dca0 = o2::dataformats::DCA(track0.dcaXY(), track0.dcaZ(), track0.cYY(), track0.cZY(), track0.cZZ()); + auto dca1 = o2::dataformats::DCA(track1.dcaXY(), track1.dcaZ(), track1.cYY(), track1.cZY(), track1.cZZ()); + auto dca2 = o2::dataformats::DCA(track2.dcaXY(), track2.dcaZ(), track2.cYY(), track2.cZY(), track2.cZZ()); + + // repropagate tracks to this collision if needed + if (track0.collisionId() != thisCollId) { + trackParCov0.propagateToDCA(primaryVertex, bz, &dca0); + } + + if (track1.collisionId() != thisCollId) { + trackParCov1.propagateToDCA(primaryVertex, bz, &dca1); + } + + if (track2.collisionId() != thisCollId) { + trackParCov2.propagateToDCA(primaryVertex, bz, &dca2); + } + + // --------------------------------- + // reconstruct 3-prong secondary vertex (Ds±) + if (df3.process(trackParCov0, trackParCov1, trackParCov2) == 0) { + continue; + } + + const auto& secondaryVertexDs = df3.getPCACandidate(); + // propagate the 3 prongs to the secondary vertex + trackParCov0.propagateTo(secondaryVertexDs[0], bz); + trackParCov1.propagateTo(secondaryVertexDs[0], bz); + trackParCov2.propagateTo(secondaryVertexDs[0], bz); + + // update pVec of tracks + df3.getTrack(0).getPxPyPzGlo(pVec0); + df3.getTrack(1).getPxPyPzGlo(pVec1); + df3.getTrack(2).getPxPyPzGlo(pVec2); + + // Ds∓ → K∓ K± π∓ + std::array pVecKK = RecoDecay::pVec(pVec0, pVec1); + std::array pVecDs = RecoDecay::pVec(pVec0, pVec1, pVec2); + auto trackParCovKK = o2::dataformats::V0(df3.getPCACandidatePos(), pVecKK, df3.calcPCACovMatrixFlat(), + trackParCov0, trackParCov1); + auto trackParCovDs = o2::dataformats::V0(df3.getPCACandidatePos(), pVecDs, df3.calcPCACovMatrixFlat(), + trackParCovKK, trackParCov2); + + int indexTrack0 = track0.globalIndex(); + int indexTrack1 = track1.globalIndex(); + int indexTrack2 = track2.globalIndex(); + + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + + for (const auto& trackId : trackIdsThisCollision) { // start loop over track indices associated to this collision + auto trackPion = trackId.track_as(); + + // check isGlobalTrackWoDCA status for pions if wanted + if (usePionIsGlobalTrackWoDCA && !trackPion.isGlobalTrackWoDCA()) { + continue; + } + + // minimum pT selection + if (trackPion.pt() < ptPionMin || !isSelectedTrackDCA(trackPion)) { + continue; + } + // reject pions that are Ds daughters + if (trackPion.globalIndex() == indexTrack0 || trackPion.globalIndex() == indexTrack1 || trackPion.globalIndex() == indexTrack2) { + continue; + } + // reject pi and Ds with same sign + if (trackPion.sign() * track0.sign() > 0) { + continue; + } + + std::array pVecPion = {trackPion.px(), trackPion.py(), trackPion.pz()}; + auto trackParCovPi = getTrackParCov(trackPion); + + // --------------------------------- + // reconstruct the 2-prong Bs vertex + if (df2.process(trackParCovDs, trackParCovPi) == 0) { + continue; + } + + // calculate relevant properties + const auto& secondaryVertexBs = df2.getPCACandidate(); + auto chi2PCA = df2.getChi2AtPCACandidate(); + auto covMatrixPCA = df2.calcPCACovMatrixFlat(); + + // propagate Ds and Pi to the Bs vertex + df2.propagateTracksToVertex(); + // track.getPxPyPzGlo(pVec) modifies pVec of track + df2.getTrack(0).getPxPyPzGlo(pVecDs); // momentum of Ds at the Bs vertex + df2.getTrack(1).getPxPyPzGlo(pVecPion); // momentum of Pi at the Bs vertex + + // calculate invariant mass and apply selection + massDsPi = RecoDecay::m(std::array{pVecDs, pVecPion}, std::array{massDs, massPi}); + if (std::abs(massDsPi - massBs) > invMassWindowBs) { + continue; + } + + // compute impact parameters of Ds and Pi + o2::dataformats::DCA dcaDs; + o2::dataformats::DCA dcaPion; + trackParCovDs.propagateToDCA(primaryVertex, bz, &dcaDs); + trackParCovPi.propagateToDCA(primaryVertex, bz, &dcaPion); + + // get uncertainty of the decay length + double phi, theta; + // getPointDirection modifies phi and theta + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexBs, phi, theta); + auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + int hfFlag = BIT(hf_cand_bs::DecayType::BsToDsPi); + + // fill output histograms for Bs candidates + hMassDsToKKPi->Fill(hfHelper.invMassDsToKKPi(candDs), candDs.pt()); + hCovSVXX->Fill(covMatrixPCA[0]); + hCovPVXX->Fill(covMatrixPV[0]); + hMassBsToDsPi->Fill(massDsPi); + hPtDs->Fill(candDs.pt()); + hCPADs->Fill(candDs.cpa()); + hPtPion->Fill(trackPion.pt()); + + // fill the candidate table for the Bs here: + rowCandidateBase(thisCollId, + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexBs[0], secondaryVertexBs[1], secondaryVertexBs[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecDs[0], pVecDs[1], pVecDs[2], + pVecPion[0], pVecPion[1], pVecPion[2], + dcaDs.getY(), dcaPion.getY(), + std::sqrt(dcaDs.getSigmaY2()), std::sqrt(dcaPion.getSigmaY2()), + candDs.globalIndex(), trackPion.globalIndex(), + hfFlag); + } // pi loop + } // Ds loop + } // collision loop + } // process +}; // struct + +/// Extends the base table with expression columns and performs MC matching. +struct HfCandidateCreatorBsExpressions { + Spawns rowCandidateBs; + Produces rowMcMatchRec; // table defined in CandidateReconstructionTables.h + Produces rowMcMatchGen; // table defined in CandidateReconstructionTables.h + + void init(InitContext const&) {} + + void processMc(aod::HfCand3Prong const& ds, + aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles) + { + rowCandidateBs->bindExternalIndices(&tracks); + rowCandidateBs->bindExternalIndices(&ds); + + int indexRec = -1; + int8_t sign = 0; + int8_t flag = 0; + std::vector arrDaughDsIndex; + std::array arrPDGDaughDs; + std::array arrPDGResonantDsPhiPi = {pdg::Code::kPhi, kPiPlus}; // Ds± → Phi π± + + // Match reconstructed candidates. + // Spawned table can be used directly + for (const auto& candidate : *rowCandidateBs) { + flag = 0; + arrDaughDsIndex.clear(); + auto candDs = candidate.prong0(); + auto arrayDaughtersBs = std::array{candDs.prong0_as(), + candDs.prong1_as(), + candDs.prong2_as(), + candidate.prong1_as()}; + auto arrayDaughtersDs = std::array{candDs.prong0_as(), + candDs.prong1_as(), + candDs.prong2_as()}; + + // Checking Bs0(bar) → Ds∓ π± → (K- K+ π∓) π± + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersBs, pdg::Code::kBS, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); + if (indexRec > -1) { + // Checking Ds∓ → K- K+ π∓ + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersDs, pdg::Code::kDSBar, std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); + if (indexRec > -1) { + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto iProng = 0u; iProng < arrDaughDsIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughDsIndex[iProng]); + arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); + } + } + } + } + + if (!flag) { + // Checking B0(bar) → Ds± π∓ → (K- K+ π±) π∓ + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersBs, pdg::Code::kB0, std::array{-kKPlus, +kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); + if (indexRec > -1) { + // Checking Ds± → K- K+ π± + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersDs, pdg::Code::kDS, std::array{-kKPlus, +kKPlus, +kPiPlus}, true, &sign, 2); + if (indexRec > -1) { + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto iProng = 0u; iProng < arrDaughDsIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughDsIndex[iProng]); + arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi); + } + } + } + } + } + + // Partly reconstructed decays, i.e. the 4 prongs have a common b-hadron ancestor + // convention: final state particles are prong0,1,2,3 + if (!flag) { + auto particleProng0 = arrayDaughtersBs[0].mcParticle(); + auto particleProng1 = arrayDaughtersBs[1].mcParticle(); + auto particleProng2 = arrayDaughtersBs[2].mcParticle(); + auto particleProng3 = arrayDaughtersBs[3].mcParticle(); + // b-hadron hypothesis + std::array bHadronMotherHypos = {pdg::Code::kB0, pdg::Code::kBPlus, pdg::Code::kBS, pdg::Code::kLambdaB0}; + + for (const auto& bHadronMotherHypo : bHadronMotherHypos) { + int index0Mother = RecoDecay::getMother(mcParticles, particleProng0, bHadronMotherHypo, true); + int index1Mother = RecoDecay::getMother(mcParticles, particleProng1, bHadronMotherHypo, true); + int index2Mother = RecoDecay::getMother(mcParticles, particleProng2, bHadronMotherHypo, true); + int index3Mother = RecoDecay::getMother(mcParticles, particleProng3, bHadronMotherHypo, true); + + // look for common b-hadron ancestor + if (index0Mother > -1 && index1Mother > -1 && index2Mother > -1 && index3Mother > -1) { + if (index0Mother == index1Mother && index1Mother == index2Mother && index2Mother == index3Mother) { + flag = BIT(hf_cand_bs::DecayTypeMc::PartlyRecoDecay); + break; + } + } + } + } + + rowMcMatchRec(flag); + } // rec + + // Match generated particles. + for (const auto& particle : mcParticles) { + flag = 0; + arrDaughDsIndex.clear(); + + // Checking Bs0(bar) → Ds∓ π± → (K- K+ π∓) π± + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kBS, std::array{+pdg::Code::kDSBar, +kPiPlus}, true)) { + // Checking Ds∓ → K- K+ π∓ + auto candDsMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, candDsMC, pdg::Code::kDSBar, std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2)) { + RecoDecay::getDaughters(candDsMC, &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto jProng = 0u; jProng < arrDaughDsIndex.size(); ++jProng) { + auto daughJ = mcParticles.rawIteratorAt(arrDaughDsIndex[jProng]); + arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); + } + if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); + } + } + } + } + + if (!flag) { + // Checking B0(bar) → Ds± π∓ → (K- K+ π±) π∓ + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kB0, std::array{+pdg::Code::kDS, -kPiPlus}, true)) { + // Checking Ds± → K- K+ π± + auto candDsMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, candDsMC, pdg::Code::kDS, std::array{-kKPlus, +kKPlus, +kPiPlus}, true, &sign, 2)) { + RecoDecay::getDaughters(candDsMC, &arrDaughDsIndex, std::array{0}, 1); + if (arrDaughDsIndex.size() == 2) { + for (auto jProng = 0u; jProng < arrDaughDsIndex.size(); ++jProng) { + auto daughJ = mcParticles.rawIteratorAt(arrDaughDsIndex[jProng]); + arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); + } + if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { + flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToKKPiPi); + } + } + } + } + } + + rowMcMatchGen(flag); + } // gen + } // processMc + PROCESS_SWITCH(HfCandidateCreatorBsExpressions, processMc, "Process MC", false); +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; + + return workflow; +} diff --git a/PWGHF/TableProducer/candidateCreatorCascade.cxx b/PWGHF/TableProducer/candidateCreatorCascade.cxx index 02e8166fa2d..95a30d9344d 100644 --- a/PWGHF/TableProducer/candidateCreatorCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorCascade.cxx @@ -15,31 +15,32 @@ /// \author Chiara Zampolli, , CERN /// Paul Buehler, , Vienna -#include "Common/Core/trackUtilities.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" +#include "Common/Core/trackUtilities.h" + #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsDebugLcToK0sP.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_2prong; // #define MY_DEBUG #ifdef MY_DEBUG -using MyBigTracks = aod::BigTracksMC; +using MyBigTracks = soa::Join; #define MY_DEBUG_MSG(condition, cmd) \ if (condition) { \ cmd; \ } #else -using MyBigTracks = aod::BigTracks; +using MyBigTracks = aod::TracksWCov; #define MY_DEBUG_MSG(condition, cmd) #endif @@ -58,7 +59,6 @@ struct HfCandidateCreatorCascade { Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; Configurable fillHistograms{"fillHistograms", true, "fill validation histograms"}; Configurable silenceV0DataWarning{"silenceV0DataWarning", false, "do not print a warning for not found V0s and silently skip them"}; - // magnetic field setting from CCDB Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -69,7 +69,6 @@ struct HfCandidateCreatorCascade { Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; - int runNumber; // for debugging #ifdef MY_DEBUG @@ -78,10 +77,11 @@ struct HfCandidateCreatorCascade { Configurable> indexProton{"indexProton", {717, 2810, 4393, 5442, 6769, 7793, 9002, 9789}, "indices of protons, for debug"}; #endif - double massP = RecoDecay::getMassPDG(kProton); - double massK0s = RecoDecay::getMassPDG(kK0Short); - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massLc = RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus); + int runNumber{0}; + double massP{0.}; + double massK0s{0.}; + double massPi{0.}; + double massLc{0.}; double mass2K0sP{0.}; double bz = 0.; @@ -91,6 +91,10 @@ struct HfCandidateCreatorCascade { void init(InitContext const&) { + massP = o2::analysis::pdg::MassProton; + massK0s = o2::analysis::pdg::MassK0Short; + massPi = o2::analysis::pdg::MassPiPlus; + massLc = o2::analysis::pdg::MassLambdaCPlus; ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -106,7 +110,7 @@ struct HfCandidateCreatorCascade { aod::BCsWithTimestamps const& #ifdef MY_DEBUG , - aod::McParticles& mcParticles + aod::McParticles const& mcParticles #endif ) { @@ -171,7 +175,7 @@ struct HfCandidateCreatorCascade { const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; const std::array momentumV0 = {v0.px(), v0.py(), v0.pz()}; // we build the neutral track to then build the cascade - auto trackV0 = o2::dataformats::V0(vertexV0, momentumV0, {0, 0, 0, 0, 0, 0}, trackParCovV0DaughPos, trackParCovV0DaughNeg, {0, 0}, {0, 0}); // build the V0 track (indices for v0 daughters set to 0 for now) + auto trackV0 = o2::dataformats::V0(vertexV0, momentumV0, {0, 0, 0, 0, 0, 0}, trackParCovV0DaughPos, trackParCovV0DaughNeg); // build the V0 track (indices for v0 daughters set to 0 for now) // reconstruct the cascade secondary vertex if (df.process(trackV0, trackParCovBach) == 0) { @@ -193,8 +197,8 @@ struct HfCandidateCreatorCascade { auto trackParVarBach = df.getTrack(1); // get track momenta - array pVecV0; - array pVecBach; + std::array pVecV0; + std::array pVecBach; trackParVarV0.getPxPyPzGlo(pVecV0); trackParVarBach.getPxPyPzGlo(pVecBach); @@ -210,7 +214,7 @@ struct HfCandidateCreatorCascade { // get uncertainty of the decay length double phi, theta; - getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, phi, theta); + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); @@ -238,7 +242,7 @@ struct HfCandidateCreatorCascade { // fill histograms if (fillHistograms) { // calculate invariant masses - mass2K0sP = RecoDecay::m(array{pVecBach, pVecV0}, array{massP, massK0s}); + mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{massP, massK0s}); hMass2->Fill(mass2K0sP); } } @@ -257,15 +261,17 @@ struct HfCandidateCreatorCascadeMc { Configurable> indexProton{"indexProton", {717, 2810, 4393, 5442, 6769, 7793, 9002, 9789}, "indices of protons, for debug"}; #endif - void processMc(aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC) + using MyTracksWMc = soa::Join; + + void processMc(MyTracksWMc const& tracks, + aod::McParticles const& mcParticles) { int8_t sign = 0; int8_t origin = 0; int indexRec = -1; std::vector arrDaughLcIndex; std::array arrDaughLcPDG; - std::array arrDaughLcPDGRef = {2212, 211, -211}; + std::array arrDaughLcPDGRef = {+kProton, +kPiPlus, -kPiPlus}; // Match reconstructed candidates. rowCandidateCasc->bindExternalIndices(&tracks); @@ -273,12 +279,12 @@ struct HfCandidateCreatorCascadeMc { origin = 0; - const auto& bach = candidate.prong0_as(); - const auto& trackV0DaughPos = candidate.posTrack_as(); - const auto& trackV0DaughNeg = candidate.negTrack_as(); + const auto& bach = candidate.prong0_as(); + const auto& trackV0DaughPos = candidate.posTrack_as(); + const auto& trackV0DaughNeg = candidate.negTrack_as(); - auto arrayDaughtersV0 = array{trackV0DaughPos, trackV0DaughNeg}; - auto arrayDaughtersLc = array{bach, trackV0DaughPos, trackV0DaughNeg}; + auto arrayDaughtersV0 = std::array{trackV0DaughPos, trackV0DaughNeg}; + auto arrayDaughtersLc = std::array{bach, trackV0DaughPos, trackV0DaughNeg}; // First we check the K0s LOG(debug) << "\n"; @@ -294,20 +300,20 @@ struct HfCandidateCreatorCascadeMc { MY_DEBUG_MSG(isK0SfromLc, LOG(info) << "correct K0S in the Lc daughters: posTrack --> " << indexV0DaughPos << ", negTrack --> " << indexV0DaughNeg); // if (isLc) { - RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersV0, kK0Short, array{+kPiPlus, -kPiPlus}, true, &sign, 1); // does it matter the "acceptAntiParticle" in the K0s case? In principle, there is no anti-K0s + RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, kK0Short, std::array{+kPiPlus, -kPiPlus}, false, &sign, 1); if (sign != 0) { // we have already positively checked the K0s // then we check the Lc MY_DEBUG_MSG(sign, LOG(info) << "K0S was correct! now we check the Lc"); MY_DEBUG_MSG(sign, LOG(info) << "index proton = " << indexBach); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersLc, pdg::Code::kLambdaCPlus, array{+kProton, +kPiPlus, -kPiPlus}, true, &sign, 3); // 3-levels Lc --> p + K0 --> p + K0s --> p + pi+ pi- + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, pdg::Code::kLambdaCPlus, std::array{+kProton, +kPiPlus, -kPiPlus}, true, &sign, 3); // 3-levels Lc --> p + K0 --> p + K0s --> p + pi+ pi- MY_DEBUG_MSG(sign, LOG(info) << "Lc found with sign " << sign; printf("\n")); } // Check whether the particle is non-prompt (from a b quark). if (sign != 0) { - auto particle = particlesMC.rawIteratorAt(indexRec); - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchRec(sign, origin); @@ -315,10 +321,14 @@ struct HfCandidateCreatorCascadeMc { //} // Match generated particles. - for (const auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { origin = 0; // checking if I have a Lc --> K0S + p - RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kLambdaCPlus, array{+kProton, +kK0Short}, true, &sign, 2); + RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kLambdaCPlus, std::array{+kProton, +kK0Short}, false, &sign, 2); + if (sign == 0) { // now check for anti-Lc + RecoDecay::isMatchedMCGen(mcParticles, particle, -pdg::Code::kLambdaCPlus, std::array{-kProton, +kK0Short}, false, &sign, 2); + sign = -sign; + } if (sign != 0) { MY_DEBUG_MSG(sign, LOG(info) << "Lc in K0S p"); arrDaughLcIndex.clear(); @@ -326,10 +336,10 @@ struct HfCandidateCreatorCascadeMc { RecoDecay::getDaughters(particle, &arrDaughLcIndex, arrDaughLcPDGRef, 3); // best would be to check the K0S daughters if (arrDaughLcIndex.size() == 3) { for (std::size_t iProng = 0; iProng < arrDaughLcIndex.size(); ++iProng) { - auto daughI = particlesMC.rawIteratorAt(arrDaughLcIndex[iProng]); + auto daughI = mcParticles.rawIteratorAt(arrDaughLcIndex[iProng]); arrDaughLcPDG[iProng] = daughI.pdgCode(); } - if (!(arrDaughLcPDG[0] == arrDaughLcPDGRef[0] && arrDaughLcPDG[1] == arrDaughLcPDGRef[1] && arrDaughLcPDG[2] == arrDaughLcPDGRef[2])) { // this should be the condition, first bach, then v0 + if (!(arrDaughLcPDG[0] == sign * arrDaughLcPDGRef[0] && arrDaughLcPDG[1] == arrDaughLcPDGRef[1] && arrDaughLcPDG[2] == arrDaughLcPDGRef[2])) { // this should be the condition, first bach, then v0 sign = 0; } else { LOG(debug) << "Lc --> K0S+p found in MC table"; @@ -339,7 +349,7 @@ struct HfCandidateCreatorCascadeMc { } // Check whether the particle is non-prompt (from a b quark). if (sign != 0) { - origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } rowMcMatchGen(sign, origin); } diff --git a/PWGHF/TableProducer/candidateCreatorDstar.cxx b/PWGHF/TableProducer/candidateCreatorDstar.cxx index 578a85501a3..1924a3aca87 100644 --- a/PWGHF/TableProducer/candidateCreatorDstar.cxx +++ b/PWGHF/TableProducer/candidateCreatorDstar.cxx @@ -14,26 +14,18 @@ /// /// \author Vít Kučera , CERN -// #include "Common/Core/trackUtilities.h" -// #include "DetectorsVertexing/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -// #include "ReconstructionDataFormats/DCA.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" using namespace o2; using namespace o2::framework; -// using namespace o2::aod::hf_cand; -// using namespace o2::aod::hf_cand_2prong; /// Reconstruction of D* decay candidates struct HfCandidateCreatorDstar { Configurable fillHistograms{"fillHistograms", true, "fill histograms"}; - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massD0 = RecoDecay::getMassPDG(pdg::Code::kD0); - OutputObj hMass{TH1F("hMass", "D* candidates;inv. mass (#pi D^{0}) (GeV/#it{c}^{2});entries", 500, 0., 5.)}; OutputObj hPtPi{TH1F("hPtPi", "#pi candidates;#it{p}_{T} (GeV/#it{c});entries", 500, 0., 5.)}; OutputObj hPtD0Prong0{TH1F("hPtD0Prong0", "D^{0} candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", 500, 0., 5.)}; @@ -42,15 +34,18 @@ struct HfCandidateCreatorDstar { void process(aod::Collisions const&, aod::HfDstars const& rowsTrackIndexDstar, - aod::BigTracks const&, + aod::Tracks const&, aod::Hf2Prongs const&) { + auto massPi = o2::analysis::pdg::MassPiPlus; + auto massD0 = o2::analysis::pdg::MassD0; + // loop over pairs of prong indices for (const auto& rowTrackIndexDstar : rowsTrackIndexDstar) { - auto trackPi = rowTrackIndexDstar.prong0_as(); + auto trackPi = rowTrackIndexDstar.prong0(); auto prongD0 = rowTrackIndexDstar.prongD0_as(); - auto trackD0Prong0 = prongD0.prong0_as(); - auto trackD0Prong1 = prongD0.prong1_as(); + auto trackD0Prong0 = prongD0.prong0(); + auto trackD0Prong1 = prongD0.prong1(); // auto collisionPiId = trackPi.collisionId(); // auto collisionD0Id = trackD0Prong0.collisionId(); diff --git a/PWGHF/TableProducer/candidateCreatorLb.cxx b/PWGHF/TableProducer/candidateCreatorLb.cxx index f65a64d5406..018608984ba 100644 --- a/PWGHF/TableProducer/candidateCreatorLb.cxx +++ b/PWGHF/TableProducer/candidateCreatorLb.cxx @@ -15,22 +15,21 @@ /// /// \author Panos Christakoglou , Nikhef -#include "Common/Core/trackUtilities.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" +#include "Common/Core/trackUtilities.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::aod::hf_cand_lb; using namespace o2::framework::expressions; void customize(std::vector& workflowOptions) @@ -59,9 +58,11 @@ struct HfCandidateCreatorLb { Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; - double massPi = RecoDecay::getMassPDG(kPiMinus); - double massLc = RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus); - double massLcPi = 0.; + HfHelper hfHelper; + + double massPi{0.}; + double massLc{0.}; + double massLcPi{0.}; Filter filterSelectCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); @@ -73,11 +74,17 @@ struct HfCandidateCreatorLb { OutputObj hCovPVXX{TH1F("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", 100, 0., 1.e-4)}; OutputObj hCovSVXX{TH1F("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", 100, 0., 0.2)}; + void init(InitContext const&) + { + massPi = o2::analysis::pdg::MassPiMinus; + massLc = o2::analysis::pdg::MassLambdaCPlus; + } + void process(aod::Collision const& collision, soa::Filtered> const& lcCands, - aod::BigTracks const& tracks) + aod::TracksWCov const& tracks) { // 2-prong vertex fitter o2::vertexing::DCAFitterN<2> df2; @@ -102,22 +109,22 @@ struct HfCandidateCreatorLb { df3.setWeightedFinalPCA(useWeightedFinalPCA); // loop over Lc candidates - for (auto& lcCand : lcCands) { + for (const auto& lcCand : lcCands) { if (!(lcCand.hfflag() & 1 << o2::aod::hf_cand_3prong::DecayType::LcToPKPi)) { continue; } if (lcCand.isSelLcToPKPi() >= selectionFlagLc) { - hMassLcToPKPi->Fill(invMassLcToPKPi(lcCand), lcCand.pt()); + hMassLcToPKPi->Fill(hfHelper.invMassLcToPKPi(lcCand), lcCand.pt()); } if (lcCand.isSelLcToPiKP() >= selectionFlagLc) { - hMassLcToPKPi->Fill(invMassLcToPiKP(lcCand), lcCand.pt()); + hMassLcToPKPi->Fill(hfHelper.invMassLcToPiKP(lcCand), lcCand.pt()); } hPtLc->Fill(lcCand.pt()); hCPALc->Fill(lcCand.cpa()); - auto track0 = lcCand.prong0_as(); - auto track1 = lcCand.prong1_as(); - auto track2 = lcCand.prong2_as(); + auto track0 = lcCand.prong0_as(); + auto track1 = lcCand.prong1_as(); + auto track2 = lcCand.prong2_as(); auto trackParVar0 = getTrackParCov(track0); auto trackParVar1 = getTrackParCov(track1); auto trackParVar2 = getTrackParCov(track2); @@ -132,19 +139,17 @@ struct HfCandidateCreatorLb { trackParVar1.propagateTo(secondaryVertex[0], bz); trackParVar2.propagateTo(secondaryVertex[0], bz); - array pvecpK = {track0.px() + track1.px(), track0.py() + track1.py(), track0.pz() + track1.pz()}; - array pvecLc = {pvecpK[0] + track2.px(), pvecpK[1] + track2.py(), pvecpK[2] + track2.pz()}; - auto trackpK = o2::dataformats::V0(df3.getPCACandidatePos(), pvecpK, df3.calcPCACovMatrixFlat(), - trackParVar0, trackParVar1, {0, 0}, {0, 0}); - auto trackLc = o2::dataformats::V0(df3.getPCACandidatePos(), pvecLc, df3.calcPCACovMatrixFlat(), - trackpK, trackParVar2, {0, 0}, {0, 0}); + std::array pvecpK = {track0.px() + track1.px(), track0.py() + track1.py(), track0.pz() + track1.pz()}; + std::array pvecLc = {pvecpK[0] + track2.px(), pvecpK[1] + track2.py(), pvecpK[2] + track2.pz()}; + auto trackpK = o2::dataformats::V0(df3.getPCACandidatePos(), pvecpK, df3.calcPCACovMatrixFlat(), trackParVar0, trackParVar1); + auto trackLc = o2::dataformats::V0(df3.getPCACandidatePos(), pvecLc, df3.calcPCACovMatrixFlat(), trackpK, trackParVar2); int index0Lc = track0.globalIndex(); int index1Lc = track1.globalIndex(); int index2Lc = track2.globalIndex(); // int charge = track0.sign() + track1.sign() + track2.sign(); - for (auto& trackPion : tracks) { + for (const auto& trackPion : tracks) { if (trackPion.pt() < ptPionMin) { continue; } @@ -155,7 +160,7 @@ struct HfCandidateCreatorLb { continue; } hPtPion->Fill(trackPion.pt()); - array pvecPion; + std::array pvecPion; auto trackParVarPi = getTrackParCov(trackPion); // reconstruct the 3-prong Lc vertex @@ -184,7 +189,7 @@ struct HfCandidateCreatorLb { // get uncertainty of the decay length double phi, theta; - getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexLb, phi, theta); + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexLb, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); @@ -204,8 +209,8 @@ struct HfCandidateCreatorLb { hfFlag); // calculate invariant mass - auto arrayMomenta = array{pvecLc, pvecPion}; - massLcPi = RecoDecay::m(std::move(arrayMomenta), array{massLc, massPi}); + auto arrayMomenta = std::array{pvecLc, pvecPion}; + massLcPi = RecoDecay::m(std::move(arrayMomenta), std::array{massLc, massPi}); if (lcCand.isSelLcToPKPi() > 0) { hMassLbToLcPi->Fill(massLcPi); } @@ -231,8 +236,8 @@ struct HfCandidateCreatorLbMc { void process(aod::HfCandLb const& candidates, aod::HfCand3Prong const&, - aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC) + aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles) { int indexRec = -1; int8_t sign = 0; @@ -241,26 +246,23 @@ struct HfCandidateCreatorLbMc { int8_t debug = 0; // Match reconstructed candidates. - for (auto& candidate : candidates) { - // Printf("New rec. candidate"); + for (const auto& candidate : candidates) { flag = 0; origin = 0; debug = 0; auto lcCand = candidate.prong0(); - auto arrayDaughters = array{lcCand.prong0_as(), - lcCand.prong1_as(), - lcCand.prong2_as(), - candidate.prong1_as()}; - auto arrayDaughtersLc = array{lcCand.prong0_as(), - lcCand.prong1_as(), - lcCand.prong2_as()}; + auto arrayDaughters = std::array{lcCand.prong0_as(), + lcCand.prong1_as(), + lcCand.prong2_as(), + candidate.prong1_as()}; + auto arrayDaughtersLc = std::array{lcCand.prong0_as(), + lcCand.prong1_as(), + lcCand.prong2_as()}; // Λb → Λc+ π- - // Printf("Checking Λb → Λc+ π-"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kLambdaB0, array{+kProton, -kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kLambdaB0, std::array{+kProton, -kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 2); if (indexRec > -1) { // Λb → Λc+ π- - // Printf("Checking Λb → Λc+ π-"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersLc, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 1); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, pdg::Code::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 1); if (indexRec > -1) { flag = 1 << hf_cand_lb::DecayType::LbToLcPi; } else { @@ -272,16 +274,14 @@ struct HfCandidateCreatorLbMc { } // Match generated particles. - for (auto& particle : particlesMC) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = 0; origin = 0; // Λb → Λc+ π- - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kLambdaB0, array{static_cast(pdg::Code::kLambdaCPlus), -kPiPlus}, true)) { - // Match Λc+ -> pKπ - auto LcCandMC = particlesMC.rawIteratorAt(particle.daughtersIds().front()); - // Printf("Checking Λc+ → p K- π+"); - if (RecoDecay::isMatchedMCGen(particlesMC, LcCandMC, static_cast(pdg::Code::kLambdaCPlus), array{+kProton, -kKPlus, +kPiPlus}, true, &sign)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kLambdaB0, std::array{static_cast(pdg::Code::kLambdaCPlus), -kPiPlus}, true)) { + // Λc+ → p K- π+ + auto LcCandMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, LcCandMC, static_cast(pdg::Code::kLambdaCPlus), std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign)) { flag = sign * (1 << hf_cand_lb::DecayType::LbToLcPi); } } diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx index 6b4ca957370..6537f76397d 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx @@ -15,10 +15,7 @@ /// /// \author Mattia Faggin , University and INFN PADOVA -#include "CCDB/BasicCCDBManager.h" // for dca recalculation -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" +#include "CCDB/BasicCCDBManager.h" // for dca recalculation #include "DataFormatsParameters/GRPMagField.h" // for dca recalculation #include "DataFormatsParameters/GRPObject.h" // for dca recalculation #include "DetectorsBase/GeometryManager.h" // for dca recalculation @@ -26,16 +23,20 @@ #include "DetectorsVertexing/PVertexer.h" // for dca recalculation #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -// #include "ReconstructionDataFormats/Vertex.h" // for dca recalculation +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" // for dca recalculation using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; struct HfCandidateCreatorSigmac0plusplus { @@ -62,9 +63,16 @@ struct HfCandidateCreatorSigmac0plusplus { Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; - HistogramRegistry histos; + HfHelper hfHelper; + /// Cut selection object for soft π-,+ + TrackSelection softPiCuts; + + // Needed for dcaXY, dcaZ recalculation of soft pions reassigned to a new collision + Service ccdb; + o2::base::MatLayerCylSet* lut; + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + int runNumber; - using TracksSigmac = soa::Join; using CandidatesLc = soa::Filtered>; /// Filter the candidate Λc+ used for the Σc0,++ creation @@ -75,14 +83,7 @@ struct HfCandidateCreatorSigmac0plusplus { // Preslice hf3ProngPerCollision = aod::track_association::collisionId; Preslice hf3ProngPerCollision = aod::hf_cand::collisionId; - /// Cut selection object for soft π-,+ - TrackSelection softPiCuts; - - // Needed for dcaXY, dcaZ recalculation of soft pions reassigned to a new collision - Service ccdb; - o2::base::MatLayerCylSet* lut; - o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - int runNumber; + HistogramRegistry histos; /// @brief init function, to define the soft pion selections and histograms /// @param @@ -132,36 +133,40 @@ struct HfCandidateCreatorSigmac0plusplus { /// @param collision is a o2::aod::Collision /// @param tracks are the tracks (with dcaXY, dcaZ information) in the collision → soft-pion candidate tracks /// @param candidates are 3-prong candidates satisfying the analysis selections for Λc+ → pK-π+ (and charge conj.) - void process(const o2::aod::Collisions& collisions, aod::TrackAssoc const& trackIndices, const TracksSigmac& tracks, CandidatesLc const& candidates, aod::BCsWithTimestamps const& bcWithTimeStamps) + void process(aod::Collisions const& collisions, + aod::TrackAssoc const& trackIndices, + aod::TracksWDcaExtra const& tracks, + CandidatesLc const& candidates, + aod::BCsWithTimestamps const& bcWithTimeStamps) { - for (auto const& collision : collisions) { + for (const auto& collision : collisions) { histos.fill(HIST("hCounter"), 1); auto thisCollId = collision.globalIndex(); /// loop over Λc+ → pK-π+ (and charge conj.) candidates auto candidatesThisColl = candidates.sliceBy(hf3ProngPerCollision, thisCollId); - for (auto const& candLc : candidatesThisColl) { + for (const auto& candLc : candidatesThisColl) { histos.fill(HIST("hCounter"), 2); /// keep only the candidates flagged as possible Λc+ (and charge conj.) decaying into a charged pion, kaon and proton /// if not selected, skip it and go to the next one - if (!(candLc.hfflag() & 1 << DecayType::LcToPKPi)) { + if (!(candLc.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { continue; } /// keep only the candidates Λc+ (and charge conj.) within the desired rapidity /// if not selected, skip it and go to the next one - if (yCandLcMax >= 0. && std::abs(yLc(candLc)) > yCandLcMax) { + if (yCandLcMax >= 0. && std::abs(hfHelper.yLc(candLc)) > yCandLcMax) { continue; } /// selection on the Λc+ inv. mass window we want to consider for Σc0,++ candidate creation auto statusSpreadMinvPKPiFromPDG = 0; auto statusSpreadMinvPiKPFromPDG = 0; - if (candLc.isSelLcToPKPi() >= 1 && std::abs(invMassLcToPKPi(candLc) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) <= mPKPiCandLcMax) { + if (candLc.isSelLcToPKPi() >= 1 && std::abs(hfHelper.invMassLcToPKPi(candLc) - o2::analysis::pdg::MassLambdaCPlus) <= mPKPiCandLcMax) { statusSpreadMinvPKPiFromPDG = 1; } - if (candLc.isSelLcToPiKP() >= 1 && std::abs(invMassLcToPiKP(candLc) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) <= mPiKPCandLcMax) { + if (candLc.isSelLcToPiKP() >= 1 && std::abs(hfHelper.invMassLcToPiKP(candLc) - o2::analysis::pdg::MassLambdaCPlus) <= mPiKPCandLcMax) { statusSpreadMinvPiKPFromPDG = 1; } if (statusSpreadMinvPKPiFromPDG == 0 && statusSpreadMinvPiKPFromPDG == 0) { @@ -172,9 +177,9 @@ struct HfCandidateCreatorSigmac0plusplus { /// loop over tracks auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - for (auto const& trackId : trackIdsThisCollision) { + for (const auto& trackId : trackIdsThisCollision) { - auto trackSoftPi = trackId.track_as(); + auto trackSoftPi = trackId.track_as(); // auto trackSoftPi = tracks.rawIteratorAt(trackId.trackId()); histos.fill(HIST("hCounter"), 4); @@ -222,7 +227,7 @@ struct HfCandidateCreatorSigmac0plusplus { histos.fill(HIST("hCounter"), 5); /// determine the Σc candidate charge - int chargeLc = candLc.prong0_as().sign() + candLc.prong1_as().sign() + candLc.prong2_as().sign(); + int chargeLc = candLc.prong0_as().sign() + candLc.prong1_as().sign() + candLc.prong2_as().sign(); int chargeSoftPi = trackSoftPi.sign(); int8_t chargeSigmac = chargeLc + chargeSoftPi; if (std::abs(chargeSigmac) != 0 && std::abs(chargeSigmac) != 2) { @@ -254,26 +259,25 @@ struct HfCandidateCreatorSigmac0plusplus { /// Extends the base table with expression columns. struct HfCandidateSigmac0plusplusMc { - Spawns candidatesSigmac; Produces rowMCMatchScRec; Produces rowMCMatchScGen; using LambdacMc = soa::Join; // using LambdacMcGen = soa::Join; - using TracksMC = soa::Join; /// @brief init function void init(InitContext const&) {} /// @brief dummy process function, to be run on data /// @param - void process(const aod::Tracks&) {} + void process(aod::Tracks const&) {} /// @brief process function for MC matching of Σc0,++ → Λc+(→pK-π+) π- reconstructed candidates and counting of generated ones /// @param candidatesSigmac reconstructed Σc0,++ candidates - /// @param particlesMc table of generated particles - void processMc(aod::McParticles const& particlesMc, const TracksMC& tracks, + /// @param mcParticles table of generated particles + void processMc(aod::McParticles const& mcParticles, + aod::TracksWMc const& tracks, LambdacMc const& /*, const LambdacMcGen&*/) { @@ -288,7 +292,7 @@ struct HfCandidateSigmac0plusplusMc { // std::vector arrDaughIndex; /// index of daughters of MC particle /// Match reconstructed Σc0,++ candidates - for (auto const& candSigmac : *candidatesSigmac) { + for (const auto& candSigmac : *candidatesSigmac) { indexRec = -1; sign = 0; flag = 0; @@ -297,16 +301,16 @@ struct HfCandidateSigmac0plusplusMc { /// skip immediately the candidate Σc0,++ w/o a Λc+ matched to MC auto candLc = candSigmac.prongLc_as(); - if (!(std::abs(candLc.flagMcMatchRec()) == 1 << DecayType::LcToPKPi)) { /// (*) + if (!(std::abs(candLc.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { /// (*) rowMCMatchScRec(flag, origin); continue; } /// matching to MC - auto arrayDaughters = array{candLc.prong0_as(), - candLc.prong1_as(), - candLc.prong2_as(), - candSigmac.prong1_as()}; + auto arrayDaughters = std::array{candLc.prong0_as(), + candLc.prong1_as(), + candLc.prong2_as(), + candSigmac.prong1_as()}; chargeSigmac = candSigmac.charge(); if (chargeSigmac == 0) { /// candidate Σc0 @@ -314,7 +318,7 @@ struct HfCandidateSigmac0plusplusMc { /// 1. Σc0 → Λc+ π-,+ /// 2. Λc+ → pK-π+ direct (i) or Λc+ → resonant channel Λc± → p± K*, Λc± → Δ(1232)±± K∓ or Λc± → Λ(1520) π± (ii) /// 3. in case of (ii): resonant channel to pK-π+ - indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughters, pdg::Code::kSigmaC0, array{+kProton, -kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kSigmaC0, std::array{+kProton, -kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); if (indexRec > -1) { /// due to (*) no need to check anything for LambdaC flag = sign * (1 << aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi); } @@ -324,7 +328,7 @@ struct HfCandidateSigmac0plusplusMc { /// 1. Σc0 → Λc+ π-,+ /// 2. Λc+ → pK-π+ direct (i) or Λc+ → resonant channel Λc± → p± K*, Λc± → Δ(1232)±± K∓ or Λc± → Λ(1520) π± (ii) /// 3. in case of (ii): resonant channel to pK-π+ - indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrayDaughters, pdg::Code::kSigmaCPlusPlus, array{+kProton, -kKPlus, +kPiPlus, +kPiPlus}, true, &sign, 3); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kSigmaCPlusPlus, std::array{+kProton, -kKPlus, +kPiPlus, +kPiPlus}, true, &sign, 3); if (indexRec > -1) { /// due to (*) no need to check anything for LambdaC flag = sign * (1 << aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi); } @@ -332,8 +336,8 @@ struct HfCandidateSigmac0plusplusMc { /// check the origin (prompt vs. non-prompt) if (flag != 0) { - auto particle = particlesMc.rawIteratorAt(indexRec); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } /// fill the table with results of reconstruction level MC matching @@ -341,7 +345,7 @@ struct HfCandidateSigmac0plusplusMc { } /// end loop over reconstructed Σc0,++ candidates /// Match generated Σc0,++ candidates - for (auto const& particle : particlesMc) { + for (const auto& particle : mcParticles) { flag = 0; origin = 0; @@ -350,29 +354,29 @@ struct HfCandidateSigmac0plusplusMc { /// 2. Λc+ → pK-π+ direct (i) or Λc+ → resonant channel Λc± → p± K*, Λc± → Δ(1232)±± K∓ or Λc± → Λ(1520) π± (ii) /// 3. in case of (ii): resonant channel to pK-π+ /// → here we check level 1. first, and then levels 2. and 3. are inherited by the Λc+ → pK-π+ MC matching in candidateCreator3Prong.cxx - if (RecoDecay::isMatchedMCGen(particlesMc, particle, pdg::Code::kSigmaC0, array{static_cast(pdg::Code::kLambdaCPlus), static_cast(kPiMinus)}, true, &sign, 1)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kSigmaC0, std::array{static_cast(pdg::Code::kLambdaCPlus), static_cast(kPiMinus)}, true, &sign, 1)) { // generated Σc0 - // for (auto& daughter : particle.daughters_as()) { - for (auto const& daughter : particle.daughters_as()) { + // for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != pdg::Code::kLambdaCPlus) continue; - // if (std::abs(daughter.flagMcMatchGen()) == (1 << DecayType::LcToPKPi)) { - if (RecoDecay::isMatchedMCGen(particlesMc, particle, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + // if (std::abs(daughter.flagMcMatchGen()) == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * (1 << aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi); break; } } - } else if (RecoDecay::isMatchedMCGen(particlesMc, particle, pdg::Code::kSigmaCPlusPlus, array{static_cast(pdg::Code::kLambdaCPlus), static_cast(kPiPlus)}, true, &sign, 1)) { + } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kSigmaCPlusPlus, std::array{static_cast(pdg::Code::kLambdaCPlus), static_cast(kPiPlus)}, true, &sign, 1)) { // generated Σc++ - // for (auto& daughter : particle.daughters_as()) { - for (auto const& daughter : particle.daughters_as()) { + // for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != pdg::Code::kLambdaCPlus) continue; - // if (std::abs(daughter.flagMcMatchGen()) == (1 << DecayType::LcToPKPi)) { - if (RecoDecay::isMatchedMCGen(particlesMc, particle, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + // if (std::abs(daughter.flagMcMatchGen()) == (1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * (1 << aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi); break; @@ -382,22 +386,21 @@ struct HfCandidateSigmac0plusplusMc { /// check the origin (prompt vs. non-prompt) if (flag != 0) { - auto particle = particlesMc.rawIteratorAt(indexRec); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle); + auto particle = mcParticles.rawIteratorAt(indexRec); + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); } /// fill the table with results of generation level MC matching rowMCMatchScGen(flag, origin); - } /// end loop over particlesMc + } /// end loop over mcParticles } /// end processMc PROCESS_SWITCH(HfCandidateSigmac0plusplusMc, processMc, "Process MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow{ + return WorkflowSpec{ adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; - return workflow; } diff --git a/PWGHF/TableProducer/candidateCreatorToXiPi.cxx b/PWGHF/TableProducer/candidateCreatorToXiPi.cxx index aabb31b001f..a100cb2c875 100644 --- a/PWGHF/TableProducer/candidateCreatorToXiPi.cxx +++ b/PWGHF/TableProducer/candidateCreatorToXiPi.cxx @@ -14,10 +14,6 @@ /// \author Federica Zanone , HEIDELBERG UNIVERSITY & GSI #include "CCDB/BasicCCDBManager.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/EventSelection.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "DCAFitter/DCAFitterN.h" @@ -30,6 +26,11 @@ #include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/V0.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" + #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGHF/Core/SelectorCuts.h" @@ -38,15 +39,13 @@ #include "PWGHF/Utils/utilsBfieldCCDB.h" using namespace o2; +using namespace o2::analysis; +// using namespace o2::analysis::pdg; using namespace o2::aod; +using namespace o2::aod::cascdata; +using namespace o2::aod::v0data; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::analysis::pdg; -using namespace o2::aod::v0data; -using namespace o2::aod::cascdata; -using namespace o2::aod::hf_track_index; -using namespace o2::aod::hf_sel_collision; -using namespace o2::aod::hf_cand_toxipi; // Reconstruction of omegac candidates struct HfCandidateCreatorToXiPi { @@ -81,10 +80,11 @@ struct HfCandidateCreatorToXiPi { Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + int runNumber; using SelectedCollisions = soa::Filtered>; - using MyTracks = soa::Join; + using MyTracks = soa::Join; using FilteredHfTrackAssocSel = soa::Filtered>; using MyCascTable = soa::Join; // to use strangeness tracking, use aod::TraCascDatas instead of aod::CascDatas using MyV0Table = soa::Join; @@ -137,17 +137,17 @@ struct HfCandidateCreatorToXiPi { df.setWeightedFinalPCA(useWeightedFinalPCA); df.setRefitWithMatCorr(refitWithMatCorr); - double massPionFromPDG = RecoDecay::getMassPDG(kPiPlus); // pdg code 211 - double massLambdaFromPDG = RecoDecay::getMassPDG(kLambda0); // pdg code 3122 - double massXiFromPDG = RecoDecay::getMassPDG(kXiMinus); // pdg code 3312 - double massOmegacFromPDG = RecoDecay::getMassPDG(kOmegaC0); // pdg code 4332 - double massXicFromPDG = RecoDecay::getMassPDG(kXiCZero); // pdg code 4132 + double massPionFromPDG = o2::analysis::pdg::MassPiPlus; // pdg code 211 + double massLambdaFromPDG = o2::analysis::pdg::MassLambda0; // pdg code 3122 + double massXiFromPDG = o2::analysis::pdg::MassXiMinus; // pdg code 3312 + double massOmegacFromPDG = o2::analysis::pdg::MassOmegaC0; // pdg code 4332 + double massXicFromPDG = o2::analysis::pdg::MassXiCZero; // pdg code 4132 // loop over cascades reconstructed by cascadebuilder.cxx auto thisCollId = collision.globalIndex(); auto groupedCascades = cascades.sliceBy(cascadesPerCollision, thisCollId); - for (auto const& casc : groupedCascades) { + for (const auto& casc : groupedCascades) { //----------------accessing particles in the decay chain------------- // cascade daughter - charged particle @@ -242,7 +242,7 @@ struct HfCandidateCreatorToXiPi { //-------------------combining cascade and pion tracks-------------------------- auto groupedTrackIndices = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - for (auto const& trackIndexPion : groupedTrackIndices) { + for (const auto& trackIndexPion : groupedTrackIndices) { auto trackPion = trackIndexPion.track_as(); @@ -256,7 +256,7 @@ struct HfCandidateCreatorToXiPi { } // check not to take the same particle twice in the decay chain - if (trackPion.globalIndex() == trackXiDauCharged.globalIndex() || trackPion.globalIndex() == trackV0Dau0.globalIndex() || trackPion.globalIndex() == trackV0Dau1.globalIndex() || trackPion.globalIndex() == casc.globalIndex()) { + if (trackPion.globalIndex() == trackXiDauCharged.globalIndex() || trackPion.globalIndex() == trackV0Dau0.globalIndex() || trackPion.globalIndex() == trackV0Dau1.globalIndex()) { continue; } @@ -374,7 +374,7 @@ struct HfCandidateCreatorToXiPi { float dcaOmegacDau = std::sqrt(df.getChi2AtPCACandidate()); // set hfFlag - int hfFlag = 1 << DecayType::DecayToXiPi; + int hfFlag = 1 << aod::hf_cand_toxipi::DecayType::DecayToXiPi; // fill test histograms hInvMassOmegac->Fill(mOmegac); @@ -435,8 +435,8 @@ struct HfCandidateCreatorToXiPiMc { PROCESS_SWITCH(HfCandidateCreatorToXiPiMc, processDoNoMc, "Do not run MC process function", true); void processMc(aod::HfCandToXiPi const& candidates, - aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC) + aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles) { int indexRec = -1; int8_t sign = -9; @@ -456,74 +456,66 @@ struct HfCandidateCreatorToXiPiMc { int pdgCodeProton = kProton; // 2212 // Match reconstructed candidates. - for (auto& candidate : candidates) { - // Printf("New rec. candidate"); + for (const auto& candidate : candidates) { flag = 0; // origin = 0; debug = 0; - auto arrayDaughters = std::array{candidate.primaryPi_as(), // pi <- omegac - candidate.bachelor_as(), // pi <- cascade - candidate.posTrack_as(), // p <- lambda - candidate.negTrack_as()}; // pi <- lambda - auto arrayDaughtersCasc = std::array{candidate.bachelor_as(), - candidate.posTrack_as(), - candidate.negTrack_as()}; - auto arrayDaughtersV0 = std::array{candidate.posTrack_as(), - candidate.negTrack_as()}; + auto arrayDaughters = std::array{candidate.primaryPi_as(), // pi <- omegac + candidate.bachelor_as(), // pi <- cascade + candidate.posTrack_as(), // p <- lambda + candidate.negTrack_as()}; // pi <- lambda + auto arrayDaughtersCasc = std::array{candidate.bachelor_as(), + candidate.posTrack_as(), + candidate.negTrack_as()}; + auto arrayDaughtersV0 = std::array{candidate.posTrack_as(), + candidate.negTrack_as()}; // Omegac matching if (matchOmegacMc) { // Omegac → pi pi pi p - // Printf("Checking Omegac → pi pi pi p"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdgCodeOmegac0, std::array{pdgCodePiPlus, pdgCodePiMinus, pdgCodeProton, pdgCodePiMinus}, true, &sign, 3); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgCodeOmegac0, std::array{pdgCodePiPlus, pdgCodePiMinus, pdgCodeProton, pdgCodePiMinus}, true, &sign, 3); if (indexRec == -1) { debug = 1; } if (indexRec > -1) { - // cascade → lambda pi - // Printf("Checking cascade → pi pi p"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersCasc, pdgCodeXiMinus, std::array{pdgCodePiMinus, pdgCodeProton, pdgCodePiMinus}, true, &sign, 2); + // Xi- → pi pi p + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersCasc, pdgCodeXiMinus, std::array{pdgCodePiMinus, pdgCodeProton, pdgCodePiMinus}, true, &sign, 2); if (indexRec == -1) { debug = 2; } if (indexRec > -1) { - // v0 → p pi - // Printf("Checking v0 → p pi"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersV0, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true, &sign, 1); + // Lambda → p pi + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true, &sign, 1); if (indexRec == -1) { debug = 3; } if (indexRec > -1) { - flag = sign * (1 << DecayType::OmegaczeroToXiPi); + flag = sign * (1 << aod::hf_cand_toxipi::DecayType::OmegaczeroToXiPi); } } } - - // Xic matching } + // Xic matching if (matchXicMc) { // Xic → pi pi pi p - // Printf("Checking Xic → pi pi pi p"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdgCodeXic0, std::array{pdgCodePiPlus, pdgCodePiMinus, pdgCodeProton, pdgCodePiMinus}, true, &sign, 3); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgCodeXic0, std::array{pdgCodePiPlus, pdgCodePiMinus, pdgCodeProton, pdgCodePiMinus}, true, &sign, 3); if (indexRec == -1) { debug = 1; } if (indexRec > -1) { - // cascade → lambda pi - // Printf("Checking cascade → pi pi p"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersCasc, pdgCodeXiMinus, std::array{pdgCodePiMinus, pdgCodeProton, pdgCodePiMinus}, true, &sign, 2); + // Xi- → pi pi p + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersCasc, pdgCodeXiMinus, std::array{pdgCodePiMinus, pdgCodeProton, pdgCodePiMinus}, true, &sign, 2); if (indexRec == -1) { debug = 2; } if (indexRec > -1) { - // v0 → p pi - // Printf("Checking v0 → p pi"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersV0, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true, &sign, 1); + // Lambda → p pi + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersV0, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true, &sign, 1); if (indexRec == -1) { debug = 3; } if (indexRec > -1) { - flag = sign * (1 << DecayType::XiczeroToXiPi); + flag = sign * (1 << aod::hf_cand_toxipi::DecayType::XiczeroToXiPi); } } } @@ -537,8 +529,7 @@ struct HfCandidateCreatorToXiPiMc { } // close loop over candidates // Match generated particles. - for (auto& particle : particlesMC) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = -9; sign = -9; debugGenCharmBar = 0; @@ -547,36 +538,34 @@ struct HfCandidateCreatorToXiPiMc { // origin = 0; if (matchOmegacMc) { // Omegac → Xi pi - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdgCodeOmegac0, std::array{pdgCodeXiMinus, pdgCodePiPlus}, true, &sign)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeOmegac0, std::array{pdgCodeXiMinus, pdgCodePiPlus}, true, &sign)) { debugGenCharmBar = 1; - // Match Xi -> lambda pi - auto cascMC = particlesMC.rawIteratorAt(particle.daughtersIds().front()); - // Printf("Checking cascade → lambda pi"); - if (RecoDecay::isMatchedMCGen(particlesMC, cascMC, pdgCodeXiMinus, std::array{pdgCodeLambda, pdgCodePiMinus}, true)) { + // Xi -> Lambda pi + auto cascMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, cascMC, pdgCodeXiMinus, std::array{pdgCodeLambda, pdgCodePiMinus}, true)) { debugGenXi = 1; - // lambda -> p pi - auto v0MC = particlesMC.rawIteratorAt(cascMC.daughtersIds().front()); - if (RecoDecay::isMatchedMCGen(particlesMC, v0MC, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { + // Lambda -> p pi + auto v0MC = mcParticles.rawIteratorAt(cascMC.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, v0MC, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { debugGenLambda = 1; - flag = sign * (1 << DecayType::OmegaczeroToXiPi); + flag = sign * (1 << aod::hf_cand_toxipi::DecayType::OmegaczeroToXiPi); } } } } if (matchXicMc) { // Xic → Xi pi - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdgCodeXic0, std::array{pdgCodeXiMinus, pdgCodePiPlus}, true, &sign)) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdgCodeXic0, std::array{pdgCodeXiMinus, pdgCodePiPlus}, true, &sign)) { debugGenCharmBar = 1; - // Match Xi -> lambda pi - auto cascMC = particlesMC.rawIteratorAt(particle.daughtersIds().front()); - // Printf("Checking cascade → lambda pi"); - if (RecoDecay::isMatchedMCGen(particlesMC, cascMC, pdgCodeXiMinus, std::array{pdgCodeLambda, pdgCodePiMinus}, true)) { + // Xi- -> Lambda pi + auto cascMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, cascMC, pdgCodeXiMinus, std::array{pdgCodeLambda, pdgCodePiMinus}, true)) { debugGenXi = 1; - // lambda -> p pi - auto v0MC = particlesMC.rawIteratorAt(cascMC.daughtersIds().front()); - if (RecoDecay::isMatchedMCGen(particlesMC, v0MC, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { + // Lambda -> p pi + auto v0MC = mcParticles.rawIteratorAt(cascMC.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, v0MC, pdgCodeLambda, std::array{pdgCodeProton, pdgCodePiMinus}, true)) { debugGenLambda = 1; - flag = sign * (1 << DecayType::XiczeroToXiPi); + flag = sign * (1 << aod::hf_cand_toxipi::DecayType::XiczeroToXiPi); } } } diff --git a/PWGHF/TableProducer/candidateCreatorXicc.cxx b/PWGHF/TableProducer/candidateCreatorXicc.cxx index 15104d8e9e9..a6a2c2305c0 100644 --- a/PWGHF/TableProducer/candidateCreatorXicc.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicc.cxx @@ -17,20 +17,21 @@ /// \author Luigi Dello Stritto , SALERNO /// \author Mattia Faggin , University and INFN PADOVA -#include "Common/Core/trackUtilities.h" #include "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "ReconstructionDataFormats/DCA.h" #include "ReconstructionDataFormats/V0.h" +#include "Common/Core/trackUtilities.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_xicc; -using namespace o2::framework::expressions; // FIXME not sure if this is needed +using namespace o2::framework::expressions; void customize(std::vector& workflowOptions) { @@ -57,9 +58,11 @@ struct HfCandidateCreatorXicc { Configurable selectionFlagXic{"selectionFlagXic", 1, "Selection Flag for Xic"}; Configurable cutPtPionMin{"cutPtPionMin", 1., "min. pt pion track"}; - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massK = RecoDecay::getMassPDG(kKPlus); - double massXic = RecoDecay::getMassPDG(static_cast(pdg::Code::kXiCPlus)); + HfHelper hfHelper; + + double massPi{0.}; + double massK{0.}; + double massXic{0.}; double massXicc{0.}; Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlagXic || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlagXic); @@ -68,9 +71,16 @@ struct HfCandidateCreatorXicc { OutputObj hCovPVXX{TH1F("hCovPVXX", "3-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", 100, 0., 1.e-4)}; OutputObj hCovSVXX{TH1F("hCovSVXX", "3-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", 100, 0., 0.2)}; + void init(InitContext const&) + { + massPi = o2::analysis::pdg::MassPiPlus; + massK = o2::analysis::pdg::MassKPlus; + massXic = o2::analysis::pdg::MassXiCPlus; + } + void process(aod::Collision const& collision, soa::Filtered> const& xicCands, - aod::BigTracks const& tracks) + aod::TracksWCov const& tracks) { // 3-prong vertex fitter to rebuild the Xic vertex o2::vertexing::DCAFitterN<3> df3; @@ -94,19 +104,19 @@ struct HfCandidateCreatorXicc { df2.setUseAbsDCA(useAbsDCA); df2.setWeightedFinalPCA(useWeightedFinalPCA); - for (auto& xicCand : xicCands) { + for (const auto& xicCand : xicCands) { if (!(xicCand.hfflag() & 1 << o2::aod::hf_cand_3prong::XicToPKPi)) { continue; } if (xicCand.isSelXicToPKPi() >= selectionFlagXic) { - hMassXic->Fill(invMassXicToPKPi(xicCand), xicCand.pt()); + hMassXic->Fill(hfHelper.invMassXicToPKPi(xicCand), xicCand.pt()); } if (xicCand.isSelXicToPiKP() >= selectionFlagXic) { - hMassXic->Fill(invMassXicToPiKP(xicCand), xicCand.pt()); + hMassXic->Fill(hfHelper.invMassXicToPiKP(xicCand), xicCand.pt()); } - auto track0 = xicCand.prong0_as(); - auto track1 = xicCand.prong1_as(); - auto track2 = xicCand.prong2_as(); + auto track0 = xicCand.prong0_as(); + auto track1 = xicCand.prong1_as(); + auto track2 = xicCand.prong2_as(); auto trackParVar0 = getTrackParCov(track0); auto trackParVar1 = getTrackParCov(track1); auto trackParVar2 = getTrackParCov(track2); @@ -121,19 +131,17 @@ struct HfCandidateCreatorXicc { trackParVar1.propagateTo(secondaryVertex[0], bz); trackParVar2.propagateTo(secondaryVertex[0], bz); - array pvecpK = {track0.px() + track1.px(), track0.py() + track1.py(), track0.pz() + track1.pz()}; - array pvecxic = {pvecpK[0] + track2.px(), pvecpK[1] + track2.py(), pvecpK[2] + track2.pz()}; - auto trackpK = o2::dataformats::V0(df3.getPCACandidatePos(), pvecpK, df3.calcPCACovMatrixFlat(), - trackParVar0, trackParVar1, {0, 0}, {0, 0}); - auto trackxic = o2::dataformats::V0(df3.getPCACandidatePos(), pvecxic, df3.calcPCACovMatrixFlat(), - trackpK, trackParVar2, {0, 0}, {0, 0}); + std::array pvecpK = {track0.px() + track1.px(), track0.py() + track1.py(), track0.pz() + track1.pz()}; + std::array pvecxic = {pvecpK[0] + track2.px(), pvecpK[1] + track2.py(), pvecpK[2] + track2.pz()}; + auto trackpK = o2::dataformats::V0(df3.getPCACandidatePos(), pvecpK, df3.calcPCACovMatrixFlat(), trackParVar0, trackParVar1); + auto trackxic = o2::dataformats::V0(df3.getPCACandidatePos(), pvecxic, df3.calcPCACovMatrixFlat(), trackpK, trackParVar2); int index0Xic = track0.globalIndex(); int index1Xic = track1.globalIndex(); int index2Xic = track2.globalIndex(); int charge = track0.sign() + track1.sign() + track2.sign(); - for (auto& trackpion : tracks) { + for (const auto& trackpion : tracks) { if (trackpion.pt() < cutPtPionMin) { continue; } @@ -143,7 +151,7 @@ struct HfCandidateCreatorXicc { if (trackpion.globalIndex() == index0Xic || trackpion.globalIndex() == index1Xic || trackpion.globalIndex() == index2Xic) { continue; } - array pvecpion; + std::array pvecpion; auto trackParVarPi = getTrackParCov(trackpion); // reconstruct the 3-prong X vertex @@ -169,11 +177,11 @@ struct HfCandidateCreatorXicc { // get uncertainty of the decay length double phi, theta; - getPointDirection(array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexXicc, phi, theta); + getPointDirection(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertexXicc, phi, theta); auto errorDecayLength = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); - int hfFlag = 1 << DecayType::XiccToXicPi; + int hfFlag = 1 << aod::hf_cand_xicc::DecayType::XiccToXicPi; rowCandidateBase(collision.globalIndex(), collision.posX(), collision.posY(), collision.posZ(), @@ -205,8 +213,8 @@ struct HfCandidateCreatorXiccMc { void process(aod::HfCandXicc const& candidates, aod::HfCand3Prong const&, - aod::BigTracksMC const& tracks, - aod::McParticles const& particlesMC) + aod::TracksWMc const& tracks, + aod::McParticles const& mcParticles) { int indexRec = -1; int8_t sign = 0; @@ -215,28 +223,25 @@ struct HfCandidateCreatorXiccMc { int8_t debug = 0; // Match reconstructed candidates. - for (auto& candidate : candidates) { - // Printf("New rec. candidate"); + for (const auto& candidate : candidates) { flag = 0; origin = 0; debug = 0; auto xicCand = candidate.prong0(); - auto arrayDaughters = array{xicCand.prong0_as(), - xicCand.prong1_as(), - xicCand.prong2_as(), - candidate.prong1_as()}; - auto arrayDaughtersXic = array{xicCand.prong0_as(), - xicCand.prong1_as(), - xicCand.prong2_as()}; + auto arrayDaughters = std::array{xicCand.prong0_as(), + xicCand.prong1_as(), + xicCand.prong2_as(), + candidate.prong1_as()}; + auto arrayDaughtersXic = std::array{xicCand.prong0_as(), + xicCand.prong1_as(), + xicCand.prong2_as()}; // Ξcc±± → p± K∓ π± π± - // Printf("Checking Ξcc±± → p± K∓ π± π±"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughters, pdg::Code::kXiCCPlusPlus, array{+kProton, -kKPlus, +kPiPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdg::Code::kXiCCPlusPlus, std::array{+kProton, -kKPlus, +kPiPlus, +kPiPlus}, true, &sign, 2); if (indexRec > -1) { // Ξc± → p± K∓ π± - // Printf("Checking Ξc± → p± K∓ π±"); - indexRec = RecoDecay::getMatchedMCRec(particlesMC, arrayDaughtersXic, pdg::Code::kXiCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 1); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersXic, pdg::Code::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 1); if (indexRec > -1) { - flag = 1 << DecayType::XiccToXicPi; + flag = 1 << aod::hf_cand_xicc::DecayType::XiccToXicPi; } else { debug = 1; LOGF(info, "WARNING: Ξc±± in decays in the expected final state but the condition on the intermediate state is not fulfilled"); @@ -246,17 +251,15 @@ struct HfCandidateCreatorXiccMc { } // Match generated particles. - for (auto& particle : particlesMC) { - // Printf("New gen. candidate"); + for (const auto& particle : mcParticles) { flag = 0; origin = 0; - // Xicc → Xic + π+ - if (RecoDecay::isMatchedMCGen(particlesMC, particle, pdg::Code::kXiCCPlusPlus, array{static_cast(pdg::Code::kXiCPlus), +kPiPlus}, true)) { - // Match Xic -> pKπ - auto XicCandMC = particlesMC.rawIteratorAt(particle.daughtersIds().front()); - // Printf("Checking Ξc± → p± K∓ π±"); - if (RecoDecay::isMatchedMCGen(particlesMC, XicCandMC, static_cast(pdg::Code::kXiCPlus), array{+kProton, -kKPlus, +kPiPlus}, true, &sign)) { - flag = sign * (1 << DecayType::XiccToXicPi); + // Ξcc±± → Ξc± + π± + if (RecoDecay::isMatchedMCGen(mcParticles, particle, pdg::Code::kXiCCPlusPlus, std::array{static_cast(pdg::Code::kXiCPlus), +kPiPlus}, true)) { + // Ξc± → p± K∓ π± + auto candXicMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + if (RecoDecay::isMatchedMCGen(mcParticles, candXicMC, static_cast(pdg::Code::kXiCPlus), std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign)) { + flag = sign * (1 << aod::hf_cand_xicc::DecayType::XiccToXicPi); } } rowMcMatchGen(flag, origin); diff --git a/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx b/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx index 517b8c4200d..c256265b341 100644 --- a/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx @@ -14,11 +14,13 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "Framework/RunningWorkflowInfo.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -26,10 +28,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand_b0; // from CandidateReconstructionTables.h using namespace o2::analysis; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_b0_to_d_pi; // from SelectorCuts.h struct HfCandidateSelectorB0ToDPi { Produces hfSelB0ToDPiCandidate; // table defined in CandidateSelectionTables.h @@ -38,7 +37,7 @@ struct HfCandidateSelectorB0ToDPi { Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; // Enable PID Configurable usePid{"usePid", true, "Switch for PID selection at track level"}; - Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::PIDNotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; // TPC PID Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; @@ -51,28 +50,28 @@ struct HfCandidateSelectorB0ToDPi { Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_b0_to_d_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_b0_to_d_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "B0 candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_b0_to_d_pi::cuts[0], hf_cuts_b0_to_d_pi::nBinsPt, hf_cuts_b0_to_d_pi::nCutVars, hf_cuts_b0_to_d_pi::labelsPt, hf_cuts_b0_to_d_pi::labelsCutVar}, "B0 candidate selection per pT bin"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; // check if selectionFlagD (defined in candidateCreatorB0.cxx) and usePid configurables are in sync - bool selectionFlagDAndUsePidInSync = true; - TrackSelectorPID selectorPion; + bool selectionFlagDAndUsePidInSync = true; + TrackSelectorPi selectorPion; + HfHelper hfHelper; - using TracksPIDWithSel = soa::Join; + using TracksPidWithSel = soa::Join; HistogramRegistry registry{"registry"}; void init(InitContext& initContext) { if (usePid) { - selectorPion.setPDG(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); } if (activateQA) { @@ -91,9 +90,9 @@ struct HfCandidateSelectorB0ToDPi { int selectionFlagD = -1; auto& workflows = initContext.services().get(); - for (DeviceSpec const& device : workflows.devices) { + for (const DeviceSpec& device : workflows.devices) { if (device.name.compare("hf-candidate-creator-b0") == 0) { - for (auto const& option : device.options) { + for (const auto& option : device.options) { if (option.name.compare("selectionFlagD") == 0) { selectionFlagD = option.defaultValue.get(); LOGF(info, "selectionFlagD = %d", selectionFlagD); @@ -113,7 +112,7 @@ struct HfCandidateSelectorB0ToDPi { } void process(aod::HfCandB0 const& hfCandsB0, - TracksPIDWithSel const&) + TracksPidWithSel const&) { for (const auto& hfCandB0 : hfCandsB0) { int statusB0ToDPi = 0; @@ -134,7 +133,7 @@ struct HfCandidateSelectorB0ToDPi { } // topological cuts - if (!hf_sel_candidate_b0::selectionTopol(hfCandB0, cuts, binsPt)) { + if (!hfHelper.selectionB0ToDPiTopol(hfCandB0, cuts, binsPt)) { hfSelB0ToDPiCandidate(statusB0ToDPi); // LOGF(info, "B0 candidate selection failed at topology selection"); continue; @@ -151,9 +150,9 @@ struct HfCandidateSelectorB0ToDPi { } // track-level PID selection if (usePid) { - auto trackPi = hfCandB0.prong1_as(); - int pidTrackPi = selectorPion.getStatusTrackPIDTpcAndTof(trackPi); - if (!hf_sel_candidate_b0::selectionPID(pidTrackPi, acceptPIDNotApplicable.value)) { + auto trackPi = hfCandB0.prong1_as(); + int pidTrackPi = selectorPion.statusTpcAndTof(trackPi); + if (!hfHelper.selectionB0ToDPiPid(pidTrackPi, acceptPIDNotApplicable.value)) { // LOGF(info, "B0 candidate selection failed at PID selection"); hfSelB0ToDPiCandidate(statusB0ToDPi); continue; diff --git a/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx b/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx index b471bfeae18..a5ca2557962 100644 --- a/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx @@ -15,11 +15,13 @@ /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari /// \author Deepa Thomas , UT Austin -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "Framework/RunningWorkflowInfo.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -27,10 +29,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand_bplus; using namespace o2::analysis; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_bplus_to_d0_pi; struct HfCandidateSelectorBplusToD0Pi { Produces hfSelBplusToD0PiCandidate; @@ -39,7 +38,7 @@ struct HfCandidateSelectorBplusToD0Pi { // Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; // Enable PID Configurable usePid{"usePid", true, "Bool to use or not the PID at filtering level"}; - Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::PIDNotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; // TPC PID Configurable ptPidTpcMin{"ptPidTpcMin", 999, "Lower bound of track pT for TPC PID"}; Configurable ptPidTpcMax{"ptPidTpcMax", 9999, "Upper bound of track pT for TPC PID"}; @@ -52,29 +51,28 @@ struct HfCandidateSelectorBplusToD0Pi { Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 999., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_bplus_to_d0_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_bplus_to_d0_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "B+ candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_bplus_to_d0_pi::cuts[0], hf_cuts_bplus_to_d0_pi::nBinsPt, hf_cuts_bplus_to_d0_pi::nCutVars, hf_cuts_bplus_to_d0_pi::labelsPt, hf_cuts_bplus_to_d0_pi::labelsCutVar}, "B+ candidate selection per pT bin"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; // check if selectionFlagD (defined in candidateCreatorBplus.cxx) and usePid configurables are in sync bool selectionFlagDAndUsePidInSync = true; + TrackSelectorPi selectorPion; + HfHelper hfHelper; - TrackSelectorPID selectorPion; - - using TracksPIDWithSel = soa::Join; + using TracksPidWithSel = soa::Join; HistogramRegistry registry{"registry"}; void init(InitContext& initContext) { if (usePid) { - selectorPion.setPDG(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); } if (activateQA) { @@ -94,9 +92,9 @@ struct HfCandidateSelectorBplusToD0Pi { int selectionFlagD0 = -1; int selectionFlagD0bar = -1; auto& workflows = initContext.services().get(); - for (DeviceSpec const& device : workflows.devices) { + for (const DeviceSpec& device : workflows.devices) { if (device.name.compare("hf-candidate-creator-bplus") == 0) { - for (auto const& option : device.options) { + for (const auto& option : device.options) { if (option.name.compare("selectionFlagD0") == 0) { selectionFlagD0 = option.defaultValue.get(); LOGF(info, "selectionFlagD0 = %d", selectionFlagD0); @@ -118,103 +116,28 @@ struct HfCandidateSelectorBplusToD0Pi { } } - // Apply topological cuts as defined in SelectorCuts.h; return true if candidate passes all cuts - /// \param hfCandBplus is the B+ candidate - /// \param hfCandD0 is prong0 of B+ candidate - /// \param trackPi is prong1 of B+ candidate - /// \return true if candidate passes all selections - template - bool selectionTopol(const T1& hfCandBplus, const T2& hfCandD0, const T3& trackPi) - { - auto candpT = hfCandBplus.pt(); - int pTBin = findBin(binsPt, candpT); - if (pTBin == -1) { - // Printf("B+ topol selection failed at getpTBin"); - return false; - } - - // pi pt - if (trackPi.pt() < cuts->get(pTBin, "pT Pi")) { - return false; - } - - // d0(D0)xd0(pi) - if (hfCandBplus.impactParameterProduct() > cuts->get(pTBin, "Imp. Par. Product")) { - return false; - } - - // D0 mass - if (trackPi.sign() > 0) { - if (std::abs(invMassD0barToKPi(hfCandD0) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "DeltaMD0")) { - return false; - } - } - if (trackPi.sign() < 0) { - if (std::abs(invMassD0ToPiK(hfCandD0) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "DeltaMD0")) { - return false; - } - } - - // B Decay length - if (hfCandBplus.decayLength() < cuts->get(pTBin, "B decLen")) { - return false; - } - - // B Decay length XY - if (hfCandBplus.decayLengthXY() < cuts->get(pTBin, "B decLenXY")) { - return false; - } - - // B+ CPA cut - if (hfCandBplus.cpa() < cuts->get(pTBin, "CPA")) { - return false; - } - - // if (candpT < ptCandMin || candpT >= ptCandMax) { - // Printf("B+ topol selection failed at cand pT check"); - // return false; - // } - - // B+ mass cut - // if (std::abs(invMassBplusToD0Pi(hfCandBplus) - RecoDecay::getMassPDG(521)) > cuts->get(pTBin, "m")) { - // Printf("B+ topol selection failed at mass diff check"); - // return false; - // } - - // d0 of D0 and pi - if (std::abs(hfCandBplus.impactParameter0()) < cuts->get(pTBin, "d0 D0")) { - return false; - } - if (std::abs(hfCandBplus.impactParameter1()) < cuts->get(pTBin, "d0 Pi")) { - return false; - } - // D0 CPA - // if (std::abs(hfCandD0.cpa()) < cuts->get(pTBin, "CPA D0")){ - // return false; - // } - return true; - } - /// Apply PID selection /// \param pidTrackPi is the PID status of trackPi (prong1 of B+ candidate) /// \return true if prong1 of B+ candidate passes all selections template bool selectionPID(const T& pidTrackPi) { - if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Status::PIDAccepted) { + if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; } - if (acceptPIDNotApplicable && pidTrackPi == TrackSelectorPID::Status::PIDRejected) { + if (acceptPIDNotApplicable && pidTrackPi == TrackSelectorPID::Rejected) { return false; } return true; } - void process(aod::HfCandBplus const& hfCandBs, soa::Join const&, TracksPIDWithSel const&) + void process(aod::HfCandBplus const& hfCandBs, + soa::Join const&, + TracksPidWithSel const&) { - for (auto& hfCandB : hfCandBs) { // looping over Bplus candidates + for (const auto& hfCandB : hfCandBs) { // looping over Bplus candidates int statusBplus = 0; auto ptCandB = hfCandB.pt(); @@ -222,7 +145,7 @@ struct HfCandidateSelectorBplusToD0Pi { // check if flagged as B+ --> D0bar Pi if (!(hfCandB.hfflag() & 1 << hf_cand_bplus::DecayType::BplusToD0Pi)) { hfSelBplusToD0PiCandidate(statusBplus); - // Printf("B+ candidate selection failed at hfflag check"); + // LOGF(debug, "B+ candidate selection failed at hfflag check"); continue; } SETBIT(statusBplus, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusBplus = 1 @@ -231,13 +154,12 @@ struct HfCandidateSelectorBplusToD0Pi { } // D0 is always index0 and pi is index1 by default - auto candD0 = hfCandB.prong0_as>(); - auto trackPi = hfCandB.prong1_as(); + auto trackPi = hfCandB.prong1_as(); // topological cuts - if (!selectionTopol(hfCandB, candD0, trackPi)) { + if (!hfHelper.selectionBplusToD0PiTopol(hfCandB, cuts, binsPt)) { hfSelBplusToD0PiCandidate(statusBplus); - // Printf("B+ candidate selection failed at topology selection"); + // LOGF(debug, "B+ candidate selection failed at topology selection"); continue; } SETBIT(statusBplus, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusBplus = 3 @@ -252,9 +174,8 @@ struct HfCandidateSelectorBplusToD0Pi { } // track-level PID selection if (usePid) { - int pidTrackPi = selectorPion.getStatusTrackPIDTpcAndTof(trackPi); - if (!selectionPID(pidTrackPi)) { - // LOGF(info, "B0 candidate selection failed at PID selection"); + int pidTrackPi = selectorPion.statusTpcAndTof(trackPi); + if (!selectionPID(pidTrackPi)) { // FIXME use helper function hfSelBplusToD0PiCandidate(statusBplus); continue; } diff --git a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx new file mode 100644 index 00000000000..b3fc426b95c --- /dev/null +++ b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx @@ -0,0 +1,239 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file candidateSelectorBsToDsPi.cxx +/// \brief Bs → Ds- π+ candidate selector +/// \note adapted from candidateSelectorB0ToDPi.cxx +/// +/// \author Phil Stahlhut + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" + +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::analysis; + +struct HfCandidateSelectorBsToDsPi { + Produces hfSelBsToDsPiCandidate; // table defined in CandidateSelectionTables.h + Produces hfMlBsToDsPiCandidate; // table defined in CandidateSelectionTables.h + + // Enable PID + Configurable usePid{"usePid", true, "Switch for PID selection at track level"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + // topological cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_bs_to_ds_pi::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_bs_to_ds_pi::cuts[0], hf_cuts_bs_to_ds_pi::nBinsPt, hf_cuts_bs_to_ds_pi::nCutVars, hf_cuts_bs_to_ds_pi::labelsPt, hf_cuts_bs_to_ds_pi::labelsCutVar}, "Bs candidate selection per pT bin"}; + // QA switch + Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + // ML inference + Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; + Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", (int8_t)hf_cuts_ml::nCutScores, "Number of classes in ML model"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable modelPathsCCDB{"modelPathsCCDB", "EventFiltering/PWGHF/BDTBs", "Path on CCDB"}; + Configurable> onnxFileNames{"onnxFilesCCDB", std::vector{"ModelHandler_onnx_BsToDsPi.onnx"}, "ONNX file names on CCDB for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + // check if selectionFlagDs (defined in candidateCreatorBs.cxx) and usePid configurables are in sync + bool selectionFlagDsAndUsePidInSync = true; + + o2::analysis::HfMlResponse hfMlResponse; + std::vector outputMl = {}; + + o2::ccdb::CcdbApi ccdbApi; + + TrackSelectorPi selectorPion; + HfHelper hfHelper; + + using TracksPidWithSel = soa::Join; + + HistogramRegistry registry{"registry"}; + + void init(InitContext& initContext) + { + if (usePid) { + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + } + + if (activateQA) { + constexpr int kNBinsSelections = 1 + SelectionStep::NSelectionSteps; + std::string labels[kNBinsSelections]; + labels[0] = "No selection"; + labels[1 + SelectionStep::RecoSkims] = "Skims selection"; + labels[1 + SelectionStep::RecoTopol] = "Skims & Topological selections"; + labels[1 + SelectionStep::RecoPID] = "Skims & Topological & PID selections"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { + registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + } + + if (applyMl) { + hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB.value, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.init(); + outputMl.assign(((std::vector)cutDirMl).size(), -1.f); // dummy value for ML output + } + + int selectionFlagDs = -1; + auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-candidate-creator-bs") == 0) { + for (const auto& option : device.options) { + if (option.name.compare("selectionFlagDs") == 0) { + selectionFlagDs = option.defaultValue.get(); + LOGF(info, "selectionFlagDs = %d", selectionFlagDs); + } + } + } + } + + if (usePid && !TESTBIT(selectionFlagDs, SelectionStep::RecoPID)) { + selectionFlagDsAndUsePidInSync = false; + LOG(warning) << "PID selections required on Bs daughters (usePid=true) but no PID selections on Ds candidates were required a priori (selectionFlagDs<7). Set selectionFlagDs=7 in hf-candidate-creator-bs"; + } + if (!usePid && TESTBIT(selectionFlagDs, SelectionStep::RecoPID)) { + selectionFlagDsAndUsePidInSync = false; + LOG(warning) << "No PID selections required on Bs daughters (usePid=false) but PID selections on Ds candidates were required a priori (selectionFlagDs=7). Set selectionFlagDs<7 in hf-candidate-creator-bs"; + } + } + + void process(aod::HfCandBs const& hfCandsBs, + TracksPidWithSel const&) + { + for (const auto& hfCandBs : hfCandsBs) { + int statusBsToDsPi = 0; + auto ptCandBs = hfCandBs.pt(); + + // check if flagged as Bs → Ds π + if (!TESTBIT(hfCandBs.hfflag(), hf_cand_bs::DecayType::BsToDsPi)) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + if (applyMl) { + hfMlBsToDsPiCandidate(outputMl); + } + if (activateQA) { + registry.fill(HIST("hSelections"), 1, ptCandBs); + } + continue; + } + SETBIT(statusBsToDsPi, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusBsToDsPi = 1 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoSkims, ptCandBs); + } + + // topological cuts + if (!hfHelper.selectionBsToDsPiTopol(hfCandBs, cuts, binsPt)) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + if (applyMl) { + hfMlBsToDsPiCandidate(outputMl); + } + continue; + } + SETBIT(statusBsToDsPi, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusBsToDsPi = 3 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandBs); + } + + // checking if selectionFlagDs and usePid are in sync + if (!selectionFlagDsAndUsePidInSync) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + if (applyMl) { + hfMlBsToDsPiCandidate(outputMl); + } + continue; + } + // track-level PID selection + if (usePid) { + auto trackPi = hfCandBs.prong1_as(); + int pidTrackPi = selectorPion.statusTpcAndTof(trackPi); + if (!hfHelper.selectionBsToDsPiPid(pidTrackPi, acceptPIDNotApplicable.value)) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + if (applyMl) { + hfMlBsToDsPiCandidate(outputMl); + } + continue; + } + SETBIT(statusBsToDsPi, SelectionStep::RecoPID); // RecoPID = 2 --> statusBsToDsPi = 7 + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoPID, ptCandBs); + } + } + + // ML selections + if (applyMl) { + std::vector inputFeatures{hfCandBs.cpa(), + hfCandBs.cpaXY(), + hfCandBs.decayLength(), + hfCandBs.decayLengthXY(), + hfCandBs.chi2PCA(), + hfCandBs.impactParameter0(), + hfCandBs.impactParameter1(), + hfCandBs.maxNormalisedDeltaIP(), + hfCandBs.impactParameterProduct()}; + + bool isSelectedMl = hfMlResponse.isSelectedMl(inputFeatures, ptCandBs, outputMl); + hfMlBsToDsPiCandidate(outputMl); + + if (!isSelectedMl) { + hfSelBsToDsPiCandidate(statusBsToDsPi); + continue; + } + SETBIT(statusBsToDsPi, aod::SelectionStep::RecoMl); + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoMl, ptCandBs); + } + } + + hfSelBsToDsPiCandidate(statusBsToDsPi); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/candidateSelectorD0.cxx b/PWGHF/TableProducer/candidateSelectorD0.cxx index 584e90f9875..497704bc7e5 100644 --- a/PWGHF/TableProducer/candidateSelectorD0.cxx +++ b/PWGHF/TableProducer/candidateSelectorD0.cxx @@ -15,21 +15,24 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; /// Struct for applying D0 selection cuts struct HfCandidateSelectorD0 { Produces hfSelD0Candidate; + Produces hfMlD0Candidate; Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; @@ -50,27 +53,76 @@ struct HfCandidateSelectorD0 { Configurable distanceFromD0MassForSidebands{"distanceFromD0MassForSidebands", 0.15, "Minimum distance from nominal D0 mass value for sideband region"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_d0_to_pi_k::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_d0_to_pi_k::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "D0 candidate selection per pT bin"}; - - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) + Configurable> cuts{"cuts", {hf_cuts_d0_to_pi_k::cuts[0], hf_cuts_d0_to_pi_k::nBinsPt, hf_cuts_d0_to_pi_k::nCutVars, hf_cuts_d0_to_pi_k::labelsPt, hf_cuts_d0_to_pi_k::labelsCutVar}, "D0 candidate selection per pT bin"}; + // ML inference + Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; + Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", (int8_t)hf_cuts_ml::nCutScores, "Number of classes in ML model"}; + Configurable enableDebugMl{"enableDebugMl", false, "Flag to enable histograms to monitor BDT application"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable modelPathsCCDB{"modelPathsCCDB", "EventFiltering/PWGHF/BDTD0", "Path on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_D0ToKPi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + o2::analysis::HfMlResponse hfMlResponse; + std::vector outputMl = {}; + o2::ccdb::CcdbApi ccdbApi; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + HfHelper hfHelper; + + using TracksSel = soa::Join; + + // Define histograms + AxisSpec axisMassDmeson{200, 1.7f, 2.1f}; + AxisSpec axisBdtScore{100, 0.f, 1.f}; + AxisSpec axisSelStatus{2, -0.5f, 1.5f}; + HistogramRegistry registry{"registry"}; + + void init(InitContext& initContext) { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check + std::array doprocess{doprocessWithDCAFitterN, doprocessWithKFParticle}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "Only one process function can be enabled at a time."); + } + + if (applyMl && enableDebugMl) { + registry.add("DebugBdt/hBdtScore1VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); + registry.add("DebugBdt/hBdtScore2VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); + registry.add("DebugBdt/hBdtScore3VsStatus", ";BDT score;status", {HistType::kTH2F, {axisBdtScore, axisSelStatus}}); + registry.add("DebugBdt/hMassDmesonSel", ";#it{M}(D) (GeV/#it{c}^{2});counts", {HistType::kTH1F, {axisMassDmeson}}); + } + + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorKaon = selectorPion; + + if (applyMl) { + hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB.value, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.init(); + outputMl.assign(((std::vector)cutDirMl).size(), -1.f); // dummy value for ML output } - return true; } - */ /// Conjugate-independent topological cuts + /// \param reconstructionType is the reconstruction type (DCAFitterN or KFParticle) /// \param candidate is candidate /// \return true if candidate passes all cuts - template + template bool selectionTopol(const T& candidate) { auto candpT = candidate.pt(); @@ -96,40 +148,40 @@ struct HfCandidateSelectorD0 { return false; } // normalised decay length in XY plane - if (candidate.decayLengthXYNormalised() < cuts->get(pTBin, "normalized decay length XY")) { + if (candidate.decayLengthXYNormalised() < cuts->get(pTBin, "min norm decay length XY")) { return false; } // candidate DCA // if (candidate.chi2PCA() > cuts[pTBin][1]) return false; - // decay exponentail law, with tau = beta*gamma*ctau - // decay length > ctau retains (1-1/e) - if (std::abs(candidate.impactParameterNormalised0()) < 0.5 || std::abs(candidate.impactParameterNormalised1()) < 0.5) { + // candidate topological chi2 over ndf when using KFParticle, need to add this selection to the SelectorCuts.h + // if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + // if (candidate.kfTopolChi2OverNdf() > cuts->get(pTBin, "topological chi2overndf as D0")) return false; + // } + if (std::abs(candidate.impactParameterNormalised0()) < cuts->get(pTBin, "norm dauImpPar XY") || std::abs(candidate.impactParameterNormalised1()) < cuts->get(pTBin, "norm dauImpPar XY")) { return false; } - double decayLengthCut = std::min((candidate.p() * 0.0066) + 0.01, cuts->get(pTBin, "minimum decay length")); - if (candidate.decayLength() * candidate.decayLength() < decayLengthCut * decayLengthCut) { + if (candidate.decayLength() < cuts->get(pTBin, "min decay length")) { return false; } - if (candidate.decayLength() > cuts->get(pTBin, "decay length")) { + if (candidate.decayLength() > cuts->get(pTBin, "max decay length")) { return false; } - if (candidate.decayLengthXY() > cuts->get(pTBin, "decay length XY")) { + if (candidate.decayLengthXY() > cuts->get(pTBin, "max decay length XY")) { return false; } - if (candidate.decayLengthNormalised() * candidate.decayLengthNormalised() < 1.0) { - // return false; // add back when getter fixed - } + return true; } /// Conjugate-dependent topological cuts + /// \param reconstructionType is the reconstruction type (DCAFitterN or KFParticle) /// \param candidate is candidate /// \param trackPion is the track with the pion hypothesis /// \param trackKaon is the track with the kaon hypothesis /// \note trackPion = positive and trackKaon = negative for D0 selection and inverse for D0bar /// \return true if candidate passes all cuts for the given Conjugate - template + template bool selectionTopolConjugate(const T1& candidate, const T2& trackPion, const T2& trackKaon) { auto candpT = candidate.pt(); @@ -139,12 +191,20 @@ struct HfCandidateSelectorD0 { } // invariant-mass cut + float massD0, massD0bar; + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + massD0 = candidate.kfGeoMassD0(); + massD0bar = candidate.kfGeoMassD0bar(); + } else { + massD0 = hfHelper.invMassD0ToPiK(candidate); + massD0bar = hfHelper.invMassD0barToKPi(candidate); + } if (trackPion.sign() > 0) { - if (std::abs(invMassD0ToPiK(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "m")) { + if (std::abs(massD0 - o2::analysis::pdg::MassD0) > cuts->get(pTBin, "m")) { return false; } } else { - if (std::abs(invMassD0barToKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > cuts->get(pTBin, "m")) { + if (std::abs(massD0bar - o2::analysis::pdg::MassD0) > cuts->get(pTBin, "m")) { return false; } } @@ -161,11 +221,11 @@ struct HfCandidateSelectorD0 { // cut on cos(theta*) if (trackPion.sign() > 0) { - if (std::abs(cosThetaStarD0(candidate)) > cuts->get(pTBin, "cos theta*")) { + if (std::abs(hfHelper.cosThetaStarD0(candidate)) > cuts->get(pTBin, "cos theta*")) { return false; } } else { - if (std::abs(cosThetaStarD0bar(candidate)) > cuts->get(pTBin, "cos theta*")) { + if (std::abs(hfHelper.cosThetaStarD0bar(candidate)) > cuts->get(pTBin, "cos theta*")) { return false; } } @@ -173,11 +233,11 @@ struct HfCandidateSelectorD0 { // in case only sideband candidates have to be stored, additional invariant-mass cut if (keepOnlySidebandCandidates) { if (trackPion.sign() > 0) { - if (std::abs(invMassD0ToPiK(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) < distanceFromD0MassForSidebands) { + if (std::abs(hfHelper.invMassD0ToPiK(candidate) - o2::analysis::pdg::MassD0) < distanceFromD0MassForSidebands) { return false; } } else { - if (std::abs(invMassD0barToKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) < distanceFromD0MassForSidebands) { + if (std::abs(hfHelper.invMassD0barToKPi(candidate) - o2::analysis::pdg::MassD0) < distanceFromD0MassForSidebands) { return false; } } @@ -185,22 +245,12 @@ struct HfCandidateSelectorD0 { return true; } - - void process(aod::HfCand2Prong const& candidates, aod::BigTracksPIDExtended const&) + template + void processSel(CandType const& candidates, + TracksSel const&) { - TrackSelectorPID selectorPion(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - - TrackSelectorPID selectorKaon(selectorPion); - selectorKaon.setPDG(kKPlus); - // looping over 2-prong candidates - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // final selection flag: 0 - rejected, 1 - accepted int statusD0 = 0; @@ -210,25 +260,25 @@ struct HfCandidateSelectorD0 { int statusCand = 0; int statusPID = 0; - if (!(candidate.hfflag() & 1 << DecayType::D0ToPiK)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { hfSelD0Candidate(statusD0, statusD0bar, statusHFFlag, statusTopol, statusCand, statusPID); + if (applyMl) { + hfMlD0Candidate(outputMl); + } continue; } statusHFFlag = 1; - auto trackPos = candidate.prong0_as(); // positive daughter - auto trackNeg = candidate.prong1_as(); // negative daughter - - /* - if (!daughterSelection(trackPos) || !daughterSelection(trackNeg)) { - hfSelD0Candidate(statusD0, statusD0bar); - continue; - } - */ + auto ptCand = candidate.pt(); + auto trackPos = candidate.template prong0_as(); // positive daughter + auto trackNeg = candidate.template prong1_as(); // negative daughter // conjugate-independent topological selection - if (!selectionTopol(candidate)) { + if (!selectionTopol(candidate)) { hfSelD0Candidate(statusD0, statusD0bar, statusHFFlag, statusTopol, statusCand, statusPID); + if (applyMl) { + hfMlD0Candidate(outputMl); + } continue; } statusTopol = 1; @@ -237,12 +287,15 @@ struct HfCandidateSelectorD0 { // need to add special cuts (additional cuts on decay length and d0 norm) // conjugate-dependent topological selection for D0 - bool topolD0 = selectionTopolConjugate(candidate, trackPos, trackNeg); + bool topolD0 = selectionTopolConjugate(candidate, trackPos, trackNeg); // conjugate-dependent topological selection for D0bar - bool topolD0bar = selectionTopolConjugate(candidate, trackNeg, trackPos); + bool topolD0bar = selectionTopolConjugate(candidate, trackNeg, trackPos); if (!topolD0 && !topolD0bar) { hfSelD0Candidate(statusD0, statusD0bar, statusHFFlag, statusTopol, statusCand, statusPID); + if (applyMl) { + hfMlD0Candidate(outputMl); + } continue; } statusCand = 1; @@ -254,38 +307,43 @@ struct HfCandidateSelectorD0 { int pidTrackNegPion = -1; if (usePidTpcAndTof) { - pidTrackPosKaon = selectorKaon.getStatusTrackPIDTpcAndTof(trackPos); - pidTrackPosPion = selectorPion.getStatusTrackPIDTpcAndTof(trackPos); - pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcAndTof(trackNeg); - pidTrackNegPion = selectorPion.getStatusTrackPIDTpcAndTof(trackNeg); + pidTrackPosKaon = selectorKaon.statusTpcAndTof(trackPos); + pidTrackPosPion = selectorPion.statusTpcAndTof(trackPos); + pidTrackNegKaon = selectorKaon.statusTpcAndTof(trackNeg); + pidTrackNegPion = selectorPion.statusTpcAndTof(trackNeg); } else { - pidTrackPosKaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackPos); - pidTrackPosPion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos); - pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackNeg); - pidTrackNegPion = selectorPion.getStatusTrackPIDTpcOrTof(trackNeg); + pidTrackPosKaon = selectorKaon.statusTpcOrTof(trackPos); + pidTrackPosPion = selectorPion.statusTpcOrTof(trackPos); + pidTrackNegKaon = selectorKaon.statusTpcOrTof(trackNeg); + pidTrackNegPion = selectorPion.statusTpcOrTof(trackNeg); } + // int pidBayesTrackPos1Pion = selectorPion.statusBayes(trackPos); + int pidD0 = -1; int pidD0bar = -1; - if (pidTrackPosPion == TrackSelectorPID::Status::PIDAccepted && - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted) { + if (pidTrackPosPion == TrackSelectorPID::Accepted && + pidTrackNegKaon == TrackSelectorPID::Accepted) { pidD0 = 1; // accept D0 - } else if (pidTrackPosPion == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackPosPion == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected) { pidD0 = 0; // exclude D0 } - if (pidTrackNegPion == TrackSelectorPID::Status::PIDAccepted && - pidTrackPosKaon == TrackSelectorPID::Status::PIDAccepted) { + if (pidTrackNegPion == TrackSelectorPID::Accepted && + pidTrackPosKaon == TrackSelectorPID::Accepted) { pidD0bar = 1; // accept D0bar - } else if (pidTrackNegPion == TrackSelectorPID::Status::PIDRejected || - pidTrackPosKaon == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackNegPion == TrackSelectorPID::Rejected || + pidTrackPosKaon == TrackSelectorPID::Rejected) { pidD0bar = 0; // exclude D0bar } if (pidD0 == 0 && pidD0bar == 0) { hfSelD0Candidate(statusD0, statusD0bar, statusHFFlag, statusTopol, statusCand, statusPID); + if (applyMl) { + hfMlD0Candidate(outputMl); + } continue; } @@ -296,9 +354,55 @@ struct HfCandidateSelectorD0 { statusD0bar = 1; // identified as D0bar } statusPID = 1; + + if (applyMl) { + // ML selections + + std::vector inputFeatures{candidate.cpa(), + candidate.cpaXY(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameterProduct()}; + + bool isSelectedMl = hfMlResponse.isSelectedMl(inputFeatures, ptCand, outputMl); + hfMlD0Candidate(outputMl); + + if (!isSelectedMl) { + statusD0 = 0; + statusD0bar = 0; + } + if (enableDebugMl) { + registry.fill(HIST("DebugBdt/hBdtScore1VsStatus"), outputMl[0], statusD0); + registry.fill(HIST("DebugBdt/hBdtScore1VsStatus"), outputMl[0], statusD0bar); + registry.fill(HIST("DebugBdt/hBdtScore2VsStatus"), outputMl[1], statusD0); + registry.fill(HIST("DebugBdt/hBdtScore2VsStatus"), outputMl[1], statusD0bar); + registry.fill(HIST("DebugBdt/hBdtScore3VsStatus"), outputMl[2], statusD0); + registry.fill(HIST("DebugBdt/hBdtScore3VsStatus"), outputMl[2], statusD0bar); + if (statusD0 > 0) { + registry.fill(HIST("DebugBdt/hMassDmesonSel"), hfHelper.invMassD0ToPiK(candidate)); + } + if (statusD0bar > 0) { + registry.fill(HIST("DebugBdt/hMassDmesonSel"), hfHelper.invMassD0barToKPi(candidate)); + } + } + } hfSelD0Candidate(statusD0, statusD0bar, statusHFFlag, statusTopol, statusCand, statusPID); } } + + void processWithDCAFitterN(aod::HfCand2Prong const& candidates, TracksSel const& tracks) + { + processSel(candidates, tracks); + } + PROCESS_SWITCH(HfCandidateSelectorD0, processWithDCAFitterN, "process candidates selection with DCAFitterN", true); + + void processWithKFParticle(soa::Join const& candidates, TracksSel const& tracks) + { + processSel(candidates, tracks); + } + PROCESS_SWITCH(HfCandidateSelectorD0, processWithKFParticle, "process candidates selection with KFParticle", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx index 0c39d197536..4e278fdc355 100644 --- a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx @@ -15,55 +15,83 @@ /// \author Fabio Catalano , Politecnico and INFN Torino /// \author Vít Kučera , CERN -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_dplus_to_pi_k_pi; + +/// Struct to extend TracksPid tables +struct HfCandidateSelectorDplusToPiKPiExpressions { + Spawns rowTracksPidFullPi; + Spawns rowTracksPidFullKa; +}; /// Struct for applying Dplus to piKpi selection cuts struct HfCandidateSelectorDplusToPiKPi { Produces hfSelDplusToPiKPiCandidate; + Produces hfMlDplusToPiKPiCandidate; Configurable ptCandMin{"ptCandMin", 1., "Lower bound of candidate pT"}; Configurable ptCandMax{"ptCandMax", 36., "Upper bound of candidate pT"}; // PID option - Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::PIDNotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; // TPC PID Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; Configurable nSigmaTpcMax{"nSigmaTpcMax", 3., "Nsigma cut on TPC"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 3., "Nsigma cut on TPC combined with TOF"}; // TOF PID Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; Configurable nSigmaTofMax{"nSigmaTofMax", 3., "Nsigma cut on TOF"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 3., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_dplus_to_pi_k_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_dplus_to_pi_k_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Dplus candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_dplus_to_pi_k_pi::cuts[0], hf_cuts_dplus_to_pi_k_pi::nBinsPt, hf_cuts_dplus_to_pi_k_pi::nCutVars, hf_cuts_dplus_to_pi_k_pi::labelsPt, hf_cuts_dplus_to_pi_k_pi::labelsCutVar}, "Dplus candidate selection per pT bin"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + // ML inference + Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; + Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", (int8_t)hf_cuts_ml::nCutScores, "Number of classes in ML model"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable modelPathsCCDB{"modelPathsCCDB", "EventFiltering/PWGHF/BDTD0", "Path on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_D0ToKPi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + o2::analysis::HfMlResponse hfMlResponse; + std::vector outputMl = {}; + o2::ccdb::CcdbApi ccdbApi; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + HfHelper hfHelper; - TrackSelectorPID selectorPion; - TrackSelectorPID selectorKaon; + using TracksSel = soa::Join; HistogramRegistry registry{"registry"}; void init(InitContext const&) { - selectorPion.setPDG(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); selectorKaon = selectorPion; - selectorKaon.setPDG(kKPlus); if (activateQA) { constexpr int kNBinsSelections = 1 + aod::SelectionStep::NSelectionSteps; @@ -72,28 +100,26 @@ struct HfCandidateSelectorDplusToPiKPi { labels[1 + aod::SelectionStep::RecoSkims] = "Skims selection"; labels[1 + aod::SelectionStep::RecoTopol] = "Skims & Topological selections"; labels[1 + aod::SelectionStep::RecoPID] = "Skims & Topological & PID selections"; + labels[1 + aod::SelectionStep::RecoMl] = "ML selection"; static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } } - } - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) - { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check + if (applyMl) { + hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB.value, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.init(); + outputMl.assign(((std::vector)cutDirMl).size(), -1.f); // dummy value for ML output } - return true; } - */ /// Candidate selections /// \param candidate is candidate @@ -118,7 +144,7 @@ struct HfCandidateSelectorDplusToPiKPi { return false; } // invariant-mass cut - if (std::abs(invMassDplusToPiKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kDPlus)) > cuts->get(pTBin, "deltaM")) { + if (std::abs(hfHelper.invMassDplusToPiKPi(candidate) - o2::analysis::pdg::MassDPlus) > cuts->get(pTBin, "deltaM")) { return false; } if (candidate.decayLength() < cuts->get(pTBin, "decay length")) { @@ -148,33 +174,37 @@ struct HfCandidateSelectorDplusToPiKPi { bool selectionPID(const T& pidTrackPos1Pion, const T& pidTrackNegKaon, const T& pidTrackPos2Pion) { if (!acceptPIDNotApplicable && - (pidTrackPos1Pion != TrackSelectorPID::Status::PIDAccepted || - pidTrackNegKaon != TrackSelectorPID::Status::PIDAccepted || - pidTrackPos2Pion != TrackSelectorPID::Status::PIDAccepted)) { + (pidTrackPos1Pion != TrackSelectorPID::Accepted || + pidTrackNegKaon != TrackSelectorPID::Accepted || + pidTrackPos2Pion != TrackSelectorPID::Accepted)) { return false; } if (acceptPIDNotApplicable && - (pidTrackPos1Pion == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Pion == TrackSelectorPID::Status::PIDRejected)) { + (pidTrackPos1Pion == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Pion == TrackSelectorPID::Rejected)) { return false; } return true; } - void process(aod::HfCand3Prong const& candidates, aod::BigTracksPID const&) + void process(aod::HfCand3Prong const& candidates, + TracksSel const&) { // looping over 3-prong candidates - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // final selection flag: auto statusDplusToPiKPi = 0; auto ptCand = candidate.pt(); - if (!TESTBIT(candidate.hfflag(), DecayType::DplusToPiKPi)) { + if (!TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); + if (applyMl) { + hfMlDplusToPiKPiCandidate(outputMl); + } if (activateQA) { registry.fill(HIST("hSelections"), 1, ptCand); } @@ -185,23 +215,16 @@ struct HfCandidateSelectorDplusToPiKPi { registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoSkims, ptCand); } - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) - - /* - // daughter track validity selection - if (!daughterSelection(trackPos1) || - !daughterSelection(trackNeg) || - !daughterSelection(trackPos2)) { - hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); - continue; - } - */ + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) // topological selection if (!selection(candidate, trackPos1, trackNeg, trackPos2)) { hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); + if (applyMl) { + hfMlDplusToPiKPiCandidate(outputMl); + } continue; } SETBIT(statusDplusToPiKPi, aod::SelectionStep::RecoTopol); @@ -210,12 +233,15 @@ struct HfCandidateSelectorDplusToPiKPi { } // track-level PID selection - int pidTrackPos1Pion = selectorPion.getStatusTrackPIDTpcAndTof(trackPos1); - int pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcAndTof(trackNeg); - int pidTrackPos2Pion = selectorPion.getStatusTrackPIDTpcAndTof(trackPos2); + int pidTrackPos1Pion = selectorPion.statusTpcAndTof(trackPos1); + int pidTrackNegKaon = selectorKaon.statusTpcAndTof(trackNeg); + int pidTrackPos2Pion = selectorPion.statusTpcAndTof(trackPos2); if (!selectionPID(pidTrackPos1Pion, pidTrackNegKaon, pidTrackPos2Pion)) { // exclude D± hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); + if (applyMl) { + hfMlDplusToPiKPiCandidate(outputMl); + } continue; } SETBIT(statusDplusToPiKPi, aod::SelectionStep::RecoPID); @@ -223,6 +249,39 @@ struct HfCandidateSelectorDplusToPiKPi { registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoPID, ptCand); } + if (applyMl) { + // ML selections + std::vector inputFeatures{candidate.ptProng0(), + candidate.impactParameter0(), + candidate.ptProng1(), + candidate.impactParameter1(), + candidate.ptProng2(), + candidate.impactParameter2(), + candidate.decayLength(), + candidate.decayLengthXYNormalised(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + trackPos1.tpcTofNSigmaPi(), + trackPos1.tpcTofNSigmaKa(), + trackNeg.tpcTofNSigmaPi(), + trackNeg.tpcTofNSigmaKa(), + trackPos2.tpcTofNSigmaPi(), + trackPos2.tpcTofNSigmaKa()}; + + bool isSelectedMl = hfMlResponse.isSelectedMl(inputFeatures, ptCand, outputMl); + hfMlDplusToPiKPiCandidate(outputMl); + + if (!isSelectedMl) { + hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); + continue; + } + SETBIT(statusDplusToPiKPi, aod::SelectionStep::RecoMl); + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoMl, ptCand); + } + } + hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); } } @@ -231,5 +290,6 @@ struct HfCandidateSelectorDplusToPiKPi { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ + adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; } diff --git a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx index 5f9509a8bb8..7cb9e5356a9 100644 --- a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx @@ -15,21 +15,24 @@ /// \author Fabio Catalano , Universita and INFN Torino /// \author Stefano Politano , Politecnico and INFN Torino -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_ds_to_k_k_pi; /// Struct for applying Ds to KKpi selection cuts struct HfCandidateSelectorDsToKKPi { Produces hfSelDsToKKPiCandidate; + Produces hfMlDsToKKPiCandidate; Configurable ptCandMin{"ptCandMin", 1., "Lower bound of candidate pT"}; Configurable ptCandMax{"ptCandMax", 36., "Upper bound of candidate pT"}; @@ -43,7 +46,68 @@ struct HfCandidateSelectorDsToKKPi { Configurable nSigmaTofMax{"nSigmaTofMax", 3., "Nsigma cut on TOF"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_ds_to_k_k_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Ds candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_ds_to_k_k_pi::cuts[0], hf_cuts_ds_to_k_k_pi::nBinsPt, hf_cuts_ds_to_k_k_pi::nCutVars, hf_cuts_ds_to_k_k_pi::labelsPt, hf_cuts_ds_to_k_k_pi::labelsCutVar}, "Ds candidate selection per pT bin"}; + // QA switch + Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + // ML inference + Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; + Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", (int8_t)hf_cuts_ml::nCutScores, "Number of classes in ML model"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable modelPathsCCDB{"modelPathsCCDB", "EventFiltering/PWGHF/BDTD0", "Path on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_D0ToKPi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + HfHelper hfHelper; + o2::analysis::HfMlResponse hfMlResponse; + std::vector outputMl = {}; + o2::ccdb::CcdbApi ccdbApi; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + + using TracksSel = soa::Join; + + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorKaon = selectorPion; + + if (activateQA) { + constexpr int kNBinsSelections = 1 + aod::SelectionStep::NSelectionSteps; + std::string labels[kNBinsSelections]; + labels[0] = "No selection"; + labels[1 + aod::SelectionStep::RecoSkims] = "Skims selection"; + labels[1 + aod::SelectionStep::RecoTopol] = "Skims & Topological selections"; + labels[1 + aod::SelectionStep::RecoPID] = "Skims & Topological & PID selections"; + labels[1 + aod::SelectionStep::RecoMl] = "ML selection"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { + registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + } + + if (applyMl) { + hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB.value, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.init(); + outputMl.assign(((std::vector)cutDirMl).size(), -1.f); // dummy value for ML output + } + } /// Candidate selections independent from the daugther-mass hypothesis /// \param candidate is candidate @@ -95,13 +159,13 @@ struct HfCandidateSelectorDsToKKPi { if (trackKaon1.pt() < cuts->get(pTBin, "pT K") || trackKaon2.pt() < cuts->get(pTBin, "pT K") || trackPion.pt() < cuts->get(pTBin, "pT Pi")) { return false; } - if (std::abs(invMassDsToKKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kDS)) > cuts->get(pTBin, "deltaM")) { + if (std::abs(hfHelper.invMassDsToKKPi(candidate) - o2::analysis::pdg::MassDS) > cuts->get(pTBin, "deltaM")) { return false; } - if (deltaMassPhiDsToKKPi(candidate) > cuts->get(pTBin, "deltaM Phi")) { + if (hfHelper.deltaMassPhiDsToKKPi(candidate) > cuts->get(pTBin, "deltaM Phi")) { return false; } - if (std::abs(cos3PiKDsToKKPi(candidate)) < cuts->get(pTBin, "cos^3 theta_PiK")) { + if (std::abs(hfHelper.cos3PiKDsToKKPi(candidate)) < cuts->get(pTBin, "cos^3 theta_PiK")) { return false; } return true; @@ -124,50 +188,54 @@ struct HfCandidateSelectorDsToKKPi { if (trackKaon1.pt() < cuts->get(pTBin, "pT K") || trackKaon2.pt() < cuts->get(pTBin, "pT K") || trackPion.pt() < cuts->get(pTBin, "pT Pi")) { return false; } - if (std::abs(invMassDsToPiKK(candidate) - RecoDecay::getMassPDG(pdg::Code::kDS)) > cuts->get(pTBin, "deltaM")) { + if (std::abs(hfHelper.invMassDsToPiKK(candidate) - o2::analysis::pdg::MassDS) > cuts->get(pTBin, "deltaM")) { return false; } - if (deltaMassPhiDsToPiKK(candidate) > cuts->get(pTBin, "deltaM Phi")) { + if (hfHelper.deltaMassPhiDsToPiKK(candidate) > cuts->get(pTBin, "deltaM Phi")) { return false; } - if (std::abs(cos3PiKDsToPiKK(candidate)) < cuts->get(pTBin, "cos^3 theta_PiK")) { + if (std::abs(hfHelper.cos3PiKDsToPiKK(candidate)) < cuts->get(pTBin, "cos^3 theta_PiK")) { return false; } return true; } - void process(aod::HfCand3Prong const& candidates, aod::BigTracksPID const&) + void process(aod::HfCand3Prong const& candidates, + TracksSel const&) { - TrackSelectorPID selectorPion(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - - TrackSelectorPID selectorKaon(selectorPion); - selectorKaon.setPDG(kKPlus); - // looping over 3-prong candidates - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // final selection flag: auto statusDsToKKPi = 0; auto statusDsToPiKK = 0; - if (!(candidate.hfflag() & 1 << DecayType::DsToKKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::DsToKKPi)) { hfSelDsToKKPiCandidate(statusDsToKKPi, statusDsToPiKK); + if (applyMl) { + hfMlDsToKKPiCandidate(outputMl); + } + if (activateQA) { + registry.fill(HIST("hSelections"), 1, candidate.pt()); + } continue; } SETBIT(statusDsToKKPi, aod::SelectionStep::RecoSkims); SETBIT(statusDsToPiKK, aod::SelectionStep::RecoSkims); + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoSkims, candidate.pt()); + } - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) // topological selections if (!selection(candidate)) { hfSelDsToKKPiCandidate(statusDsToKKPi, statusDsToPiKK); + if (applyMl) { + hfMlDsToKKPiCandidate(outputMl); + } continue; } @@ -175,6 +243,9 @@ struct HfCandidateSelectorDsToKKPi { bool topolDsToPiKK = selectionPiKK(candidate, trackPos1, trackNeg, trackPos2); if (!topolDsToKKPi && !topolDsToPiKK) { hfSelDsToKKPiCandidate(statusDsToKKPi, statusDsToPiKK); + if (applyMl) { + hfMlDsToKKPiCandidate(outputMl); + } continue; } if (topolDsToKKPi) { @@ -183,24 +254,30 @@ struct HfCandidateSelectorDsToKKPi { if (topolDsToPiKK) { SETBIT(statusDsToPiKK, aod::SelectionStep::RecoTopol); } + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoTopol, candidate.pt()); + } // track-level PID selection - int pidTrackPos1Pion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos1); - int pidTrackPos1Kaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackPos1); - int pidTrackPos2Pion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos2); - int pidTrackPos2Kaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackPos2); - int pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackNeg); + int pidTrackPos1Pion = selectorPion.statusTpcOrTof(trackPos1); + int pidTrackPos1Kaon = selectorKaon.statusTpcOrTof(trackPos1); + int pidTrackPos2Pion = selectorPion.statusTpcOrTof(trackPos2); + int pidTrackPos2Kaon = selectorKaon.statusTpcOrTof(trackPos2); + int pidTrackNegKaon = selectorKaon.statusTpcOrTof(trackNeg); - bool pidDsToKKPi = !(pidTrackPos1Kaon == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Pion == TrackSelectorPID::Status::PIDRejected); + bool pidDsToKKPi = !(pidTrackPos1Kaon == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Pion == TrackSelectorPID::Rejected); - bool pidDsToPiKK = !(pidTrackPos1Pion == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Kaon == TrackSelectorPID::Status::PIDRejected); + bool pidDsToPiKK = !(pidTrackPos1Pion == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Kaon == TrackSelectorPID::Rejected); if (!pidDsToKKPi && !pidDsToPiKK) { hfSelDsToKKPiCandidate(statusDsToKKPi, statusDsToPiKK); + if (applyMl) { + hfMlDsToKKPiCandidate(outputMl); + } continue; } if (pidDsToKKPi) { @@ -209,6 +286,39 @@ struct HfCandidateSelectorDsToKKPi { if (pidDsToPiKK) { SETBIT(statusDsToPiKK, aod::SelectionStep::RecoPID); } + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoPID, candidate.pt()); + } + + if (applyMl) { + // ML selections + std::vector inputFeatures{candidate.ptProng0(), + trackPos1.dcaXY(), + trackPos1.dcaZ(), + candidate.ptProng1(), + trackNeg.dcaXY(), + trackNeg.dcaZ(), + candidate.ptProng2(), + trackPos2.dcaXY(), + trackPos2.dcaZ()}; + + bool isSelectedMl = hfMlResponse.isSelectedMl(inputFeatures, candidate.pt(), outputMl); + hfMlDsToKKPiCandidate(outputMl); + + if (!isSelectedMl) { + hfSelDsToKKPiCandidate(statusDsToKKPi, statusDsToPiKK); + continue; + } + if (pidDsToKKPi) { + SETBIT(statusDsToKKPi, aod::SelectionStep::RecoMl); + } + if (pidDsToPiKK) { + SETBIT(statusDsToPiKK, aod::SelectionStep::RecoMl); + } + if (activateQA) { + registry.fill(HIST("hSelections"), 2 + aod::SelectionStep::RecoMl, candidate.pt()); + } + } hfSelDsToKKPiCandidate(statusDsToKKPi, statusDsToPiKK); } diff --git a/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx b/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx index f15c2d9ce05..bacfb79d983 100644 --- a/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx @@ -17,6 +17,7 @@ #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -24,10 +25,7 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand_lb; using namespace o2::analysis; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_lb_to_lc_pi; struct HfCandidateSelectorLbToLcPi { Produces hfSelLbToLcPiCandidate; @@ -46,9 +44,11 @@ struct HfCandidateSelectorLbToLcPi { Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_lb_to_lc_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_lb_to_lc_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Lb0 candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_lb_to_lc_pi::cuts[0], hf_cuts_lb_to_lc_pi::nBinsPt, hf_cuts_lb_to_lc_pi::nCutVars, hf_cuts_lb_to_lc_pi::labelsPt, hf_cuts_lb_to_lc_pi::labelsCutVar}, "Lb0 candidate selection per pT bin"}; Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc+"}; + HfHelper hfHelper; + // Apply topological cuts as defined in SelectorCuts.h; return true if candidate passes all cuts template bool selectionTopol(const T1& hfCandLb, const T2& hfCandLc, const T3& trackPi) @@ -56,7 +56,7 @@ struct HfCandidateSelectorLbToLcPi { auto candpT = hfCandLb.pt(); int pTBin = findBin(binsPt, candpT); if (pTBin == -1) { - // Printf("Lb topol selection failed at getpTBin"); + // LOGF(debug, "Lb topol selection failed at getpTBin"); return false; } @@ -66,8 +66,8 @@ struct HfCandidateSelectorLbToLcPi { } //Λb0 mass cut - if (std::abs(invMassLbToLcPi(hfCandLb) - RecoDecay::getMassPDG(pdg::Code::kLambdaB0)) > cuts->get(pTBin, "m")) { - // Printf("Lb topol selection failed at mass diff check"); + if (std::abs(hfHelper.invMassLbToLcPi(hfCandLb) - o2::analysis::pdg::MassLambdaB0) > cuts->get(pTBin, "m")) { + // LOGF(debug, "Lb topol selection failed at mass diff check"); return false; } @@ -83,7 +83,7 @@ struct HfCandidateSelectorLbToLcPi { // Lc mass // if (trackPi.sign() < 0) { - // if (std::abs(invMassLcToPKPi(hfCandLc) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) > cuts->get(pTBin, "DeltaMLc")) { + // if (std::abs(hfHelper.invMassLcToPKPi(hfCandLc) - o2::analysis::pdg::MassLambdaCPlus) > cuts->get(pTBin, "DeltaMLc")) { // return false; // } // } @@ -100,7 +100,7 @@ struct HfCandidateSelectorLbToLcPi { // Lb chi2PCA cut if (hfCandLb.chi2PCA() > cuts->get(pTBin, "Chi2PCA")) { - // Printf("Lb selection failed at chi2PCA"); + // LOGF(debug, "Lb selection failed at chi2PCA"); return false; } @@ -122,33 +122,35 @@ struct HfCandidateSelectorLbToLcPi { return true; } - void process(aod::HfCandLb const& hfCandLbs, soa::Join const&, aod::BigTracksPID const&) + void process(aod::HfCandLb const& hfCandLbs, + soa::Join const&, + aod::Tracks const&) { - for (auto& hfCandLb : hfCandLbs) { // looping over Lb candidates + for (const auto& hfCandLb : hfCandLbs) { // looping over Lb candidates int statusLb = 0; // check if flagged as Λb --> Λc+ π- if (!(hfCandLb.hfflag() & 1 << hf_cand_lb::DecayType::LbToLcPi)) { hfSelLbToLcPiCandidate(statusLb); - // Printf("Lb candidate selection failed at hfflag check"); + // LOGF(debug, "Lb candidate selection failed at hfflag check"); continue; } // Lc is always index0 and pi is index1 by default // auto candLc = hfCandLb.prong0(); auto candLc = hfCandLb.prong0_as>(); - auto trackPi = hfCandLb.prong1_as(); + auto trackPi = hfCandLb.prong1(); // topological cuts if (!selectionTopol(hfCandLb, candLc, trackPi)) { hfSelLbToLcPiCandidate(statusLb); - // Printf("Lb candidate selection failed at selection topology"); + // LOGF(debug, "Lb candidate selection failed at selection topology"); continue; } hfSelLbToLcPiCandidate(1); - // Printf("Lb candidate selection successful, candidate should be selected"); + // LOGF(debug, "Lb candidate selection successful, candidate should be selected"); } } }; diff --git a/PWGHF/TableProducer/candidateSelectorLc.cxx b/PWGHF/TableProducer/candidateSelectorLc.cxx index 0476e2ea871..7dc2f99f979 100644 --- a/PWGHF/TableProducer/candidateSelectorLc.cxx +++ b/PWGHF/TableProducer/candidateSelectorLc.cxx @@ -16,17 +16,19 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_lc_to_p_k_pi; /// Struct for applying Lc selection cuts struct HfCandidateSelectorLc { @@ -53,24 +55,29 @@ struct HfCandidateSelectorLc { Configurable usePidTpcAndTof{"usePidTpcAndTof", false, "Bool to decide how to combine TPC and TOF PID: true = both (if present, only one otherwise); false = one is enough"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_lc_to_p_k_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Lc candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_lc_to_p_k_pi::cuts[0], hf_cuts_lc_to_p_k_pi::nBinsPt, hf_cuts_lc_to_p_k_pi::nCutVars, hf_cuts_lc_to_p_k_pi::labelsPt, hf_cuts_lc_to_p_k_pi::labelsCutVar}, "Lc candidate selection per pT bin"}; - using TrksPID = soa::Join; + HfHelper hfHelper; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + TrackSelectorPr selectorProton; - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) + using TracksSel = soa::Join; + + void init(InitContext const&) { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check - } - return true; + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorPion.setRangePtBayes(ptPidBayesMin, ptPidBayesMax); + selectorKaon = selectorPion; + selectorProton = selectorPion; } - */ /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -128,11 +135,11 @@ struct HfCandidateSelectorLc { } if (trackProton.globalIndex() == candidate.prong0Id()) { - if (std::abs(invMassLcToPKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassLcToPKPi(candidate) - o2::analysis::pdg::MassLambdaCPlus) > cuts->get(pTBin, "m")) { return false; } } else { - if (std::abs(invMassLcToPiKP(candidate) - RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassLcToPiKP(candidate) - o2::analysis::pdg::MassLambdaCPlus) > cuts->get(pTBin, "m")) { return false; } } @@ -140,46 +147,24 @@ struct HfCandidateSelectorLc { return true; } - void process(aod::HfCand3Prong const& candidates, TrksPID const&) + void process(aod::HfCand3Prong const& candidates, + TracksSel const&) { - TrackSelectorPID selectorPion(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - selectorPion.setRangePtBayes(ptPidBayesMin, ptPidBayesMax); - - TrackSelectorPID selectorKaon(selectorPion); - selectorKaon.setPDG(kKPlus); - - TrackSelectorPID selectorProton(selectorPion); - selectorProton.setPDG(kProton); - // looping over 3-prong candidates - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // final selection flag: 0 - rejected, 1 - accepted auto statusLcToPKPi = 0; auto statusLcToPiKP = 0; - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { hfSelLcCandidate(statusLcToPKPi, statusLcToPiKP); continue; } - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) - - /* - // daughter track validity selection - if (!daughterSelection(trackPos1) || !daughterSelection(trackNeg) || !daughterSelection(trackPos2)) { - hfSelLcCandidate(statusLcToPKPi, statusLcToPiKP); - continue; - } - */ + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) // implement filter bit 4 cut - should be done before this task at the track selection level @@ -216,35 +201,35 @@ struct HfCandidateSelectorLc { int pidTrackPos2Pion = 999; int pidTrackNegKaon = 999; if (usePidTpcAndTof) { - pidTrackPos1Proton = selectorProton.getStatusTrackPIDTpcAndTof(trackPos1); - pidTrackPos2Proton = selectorProton.getStatusTrackPIDTpcAndTof(trackPos2); - pidTrackPos1Pion = selectorPion.getStatusTrackPIDTpcAndTof(trackPos1); - pidTrackPos2Pion = selectorPion.getStatusTrackPIDTpcAndTof(trackPos2); - pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcAndTof(trackNeg); + pidTrackPos1Proton = selectorProton.statusTpcAndTof(trackPos1); + pidTrackPos2Proton = selectorProton.statusTpcAndTof(trackPos2); + pidTrackPos1Pion = selectorPion.statusTpcAndTof(trackPos1); + pidTrackPos2Pion = selectorPion.statusTpcAndTof(trackPos2); + pidTrackNegKaon = selectorKaon.statusTpcAndTof(trackNeg); } else { - pidTrackPos1Proton = selectorProton.getStatusTrackPIDTpcOrTof(trackPos1); - pidTrackPos2Proton = selectorProton.getStatusTrackPIDTpcOrTof(trackPos2); - pidTrackPos1Pion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos1); - pidTrackPos2Pion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos2); - pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackNeg); + pidTrackPos1Proton = selectorProton.statusTpcOrTof(trackPos1); + pidTrackPos2Proton = selectorProton.statusTpcOrTof(trackPos2); + pidTrackPos1Pion = selectorPion.statusTpcOrTof(trackPos1); + pidTrackPos2Pion = selectorPion.statusTpcOrTof(trackPos2); + pidTrackNegKaon = selectorKaon.statusTpcOrTof(trackNeg); } - if (pidTrackPos1Proton == TrackSelectorPID::Status::PIDAccepted && - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidTrackPos2Pion == TrackSelectorPID::Status::PIDAccepted) { + if (pidTrackPos1Proton == TrackSelectorPID::Accepted && + pidTrackNegKaon == TrackSelectorPID::Accepted && + pidTrackPos2Pion == TrackSelectorPID::Accepted) { pidLcToPKPi = 1; // accept LcToPKPi - } else if (pidTrackPos1Proton == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Pion == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackPos1Proton == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Pion == TrackSelectorPID::Rejected) { pidLcToPKPi = 0; // exclude LcToPKPi } - if (pidTrackPos2Proton == TrackSelectorPID::Status::PIDAccepted && - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidTrackPos1Pion == TrackSelectorPID::Status::PIDAccepted) { + if (pidTrackPos2Proton == TrackSelectorPID::Accepted && + pidTrackNegKaon == TrackSelectorPID::Accepted && + pidTrackPos1Pion == TrackSelectorPID::Accepted) { pidLcToPiKP = 1; // accept LcToPiKP - } else if (pidTrackPos1Pion == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Proton == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackPos1Pion == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Proton == TrackSelectorPID::Rejected) { pidLcToPiKP = 0; // exclude LcToPiKP } } @@ -254,28 +239,28 @@ struct HfCandidateSelectorLc { pidBayesLcToPKPi = 1; pidBayesLcToPiKP = 1; } else { - int pidBayesTrackPos1Proton = selectorProton.getStatusTrackBayesPID(trackPos1); - int pidBayesTrackPos2Proton = selectorProton.getStatusTrackBayesPID(trackPos2); - int pidBayesTrackPos1Pion = selectorPion.getStatusTrackBayesPID(trackPos1); - int pidBayesTrackPos2Pion = selectorPion.getStatusTrackBayesPID(trackPos2); - int pidBayesTrackNegKaon = selectorKaon.getStatusTrackBayesPID(trackNeg); - - if (pidBayesTrackPos1Proton == TrackSelectorPID::Status::PIDAccepted && - pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidBayesTrackPos2Pion == TrackSelectorPID::Status::PIDAccepted) { + int pidBayesTrackPos1Proton = selectorProton.statusBayes(trackPos1); + int pidBayesTrackPos2Proton = selectorProton.statusBayes(trackPos2); + int pidBayesTrackPos1Pion = selectorPion.statusBayes(trackPos1); + int pidBayesTrackPos2Pion = selectorPion.statusBayes(trackPos2); + int pidBayesTrackNegKaon = selectorKaon.statusBayes(trackNeg); + + if (pidBayesTrackPos1Proton == TrackSelectorPID::Accepted && + pidBayesTrackNegKaon == TrackSelectorPID::Accepted && + pidBayesTrackPos2Pion == TrackSelectorPID::Accepted) { pidBayesLcToPKPi = 1; // accept LcToPKPi - } else if (pidBayesTrackPos1Proton == TrackSelectorPID::Status::PIDRejected || - pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidBayesTrackPos2Pion == TrackSelectorPID::Status::PIDRejected) { + } else if (pidBayesTrackPos1Proton == TrackSelectorPID::Rejected || + pidBayesTrackNegKaon == TrackSelectorPID::Rejected || + pidBayesTrackPos2Pion == TrackSelectorPID::Rejected) { pidBayesLcToPKPi = 0; // exclude LcToPKPi } - if (pidBayesTrackPos2Proton == TrackSelectorPID::Status::PIDAccepted && - pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidBayesTrackPos1Pion == TrackSelectorPID::Status::PIDAccepted) { + if (pidBayesTrackPos2Proton == TrackSelectorPID::Accepted && + pidBayesTrackNegKaon == TrackSelectorPID::Accepted && + pidBayesTrackPos1Pion == TrackSelectorPID::Accepted) { pidBayesLcToPiKP = 1; // accept LcToPiKP - } else if (pidBayesTrackPos1Pion == TrackSelectorPID::Status::PIDRejected || - pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidBayesTrackPos2Proton == TrackSelectorPID::Status::PIDRejected) { + } else if (pidBayesTrackPos1Pion == TrackSelectorPID::Rejected || + pidBayesTrackNegKaon == TrackSelectorPID::Rejected || + pidBayesTrackPos2Proton == TrackSelectorPID::Rejected) { pidBayesLcToPiKP = 0; // exclude LcToPiKP } } diff --git a/PWGHF/TableProducer/candidateSelectorLcMl.cxx b/PWGHF/TableProducer/candidateSelectorLcMl.cxx index 8dda6a58953..4cdd47caaab 100644 --- a/PWGHF/TableProducer/candidateSelectorLcMl.cxx +++ b/PWGHF/TableProducer/candidateSelectorLcMl.cxx @@ -18,10 +18,11 @@ /// \author Maja Kabus , CERN, Warsaw University of Technology #include "CCDB/CcdbApi.h" -#include "Common/Core/TrackSelectorPID.h" -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" + +#include "Common/Core/TrackSelectorPID.h" +#include "Common/Core/trackUtilities.h" #include "Tools/ML/model.h" #include "PWGHF/Core/SelectorCuts.h" @@ -29,10 +30,8 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_lc_to_p_k_pi; -using namespace hf_cuts_bdt_multiclass; using namespace o2::ml; /// Struct for applying Lc selection cuts @@ -63,23 +62,40 @@ struct HfCandidateSelectorLcMl { Configurable onnxFileLcToPiKPConf{"onnxFileLcToPiKPConf", "/cvmfs/alice.cern.ch/data/analysis/2022/vAN-20220818/PWGHF/o2/trigger/ModelHandler_onnx_LcToPKPi.onnx", "ONNX file for ML model for Lc+ candidates"}; Configurable> thresholdBDTScoreLcToPiKP{"thresholdBDTScoreLcToPiKP", {hf_cuts_bdt_multiclass::cuts[0], hf_cuts_bdt_multiclass::nBinsPt, hf_cuts_bdt_multiclass::nCutBdtScores, hf_cuts_bdt_multiclass::labelsPt, hf_cuts_bdt_multiclass::labelsCutBdt}, "Threshold values for BDT output scores of Lc+ candidates"}; - o2::ccdb::CcdbApi ccdbApi; Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable mlModelPathCCDB{"mlModelPathCCDB", "Analysis/PWGHF/ML/HFTrigger/Lc", "Path on CCDB"}; Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; - Configurable activateQA{"activateQA", 0, "flag to enable QA histos (0 no QA, 1 basic QA, 2 extended QA)"}; - HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + Configurable activateQA{"activateQA", false, "flag to enable QA histos"}; + int dataTypeML; + o2::ccdb::CcdbApi ccdbApi; OnnxModel model; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + TrackSelectorPr selectorProton; + + using TracksSel = soa::Join; - using TrksPID = soa::Join; + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - void init(o2::framework::InitContext&) + void init(InitContext&) { + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorPion.setRangePtBayes(ptPidBayesMin, ptPidBayesMax); + selectorKaon = selectorPion; + selectorProton = selectorPion; + AxisSpec bdtAxis{100, 0.f, 1.f}; - if (applyML && activateQA != 0) { + if (applyML && activateQA) { registry.add("hLcBDTScoreBkg", "BDT background score distribution for Lc;BDT background score;counts", HistType::kTH1F, {bdtAxis}); registry.add("hLcBDTScorePrompt", "BDT prompt score distribution for Lc;BDT prompt score;counts", HistType::kTH1F, {bdtAxis}); registry.add("hLcBDTScoreNonPrompt", "BDT nonprompt score distribution for Lc;BDT nonprompt score;counts", HistType::kTH1F, {bdtAxis}); @@ -120,62 +136,24 @@ struct HfCandidateSelectorLcMl { } } - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) + void process(aod::HfCand3Prong const& candidates, + TracksSel const&) { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check - } - return true; - } - */ - - void - process(aod::HfCand3Prong const& candidates, TrksPID const&) - { - TrackSelectorPID selectorPion(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - selectorPion.setRangePtBayes(ptPidBayesMin, ptPidBayesMax); - - TrackSelectorPID selectorKaon(selectorPion); - selectorKaon.setPDG(kKPlus); - - TrackSelectorPID selectorProton(selectorPion); - selectorProton.setPDG(kProton); - // looping over 3-prong candidates - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // final selection flag: 0 - rejected, 1 - accepted auto statusLcToPKPi = 0; auto statusLcToPiKP = 0; - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { hfSelLcCandidate(statusLcToPKPi, statusLcToPiKP); continue; } - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) - - /* - // daughter track validity selection - if (!daughterSelection(trackPos1) || !daughterSelection(trackNeg) || !daughterSelection(trackPos2)) { - hfSelLcCandidate(statusLcToPKPi, statusLcToPiKP); - continue; - } - */ + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) // implement filter bit 4 cut - should be done before this task at the track selection level @@ -190,28 +168,28 @@ struct HfCandidateSelectorLcMl { pidLcToPiKP = 1; } else { // track-level PID selection - int pidTrackPos1Proton = selectorProton.getStatusTrackPIDTpcOrTof(trackPos1); - int pidTrackPos2Proton = selectorProton.getStatusTrackPIDTpcOrTof(trackPos2); - int pidTrackPos1Pion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos1); - int pidTrackPos2Pion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos2); - int pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackNeg); - - if (pidTrackPos1Proton == TrackSelectorPID::Status::PIDAccepted && - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidTrackPos2Pion == TrackSelectorPID::Status::PIDAccepted) { + int pidTrackPos1Proton = selectorProton.statusTpcOrTof(trackPos1); + int pidTrackPos2Proton = selectorProton.statusTpcOrTof(trackPos2); + int pidTrackPos1Pion = selectorPion.statusTpcOrTof(trackPos1); + int pidTrackPos2Pion = selectorPion.statusTpcOrTof(trackPos2); + int pidTrackNegKaon = selectorKaon.statusTpcOrTof(trackNeg); + + if (pidTrackPos1Proton == TrackSelectorPID::Accepted && + pidTrackNegKaon == TrackSelectorPID::Accepted && + pidTrackPos2Pion == TrackSelectorPID::Accepted) { pidLcToPKPi = 1; // accept LcToPKPi - } else if (pidTrackPos1Proton == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Pion == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackPos1Proton == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Pion == TrackSelectorPID::Rejected) { pidLcToPKPi = 0; // exclude LcToPKPi } - if (pidTrackPos2Proton == TrackSelectorPID::Status::PIDAccepted && - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidTrackPos1Pion == TrackSelectorPID::Status::PIDAccepted) { + if (pidTrackPos2Proton == TrackSelectorPID::Accepted && + pidTrackNegKaon == TrackSelectorPID::Accepted && + pidTrackPos1Pion == TrackSelectorPID::Accepted) { pidLcToPiKP = 1; // accept LcToPiKP - } else if (pidTrackPos1Pion == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Proton == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackPos1Pion == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Proton == TrackSelectorPID::Rejected) { pidLcToPiKP = 0; // exclude LcToPiKP } } @@ -221,28 +199,28 @@ struct HfCandidateSelectorLcMl { pidBayesLcToPKPi = 1; pidBayesLcToPiKP = 1; } else { - int pidBayesTrackPos1Proton = selectorProton.getStatusTrackBayesPID(trackPos1); - int pidBayesTrackPos2Proton = selectorProton.getStatusTrackBayesPID(trackPos2); - int pidBayesTrackPos1Pion = selectorPion.getStatusTrackBayesPID(trackPos1); - int pidBayesTrackPos2Pion = selectorPion.getStatusTrackBayesPID(trackPos2); - int pidBayesTrackNegKaon = selectorKaon.getStatusTrackBayesPID(trackNeg); - - if (pidBayesTrackPos1Proton == TrackSelectorPID::Status::PIDAccepted && - pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidBayesTrackPos2Pion == TrackSelectorPID::Status::PIDAccepted) { + int pidBayesTrackPos1Proton = selectorProton.statusBayes(trackPos1); + int pidBayesTrackPos2Proton = selectorProton.statusBayes(trackPos2); + int pidBayesTrackPos1Pion = selectorPion.statusBayes(trackPos1); + int pidBayesTrackPos2Pion = selectorPion.statusBayes(trackPos2); + int pidBayesTrackNegKaon = selectorKaon.statusBayes(trackNeg); + + if (pidBayesTrackPos1Proton == TrackSelectorPID::Accepted && + pidBayesTrackNegKaon == TrackSelectorPID::Accepted && + pidBayesTrackPos2Pion == TrackSelectorPID::Accepted) { pidBayesLcToPKPi = 1; // accept LcToPKPi - } else if (pidBayesTrackPos1Proton == TrackSelectorPID::Status::PIDRejected || - pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidBayesTrackPos2Pion == TrackSelectorPID::Status::PIDRejected) { + } else if (pidBayesTrackPos1Proton == TrackSelectorPID::Rejected || + pidBayesTrackNegKaon == TrackSelectorPID::Rejected || + pidBayesTrackPos2Pion == TrackSelectorPID::Rejected) { pidBayesLcToPKPi = 0; // exclude LcToPKPi } - if (pidBayesTrackPos2Proton == TrackSelectorPID::Status::PIDAccepted && - pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidBayesTrackPos1Pion == TrackSelectorPID::Status::PIDAccepted) { + if (pidBayesTrackPos2Proton == TrackSelectorPID::Accepted && + pidBayesTrackNegKaon == TrackSelectorPID::Accepted && + pidBayesTrackPos1Pion == TrackSelectorPID::Accepted) { pidBayesLcToPiKP = 1; // accept LcToPiKP - } else if (pidBayesTrackPos1Pion == TrackSelectorPID::Status::PIDRejected || - pidBayesTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidBayesTrackPos2Proton == TrackSelectorPID::Status::PIDRejected) { + } else if (pidBayesTrackPos1Pion == TrackSelectorPID::Rejected || + pidBayesTrackNegKaon == TrackSelectorPID::Rejected || + pidBayesTrackPos2Proton == TrackSelectorPID::Rejected) { pidBayesLcToPiKP = 0; // exclude LcToPiKP } } @@ -274,10 +252,10 @@ struct HfCandidateSelectorLcMl { std::array pVecPos1 = {trackPos1.px(), trackPos1.py(), trackPos1.pz()}; std::array pVecNeg = {trackNeg.px(), trackNeg.py(), trackNeg.pz()}; std::array pVecPos2 = {trackPos2.px(), trackPos2.py(), trackPos2.pz()}; - const float massPi = RecoDecay::getMassPDG(kPiPlus); - const float massK = RecoDecay::getMassPDG(kKPlus); - const float massProton = RecoDecay::getMassPDG(kProton); - const float massLc = RecoDecay::getMassPDG(o2::analysis::pdg::kLambdaCPlus); + const float massPi = o2::analysis::pdg::MassPiPlus; + const float massK = o2::analysis::pdg::MassKPlus; + const float massProton = o2::analysis::pdg::MassProton; + const float massLc = o2::analysis::pdg::MassLambdaCPlus; if (statusLcToPiKP == 1) { auto invMassLcToPiKP = RecoDecay::m(std::array{pVecPos1, pVecNeg, pVecPos2}, std::array{massPi, massK, massProton}); if (std::abs(invMassLcToPiKP - massLc) >= maxDeltaMass && candidate.pt() < 10) { @@ -329,7 +307,7 @@ struct HfCandidateSelectorLcMl { // non-prompt // NOTE: Can be both prompt and non-prompt! } - if (activateQA != 0) { + if (activateQA) { registry.fill(HIST("hLcBDTScoreBkg"), scores[0]); registry.fill(HIST("hLcBDTScorePrompt"), scores[1]); registry.fill(HIST("hLcBDTScoreNonPrompt"), scores[2]); diff --git a/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx b/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx index 6b13ec907c4..a387faaf05e 100644 --- a/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx +++ b/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx @@ -16,20 +16,90 @@ /// \author Chiara Zampolli , CERN /// Daniel Samitz, , Vienna -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsDebugLcToK0sP.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_casc; -using namespace o2::analysis::hf_cuts_lc_to_k0s_p; -using MyBigTracksBayes = soa::Join; +// possible input features for ML +enum MLInputFeatures { + numContrib = 0, + posX, + posY, + posZ, + xSecondaryVertex, + ySecondaryVertex, + zSecondaryVertex, + errorDecayLength, + errorDecayLengthXY, + chi2PCA, + rSecondaryVertex, + decayLength, + decayLengthXY, + decayLengthNormalised, + decayLengthXYNormalised, + impactParameterNormalised0, + ptProng0, + pProng0, + impactParameterNormalised1, + ptProng1, + pProng1, + pxProng0, + pyProng0, + pzProng0, + pxProng1, + pyProng1, + pzProng1, + impactParameter0, + impactParameter1, + errorImpactParameter0, + errorImpactParameter1, + v0X, + v0Y, + v0Z, + v0Radius, + v0CosPA, + v0MLambda, + v0MAntiLambda, + v0MK0Short, + v0MGamma, + v0CtK0Short, + v0CtLambda, + dcaV0Daughters, + pxPos, + pyPos, + pzPos, + ptV0Pos, + dcaPosToPV, + pxNeg, + pyNeg, + pzNeg, + ptV0Neg, + dcaNegToPV, + nSigmaTPCPr0, + nSigmaTOFPr0, + m, + pt, + p, + cpa, + cpaXY, + ct, + eta, + phi, + y, + e, + NInputFeatures +}; struct HfCandidateSelectorLcToK0sP { Produces hfSelLcToK0sPCandidate; @@ -52,10 +122,39 @@ struct HfCandidateSelectorLcToK0sP { // Bayesian Configurable probBayesMinLowP{"probBayesMinLowP", 0.8, "min. Bayes probability for bachelor at low p [%]"}; Configurable probBayesMinHighP{"probBayesMinHighP", 0.8, "min. Bayes probability for bachelor at high p [%]"}; - // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_k0s_p::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_lc_to_k0s_p::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Lc candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_lc_to_k0s_p::cuts[0], hf_cuts_lc_to_k0s_p::nBinsPt, hf_cuts_lc_to_k0s_p::nCutVars, hf_cuts_lc_to_k0s_p::labelsPt, hf_cuts_lc_to_k0s_p::labelsCutVar}, "Lc candidate selection per pT bin"}; + // ML inference + Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; + Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirMl{"cutDirMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsMl{"cutsMl", {hf_cuts_ml::cuts[0], hf_cuts_ml::nBinsPt, hf_cuts_ml::nCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"}; + Configurable nClassesMl{"nClassesMl", (int8_t)hf_cuts_ml::nCutScores, "Number of classes in ML model"}; + Configurable> inputFeaturesML{"inputFeaturesML", {""}, "List of input features for the ML model"}; + // CCDB configuration + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable modelPathsCCDB{"modelPathsCCDB", "EventFiltering/PWGHF/BDTLcToK0sP", "Path on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_D0ToKPi.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + + HfHelper hfHelper; + TrackSelectorPr selectorProtonLowP; + TrackSelectorPr selectorProtonHighP; + + o2::analysis::HfMlResponse hfMlResponse; + std::vector selectedInputFeatures{std::vector(MLInputFeatures::NInputFeatures, false)}; + + o2::ccdb::CcdbApi ccdbApi; + + std::vector> hModelScore; + std::vector> hModelScoreVsPtCand; + + using TracksSel = soa::Join; + using TracksSelBayes = soa::Join; + + HistogramRegistry registry{"registry", {}}; void init(InitContext&) { @@ -65,9 +164,343 @@ struct HfCandidateSelectorLcToK0sP { if (doprocessWithStandardPID && doprocessWithBayesPID) { LOGF(fatal, "Cannot enable processWithStandardPID and processWithBayesPID at the same time. Please choose one."); } + + selectorProtonLowP.setRangeNSigmaTpc(-nSigmaTpcMaxLowP, nSigmaTpcMaxLowP); + selectorProtonLowP.setRangeNSigmaTof(-nSigmaTofMaxLowP, nSigmaTofMaxLowP); + selectorProtonLowP.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMaxLowP, nSigmaTpcCombinedMaxLowP); + selectorProtonLowP.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMaxLowP, nSigmaTofCombinedMaxLowP); + selectorProtonLowP.setProbBayesMin(probBayesMinLowP); + + selectorProtonHighP.setRangeNSigmaTpc(-nSigmaTpcMaxHighP, nSigmaTpcMaxHighP); + selectorProtonHighP.setRangeNSigmaTof(-nSigmaTofMaxHighP, nSigmaTofMaxHighP); + selectorProtonHighP.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMaxHighP, nSigmaTpcCombinedMaxHighP); + selectorProtonHighP.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMaxHighP, nSigmaTofCombinedMaxHighP); + selectorProtonHighP.setProbBayesMin(probBayesMinHighP); + + if (applyMl) { + hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB.value, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.init(); + + // load histograms for ML score + AxisSpec axisScore = {100, 0, 1, "score"}; + AxisSpec axisBinsPt = {binsPtMl, "#it{p}_{T} (GeV/#it{c})"}; + for (int classMl = 0; classMl < nClassesMl; classMl++) { + hModelScore.push_back(registry.add(Form("hMlScoreClass%d", classMl), "Model core distribution for Lc;Model score;counts", HistType::kTH1F, {axisScore})); + hModelScoreVsPtCand.push_back(registry.add(Form("hMlScoreClass%dVsPtCand", classMl), "Model score distribution for Lc;Model score;counts", HistType::kTH2F, {axisScore, axisBinsPt})); + } + + // set the selected input features + initInputFeatures(); + } } - /// Conjugate independent toplogical cuts + // Check the list of selected input features for ML model + void initInputFeatures() + { + std::map inputFeatureNames{ + {numContrib, "numContrib"}, + {posX, "posX"}, + {posY, "posY"}, + {posZ, "posZ"}, + {xSecondaryVertex, "xSecondaryVertex"}, + {ySecondaryVertex, "ySecondaryVertex"}, + {zSecondaryVertex, "zSecondaryVertex"}, + {errorDecayLength, "errorDecayLength"}, + {errorDecayLengthXY, "errorDecayLengthXY"}, + {chi2PCA, "chi2PCA"}, + {rSecondaryVertex, "rSecondaryVertex"}, + {decayLength, "decayLength"}, + {decayLengthXY, "decayLengthXY"}, + {decayLengthNormalised, "decayLengthNormalised"}, + {decayLengthXYNormalised, "decayLengthXYNormalised"}, + {impactParameterNormalised0, "impactParameterNormalised0"}, + {ptProng0, "ptProng0"}, + {pProng0, "pProng0"}, + {impactParameterNormalised1, "impactParameterNormalised1"}, + {ptProng1, "ptProng1"}, + {pProng1, "pProng1"}, + {pxProng0, "pxProng0"}, + {pyProng0, "pyProng0"}, + {pzProng0, "pzProng0"}, + {pxProng1, "pxProng1"}, + {pyProng1, "pyProng1"}, + {pzProng1, "pzProng1"}, + {impactParameter0, "impactParameter0"}, + {impactParameter1, "impactParameter1"}, + {errorImpactParameter0, "errorImpactParameter0"}, + {errorImpactParameter1, "errorImpactParameter1"}, + {v0X, "v0X"}, + {v0Y, "v0Y"}, + {v0Z, "v0Z"}, + {v0Radius, "v0Radius"}, + {v0CosPA, "v0CosPA"}, + {v0MLambda, "v0MLambda"}, + {v0MAntiLambda, "v0MAntiLambda"}, + {v0MK0Short, "v0MK0Short"}, + {v0MGamma, "v0MGamma"}, + {v0CtK0Short, "v0CtK0Short"}, + {v0CtLambda, "v0CtLambda"}, + {dcaV0Daughters, "dcaV0Daughters"}, + {pxPos, "pxPos"}, + {pyPos, "pyPos"}, + {pzPos, "pzPos"}, + {ptV0Pos, "ptV0Pos"}, + {dcaPosToPV, "dcaPosToPV"}, + {pxNeg, "pxNeg"}, + {pyNeg, "pyNeg"}, + {pzNeg, "pzNeg"}, + {ptV0Neg, "ptV0Neg"}, + {dcaNegToPV, "dcaNegToPV"}, + {nSigmaTPCPr0, "nSigmaTPCPr0"}, + {nSigmaTOFPr0, "nSigmaTOFPr0"}, + {m, "m"}, + {pt, "pt"}, + {p, "p"}, + {cpa, "cpa"}, + {cpaXY, "cpaXY"}, + {ct, "ct"}, + {eta, "eta"}, + {phi, "phi"}, + {y, "y"}, + {e, "e"}}; + + // check for each possible input feature if it is included in the list of selected input features or not + for (const auto& inputFeature : inputFeatureNames) { + if (std::find(std::begin(inputFeaturesML.value), std::end(inputFeaturesML.value), inputFeature.second) != std::end(inputFeaturesML.value)) { + selectedInputFeatures[inputFeature.first] = true; + LOG(info) << "Included \'" << inputFeature.second << "\' in list of ML input features."; + } else { + selectedInputFeatures[inputFeature.first] = false; + } + } + + // check if all given input features are recongnized + for (const auto& inputFeature : inputFeaturesML.value) { + bool found = false; + for (const auto& inputFeatureName : inputFeatureNames) { + if (inputFeatureName.second == inputFeature) { + found = true; + break; + } + } + if (!found) { + LOG(fatal) << "Can not find \'" << inputFeature << "\' in list of possible ML input features."; + } + } + } + + // fill only the selcted input features into the the vector of ML input features + template + std::vector setInputFeatures(const T& candidate, const U& bach) + { + std::vector inputFeatures; + + if (selectedInputFeatures[MLInputFeatures::numContrib]) { + inputFeatures.push_back(bach.collision().numContrib()); + } + if (selectedInputFeatures[MLInputFeatures::posX]) { + inputFeatures.push_back(candidate.posX()); + } + if (selectedInputFeatures[MLInputFeatures::posY]) { + inputFeatures.push_back(candidate.posY()); + } + if (selectedInputFeatures[MLInputFeatures::posZ]) { + inputFeatures.push_back(candidate.posZ()); + } + if (selectedInputFeatures[MLInputFeatures::xSecondaryVertex]) { + inputFeatures.push_back(candidate.xSecondaryVertex()); + } + if (selectedInputFeatures[MLInputFeatures::ySecondaryVertex]) { + inputFeatures.push_back(candidate.ySecondaryVertex()); + } + if (selectedInputFeatures[MLInputFeatures::zSecondaryVertex]) { + inputFeatures.push_back(candidate.zSecondaryVertex()); + } + if (selectedInputFeatures[MLInputFeatures::errorDecayLength]) { + inputFeatures.push_back(candidate.errorDecayLength()); + } + if (selectedInputFeatures[MLInputFeatures::errorDecayLengthXY]) { + inputFeatures.push_back(candidate.errorDecayLengthXY()); + } + if (selectedInputFeatures[MLInputFeatures::chi2PCA]) { + inputFeatures.push_back(candidate.chi2PCA()); + } + if (selectedInputFeatures[MLInputFeatures::rSecondaryVertex]) { + inputFeatures.push_back(candidate.rSecondaryVertex()); + } + if (selectedInputFeatures[MLInputFeatures::decayLength]) { + inputFeatures.push_back(candidate.decayLength()); + } + if (selectedInputFeatures[MLInputFeatures::decayLengthXY]) { + inputFeatures.push_back(candidate.decayLengthXY()); + } + if (selectedInputFeatures[MLInputFeatures::decayLengthNormalised]) { + inputFeatures.push_back(candidate.decayLengthNormalised()); + } + if (selectedInputFeatures[MLInputFeatures::decayLengthXYNormalised]) { + inputFeatures.push_back(candidate.decayLengthXYNormalised()); + } + if (selectedInputFeatures[MLInputFeatures::impactParameterNormalised0]) { + inputFeatures.push_back(candidate.impactParameterNormalised0()); + } + if (selectedInputFeatures[MLInputFeatures::ptProng0]) { + inputFeatures.push_back(candidate.ptProng0()); + } + if (selectedInputFeatures[MLInputFeatures::pProng0]) { + inputFeatures.push_back(RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0())); + } + if (selectedInputFeatures[MLInputFeatures::impactParameterNormalised1]) { + inputFeatures.push_back(candidate.impactParameterNormalised1()); + } + if (selectedInputFeatures[MLInputFeatures::ptProng1]) { + inputFeatures.push_back(candidate.ptProng1()); + } + if (selectedInputFeatures[MLInputFeatures::pProng1]) { + inputFeatures.push_back(RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1())); + } + if (selectedInputFeatures[MLInputFeatures::pxProng0]) { + inputFeatures.push_back(candidate.pxProng0()); + } + if (selectedInputFeatures[MLInputFeatures::pyProng0]) { + inputFeatures.push_back(candidate.pyProng0()); + } + if (selectedInputFeatures[MLInputFeatures::pzProng0]) { + inputFeatures.push_back(candidate.pzProng0()); + } + if (selectedInputFeatures[MLInputFeatures::pxProng1]) { + inputFeatures.push_back(candidate.pxProng1()); + } + if (selectedInputFeatures[MLInputFeatures::pyProng1]) { + inputFeatures.push_back(candidate.pyProng1()); + } + if (selectedInputFeatures[MLInputFeatures::pzProng1]) { + inputFeatures.push_back(candidate.pzProng1()); + } + if (selectedInputFeatures[MLInputFeatures::errorImpactParameter0]) { + inputFeatures.push_back(candidate.impactParameter0()); + } + if (selectedInputFeatures[MLInputFeatures::impactParameter1]) { + inputFeatures.push_back(candidate.impactParameter1()); + } + if (selectedInputFeatures[MLInputFeatures::errorImpactParameter0]) { + inputFeatures.push_back(candidate.errorImpactParameter0()); + } + if (selectedInputFeatures[MLInputFeatures::errorImpactParameter1]) { + inputFeatures.push_back(candidate.errorImpactParameter1()); + } + if (selectedInputFeatures[MLInputFeatures::v0X]) { + inputFeatures.push_back(candidate.v0x()); + } + if (selectedInputFeatures[MLInputFeatures::v0Y]) { + inputFeatures.push_back(candidate.v0y()); + } + if (selectedInputFeatures[MLInputFeatures::v0Z]) { + inputFeatures.push_back(candidate.v0z()); + } + if (selectedInputFeatures[MLInputFeatures::v0Radius]) { + inputFeatures.push_back(candidate.v0radius()); + } + if (selectedInputFeatures[MLInputFeatures::v0CosPA]) { + inputFeatures.push_back(candidate.v0cosPA()); + } + if (selectedInputFeatures[MLInputFeatures::v0MLambda]) { + inputFeatures.push_back(candidate.mLambda()); + } + if (selectedInputFeatures[MLInputFeatures::v0MAntiLambda]) { + inputFeatures.push_back(candidate.mAntiLambda()); + } + if (selectedInputFeatures[MLInputFeatures::v0MK0Short]) { + inputFeatures.push_back(candidate.mK0Short()); + } + if (selectedInputFeatures[MLInputFeatures::v0MGamma]) { + inputFeatures.push_back(candidate.mGamma()); + } + if (selectedInputFeatures[MLInputFeatures::v0CtK0Short]) { + inputFeatures.push_back(hfHelper.ctV0K0s(candidate)); + } + if (selectedInputFeatures[MLInputFeatures::v0CtK0Short]) { + inputFeatures.push_back(hfHelper.ctV0Lambda(candidate)); + } + if (selectedInputFeatures[MLInputFeatures::dcaV0Daughters]) { + inputFeatures.push_back(candidate.dcaV0daughters()); + } + if (selectedInputFeatures[MLInputFeatures::pxPos]) { + inputFeatures.push_back(candidate.pxpos()); + } + if (selectedInputFeatures[MLInputFeatures::pyPos]) { + inputFeatures.push_back(candidate.pypos()); + } + if (selectedInputFeatures[MLInputFeatures::pzPos]) { + inputFeatures.push_back(candidate.pzpos()); + } + if (selectedInputFeatures[MLInputFeatures::ptV0Pos]) { + inputFeatures.push_back(candidate.ptV0Pos()); + } + if (selectedInputFeatures[MLInputFeatures::dcaPosToPV]) { + inputFeatures.push_back(candidate.dcapostopv()); + } + if (selectedInputFeatures[MLInputFeatures::pxNeg]) { + inputFeatures.push_back(candidate.pxneg()); + } + if (selectedInputFeatures[MLInputFeatures::pyNeg]) { + inputFeatures.push_back(candidate.pyneg()); + } + if (selectedInputFeatures[MLInputFeatures::pzNeg]) { + inputFeatures.push_back(candidate.pzneg()); + } + if (selectedInputFeatures[MLInputFeatures::ptV0Neg]) { + inputFeatures.push_back(candidate.ptV0Neg()); + } + if (selectedInputFeatures[MLInputFeatures::dcaNegToPV]) { + inputFeatures.push_back(candidate.dcanegtopv()); + } + if (selectedInputFeatures[MLInputFeatures::nSigmaTPCPr0]) { + inputFeatures.push_back(bach.tpcNSigmaPr()); + } + if (selectedInputFeatures[MLInputFeatures::nSigmaTOFPr0]) { + inputFeatures.push_back(bach.tofNSigmaPr()); + } + if (selectedInputFeatures[MLInputFeatures::m]) { + inputFeatures.push_back(hfHelper.invMassLcToK0sP(candidate)); + } + if (selectedInputFeatures[MLInputFeatures::pt]) { + inputFeatures.push_back(candidate.pt()); + } + if (selectedInputFeatures[MLInputFeatures::p]) { + inputFeatures.push_back(candidate.p()); + } + if (selectedInputFeatures[MLInputFeatures::cpa]) { + inputFeatures.push_back(candidate.cpa()); + } + if (selectedInputFeatures[MLInputFeatures::cpaXY]) { + inputFeatures.push_back(candidate.cpaXY()); + } + if (selectedInputFeatures[MLInputFeatures::ct]) { + inputFeatures.push_back(hfHelper.ctLc(candidate)); + } + if (selectedInputFeatures[MLInputFeatures::eta]) { + inputFeatures.push_back(candidate.eta()); + } + if (selectedInputFeatures[MLInputFeatures::phi]) { + inputFeatures.push_back(candidate.phi()); + } + if (selectedInputFeatures[MLInputFeatures::y]) { + inputFeatures.push_back(hfHelper.yLc(candidate)); + } + if (selectedInputFeatures[MLInputFeatures::e]) { + inputFeatures.push_back(hfHelper.eLc(candidate)); + } + + return inputFeatures; + } + + /// Conjugate independent topological cuts /// \param hfCandCascade is candidate /// \return true if candidate passes all cuts template @@ -83,15 +516,15 @@ struct HfCandidateSelectorLcToK0sP { return false; // check that the candidate pT is within the analysis range } - if (std::abs(hfCandCascade.mK0Short() - RecoDecay::getMassPDG(kK0Short)) > cuts->get(ptBin, "mK0s")) { + if (std::abs(hfCandCascade.mK0Short() - o2::analysis::pdg::MassK0Short) > cuts->get(ptBin, "mK0s")) { return false; // mass of the K0s } - if ((std::abs(hfCandCascade.mLambda() - RecoDecay::getMassPDG(kLambda0)) < cuts->get(ptBin, "mLambda")) || (std::abs(hfCandCascade.mAntiLambda() - RecoDecay::getMassPDG(kLambda0)) < cuts->get(ptBin, "mLambda"))) { + if ((std::abs(hfCandCascade.mLambda() - o2::analysis::pdg::MassLambda0) < cuts->get(ptBin, "mLambda")) || (std::abs(hfCandCascade.mAntiLambda() - o2::analysis::pdg::MassLambda0) < cuts->get(ptBin, "mLambda"))) { return false; // mass of the Lambda } - if (std::abs(hfCandCascade.mGamma() - RecoDecay::getMassPDG(kGamma)) < cuts->get(ptBin, "mGamma")) { + if (std::abs(hfCandCascade.mGamma() - o2::analysis::pdg::MassGamma) < cuts->get(ptBin, "mGamma")) { return false; // mass of the Gamma } @@ -132,20 +565,11 @@ struct HfCandidateSelectorLcToK0sP { template bool selectionStandardPID(const T& track) { - TrackSelectorPID selectorProton = TrackSelectorPID(kProton); if (track.p() < pPidThreshold) { - selectorProton.setRangeNSigmaTPC(-nSigmaTpcMaxLowP, nSigmaTpcMaxLowP); - selectorProton.setRangeNSigmaTOF(-nSigmaTofMaxLowP, nSigmaTofMaxLowP); - selectorProton.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMaxLowP, nSigmaTpcCombinedMaxLowP); - selectorProton.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMaxLowP, nSigmaTofCombinedMaxLowP); + return selectorProtonLowP.statusTpcAndTof(track) == TrackSelectorPID::Accepted; } else { - selectorProton.setRangeNSigmaTPC(-nSigmaTpcMaxHighP, nSigmaTpcMaxHighP); - selectorProton.setRangeNSigmaTOF(-nSigmaTofMaxHighP, nSigmaTofMaxHighP); - selectorProton.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMaxHighP, nSigmaTpcCombinedMaxHighP); - selectorProton.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMaxHighP, nSigmaTofCombinedMaxHighP); + return selectorProtonHighP.statusTpcAndTof(track) == TrackSelectorPID::Accepted; } - - return selectorProton.getStatusTrackPIDTpcAndTof(track) == TrackSelectorPID::Status::PIDAccepted; } template @@ -155,22 +579,38 @@ struct HfCandidateSelectorLcToK0sP { return false; } - TrackSelectorPID selectorProton = TrackSelectorPID(kProton); if (track.p() < pPidThreshold) { - selectorProton.setProbBayesMin(probBayesMinLowP); + return selectorProtonLowP.statusBayesProb(track) == TrackSelectorPID::Accepted; } else { - selectorProton.setProbBayesMin(probBayesMinHighP); + return selectorProtonHighP.statusBayesProb(track) == TrackSelectorPID::Accepted; + } + } + + template + bool selectionMl(const T& hfCandCascade, const U& bach) + { + + auto ptCand = hfCandCascade.pt(); + std::vector inputFeatures = setInputFeatures(hfCandCascade, bach); + std::vector outputMl = {}; + + bool isSelectedMl = hfMlResponse.isSelectedMl(inputFeatures, ptCand, outputMl); + + for (int classMl = 0; classMl < nClassesMl; classMl++) { + hModelScore[classMl]->Fill(outputMl[classMl]); + hModelScoreVsPtCand[classMl]->Fill(outputMl[classMl], ptCand); } - return selectorProton.getStatusTrackBayesProbPID(track) == TrackSelectorPID::Status::PIDAccepted; + return isSelectedMl; } - void processWithStandardPID(aod::HfCandCascade const& candidates, aod::BigTracksPID const& tracks) + void processWithStandardPID(aod::HfCandCascade const& candidates, + TracksSel const& tracks) { int statusLc = 0; // final selection flag : 0-rejected 1-accepted for (const auto& candidate : candidates) { // looping over cascade candidates - const auto& bach = candidate.prong0_as(); // bachelor track + const auto& bach = candidate.prong0_as(); // bachelor track statusLc = 0; @@ -186,6 +626,11 @@ struct HfCandidateSelectorLcToK0sP { continue; } + if (applyMl && !selectionMl(candidate, bach)) { + hfSelLcToK0sPCandidate(statusLc); + continue; + } + statusLc = 1; hfSelLcToK0sPCandidate(statusLc); @@ -193,12 +638,13 @@ struct HfCandidateSelectorLcToK0sP { } PROCESS_SWITCH(HfCandidateSelectorLcToK0sP, processWithStandardPID, "Use standard PID for bachelor track", true); - void processWithBayesPID(aod::HfCandCascade const& candidates, MyBigTracksBayes const& tracks) + void processWithBayesPID(aod::HfCandCascade const& candidates, + TracksSelBayes const& tracks) { int statusLc = 0; // final selection flag : 0-rejected 1-accepted for (const auto& candidate : candidates) { // looping over cascade candidates - const auto& bach = candidate.prong0_as(); // bachelor track + const auto& bach = candidate.prong0_as(); // bachelor track statusLc = 0; @@ -212,6 +658,11 @@ struct HfCandidateSelectorLcToK0sP { continue; } + if (applyMl && !selectionMl(candidate, bach)) { + hfSelLcToK0sPCandidate(statusLc); + continue; + } + statusLc = 1; hfSelLcToK0sPCandidate(statusLc); diff --git a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx index 8ed3cb5909a..aa04576dd9a 100644 --- a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx @@ -10,14 +10,15 @@ // or submit itself to any jurisdiction. /// \file candidateSelectorOmegac.cxx -/// \brief Omegac → Xi Pi selection task +/// \brief Xic and Omegac → Xi Pi selection task /// \author Federica Zanone , Heidelberg University & GSI -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectorPID.h" + #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -25,8 +26,13 @@ using namespace o2; using namespace o2::aod; using namespace o2::framework; using namespace o2::analysis::pdg; -using namespace o2::aod::hf_cand_toxipi; -using namespace o2::aod::hf_sel_toxipi; + +enum pidInfoStored { + kPiFromLam = 0, + kPrFromLam, + kPiFromCasc, + kPiFromCharm +}; /// Struct for applying Omegac selection cuts struct HfCandidateSelectorToXiPi { @@ -49,7 +55,8 @@ struct HfCandidateSelectorToXiPi { Configurable invMassOmegacMax{"invMassOmegacMax", 3.1, "Upper limit invariant mass spectrum charm baryon"}; // kinematic selections - Configurable etaTrackMax{"etaTrackMax", 0.8, "Max absolute value of eta"}; + Configurable etaTrackCharmBachMax{"etaTrackCharmBachMax", 0.8, "Max absolute value of eta for charm baryon bachelor"}; + Configurable etaTrackLFDauMax{"etaTrackLFDauMax", 1.0, "Max absolute value of eta for V0 and cascade daughters"}; Configurable ptPiFromCascMin{"ptPiFromCascMin", 0.15, "Min pT pi <- casc"}; Configurable ptPiFromOmeMin{"ptPiFromOmeMin", 0.2, "Min pT pi <- omegac"}; @@ -104,7 +111,10 @@ struct HfCandidateSelectorToXiPi { Configurable nClustersItsMin{"nClustersItsMin", 3, "Minimum number of ITS clusters requirement for pi <- Omegac"}; Configurable nClustersItsInnBarrMin{"nClustersItsInnBarrMin", 1, "Minimum number of ITS clusters in inner barrel requirement for pi <- Omegac"}; - using MyTrackInfo = aod::BigTracksPIDExtended; + TrackSelectorPi selectorPion; + TrackSelectorPr selectorProton; + + using TracksSel = soa::Join; HistogramRegistry registry{"registry"}; // for QA of selections @@ -113,6 +123,20 @@ struct HfCandidateSelectorToXiPi { void init(InitContext const&) { + selectorPion.setRangePtTpc(ptPiPidTpcMin, ptPiPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcPiMax, nSigmaTpcPiMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedPiMax, nSigmaTpcCombinedPiMax); + selectorPion.setRangePtTof(ptPiPidTofMin, ptPiPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofPiMax, nSigmaTofPiMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedPiMax, nSigmaTofCombinedPiMax); + + selectorProton.setRangePtTpc(ptPrPidTpcMin, ptPrPidTpcMax); + selectorProton.setRangeNSigmaTpc(-nSigmaTpcPrMax, nSigmaTpcPrMax); + selectorProton.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedPrMax, nSigmaTpcCombinedPrMax); + selectorProton.setRangePtTof(ptPrPidTofMin, ptPrPidTofMax); + selectorProton.setRangeNSigmaTof(-nSigmaTofPrMax, nSigmaTofPrMax); + selectorProton.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedPrMax, nSigmaTofCombinedPrMax); + registry.add("hSelPID", "hSelPID;status;entries", {HistType::kTH1F, {{12, 0., 12.}}}); registry.add("hTest", "Test status consecutive;status;entries", {HistType::kTH1F, {{12, 0., 12.}}}); @@ -151,38 +175,23 @@ struct HfCandidateSelectorToXiPi { registry.add("hSelMassOme", "hSelMassOme;status;entries", {HistType::kTH1F, {{5, 0., 5.}}}); } - void process(aod::HfCandToXiPi const& candidates, MyTrackInfo const&) + void process(aod::HfCandToXiPi const& candidates, + TracksSel const&) { - TrackSelectorPID selectorPion(kPiPlus); - selectorPion.setRangePtTPC(ptPiPidTpcMin, ptPiPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcPiMax, nSigmaTpcPiMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedPiMax, nSigmaTpcCombinedPiMax); - selectorPion.setRangePtTOF(ptPiPidTofMin, ptPiPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofPiMax, nSigmaTofPiMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedPiMax, nSigmaTofCombinedPiMax); - - TrackSelectorPID selectorProton(kProton); - selectorProton.setRangePtTPC(ptPrPidTpcMin, ptPrPidTpcMax); - selectorProton.setRangeNSigmaTPC(-nSigmaTpcPrMax, nSigmaTpcPrMax); - selectorProton.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedPrMax, nSigmaTpcCombinedPrMax); - selectorProton.setRangePtTOF(ptPrPidTofMin, ptPrPidTofMax); - selectorProton.setRangeNSigmaTOF(-nSigmaTofPrMax, nSigmaTofPrMax); - selectorProton.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedPrMax, nSigmaTofCombinedPrMax); - - double massLambdaFromPDG = RecoDecay::getMassPDG(kLambda0); - double massXiFromPDG = RecoDecay::getMassPDG(kXiMinus); + double massLambdaFromPDG = o2::analysis::pdg::MassLambda0; + double massXiFromPDG = o2::analysis::pdg::MassXiMinus; int collId = -999; // looping over omegac candidates - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { bool resultSelections = true; // True if the candidate passes all the selections, False otherwise - auto trackV0PosDau = candidate.posTrack_as(); // positive V0 daughter - auto trackV0NegDau = candidate.negTrack_as(); // negative V0 daughter - auto trackPiFromCasc = candidate.bachelor_as(); // pion <- cascade - auto trackPiFromOmeg = candidate.primaryPi_as(); // pion <- omegac + auto trackV0PosDau = candidate.posTrack_as(); // positive V0 daughter + auto trackV0NegDau = candidate.negTrack_as(); // negative V0 daughter + auto trackPiFromCasc = candidate.bachelor_as(); // pion <- cascade + auto trackPiFromOmeg = candidate.primaryPi_as(); // pion <- omegac auto trackPiFromLam = trackV0NegDau; auto trackPrFromLam = trackV0PosDau; @@ -205,25 +214,25 @@ struct HfCandidateSelectorToXiPi { double etaV0NegDau = candidate.etaV0NegDau(); double etaPiFromCasc = candidate.etaPiFromCasc(); double etaPiFromOme = candidate.etaPiFromOme(); - if (std::abs(etaV0PosDau) > etaTrackMax) { + if (std::abs(etaV0PosDau) > etaTrackLFDauMax) { resultSelections = false; registry.fill(HIST("hSelEtaPosV0Dau"), 0); } else { registry.fill(HIST("hSelEtaPosV0Dau"), 1); } - if (std::abs(etaV0NegDau) > etaTrackMax) { + if (std::abs(etaV0NegDau) > etaTrackLFDauMax) { resultSelections = false; registry.fill(HIST("hSelEtaNegV0Dau"), 0); } else { registry.fill(HIST("hSelEtaNegV0Dau"), 1); } - if (std::abs(etaPiFromCasc) > etaTrackMax) { + if (std::abs(etaPiFromCasc) > etaTrackLFDauMax) { resultSelections = false; registry.fill(HIST("hSelEtaPiFromCasc"), 0); } else { registry.fill(HIST("hSelEtaPiFromCasc"), 1); } - if (std::abs(etaPiFromOme) > etaTrackMax) { + if (std::abs(etaPiFromOme) > etaTrackCharmBachMax) { resultSelections = false; registry.fill(HIST("hSelEtaPiFromOme"), 0); } else { @@ -418,45 +427,77 @@ struct HfCandidateSelectorToXiPi { } // track-level PID selection - int pidProton = -999; - int pidPiFromLam = -999; - int pidPiFromCasc = -999; - int pidPiFromOme = -999; + + // for TrackSelectorPID + int statusPidPrFromLam = -999; + int statusPidPiFromLam = -999; + int statusPidPiFromCasc = -999; + int statusPidPiFromCharm = -999; + + bool statusPidLambda = false; + bool statusPidCascade = false; + bool statusPidCharm = false; + + int infoTpcStored = 0; + int infoTofStored = 0; + if (usePidTpcOnly == usePidTpcTofCombined) { LOGF(fatal, "Check the PID configurables, usePidTpcOnly and usePidTpcTofCombined can't have the same value"); } + + if (trackPiFromLam.hasTPC()) { + SETBIT(infoTpcStored, kPiFromLam); + } + if (trackPrFromLam.hasTPC()) { + SETBIT(infoTpcStored, kPrFromLam); + } + if (trackPiFromCasc.hasTPC()) { + SETBIT(infoTpcStored, kPiFromCasc); + } + if (trackPiFromOmeg.hasTPC()) { + SETBIT(infoTpcStored, kPiFromCharm); + } + if (trackPiFromLam.hasTOF()) { + SETBIT(infoTofStored, kPiFromLam); + } + if (trackPrFromLam.hasTOF()) { + SETBIT(infoTofStored, kPrFromLam); + } + if (trackPiFromCasc.hasTOF()) { + SETBIT(infoTofStored, kPiFromCasc); + } + if (trackPiFromOmeg.hasTOF()) { + SETBIT(infoTofStored, kPiFromCharm); + } + if (usePidTpcOnly) { - pidProton = selectorProton.getStatusTrackPIDTPC(trackPrFromLam); - pidPiFromLam = selectorPion.getStatusTrackPIDTPC(trackPiFromLam); - pidPiFromCasc = selectorPion.getStatusTrackPIDTPC(trackPiFromCasc); - pidPiFromOme = selectorPion.getStatusTrackPIDTPC(trackPiFromOmeg); + statusPidPrFromLam = selectorProton.statusTpc(trackPrFromLam); + statusPidPiFromLam = selectorPion.statusTpc(trackPiFromLam); + statusPidPiFromCasc = selectorPion.statusTpc(trackPiFromCasc); + statusPidPiFromCharm = selectorPion.statusTpc(trackPiFromOmeg); } else if (usePidTpcTofCombined) { - pidProton = selectorProton.getStatusTrackPIDTpcAndTof(trackPrFromLam); - pidPiFromLam = selectorPion.getStatusTrackPIDTpcAndTof(trackPiFromLam); - pidPiFromCasc = selectorPion.getStatusTrackPIDTpcAndTof(trackPiFromCasc); - pidPiFromOme = selectorPion.getStatusTrackPIDTpcAndTof(trackPiFromOmeg); + statusPidPrFromLam = selectorProton.statusTpcAndTof(trackPrFromLam); + statusPidPiFromLam = selectorPion.statusTpcAndTof(trackPiFromLam); + statusPidPiFromCasc = selectorPion.statusTpcAndTof(trackPiFromCasc); + statusPidPiFromCharm = selectorPion.statusTpcAndTof(trackPiFromOmeg); } - bool statusPidLambda = false; - bool statusPidCascade = false; - bool statusPidOmegac = false; - - if (pidProton == TrackSelectorPID::Status::PIDAccepted && pidPiFromLam == TrackSelectorPID::Status::PIDAccepted) { + if (statusPidPrFromLam == TrackSelectorPID::Accepted && statusPidPiFromLam == TrackSelectorPID::Accepted) { statusPidLambda = true; if (resultSelections) { registry.fill(HIST("hTest"), 0.5); } } - if (pidProton == TrackSelectorPID::Status::PIDAccepted && pidPiFromLam == TrackSelectorPID::Status::PIDAccepted && pidPiFromCasc == TrackSelectorPID::Status::PIDAccepted) { + if (statusPidPrFromLam == TrackSelectorPID::Accepted && statusPidPiFromLam == TrackSelectorPID::Accepted && statusPidPiFromCasc == TrackSelectorPID::Accepted) { statusPidCascade = true; if (resultSelections) { registry.fill(HIST("hTest"), 1.5); } } - if (pidProton == TrackSelectorPID::Status::PIDAccepted && pidPiFromLam == TrackSelectorPID::Status::PIDAccepted && pidPiFromCasc == TrackSelectorPID::Status::PIDAccepted && pidPiFromOme == TrackSelectorPID::Status::PIDAccepted) { - statusPidOmegac = true; + if (statusPidPrFromLam == TrackSelectorPID::Accepted && statusPidPiFromLam == TrackSelectorPID::Accepted && statusPidPiFromCasc == TrackSelectorPID::Accepted && statusPidPiFromCharm == TrackSelectorPID::Accepted) { + statusPidCharm = true; if (resultSelections) { registry.fill(HIST("hTest"), 2.5); } @@ -474,7 +515,7 @@ struct HfCandidateSelectorToXiPi { if (std::abs(invMassLambda - massLambdaFromPDG) < (nSigmaInvMassCut * sigmaInvMassLambda)) { statusInvMassLambda = true; registry.fill(HIST("hSelMassLam"), 1); - if (statusPidLambda && statusPidCascade && statusPidOmegac && resultSelections) { + if (statusPidLambda && statusPidCascade && statusPidCharm && resultSelections) { registry.fill(HIST("hTest"), 3.5); } } else { @@ -484,7 +525,7 @@ struct HfCandidateSelectorToXiPi { if (std::abs(invMassCascade - massXiFromPDG) < (nSigmaInvMassCut * sigmaInvMassCascade)) { statusInvMassCascade = true; registry.fill(HIST("hSelMassCasc"), 1); - if (statusPidLambda && statusPidCascade && statusPidOmegac && statusInvMassLambda && resultSelections) { + if (statusPidLambda && statusPidCascade && statusPidCharm && statusInvMassLambda && resultSelections) { registry.fill(HIST("hTest"), 4.5); } } else { @@ -494,14 +535,14 @@ struct HfCandidateSelectorToXiPi { if ((invMassOmegac >= invMassOmegacMin) && (invMassOmegac <= invMassOmegacMax)) { statusInvMassOmegac = true; registry.fill(HIST("hSelMassOme"), 1); - if (statusPidLambda && statusPidCascade && statusPidOmegac && statusInvMassLambda && statusInvMassCascade && resultSelections) { + if (statusPidLambda && statusPidCascade && statusPidCharm && statusInvMassLambda && statusInvMassCascade && resultSelections) { registry.fill(HIST("hTest"), 5.5); } } else { registry.fill(HIST("hSelMassOme"), 0); } - hfSelToXiPi(statusPidLambda, statusPidCascade, statusPidOmegac, statusInvMassLambda, statusInvMassCascade, statusInvMassOmegac, resultSelections, + hfSelToXiPi(statusPidLambda, statusPidCascade, statusPidCharm, statusInvMassLambda, statusInvMassCascade, statusInvMassOmegac, resultSelections, infoTpcStored, infoTofStored, trackPiFromOmeg.tpcNSigmaPi(), trackPiFromCasc.tpcNSigmaPi(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(), trackPiFromOmeg.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); @@ -518,10 +559,10 @@ struct HfCandidateSelectorToXiPi { if (statusPidCascade) { registry.fill(HIST("hSelPID"), 3.5); } - if (!statusPidOmegac) { + if (!statusPidCharm) { registry.fill(HIST("hSelPID"), 4.5); } - if (statusPidOmegac) { + if (statusPidCharm) { registry.fill(HIST("hSelPID"), 5.5); } if (!statusInvMassLambda) { @@ -544,12 +585,12 @@ struct HfCandidateSelectorToXiPi { } } - if (statusPidLambda && statusPidCascade && statusPidOmegac && statusInvMassLambda && statusInvMassCascade && statusInvMassOmegac && resultSelections) { + if (statusPidLambda && statusPidCascade && statusPidCharm && statusInvMassLambda && statusInvMassCascade && statusInvMassOmegac && resultSelections) { hInvMassOmegac->Fill(invMassOmegac); if (candidate.collisionId() != collId) { hNEventsSaved->Fill(0.5); - collId = trackPiFromCasc.collisionId(); + collId = candidate.collisionId(); } } } diff --git a/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx index a4dac9eeb51..0b66480b35b 100644 --- a/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx @@ -16,17 +16,18 @@ /// \author Mattia Faggin , University and INFN PADOVA /// \author Vít Kučera , CERN -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_xic_to_p_k_pi; /// Struct for applying Xic selection cuts struct HfCandidateSelectorXicToPKPi { @@ -48,22 +49,26 @@ struct HfCandidateSelectorXicToPKPi { // topological cuts Configurable decayLengthXYNormalisedMin{"decayLengthXYNormalisedMin", 3., "Min. normalised decay length XY"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_p_k_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_xic_to_p_k_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Xic candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_xic_to_p_k_pi::cuts[0], hf_cuts_xic_to_p_k_pi::nBinsPt, hf_cuts_xic_to_p_k_pi::nCutVars, hf_cuts_xic_to_p_k_pi::labelsPt, hf_cuts_xic_to_p_k_pi::labelsCutVar}, "Xic candidate selection per pT bin"}; - /* - /// Selection on goodness of daughter tracks - /// \note should be applied at candidate selection - /// \param track is daughter track - /// \return true if track is good - template - bool daughterSelection(const T& track) + HfHelper hfHelper; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + TrackSelectorPr selectorProton; + + using TracksSel = soa::Join; + + void init(InitContext const&) { - if (track.tpcNClsFound() == 0) { - return false; //is it clusters findable or found - need to check - } - return true; + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + selectorKaon = selectorPion; + selectorProton = selectorPion; } - */ /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -113,7 +118,7 @@ struct HfCandidateSelectorXicToPKPi { } // candidate ct - if (ctXic(candidate) > cuts->get(pTBin, "ct")) { + if (hfHelper.ctXic(candidate) > cuts->get(pTBin, "ct")) { return false; } @@ -147,11 +152,11 @@ struct HfCandidateSelectorXicToPKPi { } if (trackProton.globalIndex() == candidate.prong0Id()) { - if (std::abs(invMassXicToPKPi(candidate) - RecoDecay::getMassPDG(pdg::Code::kXiCPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassXicToPKPi(candidate) - o2::analysis::pdg::MassXiCPlus) > cuts->get(pTBin, "m")) { return false; } } else { - if (std::abs(invMassXicToPiKP(candidate) - RecoDecay::getMassPDG(pdg::Code::kXiCPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassXicToPiKP(candidate) - o2::analysis::pdg::MassXiCPlus) > cuts->get(pTBin, "m")) { return false; } } @@ -159,45 +164,24 @@ struct HfCandidateSelectorXicToPKPi { return true; } - void process(aod::HfCand3Prong const& candidates, aod::BigTracksPID const&) + void process(aod::HfCand3Prong const& candidates, + TracksSel const&) { - TrackSelectorPID selectorPion(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - - TrackSelectorPID selectorKaon(selectorPion); - selectorKaon.setPDG(kKPlus); - - TrackSelectorPID selectorProton(selectorPion); - selectorProton.setPDG(kProton); - // looping over 3-prong candidates - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { // final selection flag: 0 - rejected, 1 - accepted auto statusXicToPKPi = 0; auto statusXicToPiKP = 0; - if (!(candidate.hfflag() & 1 << DecayType::XicToPKPi)) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::XicToPKPi)) { hfSelXicToPKPiCandidate(statusXicToPKPi, statusXicToPiKP); continue; } - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) - - /* - // daughter track validity selection - if (!daughterSelection(trackPos1) || !daughterSelection(trackNeg) || !daughterSelection(trackPos2)) { - hfSelXicToPKPiCandidate(statusXicToPKPi, statusXicToPiKP); - continue; - } - */ + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) // implement filter bit 4 cut - should be done before this task at the track selection level @@ -226,28 +210,28 @@ struct HfCandidateSelectorXicToPKPi { pidXicToPiKP = 1; } else { // track-level PID selection - auto pidTrackPos1Proton = selectorProton.getStatusTrackPIDTpcOrTof(trackPos1); - auto pidTrackPos2Proton = selectorProton.getStatusTrackPIDTpcOrTof(trackPos2); - auto pidTrackPos1Pion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos1); - auto pidTrackPos2Pion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos2); - auto pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackNeg); - - if (pidTrackPos1Proton == TrackSelectorPID::Status::PIDAccepted && - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidTrackPos2Pion == TrackSelectorPID::Status::PIDAccepted) { + auto pidTrackPos1Proton = selectorProton.statusTpcOrTof(trackPos1); + auto pidTrackPos2Proton = selectorProton.statusTpcOrTof(trackPos2); + auto pidTrackPos1Pion = selectorPion.statusTpcOrTof(trackPos1); + auto pidTrackPos2Pion = selectorPion.statusTpcOrTof(trackPos2); + auto pidTrackNegKaon = selectorKaon.statusTpcOrTof(trackNeg); + + if (pidTrackPos1Proton == TrackSelectorPID::Accepted && + pidTrackNegKaon == TrackSelectorPID::Accepted && + pidTrackPos2Pion == TrackSelectorPID::Accepted) { pidXicToPKPi = 1; // accept XicpKpi - } else if (pidTrackPos1Proton == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Pion == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackPos1Proton == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Pion == TrackSelectorPID::Rejected) { pidXicToPKPi = 0; // exclude XicpKpi } - if (pidTrackPos2Proton == TrackSelectorPID::Status::PIDAccepted && - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted && - pidTrackPos1Pion == TrackSelectorPID::Status::PIDAccepted) { + if (pidTrackPos2Proton == TrackSelectorPID::Accepted && + pidTrackNegKaon == TrackSelectorPID::Accepted && + pidTrackPos1Pion == TrackSelectorPID::Accepted) { pidXicToPiKP = 1; // accept XicpiKp - } else if (pidTrackPos1Pion == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackPos2Proton == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackPos1Pion == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackPos2Proton == TrackSelectorPID::Rejected) { pidXicToPiKP = 0; // exclude XicpiKp } } diff --git a/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx b/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx index 9d3b890c2e7..f2d12003403 100644 --- a/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx @@ -14,18 +14,18 @@ /// /// \author Gian Michele Innocenti , CERN -#include "Common/Core/TrackSelectorPID.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/TrackSelectorPID.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; -// using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_xicc; -using namespace o2::analysis::hf_cuts_xicc_to_p_k_pi_pi; /// Struct for applying Xicc selection cuts struct HfCandidateSelectorXiccToPKPiPi { @@ -46,7 +46,22 @@ struct HfCandidateSelectorXiccToPKPiPi { Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_xicc_to_p_k_pi_pi::vecBinsPt}, "pT bin limits"}; - Configurable> cuts{"cuts", {hf_cuts_xicc_to_p_k_pi_pi::cuts[0], nBinsPt, nCutVars, labelsPt, labelsCutVar}, "Xicc candidate selection per pT bin"}; + Configurable> cuts{"cuts", {hf_cuts_xicc_to_p_k_pi_pi::cuts[0], hf_cuts_xicc_to_p_k_pi_pi::nBinsPt, hf_cuts_xicc_to_p_k_pi_pi::nCutVars, hf_cuts_xicc_to_p_k_pi_pi::labelsPt, hf_cuts_xicc_to_p_k_pi_pi::labelsCutVar}, "Xicc candidate selection per pT bin"}; + + HfHelper hfHelper; + TrackSelectorPi selectorPion; + + using TracksSel = soa::Join; + + void init(InitContext const&) + { + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorPion.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorPion.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorPion.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + } /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -66,7 +81,7 @@ struct HfCandidateSelectorXiccToPKPiPi { } // check candidate mass is within a defined mass window - if (std::abs(invMassXiccToXicPi(hfCandXicc) - RecoDecay::getMassPDG(pdg::Code::kXiCCPlusPlus)) > cuts->get(pTBin, "m")) { + if (std::abs(hfHelper.invMassXiccToXicPi(hfCandXicc) - o2::analysis::pdg::MassXiCCPlusPlus) > cuts->get(pTBin, "m")) { return false; } @@ -125,24 +140,18 @@ struct HfCandidateSelectorXiccToPKPiPi { return true; } - void process(aod::HfCandXicc const& hfCandXiccs, aod::HfCand3Prong const&, aod::BigTracksPID const&) + void process(aod::HfCandXicc const& hfCandXiccs, + aod::HfCand3Prong const&, + TracksSel const&) { - TrackSelectorPID selectorPion(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpcMax, nSigmaTpcMax); - selectorPion.setRangeNSigmaTPCCondTOF(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); - selectorPion.setRangePtTOF(ptPidTofMin, ptPidTofMax); - selectorPion.setRangeNSigmaTOF(-nSigmaTofMax, nSigmaTofMax); - selectorPion.setRangeNSigmaTOFCondTPC(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); - // looping over 3-prong candidates - for (auto& hfCandXicc : hfCandXiccs) { + for (const auto& hfCandXicc : hfCandXiccs) { auto hfCandXic = hfCandXicc.prong0(); - auto trackPi = hfCandXicc.prong1_as(); + auto trackPi = hfCandXicc.prong1_as(); // final selection flag: 0 - rejected, 1 - accepted auto statusXiccToPKPiPi = 0; - if (!(hfCandXicc.hfflag() & 1 << DecayType::XiccToXicPi)) { + if (!(hfCandXicc.hfflag() & 1 << aod::hf_cand_xicc::DecayType::XiccToXicPi)) { hfSelXiccToPKPiPiCandidate(statusXiccToPKPiPi); continue; } @@ -160,8 +169,8 @@ struct HfCandidateSelectorXiccToPKPiPi { pidPi = 1; } else { // track-level PID selection - int pidPion = selectorPion.getStatusTrackPIDTpcOrTof(trackPi); - if (pidPion == TrackSelectorPID::Status::PIDAccepted) { + int pidPion = selectorPion.statusTpcOrTof(trackPi); + if (pidPion == TrackSelectorPID::Accepted) { pidPi = 1; } } diff --git a/PWGHF/TableProducer/refitPvDummy.cxx b/PWGHF/TableProducer/refitPvDummy.cxx index 62ebe54de23..64b13f2d5cb 100644 --- a/PWGHF/TableProducer/refitPvDummy.cxx +++ b/PWGHF/TableProducer/refitPvDummy.cxx @@ -14,14 +14,16 @@ /// /// \author Mattia Faggin , University and INFN Padova, Italy -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" +#include "Common/Core/trackUtilities.h" + #include "PWGHF/DataModel/CandidateReconstructionTables.h" +using namespace o2; using namespace o2::framework; struct HfRefitPvDummy { diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index c913828ac58..6380be9b194 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -19,41 +19,47 @@ /// \author Jinjoo Seo , Inha University /// \author Fabrizio Grosa , CERN -#include +#include // std::find +#include // std::distance +#include // std::string +#include // std::vector -#include "CCDB/BasicCCDBManager.h" // for PV refit -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "CCDB/BasicCCDBManager.h" // for PV refit #include "DataFormatsParameters/GRPMagField.h" // for PV refit #include "DataFormatsParameters/GRPObject.h" // for PV refit #include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" // for PV refit -#include "DetectorsVertexing/PVertexer.h" // for PV refit +#include "DetectorsBase/Propagator.h" // for PV refit +#include "DetectorsVertexing/PVertexer.h" // for PV refit #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/V0.h" #include "ReconstructionDataFormats/Vertex.h" // for PV refit +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsDebugLcToK0sP.h" using namespace o2; +using namespace o2::analysis; +using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod; -using namespace o2::analysis::hf_cuts_single_track; // enum for candidate type enum CandidateType { Cand2Prong = 0, Cand3Prong, CandV0bachelor, + CandDstar, NCandidateTypes }; @@ -68,22 +74,16 @@ enum EventRejection { NEventRejection }; -static const double massPi = RecoDecay::getMassPDG(kPiPlus); -static const double massK = RecoDecay::getMassPDG(kKPlus); -static const double massProton = RecoDecay::getMassPDG(kProton); -static const double massElectron = RecoDecay::getMassPDG(kElectron); -static const double massMuon = RecoDecay::getMassPDG(kMuonPlus); - // #define MY_DEBUG #ifdef MY_DEBUG -using TracksWithSelAndDCA = soa::Join; +using TracksWithSelAndDCA = soa::Join; #define MY_DEBUG_MSG(condition, cmd) \ if (condition) { \ cmd; \ } #else -using TracksWithSelAndDCA = soa::Join; +using TracksWithSelAndDCA = soa::Join; #define MY_DEBUG_MSG(condition, cmd) #endif @@ -131,9 +131,9 @@ struct HfTrackIndexSkimCreatorTagSelCollisions { } // primary vertex histograms registry.add("hNContributors", "Number of PV contributors;entries", {HistType::kTH1F, {axisNumContributors}}); - registry.add("hPrimVtxX", "selected events;#it{x}_{prim. vtx.} (cm);entries", {HistType::kTH1F, {{400, -0.5, 0.5}}}); - registry.add("hPrimVtxY", "selected events;#it{y}_{prim. vtx.} (cm);entries", {HistType::kTH1F, {{400, -0.5, 0.5}}}); - registry.add("hPrimVtxZ", "selected events;#it{z}_{prim. vtx.} (cm);entries", {HistType::kTH1F, {{400, -20., 20.}}}); + registry.add("hPrimVtxX", "selected events;#it{x}_{prim. vtx.} (cm);entries", {HistType::kTH1F, {{200, -0.5, 0.5}}}); + registry.add("hPrimVtxY", "selected events;#it{y}_{prim. vtx.} (cm);entries", {HistType::kTH1F, {{200, -0.5, 0.5}}}); + registry.add("hPrimVtxZ", "selected events;#it{z}_{prim. vtx.} (cm);entries", {HistType::kTH1F, {{200, -20., 20.}}}); } } @@ -258,7 +258,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; Configurable doPvRefit{"doPvRefit", false, "do PV refit excluding the considered track"}; Configurable fillHistograms{"fillHistograms", true, "fill histograms"}; - Configurable debug{"debug", true, "debug mode"}; + Configurable debugPvRefit{"debugPvRefit", false, "debug lines for primary vertex refit"}; // Configurable bz{"bz", 5., "bz field"}; // quality cut Configurable doCutQuality{"doCutQuality", true, "apply quality cuts"}; @@ -269,19 +269,28 @@ struct HfTrackIndexSkimCreatorTagSelTracks { Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for 2-prong DCA XY pT-dependent cut"}; // 2-prong cuts Configurable ptMinTrack2Prong{"ptMinTrack2Prong", -1., "min. track pT for 2 prong candidate"}; - Configurable> cutsTrack2Prong{"cutsTrack2Prong", {hf_cuts_single_track::cutsTrack[0], nBinsPtTrack, nCutVarsTrack, labelsPtTrack, labelsCutVarTrack}, "Single-track selections per pT bin for 2-prong candidates"}; + Configurable> cutsTrack2Prong{"cutsTrack2Prong", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for 2-prong candidates"}; Configurable etaMinTrack2Prong{"etaMinTrack2Prong", -99999., "min. pseudorapidity for 2 prong candidate"}; Configurable etaMaxTrack2Prong{"etaMaxTrack2Prong", 4., "max. pseudorapidity for 2 prong candidate"}; // 3-prong cuts Configurable ptMinTrack3Prong{"ptMinTrack3Prong", -1., "min. track pT for 3 prong candidate"}; - Configurable> cutsTrack3Prong{"cutsTrack3Prong", {hf_cuts_single_track::cutsTrack[0], nBinsPtTrack, nCutVarsTrack, labelsPtTrack, labelsCutVarTrack}, "Single-track selections per pT bin for 3-prong candidates"}; + Configurable> cutsTrack3Prong{"cutsTrack3Prong", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for 3-prong candidates"}; Configurable etaMinTrack3Prong{"etaMinTrack3Prong", -99999., "min. pseudorapidity for 3 prong candidate"}; Configurable etaMaxTrack3Prong{"etaMaxTrack3Prong", 4., "max. pseudorapidity for 3 prong candidate"}; // bachelor cuts (when using cascades) Configurable ptMinTrackBach{"ptMinTrackBach", 0.3, "min. track pT for bachelor in cascade candidate"}; // 0.5 for PbPb 2015? - Configurable> cutsTrackBach{"cutsTrackBach", {hf_cuts_single_track::cutsTrack[0], nBinsPtTrack, nCutVarsTrack, labelsPtTrack, labelsCutVarTrack}, "Single-track selections per pT bin for the bachelor of V0-bachelor candidates"}; + Configurable> cutsTrackBach{"cutsTrackBach", {hf_cuts_single_track::cutsTrack[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for the bachelor of V0-bachelor candidates"}; Configurable etaMinTrackBach{"etaMinTrackBach", -99999., "min. pseudorapidity for bachelor in cascade candidate"}; Configurable etaMaxTrackBach{"etaMaxTrackBach", 0.8, "max. pseudorapidity for bachelor in cascade candidate"}; + // soft pion cuts for D* + Configurable ptMinSoftPionForDstar{"ptMinSoftPionForDstar", 0.05, "min. track pT for soft pion in D* candidate"}; + Configurable ptMaxSoftPionForDstar{"ptMaxSoftPionForDstar", 2., "max. track pT for soft pion in D* candidate"}; + Configurable etaMinSoftPionForDstar{"etaMinSoftPionForDstar", -99999., "min. pseudorapidity for soft pion in D* candidate"}; + Configurable etaMaxSoftPionForDstar{"etaMaxSoftPionForDstar", 0.8, "max. pseudorapidity for soft pion in D* candidate"}; + Configurable> cutsTrackDstar{"cutsTrackDstar", {hf_cuts_single_track::cutsTrackPrimary[0], hf_cuts_single_track::nBinsPtTrack, hf_cuts_single_track::nCutVarsTrack, hf_cuts_single_track::labelsPtTrack, hf_cuts_single_track::labelsCutVarTrack}, "Single-track selections per pT bin for the soft pion of D* candidates"}; + Configurable useIsGlobalTrackForSoftPion{"useIsGlobalTrackForSoftPion", false, "check isGlobalTrack status for soft pion tracks"}; + Configurable useIsGlobalTrackWoDCAForSoftPion{"useIsGlobalTrackWoDCAForSoftPion", false, "check isGlobalTrackWoDCA status for soft pion tracks"}; + Configurable useIsQualityTrackITSForSoftPion{"useIsQualityTrackITSForSoftPion", true, "check qualityTracksITS status for soft pion tracks"}; // CCDB Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; @@ -303,7 +312,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { // single-track cuts static const int nCuts = 4; // array of 2-prong and 3-prong cuts - std::array, 3> cutsSingleTrack; + std::array, CandidateType::NCandidateTypes> cutsSingleTrack; // QA of PV refit ConfigurableAxis axisPvRefitDeltaX{"axisPvRefitDeltaX", {1000, -0.5f, 0.5f}, "DeltaX binning PV refit"}; @@ -314,7 +323,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { void init(InitContext const&) { - cutsSingleTrack = {cutsTrack2Prong, cutsTrack3Prong, cutsTrackBach}; + cutsSingleTrack = {cutsTrack2Prong, cutsTrack3Prong, cutsTrackBach, cutsTrackDstar}; if (etaMinTrack2Prong == -99999.) { etaMinTrack2Prong.value = -etaMaxTrack2Prong; @@ -325,10 +334,13 @@ struct HfTrackIndexSkimCreatorTagSelTracks { if (etaMinTrackBach == -99999.) { etaMinTrackBach.value = -etaMaxTrackBach; } + if (etaMinSoftPionForDstar == -99999.) { + etaMinSoftPionForDstar.value = -etaMaxSoftPionForDstar; + } if (fillHistograms) { // general tracks - registry.add("hRejTracks", "Tracks;;entries", {HistType::kTH1F, {{15, 0.5, 15.5}}}); + registry.add("hRejTracks", "Tracks;;entries", {HistType::kTH1F, {{20, 0.5, 20.5}}}); registry.add("hPtNoCuts", "all tracks;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); // 2-prong histograms @@ -340,12 +352,16 @@ struct HfTrackIndexSkimCreatorTagSelTracks { registry.add("hDCAToPrimXYVsPtCuts3Prong", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2F, {{360, 0., 36.}, {400, -2., 2.}}}); registry.add("hEtaCuts3Prong", "tracks selected for 3-prong vertexing;#it{#eta};entries", {HistType::kTH1F, {{static_cast(0.6 * (etaMaxTrack3Prong - etaMinTrack3Prong) * 100), -1.2 * etaMinTrack3Prong, 1.2 * etaMaxTrack3Prong}}}); // bachelor (for cascades) histograms - registry.add("hPtCutsV0bachelor", "tracks selected for 3-prong vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); + registry.add("hPtCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); registry.add("hDCAToPrimXYVsPtCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2F, {{360, 0., 36.}, {400, -2., 2.}}}); - registry.add("hEtaCutsV0bachelor", "tracks selected for 3-prong vertexing;#it{#eta};entries", {HistType::kTH1F, {{static_cast(0.6 * (etaMaxTrackBach - etaMinTrackBach) * 100), -1.2 * etaMinTrackBach, 1.2 * etaMaxTrackBach}}}); + registry.add("hEtaCutsV0bachelor", "tracks selected for V0-bachelor vertexing;#it{#eta};entries", {HistType::kTH1F, {{static_cast(0.6 * (etaMaxTrackBach - etaMinTrackBach) * 100), -1.2 * etaMinTrackBach, 1.2 * etaMaxTrackBach}}}); + // soft pion (for D*) histograms + registry.add("hPtCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{p}_{T}^{track} (GeV/#it{c});entries", {HistType::kTH1F, {{360, 0., 36.}}}); + registry.add("hDCAToPrimXYVsPtCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{p}_{T}^{track} (GeV/#it{c});DCAxy to prim. vtx. (cm);entries", {HistType::kTH2F, {{360, 0., 36.}, {400, -2., 2.}}}); + registry.add("hEtaCutsSoftPionForDstar", "tracks selected for D* soft pion;#it{#eta};entries", {HistType::kTH1F, {{static_cast(0.6 * (etaMaxSoftPionForDstar - etaMinSoftPionForDstar) * 100), -1.2 * etaMinSoftPionForDstar, 1.2 * etaMaxSoftPionForDstar}}}); std::string cutNames[nCuts + 1] = {"selected", "rej pT", "rej eta", "rej track quality", "rej dca"}; - std::string candNames[CandidateType::NCandidateTypes] = {"2-prong", "3-prong", "bachelor"}; + std::string candNames[CandidateType::NCandidateTypes] = {"2-prong", "3-prong", "bachelor", "dstar"}; for (int iCandType = 0; iCandType < CandidateType::NCandidateTypes; iCandType++) { for (int iCut = 0; iCut < nCuts + 1; iCut++) { registry.get(HIST("hRejTracks"))->GetXaxis()->SetBinLabel((nCuts + 1) * iCandType + iCut + 1, Form("%s %s", candNames[iCandType].data(), cutNames[iCut].data())); @@ -359,9 +375,9 @@ struct HfTrackIndexSkimCreatorTagSelTracks { AxisSpec axisCollisionX{100, -20.f, 20.f, "X (cm)"}; AxisSpec axisCollisionY{100, -20.f, 20.f, "Y (cm)"}; AxisSpec axisCollisionZ{100, -20.f, 20.f, "Z (cm)"}; - AxisSpec axisCollisionXOriginal{1000, -20.f, 20.f, "X original PV (cm)"}; - AxisSpec axisCollisionYOriginal{1000, -20.f, 20.f, "Y original PV (cm)"}; - AxisSpec axisCollisionZOriginal{1000, -20.f, 20.f, "Z original PV (cm)"}; + AxisSpec axisCollisionXOriginal{100, -2.f, 2.f, "X original PV (cm)"}; + AxisSpec axisCollisionYOriginal{100, -2.f, 2.f, "Y original PV (cm)"}; + AxisSpec axisCollisionZOriginal{100, -2.f, 2.f, "Z original PV (cm)"}; AxisSpec axisCollisionNContrib{1000, 0, 1000, "Number of contributors"}; AxisSpec axisCollisionDeltaX{axisPvRefitDeltaX, "#Delta x_{PV} (cm)"}; AxisSpec axisCollisionDeltaY{axisPvRefitDeltaY, "#Delta y_{PV} (cm)"}; @@ -396,7 +412,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { /// \param dca is a 2-element array with dca in transverse and longitudinal directions /// \param candType is the flag to decide which cuts to be applied (either for 2-prong, 3-prong, or cascade decays) /// \return true if track passes all cuts - bool isSelectedTrackDCA(const float& trackPt, const array& dca, const int candType) + bool isSelectedTrackDCA(const float& trackPt, const std::array& dca, const int candType) { auto pTBinTrack = findBin(binsPtTrack, trackPt); if (pTBinTrack == -1) { @@ -425,133 +441,138 @@ struct HfTrackIndexSkimCreatorTagSelTracks { registry.fill(HIST("hPtNoCuts"), trackPt); } - int iDebugCut = 2; + int iCut{2}; // pT cut if (trackPt < ptMinTrack2Prong) { CLRBIT(statusProng, CandidateType::Cand2Prong); // set the nth bit to 0 - if (debug) { - // cutStatus[CandidateType::Cand2Prong][0] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand2Prong + iDebugCut); - } + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand2Prong + iCut); } } if (trackPt < ptMinTrack3Prong) { CLRBIT(statusProng, CandidateType::Cand3Prong); - if (debug) { - // cutStatus[CandidateType::Cand3Prong][0] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand3Prong + iDebugCut); - } + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand3Prong + iCut); } } MY_DEBUG_MSG(isProtonFromLc, LOG(info) << "proton " << indexBach << " pt = " << trackPt << " (cut " << ptMinTrackBach << ")"); if (trackPt < ptMinTrackBach) { CLRBIT(statusProng, CandidateType::CandV0bachelor); - if (debug) { - // cutStatus[CandidateType::CandV0bachelor][0] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandV0bachelor + iDebugCut); - } + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandV0bachelor + iCut); + } + } + if (trackPt < ptMinSoftPionForDstar || trackPt > ptMaxSoftPionForDstar) { + CLRBIT(statusProng, CandidateType::CandDstar); + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandDstar + iCut); } } - iDebugCut = 3; + iCut = 3; // eta cut - if ((debug || TESTBIT(statusProng, CandidateType::Cand2Prong)) && (trackEta > etaMaxTrack2Prong || trackEta < etaMinTrack2Prong)) { + if (TESTBIT(statusProng, CandidateType::Cand2Prong) && (trackEta > etaMaxTrack2Prong || trackEta < etaMinTrack2Prong)) { CLRBIT(statusProng, CandidateType::Cand2Prong); - if (debug) { - // cutStatus[CandidateType::Cand2Prong][1] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand2Prong + iDebugCut); - } + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand2Prong + iCut); } } - if ((debug || TESTBIT(statusProng, CandidateType::Cand3Prong)) && (trackEta > etaMaxTrack3Prong || trackEta < etaMinTrack3Prong)) { + if (TESTBIT(statusProng, CandidateType::Cand3Prong) && (trackEta > etaMaxTrack3Prong || trackEta < etaMinTrack3Prong)) { CLRBIT(statusProng, CandidateType::Cand3Prong); - if (debug) { - // cutStatus[CandidateType::Cand3Prong][1] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand3Prong + iDebugCut); - } + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand3Prong + iCut); } } MY_DEBUG_MSG(isProtonFromLc, LOG(info) << "proton " << indexBach << " eta = " << trackEta << " (cut " << etaMinTrackBach << " to " << etaMaxTrackBach << ")"); - if ((debug || TESTBIT(statusProng, CandidateType::CandV0bachelor)) && (trackEta > etaMaxTrackBach || trackEta < etaMinTrackBach)) { + if (TESTBIT(statusProng, CandidateType::CandV0bachelor) && (trackEta > etaMaxTrackBach || trackEta < etaMinTrackBach)) { CLRBIT(statusProng, CandidateType::CandV0bachelor); - if (debug) { - // cutStatus[CandidateType::CandV0bachelor][1] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandV0bachelor + iDebugCut); - } + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandV0bachelor + iCut); + } + } + + if (TESTBIT(statusProng, CandidateType::CandDstar) && (trackEta > etaMaxSoftPionForDstar || trackEta < etaMinSoftPionForDstar)) { + CLRBIT(statusProng, CandidateType::CandDstar); + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandDstar + iCut); } } // quality cut MY_DEBUG_MSG(isProtonFromLc, LOG(info) << "proton " << indexBach << " tpcNClsFound = " << hfTrack.tpcNClsFound() << " (cut " << tpcNClsFoundMin.value << ")"); - iDebugCut = 4; - if (doCutQuality.value && (debug || statusProng > 0)) { // FIXME to make a more complete selection e.g track.flags() & o2::aod::track::TPCrefit && track.flags() & o2::aod::track::GoldenChi2 && - bool hasGoodQuality = true; + iCut = 4; + bool hasGoodQuality = true; + if (doCutQuality.value && statusProng > 0) { // FIXME to make a more complete selection e.g track.flags() & o2::aod::track::TPCrefit && track.flags() & o2::aod::track::GoldenChi2 && if (useIsGlobalTrack) { - if (hfTrack.isGlobalTrack() != (uint8_t) true) { + if (!hfTrack.isGlobalTrack()) { hasGoodQuality = false; } } else if (useIsGlobalTrackWoDCA) { - if (hfTrack.isGlobalTrackWoDCA() != (uint8_t) true) { + if (!hfTrack.isGlobalTrackWoDCA()) { hasGoodQuality = false; } } else { UChar_t clustermap = hfTrack.itsClusterMap(); if (!(hfTrack.tpcNClsFound() >= tpcNClsFoundMin.value && // is this the number of TPC clusters? It should not be used - hfTrack.flags() & o2::aod::track::ITSrefit && + TESTBIT(hfTrack.flags(), o2::aod::track::ITSrefit) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)))) { hasGoodQuality = false; } } if (!hasGoodQuality) { - statusProng = 0; MY_DEBUG_MSG(isProtonFromLc, LOG(info) << "proton " << indexBach << " did not pass clusters cut"); - if (debug) { - for (int iCandType = 0; iCandType < CandidateType::NCandidateTypes; iCandType++) { - // cutStatus[iCandType][2] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * iCandType + iDebugCut); - } + for (int iCandType = 0; iCandType < CandidateType::NCandidateTypes; iCandType++) { + if (iCandType == CandidateType::CandDstar) { // different quality criteria for D* soft pions + continue; + } + CLRBIT(statusProng, iCandType); + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * iCandType + iCut); } } } } - iDebugCut = 5; - // DCA cut - if ((debug || statusProng > 0)) { - if ((debug || TESTBIT(statusProng, CandidateType::Cand2Prong)) && !isSelectedTrackDCA(trackPt, dca, CandidateType::Cand2Prong)) { - CLRBIT(statusProng, CandidateType::Cand2Prong); - if (debug) { - // cutStatus[CandidateType::Cand2Prong][3] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand2Prong + iDebugCut); - } + // quality cut for soft pion + hasGoodQuality = true; + if (doCutQuality.value && TESTBIT(statusProng, CandidateType::CandDstar)) { + if (useIsGlobalTrackForSoftPion) { + if (!hfTrack.isGlobalTrack()) { + hasGoodQuality = false; + } + } else if (useIsGlobalTrackWoDCAForSoftPion) { + if (!hfTrack.isGlobalTrackWoDCA()) { + hasGoodQuality = false; + } + } else if (useIsQualityTrackITSForSoftPion) { + if (!hfTrack.isQualityTrackITS()) { + hasGoodQuality = false; + } + } else { // selections for Run2 converted data + UChar_t clustermap = hfTrack.itsClusterMap(); + if (!(TESTBIT(hfTrack.flags(), o2::aod::track::ITSrefit) && (TESTBIT(clustermap, 0) || TESTBIT(clustermap, 1)))) { + hasGoodQuality = false; } } - if ((debug || TESTBIT(statusProng, CandidateType::Cand3Prong)) && !isSelectedTrackDCA(trackPt, dca, CandidateType::Cand3Prong)) { - CLRBIT(statusProng, CandidateType::Cand3Prong); - if (debug) { - // cutStatus[CandidateType::Cand3Prong][3] = false; - if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand3Prong + iDebugCut); - } + if (!hasGoodQuality) { + CLRBIT(statusProng, CandidateType::CandDstar); + if (fillHistograms) { + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandDstar + iCut); } } - if ((debug || TESTBIT(statusProng, CandidateType::CandV0bachelor)) && !isSelectedTrackDCA(trackPt, dca, CandidateType::CandV0bachelor)) { - CLRBIT(statusProng, CandidateType::CandV0bachelor); - if (debug) { - // cutStatus[CandidateType::CandV0bachelor][3] = false; + } + + // DCA cut + iCut = 5; + if (statusProng > 0) { + for (int iCandType = 0; iCandType < CandidateType::NCandidateTypes; ++iCandType) { + if (TESTBIT(statusProng, iCandType) && !isSelectedTrackDCA(trackPt, dca, iCandType)) { + CLRBIT(statusProng, iCandType); if (fillHistograms) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandV0bachelor + iDebugCut); + registry.fill(HIST("hRejTracks"), (nCuts + 1) * iCandType + iCut); } } } @@ -560,31 +581,31 @@ struct HfTrackIndexSkimCreatorTagSelTracks { // fill histograms if (fillHistograms) { - iDebugCut = 1; + iCut = 1; if (TESTBIT(statusProng, CandidateType::Cand2Prong)) { registry.fill(HIST("hPtCuts2Prong"), trackPt); registry.fill(HIST("hEtaCuts2Prong"), trackEta); registry.fill(HIST("hDCAToPrimXYVsPtCuts2Prong"), trackPt, dca[0]); - if (debug) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand2Prong + iDebugCut); - } + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand2Prong + iCut); } if (TESTBIT(statusProng, CandidateType::Cand3Prong)) { registry.fill(HIST("hPtCuts3Prong"), trackPt); registry.fill(HIST("hEtaCuts3Prong"), trackEta); registry.fill(HIST("hDCAToPrimXYVsPtCuts3Prong"), trackPt, dca[0]); - if (debug) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand3Prong + iDebugCut); - } + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::Cand3Prong + iCut); } if (TESTBIT(statusProng, CandidateType::CandV0bachelor)) { MY_DEBUG_MSG(isProtonFromLc, LOG(info) << "Will be kept: Proton from Lc " << indexBach); registry.fill(HIST("hPtCutsV0bachelor"), trackPt); registry.fill(HIST("hEtaCutsV0bachelor"), trackEta); registry.fill(HIST("hDCAToPrimXYVsPtCutsV0bachelor"), trackPt, dca[0]); - if (debug) { - registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandV0bachelor + iDebugCut); - } + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandV0bachelor + iCut); + } + if (TESTBIT(statusProng, CandidateType::CandDstar)) { + registry.fill(HIST("hPtCutsSoftPionForDstar"), trackPt); + registry.fill(HIST("hEtaCutsSoftPionForDstar"), trackEta); + registry.fill(HIST("hDCAToPrimXYVsPtCutsSoftPionForDstar"), trackPt, dca[0]); + registry.fill(HIST("hRejTracks"), (nCuts + 1) * CandidateType::CandDstar + iCut); } } } @@ -655,7 +676,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { registry.fill(HIST("PvRefit/hNContribPvRefitNotDoable"), collision.numContrib()); } } - if (debug) { + if (debugPvRefit) { LOG(info) << "prepareVertexRefit = " << pvRefitDoable << " Ncontrib= " << vecPvContributorTrackParCov.size() << " Ntracks= " << collision.numContrib() << " Vtx= " << primVtx.asString(); } @@ -680,11 +701,11 @@ struct HfTrackIndexSkimCreatorTagSelTracks { auto primVtxRefitted = vertexer.refitVertex(vecPvRefitContributorUsed, primVtx); // vertex refit // LOG(info) << "refit " << cnt << "/" << ntr << " result = " << primVtxRefitted.asString(); - if (debug) { + if (debugPvRefit) { LOG(info) << "refit for track with global index " << static_cast(myTrack.globalIndex()) << " " << primVtxRefitted.asString(); } if (primVtxRefitted.getChi2() < 0) { - if (debug) { + if (debugPvRefit) { LOG(info) << "---> Refitted vertex has bad chi2 = " << primVtxRefitted.getChi2(); } if (fillHistograms) { @@ -787,16 +808,22 @@ struct HfTrackIndexSkimCreatorTagSelTracks { #endif ) { - - if (doPvRefit && debug) { - LOG(info) << ">>> number of tracks: " << tracks.size(); - LOG(info) << ">>> number of collisions: " << collisions.size(); - } + rowSelectedTrack.reserve(tracks.size()); // prepare vectors to cache quantities needed for PV refit - std::vector> pvRefitDcaPerTrack(tracks.size()); - std::vector> pvRefitPvCoordPerTrack(tracks.size()); - std::vector> pvRefitPvCovMatrixPerTrack(tracks.size()); + std::vector> pvRefitDcaPerTrack{}; + std::vector> pvRefitPvCoordPerTrack{}; + std::vector> pvRefitPvCovMatrixPerTrack{}; + if (doPvRefit) { + pvRefitDcaPerTrack.resize(tracks.size()); + pvRefitPvCoordPerTrack.resize(tracks.size()); + pvRefitPvCovMatrixPerTrack.resize(tracks.size()); + if (debugPvRefit) { + LOG(info) << ">>> number of tracks: " << tracks.size(); + LOG(info) << ">>> number of collisions: " << collisions.size(); + } + tabPvRefitTrack.reserve(tracks.size()); + } for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); @@ -829,19 +856,22 @@ struct HfTrackIndexSkimCreatorTagSelTracks { /// contributors for the current collision auto pvContrCollision = pvContributors->sliceByCached(aod::track::collisionId, thisCollId, cache); - for (auto contributor : pvContrCollision) { + for (const auto& contributor : pvContrCollision) { vecPvContributorGlobId.push_back(contributor.globalIndex()); vecPvContributorTrackParCov.push_back(getTrackParCov(contributor)); } - if (debug) { + if (debugPvRefit) { LOG(info) << "### vecPvContributorGlobId.size()=" << vecPvContributorGlobId.size() << ", vecPvContributorTrackParCov.size()=" << vecPvContributorTrackParCov.size() << ", N. original contributors=" << collision.numContrib(); } /// Perform the PV refit only for tracks with an assigned collision - if (debug) { + if (debugPvRefit) { LOG(info) << "[BEFORE performPvRefitTrack] track.collision().globalIndex(): " << collision.globalIndex(); } performPvRefitTrack(collision, bcWithTimeStamps, vecPvContributorGlobId, vecPvContributorTrackParCov, track, pvRefitPvCoord, pvRefitPvCovMatrix, pvRefitDcaXYDcaZ); + pvRefitDcaPerTrack[trackIdx] = pvRefitDcaXYDcaZ; + pvRefitPvCoordPerTrack[trackIdx] = pvRefitPvCoord; + pvRefitPvCovMatrixPerTrack[trackIdx] = pvRefitPvCovMatrix; } else if (track.collisionId() != thisCollId) { auto bc = collision.bc_as(); initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); @@ -867,18 +897,15 @@ struct HfTrackIndexSkimCreatorTagSelTracks { isSelectedTrack(track, trackPt, trackEta, pvRefitDcaXYDcaZ, statusProng); rowSelectedTrack(statusProng); - - pvRefitDcaPerTrack[trackIdx] = pvRefitDcaXYDcaZ; - pvRefitPvCoordPerTrack[trackIdx] = pvRefitPvCoord; - pvRefitPvCovMatrixPerTrack[trackIdx] = pvRefitPvCovMatrix; } } - /// fill table with PV refit info (it has to be filled per track) - for (auto iTrack{0u}; iTrack < tracks.size(); ++iTrack) { - tabPvRefitTrack(pvRefitPvCoordPerTrack[iTrack][0], pvRefitPvCoordPerTrack[iTrack][1], pvRefitPvCoordPerTrack[iTrack][2], - pvRefitPvCovMatrixPerTrack[iTrack][0], pvRefitPvCovMatrixPerTrack[iTrack][1], pvRefitPvCovMatrixPerTrack[iTrack][2], pvRefitPvCovMatrixPerTrack[iTrack][3], pvRefitPvCovMatrixPerTrack[iTrack][4], pvRefitPvCovMatrixPerTrack[iTrack][5], - pvRefitDcaPerTrack[iTrack][0], pvRefitDcaPerTrack[iTrack][1]); + if (doPvRefit) { /// fill table with PV refit info (it has to be filled per track) + for (auto iTrack{0u}; iTrack < tracks.size(); ++iTrack) { + tabPvRefitTrack(pvRefitPvCoordPerTrack[iTrack][0], pvRefitPvCoordPerTrack[iTrack][1], pvRefitPvCoordPerTrack[iTrack][2], + pvRefitPvCovMatrixPerTrack[iTrack][0], pvRefitPvCovMatrixPerTrack[iTrack][1], pvRefitPvCovMatrixPerTrack[iTrack][2], pvRefitPvCovMatrixPerTrack[iTrack][3], pvRefitPvCovMatrixPerTrack[iTrack][4], pvRefitPvCovMatrixPerTrack[iTrack][5], + pvRefitDcaPerTrack[iTrack][0], pvRefitDcaPerTrack[iTrack][1]); + } } } }; @@ -893,11 +920,15 @@ struct HfTrackIndexSkimCreator { Produces rowTrackIndexProng3; Produces rowProng3CutStatus; Produces rowProng3PVrefit; + Produces rowTrackIndexDstar; + Produces rowDstarCutStatus; + Produces rowDstarPVrefit; Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; Configurable do3Prong{"do3Prong", 0, "do 3 prong"}; - Configurable doPvRefit{"doPvRefit", false, "do PV refit excluding the considered track"}; + Configurable doDstar{"doDstar", false, "do D* candidates"}; Configurable debug{"debug", false, "debug mode"}; + Configurable debugPvRefit{"debugPvRefit", false, "debug lines for primary vertex refit"}; Configurable fillHistograms{"fillHistograms", true, "fill histograms"}; ConfigurableAxis axisNumTracks{"axisNumTracks", {250, -0.5f, 249.5f}, "Number of tracks"}; ConfigurableAxis axisNumCands{"axisNumCands", {200, -0.5f, 199.f}, "Number of candidates"}; @@ -940,6 +971,9 @@ struct HfTrackIndexSkimCreator { // Xic+ cuts Configurable> binsPtXicToPKPi{"binsPtXicToPKPi", std::vector{hf_cuts_presel_3prong::vecBinsPt}, "pT bin limits for Xic->pKpi pT-dependent cuts"}; Configurable> cutsXicToPKPi{"cutsXicToPKPi", {hf_cuts_presel_3prong::cuts[0], hf_cuts_presel_3prong::nBinsPt, hf_cuts_presel_3prong::nCutVars, hf_cuts_presel_3prong::labelsPt, hf_cuts_presel_3prong::labelsCutVar}, "Xic->pKpi selections per pT bin"}; + // D*+ cuts + Configurable> binsPtDstarToD0Pi{"binsPtDstarToD0Pi", std::vector{hf_cuts_presel_dstar::vecBinsPt}, "pT bin limits for D*+->D0pi pT-dependent cuts"}; + Configurable> cutsDstarToD0Pi{"cutsDstarToD0Pi", {hf_cuts_presel_dstar::cuts[0], hf_cuts_presel_dstar::nBinsPt, hf_cuts_presel_dstar::nCutVars, hf_cuts_presel_dstar::labelsPt, hf_cuts_presel_dstar::labelsCutVar}, "D*+->D0pi selections per pT bin"}; // Needed for PV refitting Service ccdb; @@ -947,12 +981,20 @@ struct HfTrackIndexSkimCreator { o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int runNumber; + double massPi{0.}; + double massK{0.}; + double massProton{0.}; + double massElectron{0.}; + double massMuon{0.}; + double massDzero{0.}; + // int nColls{0}; //can be added to run over limited collisions per file - for tesing purposes static constexpr int kN2ProngDecays = hf_cand_2prong::DecayType::N2ProngDecays; // number of 2-prong hadron types static constexpr int kN3ProngDecays = hf_cand_3prong::DecayType::N3ProngDecays; // number of 3-prong hadron types static constexpr int kNCuts2Prong = 4; // how many different selections are made on 2-prongs static constexpr int kNCuts3Prong = 4; // how many different selections are made on 3-prongs + static constexpr int kNCutsDstar = 3; // how many different selections are made on Dstars std::array, 2>, kN2ProngDecays> arrMass2Prong; std::array, 2>, kN3ProngDecays> arrMass3Prong; // arrays of 2-prong and 3-prong cuts @@ -962,10 +1004,18 @@ struct HfTrackIndexSkimCreator { std::array, kN3ProngDecays> pTBins3Prong; using SelectedCollisions = soa::Filtered>; - using TracksWithPVRefitAndDCA = soa::Join; + using TracksWithPVRefitAndDCA = soa::Join; + using FilteredTrackAssocSel = soa::Filtered>; + // filter collisions Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == 0); - Filter filterSelectedTrackIds = aod::hf_sel_track::isSelProng > 0; + + // define slice of track indices per collisions + Preslice tracksPerCollision = aod::track::collisionId; // needed for PV refit + + // filter track indices + Filter filterSelectTrackIds = (aod::hf_sel_track::isSelProng > 0); + Preslice trackIndicesPerCollision = aod::track_association::collisionId; // FIXME // Partition tracksPos = aod::track::signed1Pt > 0.f; @@ -980,30 +1030,37 @@ struct HfTrackIndexSkimCreator { void init(InitContext const& context) { - if (!doprocess2And3Prongs) { + if (!doprocess2And3ProngsWithPvRefit && !doprocess2And3ProngsNoPvRefit) { return; } - arrMass2Prong[hf_cand_2prong::DecayType::D0ToPiK] = array{array{massPi, massK}, - array{massK, massPi}}; + massPi = o2::analysis::pdg::MassPiPlus; + massK = o2::analysis::pdg::MassKPlus; + massProton = o2::analysis::pdg::MassProton; + massElectron = o2::analysis::pdg::MassElectron; + massMuon = o2::analysis::pdg::MassMuonPlus; + massDzero = o2::analysis::pdg::MassD0; + + arrMass2Prong[hf_cand_2prong::DecayType::D0ToPiK] = std::array{std::array{massPi, massK}, + std::array{massK, massPi}}; - arrMass2Prong[hf_cand_2prong::DecayType::JpsiToEE] = array{array{massElectron, massElectron}, - array{massElectron, massElectron}}; + arrMass2Prong[hf_cand_2prong::DecayType::JpsiToEE] = std::array{std::array{massElectron, massElectron}, + std::array{massElectron, massElectron}}; - arrMass2Prong[hf_cand_2prong::DecayType::JpsiToMuMu] = array{array{massMuon, massMuon}, - array{massMuon, massMuon}}; + arrMass2Prong[hf_cand_2prong::DecayType::JpsiToMuMu] = std::array{std::array{massMuon, massMuon}, + std::array{massMuon, massMuon}}; - arrMass3Prong[hf_cand_3prong::DecayType::DplusToPiKPi] = array{array{massPi, massK, massPi}, - array{massPi, massK, massPi}}; + arrMass3Prong[hf_cand_3prong::DecayType::DplusToPiKPi] = std::array{std::array{massPi, massK, massPi}, + std::array{massPi, massK, massPi}}; - arrMass3Prong[hf_cand_3prong::DecayType::LcToPKPi] = array{array{massProton, massK, massPi}, - array{massPi, massK, massProton}}; + arrMass3Prong[hf_cand_3prong::DecayType::LcToPKPi] = std::array{std::array{massProton, massK, massPi}, + std::array{massPi, massK, massProton}}; - arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi] = array{array{massK, massK, massPi}, - array{massPi, massK, massK}}; + arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi] = std::array{std::array{massK, massK, massPi}, + std::array{massPi, massK, massK}}; - arrMass3Prong[hf_cand_3prong::DecayType::XicToPKPi] = array{array{massProton, massK, massPi}, - array{massPi, massK, massProton}}; + arrMass3Prong[hf_cand_3prong::DecayType::XicToPKPi] = std::array{std::array{massProton, massK, massPi}, + std::array{massPi, massK, massProton}}; // cuts for 2-prong decays retrieved by json. the order must be then one in hf_cand_2prong::DecayType cut2Prong = {cutsD0ToPiK, cutsJpsiToEE, cutsJpsiToMuMu}; @@ -1033,11 +1090,10 @@ struct HfTrackIndexSkimCreator { registry.add("hMassLcToPKPi", "#Lambda_{c}^{#plus} candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); registry.add("hMassDsToKKPi", "D_{s}^{#plus} candidates;inv. mass (K K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); registry.add("hMassXicToPKPi", "#Xi_{c}^{#plus} candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}); - } + registry.add("hMassDstarToD0Pi", "D^{*#plus} candidates;inv. mass (K #pi #pi) - mass (K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0.135, 0.185}}}); - // needed for PV refitting - if (doPvRefit) { - if (fillHistograms) { + // needed for PV refitting + if (doprocess2And3ProngsWithPvRefit) { AxisSpec axisCollisionX{100, -20.f, 20.f, "X (cm)"}; AxisSpec axisCollisionY{100, -20.f, 20.f, "Y (cm)"}; AxisSpec axisCollisionZ{100, -20.f, 20.f, "Z (cm)"}; @@ -1102,7 +1158,7 @@ struct HfTrackIndexSkimCreator { }; cacheIndices(cut2Prong, massMinIndex, massMaxIndex, d0d0Index); - auto arrMom = array{pVecTrack0, pVecTrack1}; + auto arrMom = std::array{pVecTrack0, pVecTrack1}; auto pT = RecoDecay::pt(pVecTrack0, pVecTrack1) + ptTolerance; // add tolerance because of no reco decay vertex for (int iDecay2P = 0; iDecay2P < kN2ProngDecays; iDecay2P++) { @@ -1178,7 +1234,7 @@ struct HfTrackIndexSkimCreator { }; cacheIndices(cut3Prong, massMinIndex, massMaxIndex); - auto arrMom = array{pVecTrack0, pVecTrack1, pVecTrack2}; + auto arrMom = std::array{pVecTrack0, pVecTrack1, pVecTrack2}; auto pT = RecoDecay::pt(pVecTrack0, pVecTrack1, pVecTrack2) + ptTolerance; // add tolerance because of no reco decay vertex for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { @@ -1230,7 +1286,7 @@ struct HfTrackIndexSkimCreator { { if (debug || isSelected > 0) { - /// FIXME: this would be better fixed by having a convention on the position of min and max in the 2D Array + /// FIXME: this would be better fixed by having a convention on the position of cuts in the 2D Array static std::vector cospIndex; static auto cacheIndices = [](std::array, kN2ProngDecays>& cut2Prong, std::vector& cosp) { cosp.resize(cut2Prong.size()); @@ -1278,7 +1334,7 @@ struct HfTrackIndexSkimCreator { { if (debug || isSelected > 0) { - /// FIXME: this would be better fixed by having a convention on the position of min and max in the 2D Array + /// FIXME: this would be better fixed by having a convention on the position of cuts in the 2D Array static std::vector cospIndex; static std::vector decLenIndex; static auto cacheIndices = [](std::array, kN3ProngDecays>& cut3Prong, std::vector& cosp, std::vector& decL) { @@ -1329,6 +1385,70 @@ struct HfTrackIndexSkimCreator { } } + /// Method to perform selections for D* candidates before vertex reconstruction + /// \param pVecTrack0 is the momentum array of the first daughter track (same charge) + /// \param pVecTrack1 is the momentum array of the second daughter track (opposite charge) + /// \param pVecTrack2 is the momentum array of the third daughter track (same charge) + /// \param cutStatus is the cut status (filled only in case of debug) + /// \param deltaMass is the M(Kpipi) - M(Kpi) value to be filled in the control histogram + /// \return a bitmap with selection outcome + template + uint8_t isDstarSelected(T1 const& pVecTrack0, T1 const& pVecTrack1, T1 const& pVecTrack2, uint8_t& cutStatus, T2& deltaMass) + { + uint8_t isSelected{1}; + /// FIXME: this would be better fixed by having a convention on the position of cuts in the 2D Array + int deltaMassIndex, deltaMassD0Index; + static auto cacheIndices = [](LabeledArray& cutDstar, int& deltaMassIdx, int& deltaMassD0Idx) { + deltaMassIdx = cutDstar.colmap.find("deltaMassMax")->second; + deltaMassD0Idx = cutDstar.colmap.find("deltaMassD0")->second; + return true; + }; + cacheIndices(cutsDstarToD0Pi.value, deltaMassIndex, deltaMassD0Index); + + auto arrMom = std::array{pVecTrack0, pVecTrack1, pVecTrack2}; + auto arrMomD0 = std::array{pVecTrack0, pVecTrack1}; + auto pT = RecoDecay::pt(pVecTrack0, pVecTrack1, pVecTrack2) + ptTolerance; // add tolerance because of no reco decay vertex + + // pT + auto pTBin = findBin(binsPtDstarToD0Pi, pT); + // return immediately if it is outside the defined pT bins + if (pTBin == -1) { + isSelected = 0; + if (debug) { + CLRBIT(cutStatus, 0); + } else { + return isSelected; + } + } + + // D0 mass + double deltaMassD0 = cutsDstarToD0Pi->get(pTBin, deltaMassD0Index); + double invMassD0 = RecoDecay::m(arrMomD0, std::array{massPi, massK}); + if (std::abs(invMassD0 - massDzero) > deltaMassD0) { + isSelected = 0; + if (debug) { + CLRBIT(cutStatus, 1); + } else { + return isSelected; + } + } + + // D*+ mass + double maxDeltaMass = cutsDstarToD0Pi->get(pTBin, deltaMassIndex); + double invMassDstar = RecoDecay::m(arrMom, std::array{massPi, massK, massPi}); + deltaMass = invMassDstar - invMassD0; + if (deltaMass > maxDeltaMass) { + isSelected = 0; + if (debug) { + CLRBIT(cutStatus, 1); + } else { + return isSelected; + } + } + + return isSelected; + } + /// Method for the PV refit excluding the candidate daughters /// \param collision is a collision /// \param bcWithTimeStamps is a table of bunch crossing joined with timestamps used to query the CCDB for B and material budget @@ -1365,22 +1485,21 @@ struct HfTrackIndexSkimCreator { bool pvRefitDoable = vertexer.prepareVertexRefit(vecPvContributorTrackParCov, primVtx); if (!pvRefitDoable) { LOG(info) << "Not enough tracks accepted for the refit"; - if (doPvRefit && fillHistograms) { + if (doprocess2And3ProngsWithPvRefit && fillHistograms) { registry.fill(HIST("PvRefit/hNContribPvRefitNotDoable"), collision.numContrib()); } } - if (debug) { + if (debugPvRefit) { LOG(info) << "prepareVertexRefit = " << pvRefitDoable << " Ncontrib= " << vecPvContributorTrackParCov.size() << " Ntracks= " << collision.numContrib() << " Vtx= " << primVtx.asString(); } - // registry.fill(HIST("PvRefit/verticesPerCandidate"), 1); - if (pvRefitDoable && fillHistograms) { - registry.fill(HIST("PvRefit/verticesPerCandidate"), 2); - } /// PV refitting, if the tracks contributed to this at the beginning o2::dataformats::VertexBase primVtxBaseRecalc; bool recalcPvRefit = false; - if (doPvRefit && pvRefitDoable) { + if (doprocess2And3ProngsWithPvRefit && pvRefitDoable) { + if (fillHistograms) { + registry.fill(HIST("PvRefit/verticesPerCandidate"), 2); + } recalcPvRefit = true; int nCandContr = 0; for (uint64_t myGlobalID : vecCandPvContributorGlobId) { @@ -1394,14 +1513,14 @@ struct HfTrackIndexSkimCreator { } /// do the PV refit excluding the candidate daughters that originally contributed to fit it - if (debug) { + if (debugPvRefit) { LOG(info) << "### PV refit after removing " << nCandContr << " tracks"; } auto primVtxRefitted = vertexer.refitVertex(vecPvRefitContributorUsed, primVtx); // vertex refit // LOG(info) << "refit " << cnt << "/" << ntr << " result = " << primVtxRefitted.asString(); // LOG(info) << "refit for track with global index " << static_cast(myTrack.globalIndex()) << " " << primVtxRefitted.asString(); if (primVtxRefitted.getChi2() < 0) { - if (debug) { + if (debugPvRefit) { LOG(info) << "---> Refitted vertex has bad chi2 = " << primVtxRefitted.getChi2(); } if (fillHistograms) { @@ -1461,29 +1580,16 @@ struct HfTrackIndexSkimCreator { // cnt++; - } /// end 'if (doPvRefit && pvRefitDoable)' + } /// end 'if (doprocess2And3ProngsWithPvRefit && pvRefitDoable)' return; } /// end of performPvRefitCandProngs function - // define slice of track indices per collisions - Preslice tracksPerCollision = aod::track::collisionId; // needed for PV refit - - Filter filterSelectTrackIds = (aod::hf_sel_track::isSelProng > 0); - using FilteredTrackAssocSel = soa::Filtered>; - Preslice trackIndicesPerCollision = aod::track_association::collisionId; - - void processNo2And3Prongs(SelectedCollisions const&) - { - // dummy - } - PROCESS_SWITCH(HfTrackIndexSkimCreator, processNo2And3Prongs, "Do not process 2-prongs and 3-prongs", false); - - void process2And3Prongs( // soa::Join::iterator const& collision, //FIXME add centrality when option for variations to the process function appears - SelectedCollisions const& collisions, - aod::BCsWithTimestamps const& bcWithTimeStamps, - FilteredTrackAssocSel const& trackIndices, - TracksWithPVRefitAndDCA const& tracks) + template + void run2And3Prongs(SelectedCollisions const& collisions, + aod::BCsWithTimestamps const& bcWithTimeStamps, + FilteredTrackAssocSel const& trackIndices, + TTracks const& tracks) { // can be added to run over limited collisions per file - for tesing purposes @@ -1500,10 +1606,11 @@ struct HfTrackIndexSkimCreator { for (const auto& collision : collisions) { /// retrieve PV contributors for the current collision - std::vector vecPvContributorGlobId = {}; - std::vector vecPvContributorTrackParCov = {}; - auto groupedTracksUnfiltered = tracks.sliceBy(tracksPerCollision, collision.globalIndex()); - if (doPvRefit) { + std::vector vecPvContributorGlobId{}; + std::vector vecPvContributorTrackParCov{}; + std::vector vecPvRefitContributorUsed{}; + if constexpr (doPvRefit) { + auto groupedTracksUnfiltered = tracks.sliceBy(tracksPerCollision, collision.globalIndex()); const int nTrk = groupedTracksUnfiltered.size(); int nContrib = 0; int nNonContrib = 0; @@ -1516,20 +1623,20 @@ struct HfTrackIndexSkimCreator { vecPvContributorGlobId.push_back(trackUnfiltered.globalIndex()); vecPvContributorTrackParCov.push_back(getTrackParCov(trackUnfiltered)); nContrib++; - if (debug) { + if (debugPvRefit) { LOG(info) << "---> a contributor! stuff saved"; LOG(info) << "vec_contrib size: " << vecPvContributorTrackParCov.size() << ", nContrib: " << nContrib; } } } - if (debug) { + if (debugPvRefit) { LOG(info) << "===> nTrk: " << nTrk << ", nContrib: " << nContrib << ", nNonContrib: " << nNonContrib; if ((uint16_t)vecPvContributorTrackParCov.size() != collision.numContrib() || (uint16_t)nContrib != collision.numContrib()) { LOG(info) << "!!! Some problem here !!! vecPvContributorTrackParCov.size()= " << vecPvContributorTrackParCov.size() << ", nContrib=" << nContrib << ", collision.numContrib()" << collision.numContrib(); } } + vecPvRefitContributorUsed = std::vector(vecPvContributorGlobId.size(), true); } - std::vector vecPvRefitContributorUsed(vecPvContributorGlobId.size(), true); // auto centrality = collision.centV0M(); //FIXME add centrality when option for variations to the process function appears @@ -1586,7 +1693,7 @@ struct HfTrackIndexSkimCreator { auto groupedTrackIndices = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); for (auto trackIndexPos1 = groupedTrackIndices.begin(); trackIndexPos1 != groupedTrackIndices.end(); ++trackIndexPos1) { - auto trackPos1 = trackIndexPos1.track_as(); + auto trackPos1 = trackIndexPos1.template track_as(); if (trackPos1.signed1Pt() < 0) { continue; @@ -1611,7 +1718,7 @@ struct HfTrackIndexSkimCreator { // first loop over negative tracks // for (auto trackNeg1 = tracksNeg.begin(); trackNeg1 != tracksNeg.end(); ++trackNeg1) { for (auto trackIndexNeg1 = groupedTrackIndices.begin(); trackIndexNeg1 != groupedTrackIndices.end(); ++trackIndexNeg1) { - auto trackNeg1 = trackIndexNeg1.track_as(); + auto trackNeg1 = trackIndexNeg1.template track_as(); if (trackNeg1.signed1Pt() > 0) { continue; } @@ -1654,15 +1761,15 @@ struct HfTrackIndexSkimCreator { // get secondary vertex const auto& secondaryVertex2 = df2.getPCACandidate(); // get track momenta - array pvec0; - array pvec1; + std::array pvec0; + std::array pvec1; df2.getTrack(0).getPxPyPzGlo(pvec0); df2.getTrack(1).getPxPyPzGlo(pvec1); /// PV refit excluding the candidate daughters, if contributors - array pvRefitCoord2Prong = {collision.posX(), collision.posY(), collision.posZ()}; /// initialize to the original PV - array pvRefitCovMatrix2Prong = getPrimaryVertex(collision).getCov(); /// initialize to the original PV - if (doPvRefit) { + std::array pvRefitCoord2Prong = {collision.posX(), collision.posY(), collision.posZ()}; /// initialize to the original PV + std::array pvRefitCovMatrix2Prong = getPrimaryVertex(collision).getCov(); /// initialize to the original PV + if constexpr (doPvRefit) { if (fillHistograms) { registry.fill(HIST("PvRefit/verticesPerCandidate"), 1); } @@ -1673,7 +1780,7 @@ struct HfTrackIndexSkimCreator { bool isTrackSecondContr = true; if (trackFirstIt == vecPvContributorGlobId.end()) { /// This track did not contribute to the original PV refit - if (debug) { + if (debugPvRefit) { LOG(info) << "--- [2 Prong] trackPos1 with globalIndex " << trackPos1.globalIndex() << " was not a PV contributor"; } nCandContr--; @@ -1681,7 +1788,7 @@ struct HfTrackIndexSkimCreator { } if (trackSecondIt == vecPvContributorGlobId.end()) { /// This track did not contribute to the original PV refit - if (debug) { + if (debugPvRefit) { LOG(info) << "--- [2 Prong] trackNeg1 with globalIndex " << trackNeg1.globalIndex() << " was not a PV contributor"; } nCandContr--; @@ -1689,13 +1796,13 @@ struct HfTrackIndexSkimCreator { } if (nCandContr == 2) { /// Both the daughter tracks were used for the original PV refit, let's refit it after excluding them - if (debug) { + if (debugPvRefit) { LOG(info) << "### [2 Prong] Calling performPvRefitCandProngs for HF 2 prong candidate"; } performPvRefitCandProngs(collision, bcWithTimeStamps, vecPvContributorGlobId, vecPvContributorTrackParCov, {trackPos1.globalIndex(), trackNeg1.globalIndex()}, pvRefitCoord2Prong, pvRefitCovMatrix2Prong); } else if (nCandContr == 1) { /// Only one daughter was a contributor, let's use then the PV recalculated by excluding only it - if (debug) { + if (debugPvRefit) { LOG(info) << "####### [2 Prong] nCandContr==" << nCandContr << " ---> just 1 contributor!"; } if (fillHistograms) { @@ -1712,8 +1819,10 @@ struct HfTrackIndexSkimCreator { } } else { /// 0 contributors among the HF candidate daughters - registry.fill(HIST("PvRefit/verticesPerCandidate"), 6); - if (debug) { + if (fillHistograms) { + registry.fill(HIST("PvRefit/verticesPerCandidate"), 6); + } + if (debugPvRefit) { LOG(info) << "####### [2 Prong] nCandContr==" << nCandContr << " ---> some of the candidate daughters did not contribute to the original PV fit, PV refit not redone"; } } @@ -1721,8 +1830,8 @@ struct HfTrackIndexSkimCreator { auto pVecCandProng2 = RecoDecay::pVec(pvec0, pvec1); // 2-prong selections after secondary vertex - array pvCoord2Prong = {collision.posX(), collision.posY(), collision.posZ()}; - if (doPvRefit) { + std::array pvCoord2Prong = {collision.posX(), collision.posY(), collision.posZ()}; + if constexpr (doPvRefit) { pvCoord2Prong[0] = pvRefitCoord2Prong[0]; pvCoord2Prong[1] = pvRefitCoord2Prong[1]; pvCoord2Prong[2] = pvRefitCoord2Prong[2]; @@ -1732,9 +1841,12 @@ struct HfTrackIndexSkimCreator { if (isSelected2ProngCand > 0) { // fill table row rowTrackIndexProng2(thisCollId, trackPos1.globalIndex(), trackNeg1.globalIndex(), isSelected2ProngCand); - // fill table row with coordinates of PV refit - rowProng2PVrefit(pvRefitCoord2Prong[0], pvRefitCoord2Prong[1], pvRefitCoord2Prong[2], - pvRefitCovMatrix2Prong[0], pvRefitCovMatrix2Prong[1], pvRefitCovMatrix2Prong[2], pvRefitCovMatrix2Prong[3], pvRefitCovMatrix2Prong[4], pvRefitCovMatrix2Prong[5]); + + if constexpr (doPvRefit) { + // fill table row with coordinates of PV refit + rowProng2PVrefit(pvRefitCoord2Prong[0], pvRefitCoord2Prong[1], pvRefitCoord2Prong[2], + pvRefitCovMatrix2Prong[0], pvRefitCovMatrix2Prong[1], pvRefitCovMatrix2Prong[2], pvRefitCovMatrix2Prong[3], pvRefitCovMatrix2Prong[4], pvRefitCovMatrix2Prong[5]); + } if (debug) { int Prong2CutStatus[kN2ProngDecays]; @@ -1754,7 +1866,7 @@ struct HfTrackIndexSkimCreator { registry.fill(HIST("hVtx2ProngX"), secondaryVertex2[0]); registry.fill(HIST("hVtx2ProngY"), secondaryVertex2[1]); registry.fill(HIST("hVtx2ProngZ"), secondaryVertex2[2]); - array, 2> arrMom = {pvec0, pvec1}; + std::array, 2> arrMom = {pvec0, pvec1}; for (int iDecay2P = 0; iDecay2P < kN2ProngDecays; iDecay2P++) { if (TESTBIT(isSelected2ProngCand, iDecay2P)) { if (whichHypo2Prong[iDecay2P] == 1 || whichHypo2Prong[iDecay2P] == 3) { @@ -1784,71 +1896,84 @@ struct HfTrackIndexSkimCreator { } } - // 3-prong vertex reconstruction - if (do3Prong == 1) { - if (!sel3ProngStatusPos1 || !sel3ProngStatusNeg1) { + // 3-prong vertex and D* reconstruction + if (do3Prong == 1 || doDstar) { + if (!doDstar && (!sel3ProngStatusPos1 || !sel3ProngStatusNeg1)) { continue; } - if (tracks.size() < 2) { - continue; - } // second loop over positive tracks // for (auto trackPos2 = trackPos1 + 1; trackPos2 != tracksPos.end(); ++trackPos2) { for (auto trackIndexPos2 = trackIndexPos1 + 1; trackIndexPos2 != groupedTrackIndices.end(); ++trackIndexPos2) { - auto trackPos2 = trackIndexPos2.track_as(); + auto trackPos2 = trackIndexPos2.template track_as(); if (trackPos2.signed1Pt() < 0) { continue; } - // retrieve the selection flag that corresponds to this collision - auto isSelProngPos2 = trackIndexPos2.isSelProng(); - if (!TESTBIT(isSelProngPos2, CandidateType::Cand3Prong)) { - continue; - } - auto trackParVarPos2 = getTrackParCov(trackPos2); std::array pVecTrackPos2{trackPos2.px(), trackPos2.py(), trackPos2.pz()}; o2::gpu::gpustd::array dcaInfoPos2{trackPos2.dcaXY(), trackPos2.dcaZ()}; - if (thisCollId != trackPos2.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarPos2, 2.f, noMatCorr, &dcaInfoPos2); - getPxPyPz(trackParVarPos2, pVecTrackPos2); + bool propagatedPos2{false}; + + // first we build D*+ candidates if enabled + auto isSelProngPos2 = trackIndexPos2.isSelProng(); + uint8_t isSelectedDstar{0}; + if (doDstar && TESTBIT(isSelected2ProngCand, hf_cand_2prong::DecayType::D0ToPiK) && (whichHypo2Prong[0] == 1 || whichHypo2Prong[0] == 3)) { // the 2-prong decay is compatible with a D0 + if (TESTBIT(isSelProngPos2, CandidateType::CandDstar)) { // compatible with a soft pion + if (thisCollId != trackPos2.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarPos2, 2.f, noMatCorr, &dcaInfoPos2); + getPxPyPz(trackParVarPos2, pVecTrackPos2); + propagatedPos2 = true; + } + uint8_t cutStatus{BIT(kNCutsDstar) - 1}; + float deltaMass{-1.}; + isSelectedDstar = isDstarSelected(pVecTrackPos1, pVecTrackNeg1, pVecTrackPos2, cutStatus, deltaMass); // we do not compute the D* decay vertex at this stage because we are not interested in applying topological selections + if (isSelectedDstar) { + rowTrackIndexDstar(thisCollId, trackPos2.globalIndex(), rowTrackIndexProng2.lastIndex()); + if (fillHistograms) { + registry.fill(HIST("hMassDstarToD0Pi"), deltaMass); + } + } + if (debug) { + rowDstarCutStatus(cutStatus); + } + } } + // preselection of 3-prong candidates int isSelected3ProngCand = n3ProngBit; + if (do3Prong && TESTBIT(isSelProngPos2, CandidateType::Cand3Prong) && (sel3ProngStatusPos1 && sel3ProngStatusNeg1)) { + if (thisCollId != trackPos2.collisionId() && !propagatedPos2) { // this is not the "default" collision for this track and we still did not re-propagate it, we have to re-propagate it + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarPos2, 2.f, noMatCorr, &dcaInfoPos2); + getPxPyPz(trackParVarPos2, pVecTrackPos2); + } - if (debug) { - for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { - for (int iCut = 0; iCut < kNCuts3Prong; iCut++) { - cutStatus3Prong[iDecay3P][iCut] = true; + if (debug) { + for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { + for (int iCut = 0; iCut < kNCuts3Prong; iCut++) { + cutStatus3Prong[iDecay3P][iCut] = true; + } } } - } - // 3-prong preselections - is3ProngPreselected(pVecTrackPos1, pVecTrackNeg1, pVecTrackPos2, cutStatus3Prong, whichHypo3Prong, isSelected3ProngCand); - if (!debug && isSelected3ProngCand == 0) { - continue; + // 3-prong preselections + is3ProngPreselected(pVecTrackPos1, pVecTrackNeg1, pVecTrackPos2, cutStatus3Prong, whichHypo3Prong, isSelected3ProngCand); + if (!debug && isSelected3ProngCand == 0) { + continue; + } + } else { + isSelected3ProngCand = 0; } - // reconstruct the 3-prong secondary vertex - if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) { + // if we did not preselected any D* or 3-prong candidate, continue + if (!debug && (isSelectedDstar == 0 && isSelected3ProngCand == 0)) { continue; } - // get secondary vertex - const auto& secondaryVertex3 = df3.getPCACandidate(); - // get track momenta - array pvec0; - array pvec1; - array pvec2; - df3.getTrack(0).getPxPyPzGlo(pvec0); - df3.getTrack(1).getPxPyPzGlo(pvec1); - df3.getTrack(2).getPxPyPzGlo(pvec2); /// PV refit excluding the candidate daughters, if contributors - array pvRefitCoord3Prong2Pos1Neg = {collision.posX(), collision.posY(), collision.posZ()}; /// initialize to the original PV - array pvRefitCovMatrix3Prong2Pos1Neg = getPrimaryVertex(collision).getCov(); /// initialize to the original PV - if (doPvRefit) { + std::array pvRefitCoord3Prong2Pos1Neg = {collision.posX(), collision.posY(), collision.posZ()}; /// initialize to the original PV + std::array pvRefitCovMatrix3Prong2Pos1Neg = getPrimaryVertex(collision).getCov(); /// initialize to the original PV + if constexpr (doPvRefit) { if (fillHistograms) { registry.fill(HIST("PvRefit/verticesPerCandidate"), 1); } @@ -1861,7 +1986,7 @@ struct HfTrackIndexSkimCreator { bool isTrackThirdContr = true; if (trackFirstIt == vecPvContributorGlobId.end()) { /// This track did not contribute to the original PV refit - if (debug) { + if (debugPvRefit) { LOG(info) << "--- [3 prong] trackPos1 with globalIndex " << trackPos1.globalIndex() << " was not a PV contributor"; } nCandContr--; @@ -1869,7 +1994,7 @@ struct HfTrackIndexSkimCreator { } if (trackSecondIt == vecPvContributorGlobId.end()) { /// This track did not contribute to the original PV refit - if (debug) { + if (debugPvRefit) { LOG(info) << "--- [3 prong] trackNeg1 with globalIndex " << trackNeg1.globalIndex() << " was not a PV contributor"; } nCandContr--; @@ -1877,7 +2002,7 @@ struct HfTrackIndexSkimCreator { } if (trackThirdIt == vecPvContributorGlobId.end()) { /// This track did not contribute to the original PV refit - if (debug) { + if (debugPvRefit) { LOG(info) << "--- [3 prong] trackPos2 with globalIndex " << trackPos2.globalIndex() << " was not a PV contributor"; } nCandContr--; @@ -1898,13 +2023,13 @@ struct HfTrackIndexSkimCreator { if (nCandContr == 3 || nCandContr == 2) { /// At least two of the daughter tracks were used for the original PV refit, let's refit it after excluding them - if (debug) { + if (debugPvRefit) { LOG(info) << "### [3 prong] Calling performPvRefitCandProngs for HF 3 prong candidate, removing " << nCandContr << " daughters"; } performPvRefitCandProngs(collision, bcWithTimeStamps, vecPvContributorGlobId, vecPvContributorTrackParCov, vecCandPvContributorGlobId, pvRefitCoord3Prong2Pos1Neg, pvRefitCovMatrix3Prong2Pos1Neg); } else if (nCandContr == 1) { /// Only one daughter was a contributor, let's use then the PV recalculated by excluding only it - if (debug) { + if (debugPvRefit) { LOG(info) << "####### [3 Prong] nCandContr==" << nCandContr << " ---> just 1 contributor!"; } if (fillHistograms) { @@ -1928,30 +2053,48 @@ struct HfTrackIndexSkimCreator { if (fillHistograms) { registry.fill(HIST("PvRefit/verticesPerCandidate"), 6); } - if (debug) { + if (debugPvRefit) { LOG(info) << "####### [3 prong] nCandContr==" << nCandContr << " ---> some of the candidate daughters did not contribute to the original PV fit, PV refit not redone"; } } + if (isSelectedDstar) { + rowDstarPVrefit(pvRefitCoord3Prong2Pos1Neg[0], pvRefitCoord3Prong2Pos1Neg[1], pvRefitCoord3Prong2Pos1Neg[2], + pvRefitCovMatrix3Prong2Pos1Neg[0], pvRefitCovMatrix3Prong2Pos1Neg[1], pvRefitCovMatrix3Prong2Pos1Neg[2], pvRefitCovMatrix3Prong2Pos1Neg[3], pvRefitCovMatrix3Prong2Pos1Neg[4], pvRefitCovMatrix3Prong2Pos1Neg[5]); + } + } // end of D* + + if (!debug && isSelected3ProngCand == 0) { // below only for 3-prong candidates + continue; } + // reconstruct the 3-prong secondary vertex + if (df3.process(trackParVarPos1, trackParVarNeg1, trackParVarPos2) == 0) { + continue; + } + // get secondary vertex + const auto& secondaryVertex3 = df3.getPCACandidate(); + // get track momenta + std::array pvec0; + std::array pvec1; + std::array pvec2; + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); auto pVecCandProng3Pos = RecoDecay::pVec(pvec0, pvec1, pvec2); + // 3-prong selections after secondary vertex - array pvCoord3Prong2Pos1Neg = {collision.posX(), collision.posY(), collision.posZ()}; - if (doPvRefit) { - pvCoord3Prong2Pos1Neg[0] = pvRefitCoord3Prong2Pos1Neg[0]; - pvCoord3Prong2Pos1Neg[1] = pvRefitCoord3Prong2Pos1Neg[1]; - pvCoord3Prong2Pos1Neg[2] = pvRefitCoord3Prong2Pos1Neg[2]; - } - is3ProngSelected(pVecCandProng3Pos, secondaryVertex3, pvCoord3Prong2Pos1Neg, cutStatus3Prong, isSelected3ProngCand); + is3ProngSelected(pVecCandProng3Pos, secondaryVertex3, pvRefitCoord3Prong2Pos1Neg, cutStatus3Prong, isSelected3ProngCand); if (!debug && isSelected3ProngCand == 0) { continue; } // fill table row rowTrackIndexProng3(thisCollId, trackPos1.globalIndex(), trackNeg1.globalIndex(), trackPos2.globalIndex(), isSelected3ProngCand); - // fill table row of coordinates of PV refit - rowProng3PVrefit(pvRefitCoord3Prong2Pos1Neg[0], pvRefitCoord3Prong2Pos1Neg[1], pvRefitCoord3Prong2Pos1Neg[2], - pvRefitCovMatrix3Prong2Pos1Neg[0], pvRefitCovMatrix3Prong2Pos1Neg[1], pvRefitCovMatrix3Prong2Pos1Neg[2], pvRefitCovMatrix3Prong2Pos1Neg[3], pvRefitCovMatrix3Prong2Pos1Neg[4], pvRefitCovMatrix3Prong2Pos1Neg[5]); + if constexpr (doPvRefit) { + // fill table row of coordinates of PV refit + rowProng3PVrefit(pvRefitCoord3Prong2Pos1Neg[0], pvRefitCoord3Prong2Pos1Neg[1], pvRefitCoord3Prong2Pos1Neg[2], + pvRefitCovMatrix3Prong2Pos1Neg[0], pvRefitCovMatrix3Prong2Pos1Neg[1], pvRefitCovMatrix3Prong2Pos1Neg[2], pvRefitCovMatrix3Prong2Pos1Neg[3], pvRefitCovMatrix3Prong2Pos1Neg[4], pvRefitCovMatrix3Prong2Pos1Neg[5]); + } if (debug) { int Prong3CutStatus[kN3ProngDecays]; @@ -1971,7 +2114,7 @@ struct HfTrackIndexSkimCreator { registry.fill(HIST("hVtx3ProngX"), secondaryVertex3[0]); registry.fill(HIST("hVtx3ProngY"), secondaryVertex3[1]); registry.fill(HIST("hVtx3ProngZ"), secondaryVertex3[2]); - array, 3> arr3Mom = {pvec0, pvec1, pvec2}; + std::array, 3> arr3Mom = {pvec0, pvec1, pvec2}; for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { if (TESTBIT(isSelected3ProngCand, iDecay3P)) { if (whichHypo3Prong[iDecay3P] == 1 || whichHypo3Prong[iDecay3P] == 3) { @@ -2013,60 +2156,75 @@ struct HfTrackIndexSkimCreator { // second loop over negative tracks // for (auto trackNeg2 = trackNeg1 + 1; trackNeg2 != tracksNeg.end(); ++trackNeg2) { for (auto trackIndexNeg2 = trackIndexNeg1 + 1; trackIndexNeg2 != groupedTrackIndices.end(); ++trackIndexNeg2) { - auto trackNeg2 = trackIndexNeg2.track_as(); + auto trackNeg2 = trackIndexNeg2.template track_as(); if (trackNeg2.signed1Pt() > 0) { continue; } - // retrieve the selection flag that corresponds to this collision - auto isSelProngNeg2 = trackIndexNeg2.isSelProng(); - if (!TESTBIT(isSelProngNeg2, CandidateType::Cand3Prong)) { - continue; - } - auto trackParVarNeg2 = getTrackParCov(trackNeg2); std::array pVecTrackNeg2{trackNeg2.px(), trackNeg2.py(), trackNeg2.pz()}; o2::gpu::gpustd::array dcaInfoNeg2{trackNeg2.dcaXY(), trackNeg2.dcaZ()}; - if (thisCollId != trackNeg2.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarNeg2, 2.f, noMatCorr, &dcaInfoNeg2); - getPxPyPz(trackParVarNeg2, pVecTrackNeg2); + bool propagatedNeg2{false}; + + // first we build D*+ candidates if enabled + auto isSelProngNeg2 = trackIndexNeg2.isSelProng(); + uint8_t isSelectedDstar{0}; + if (doDstar && TESTBIT(isSelected2ProngCand, hf_cand_2prong::DecayType::D0ToPiK) && (whichHypo2Prong[0] >= 2)) { // the 2-prong decay is compatible with a D0bar + if (TESTBIT(isSelProngNeg2, CandidateType::CandDstar)) { // compatible with a soft pion + if (thisCollId != trackNeg2.collisionId()) { // this is not the "default" collision for this track, we have to re-propagate it + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarNeg2, 2.f, noMatCorr, &dcaInfoNeg2); + getPxPyPz(trackParVarNeg2, pVecTrackNeg2); + propagatedNeg2 = true; + } + uint8_t cutStatus{BIT(kNCutsDstar) - 1}; + float deltaMass{-1.}; + isSelectedDstar = isDstarSelected(pVecTrackNeg1, pVecTrackPos1, pVecTrackNeg2, cutStatus, deltaMass); // we do not compute the D* decay vertex at this stage because we are not interested in applying topological selections + if (isSelectedDstar) { + rowTrackIndexDstar(thisCollId, trackNeg2.globalIndex(), rowTrackIndexProng2.lastIndex()); + if (fillHistograms) { + registry.fill(HIST("hMassDstarToD0Pi"), deltaMass); + } + } + if (debug) { + rowDstarCutStatus(cutStatus); + } + } } + // preselection of 3-prong candidates int isSelected3ProngCand = n3ProngBit; + if (do3Prong && TESTBIT(isSelProngNeg2, CandidateType::Cand3Prong) && (sel3ProngStatusPos1 && sel3ProngStatusNeg1)) { + if (thisCollId != trackNeg2.collisionId() && !propagatedNeg2) { // this is not the "default" collision for this track and we still did not re-propagate it, we have to re-propagate it + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParVarNeg2, 2.f, noMatCorr, &dcaInfoNeg2); + getPxPyPz(trackParVarNeg2, pVecTrackNeg2); + } - if (debug) { - for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { - for (int iCut = 0; iCut < kNCuts3Prong; iCut++) { - cutStatus3Prong[iDecay3P][iCut] = true; + if (debug) { + for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { + for (int iCut = 0; iCut < kNCuts3Prong; iCut++) { + cutStatus3Prong[iDecay3P][iCut] = true; + } } } - } - // 3-prong preselections - is3ProngPreselected(pVecTrackNeg1, pVecTrackPos1, pVecTrackNeg2, cutStatus3Prong, whichHypo3Prong, isSelected3ProngCand); - if (!debug && isSelected3ProngCand == 0) { - continue; + // 3-prong preselections + is3ProngPreselected(pVecTrackNeg1, pVecTrackPos1, pVecTrackNeg2, cutStatus3Prong, whichHypo3Prong, isSelected3ProngCand); + if (!debug && isSelected3ProngCand == 0) { + continue; + } + } else { + isSelected3ProngCand = 0; } - // reconstruct the 3-prong secondary vertex - if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) { + // if we did not preselected any D* or 3-prong candidate, continue + if (!debug && (isSelectedDstar == 0 && isSelected3ProngCand == 0)) { continue; } - // get secondary vertex - const auto& secondaryVertex3 = df3.getPCACandidate(); - // get track momenta - array pvec0; - array pvec1; - array pvec2; - df3.getTrack(0).getPxPyPzGlo(pvec0); - df3.getTrack(1).getPxPyPzGlo(pvec1); - df3.getTrack(2).getPxPyPzGlo(pvec2); - /// PV refit excluding the candidate daughters, if contributors - array pvRefitCoord3Prong1Pos2Neg = {collision.posX(), collision.posY(), collision.posZ()}; /// initialize to the original PV - array pvRefitCovMatrix3Prong1Pos2Neg = getPrimaryVertex(collision).getCov(); /// initialize to the original PV - if (doPvRefit) { + std::array pvRefitCoord3Prong1Pos2Neg = {collision.posX(), collision.posY(), collision.posZ()}; /// initialize to the original PV + std::array pvRefitCovMatrix3Prong1Pos2Neg = getPrimaryVertex(collision).getCov(); /// initialize to the original PV + if constexpr (doPvRefit) { if (fillHistograms) { registry.fill(HIST("PvRefit/verticesPerCandidate"), 1); } @@ -2079,7 +2237,7 @@ struct HfTrackIndexSkimCreator { bool isTrackThirdContr = true; if (trackFirstIt == vecPvContributorGlobId.end()) { /// This track did not contribute to the original PV refit - if (debug) { + if (debugPvRefit) { LOG(info) << "--- [3 prong] trackPos1 with globalIndex " << trackPos1.globalIndex() << " was not a PV contributor"; } nCandContr--; @@ -2087,7 +2245,7 @@ struct HfTrackIndexSkimCreator { } if (trackSecondIt == vecPvContributorGlobId.end()) { /// This track did not contribute to the original PV refit - if (debug) { + if (debugPvRefit) { LOG(info) << "--- [3 prong] trackNeg1 with globalIndex " << trackNeg1.globalIndex() << " was not a PV contributor"; } nCandContr--; @@ -2095,7 +2253,7 @@ struct HfTrackIndexSkimCreator { } if (trackThirdIt == vecPvContributorGlobId.end()) { /// This track did not contribute to the original PV refit - if (debug) { + if (debugPvRefit) { LOG(info) << "--- [3 prong] trackNeg2 with globalIndex " << trackNeg2.globalIndex() << " was not a PV contributor"; } nCandContr--; @@ -2116,13 +2274,13 @@ struct HfTrackIndexSkimCreator { if (nCandContr == 3 || nCandContr == 2) { /// At least two of the daughter tracks were used for the original PV refit, let's refit it after excluding them - if (debug) { + if (debugPvRefit) { LOG(info) << "### [3 prong] Calling performPvRefitCandProngs for HF 3 prong candidate, removing " << nCandContr << " daughters"; } performPvRefitCandProngs(collision, bcWithTimeStamps, vecPvContributorGlobId, vecPvContributorTrackParCov, vecCandPvContributorGlobId, pvRefitCoord3Prong1Pos2Neg, pvRefitCovMatrix3Prong1Pos2Neg); } else if (nCandContr == 1) { /// Only one daughter was a contributor, let's use then the PV recalculated by excluding only it - if (debug) { + if (debugPvRefit) { LOG(info) << "####### [3 Prong] nCandContr==" << nCandContr << " ---> just 1 contributor!"; } if (fillHistograms) { @@ -2146,21 +2304,37 @@ struct HfTrackIndexSkimCreator { if (fillHistograms) { registry.fill(HIST("PvRefit/verticesPerCandidate"), 6); } - if (debug) { + if (debugPvRefit) { LOG(info) << "####### [3 prong] nCandContr==" << nCandContr << " ---> some of the candidate daughters did not contribute to the original PV fit, PV refit not redone"; } } + if (isSelectedDstar) { + rowDstarPVrefit(pvRefitCoord3Prong1Pos2Neg[0], pvRefitCoord3Prong1Pos2Neg[1], pvRefitCoord3Prong1Pos2Neg[2], + pvRefitCovMatrix3Prong1Pos2Neg[0], pvRefitCovMatrix3Prong1Pos2Neg[1], pvRefitCovMatrix3Prong1Pos2Neg[2], pvRefitCovMatrix3Prong1Pos2Neg[3], pvRefitCovMatrix3Prong1Pos2Neg[4], pvRefitCovMatrix3Prong1Pos2Neg[5]); + } + } // end of D* + + if (!debug && isSelected3ProngCand == 0) { // below only for 3-prong candidates + continue; } + // reconstruct the 3-prong secondary vertex + if (df3.process(trackParVarNeg1, trackParVarPos1, trackParVarNeg2) == 0) { + continue; + } + // get secondary vertex + const auto& secondaryVertex3 = df3.getPCACandidate(); + // get track momenta + std::array pvec0; + std::array pvec1; + std::array pvec2; + df3.getTrack(0).getPxPyPzGlo(pvec0); + df3.getTrack(1).getPxPyPzGlo(pvec1); + df3.getTrack(2).getPxPyPzGlo(pvec2); auto pVecCandProng3Neg = RecoDecay::pVec(pvec0, pvec1, pvec2); + // 3-prong selections after secondary vertex - array pvCoord3Prong1Pos2Neg = {collision.posX(), collision.posY(), collision.posZ()}; - if (doPvRefit) { - pvCoord3Prong1Pos2Neg[0] = pvRefitCoord3Prong1Pos2Neg[0]; - pvCoord3Prong1Pos2Neg[1] = pvRefitCoord3Prong1Pos2Neg[1]; - pvCoord3Prong1Pos2Neg[2] = pvRefitCoord3Prong1Pos2Neg[2]; - } - is3ProngSelected(pVecCandProng3Neg, secondaryVertex3, pvCoord3Prong1Pos2Neg, cutStatus3Prong, isSelected3ProngCand); + is3ProngSelected(pVecCandProng3Neg, secondaryVertex3, pvRefitCoord3Prong1Pos2Neg, cutStatus3Prong, isSelected3ProngCand); if (!debug && isSelected3ProngCand == 0) { continue; } @@ -2168,8 +2342,10 @@ struct HfTrackIndexSkimCreator { // fill table row rowTrackIndexProng3(thisCollId, trackNeg1.globalIndex(), trackPos1.globalIndex(), trackNeg2.globalIndex(), isSelected3ProngCand); // fill table row of coordinates of PV refit - rowProng3PVrefit(pvRefitCoord3Prong1Pos2Neg[0], pvRefitCoord3Prong1Pos2Neg[1], pvRefitCoord3Prong1Pos2Neg[2], - pvRefitCovMatrix3Prong1Pos2Neg[0], pvRefitCovMatrix3Prong1Pos2Neg[1], pvRefitCovMatrix3Prong1Pos2Neg[2], pvRefitCovMatrix3Prong1Pos2Neg[3], pvRefitCovMatrix3Prong1Pos2Neg[4], pvRefitCovMatrix3Prong1Pos2Neg[5]); + if constexpr (doPvRefit) { + rowProng3PVrefit(pvRefitCoord3Prong1Pos2Neg[0], pvRefitCoord3Prong1Pos2Neg[1], pvRefitCoord3Prong1Pos2Neg[2], + pvRefitCovMatrix3Prong1Pos2Neg[0], pvRefitCovMatrix3Prong1Pos2Neg[1], pvRefitCovMatrix3Prong1Pos2Neg[2], pvRefitCovMatrix3Prong1Pos2Neg[3], pvRefitCovMatrix3Prong1Pos2Neg[4], pvRefitCovMatrix3Prong1Pos2Neg[5]); + } if (debug) { int Prong3CutStatus[kN3ProngDecays]; @@ -2189,7 +2365,7 @@ struct HfTrackIndexSkimCreator { registry.fill(HIST("hVtx3ProngX"), secondaryVertex3[0]); registry.fill(HIST("hVtx3ProngY"), secondaryVertex3[1]); registry.fill(HIST("hVtx3ProngZ"), secondaryVertex3[2]); - array, 3> arr3Mom = {pvec0, pvec1, pvec2}; + std::array, 3> arr3Mom = {pvec0, pvec1, pvec2}; for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { if (TESTBIT(isSelected3ProngCand, iDecay3P)) { if (whichHypo3Prong[iDecay3P] == 1 || whichHypo3Prong[iDecay3P] == 3) { @@ -2244,8 +2420,35 @@ struct HfTrackIndexSkimCreator { registry.fill(HIST("hNCand3ProngVsNTracks"), nTracks, nCand3); } } + } /// end of run2And3Prongs function + + void processNo2And3Prongs(SelectedCollisions const&) + { + // dummy + } + PROCESS_SWITCH(HfTrackIndexSkimCreator, processNo2And3Prongs, "Do not process 2-prongs and 3-prongs", false); + + void process2And3ProngsWithPvRefit( // soa::Join::iterator const& collision, //FIXME add centrality when option for variations to the process function appears + SelectedCollisions const& collisions, + aod::BCsWithTimestamps const& bcWithTimeStamps, + FilteredTrackAssocSel const& trackIndices, + TracksWithPVRefitAndDCA const& tracks) + { + run2And3Prongs(collisions, bcWithTimeStamps, trackIndices, tracks); + } + + PROCESS_SWITCH(HfTrackIndexSkimCreator, process2And3ProngsWithPvRefit, "Process 2-prong and 3-prong skim with PV refit", false); + + void process2And3ProngsNoPvRefit( // soa::Join::iterator const& collision, //FIXME add centrality when option for variations to the process function appears + SelectedCollisions const& collisions, + aod::BCsWithTimestamps const& bcWithTimeStamps, + FilteredTrackAssocSel const& trackIndices, + aod::TracksWCovDcaExtra const& tracks) + { + run2And3Prongs(collisions, bcWithTimeStamps, trackIndices, tracks); } - PROCESS_SWITCH(HfTrackIndexSkimCreator, process2And3Prongs, "Process 2-prong and 3-prong skim", true); + + PROCESS_SWITCH(HfTrackIndexSkimCreator, process2And3ProngsNoPvRefit, "Process 2-prong and 3-prong skim without PV refit", true); }; //________________________________________________________________________________________________________________________ @@ -2314,21 +2517,19 @@ struct HfTrackIndexSkimCreatorCascades { o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int runNumber; - double massP = RecoDecay::getMassPDG(kProton); - double massK0s = RecoDecay::getMassPDG(kK0Short); - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massLc = RecoDecay::getMassPDG(pdg::Code::kLambdaCPlus); + double massP{0.}; + double massK0s{0.}; + double massPi{0.}; + double massLc{0.}; double mass2K0sP{0.}; // WHY HERE? using SelectedCollisions = soa::Filtered>; - using TracksWithPVRefitAndDCA = soa::Join; + using FilteredTrackAssocSel = soa::Filtered>; Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == 0); Filter filterSelectTrackIds = (aod::hf_sel_track::isSelProng >= 4); // Partition TracksWithPVRefitAndDCA = aod::hf_sel_track::isSelProng >= 4; - Preslice tracksPerCollision = aod::track::collisionId; // needed for PV refit - using FilteredTrackAssocSel = soa::Filtered>; Preslice trackIndicesPerCollision = aod::track_association::collisionId; Preslice v0sPerCollision = aod::v0data::collisionId; @@ -2345,6 +2546,11 @@ struct HfTrackIndexSkimCreatorCascades { etaMinV0Daugh.value = -etaMaxV0Daugh; } + massP = o2::analysis::pdg::MassProton; + massK0s = o2::analysis::pdg::MassK0Short; + massPi = o2::analysis::pdg::MassPiPlus; + massLc = o2::analysis::pdg::MassLambdaCPlus; + ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -2366,16 +2572,13 @@ struct HfTrackIndexSkimCreatorCascades { PROCESS_SWITCH(HfTrackIndexSkimCreatorCascades, processNoCascades, "Do not skim HF -> V0 cascades", true); void processCascades(SelectedCollisions const& collisions, - aod::BCsWithTimestamps const&, - // soa::Filtered const& V0s, - aod::V0Datas const& V0s, + aod::V0Datas const& v0s, // TODO: I am now assuming that the V0s are already filtered with my cuts (David's work to come) FilteredTrackAssocSel const& trackIndices, - TracksWithPVRefitAndDCA const& tracks + aod::TracksWCovDcaExtra const& tracks, #ifdef MY_DEBUG - , - aod::McParticles& mcParticles + aod::McParticles& mcParticles, #endif - ) // TODO: I am now assuming that the V0s are already filtered with my cuts (David's work to come) + aod::BCsWithTimestamps const&) { // set the magnetic field from CCDB for (const auto& collision : collisions) { @@ -2401,7 +2604,7 @@ struct HfTrackIndexSkimCreatorCascades { // for (const auto& bach : selectedTracks) { for (const auto& bachIdx : groupedBachTrackIndices) { - auto bach = bachIdx.track_as(); + auto bach = bachIdx.track_as(); MY_DEBUG_MSG(1, printf("\n"); LOG(info) << "Bachelor loop"); #ifdef MY_DEBUG @@ -2432,13 +2635,13 @@ struct HfTrackIndexSkimCreatorCascades { auto trackBach = getTrackParCov(bach); - auto groupedV0s = V0s.sliceBy(v0sPerCollision, thisCollId); + auto groupedV0s = v0s.sliceBy(v0sPerCollision, thisCollId); // now we loop over the V0s for (const auto& v0 : groupedV0s) { MY_DEBUG_MSG(1, LOG(info) << "*** Checking next K0S"); // selections on the V0 daughters - const auto& trackV0DaughPos = v0.posTrack_as(); - const auto& trackV0DaughNeg = v0.negTrack_as(); + const auto& trackV0DaughPos = v0.posTrack_as(); + const auto& trackV0DaughNeg = v0.negTrack_as(); // check not to take the same track twice (as bachelor and V0 daughter) if (trackV0DaughPos.globalIndex() == bach.globalIndex() || trackV0DaughNeg.globalIndex() == bach.globalIndex()) { @@ -2506,7 +2709,7 @@ struct HfTrackIndexSkimCreatorCascades { // invariant-mass cut: we do it here, before updating the momenta of bach and V0 during the fitting to save CPU // TODO: but one should better check that the value here and after the fitter do not change significantly!!! - mass2K0sP = RecoDecay::m(array{array{bach.px(), bach.py(), bach.pz()}, momentumV0}, array{massP, massK0s}); + mass2K0sP = RecoDecay::m(std::array{std::array{bach.px(), bach.py(), bach.pz()}, momentumV0}, std::array{massP, massK0s}); if ((cutInvMassCascLc >= 0.) && (std::abs(mass2K0sP - massLc) > cutInvMassCascLc)) { MY_DEBUG_MSG(isK0SfromLc && isProtonFromLc, LOG(info) << "True Lc from proton " << indexBach << " and K0S pos " << indexV0DaughPos << " and neg " << indexV0DaughNeg << " rejected due to invMass cut: " << mass2K0sP << ", mass Lc " << massLc << " (cut " << cutInvMassCascLc << ")"); continue; @@ -2523,7 +2726,7 @@ struct HfTrackIndexSkimCreatorCascades { const std::array vertexV0 = {v0.x(), v0.y(), v0.z()}; // we build the neutral track to then build the cascade - auto trackV0 = o2::dataformats::V0(vertexV0, momentumV0, {0, 0, 0, 0, 0, 0}, trackParCovV0DaughPos, trackParCovV0DaughNeg, {0, 0}, {0, 0}); // build the V0 track + auto trackV0 = o2::dataformats::V0(vertexV0, momentumV0, {0, 0, 0, 0, 0, 0}, trackParCovV0DaughPos, trackParCovV0DaughNeg); // build the V0 track // now we find the DCA between the V0 and the bachelor, for the cascade int nCand2 = fitter.process(trackV0, trackBach); @@ -2545,7 +2748,7 @@ struct HfTrackIndexSkimCreatorCascades { // invariant mass // re-calculate invariant masses with updated momenta, to fill the histogram - mass2K0sP = RecoDecay::m(array{pVecBach, pVecV0}, array{massP, massK0s}); + mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{massP, massK0s}); std::array posCasc = {0., 0., 0.}; const auto& cascVtx = fitter.getPCACandidate(); @@ -2566,7 +2769,8 @@ struct HfTrackIndexSkimCreatorCascades { } // loop over V0s } // loop over tracks } // loop over collisions - } // process + } // processCascades + PROCESS_SWITCH(HfTrackIndexSkimCreatorCascades, processCascades, "Skim HF -> V0 cascades", false); }; @@ -2626,29 +2830,37 @@ struct HfTrackIndexSkimCreatorLfCascades { std::array, 2>, kN2ProngDecays> arrMass2Prong; std::array, 2>, kN3ProngDecays> arrMass3Prong; + double massP{0.}; + double massPi{0.}; + double massXi{0.}; + double massOmega{0.}; + double massXiczero{0.}; + double massXicplus{0.}; + // histograms HistogramRegistry registry{"registry"}; - double massP = RecoDecay::getMassPDG(kProton); - double massPi = RecoDecay::getMassPDG(kPiPlus); - double massXi = RecoDecay::getMassPDG(kXiMinus); - double massOmega = RecoDecay::getMassPDG(kOmegaMinus); - double massXiczero = RecoDecay::getMassPDG(pdg::Code::kXiCZero); - double massXicplus = RecoDecay::getMassPDG(pdg::Code::kXiCPlus); - void init(InitContext const&) { if (!doprocessLfCascades) { return; } - arrMass2Prong[hf_cand_casc_lf_2prong::DecayType::XiczeroToXiPi] = array{array{massXi, massPi}, - array{massPi, massXi}}; - arrMass2Prong[hf_cand_casc_lf_2prong::DecayType::OmegaczeroToOmegaPi] = array{array{massOmega, massPi}, - array{massPi, massOmega}}; + massP = o2::analysis::pdg::MassProton; + massPi = o2::analysis::pdg::MassPiPlus; + massXi = o2::analysis::pdg::MassXiMinus; + massOmega = o2::analysis::pdg::MassOmegaMinus; + massXiczero = o2::analysis::pdg::MassXiCZero; + massXicplus = o2::analysis::pdg::MassXiCPlus; + + arrMass2Prong[hf_cand_casc_lf_2prong::DecayType::XiczeroToXiPi] = std::array{std::array{massXi, massPi}, + std::array{massPi, massXi}}; - arrMass3Prong[hf_cand_casc_lf_3prong::DecayType::XicplusToXiPiPi] = array{array{massXi, massPi, massPi}, - array{massPi, massPi, massXi}}; + arrMass2Prong[hf_cand_casc_lf_2prong::DecayType::OmegaczeroToOmegaPi] = std::array{std::array{massOmega, massPi}, + std::array{massPi, massOmega}}; + + arrMass3Prong[hf_cand_casc_lf_3prong::DecayType::XicplusToXiPiPi] = std::array{std::array{massXi, massPi, massPi}, + std::array{massPi, massPi, massXi}}; ccdb->setURL(ccdbUrl); ccdb->setCaching(true); @@ -2705,7 +2917,7 @@ struct HfTrackIndexSkimCreatorLfCascades { Filter filterSelectTrackIds = (aod::hf_sel_track::isSelProng > 0); using SelectedCollisions = soa::Filtered>; - using TracksWithPVRefitAndDCA = soa::Join; + using TracksWithPVRefitAndDCA = soa::Join; using V0Full = soa::Join; Preslice tracksPerCollision = aod::track::collisionId; // needed for PV refit @@ -2769,12 +2981,12 @@ struct HfTrackIndexSkimCreatorLfCascades { PROCESS_SWITCH(HfTrackIndexSkimCreatorLfCascades, processNoLfCascades, "Do not skim LF cascades", true); void processLfCascades(SelectedCollisions const& collisions, - aod::BCsWithTimestamps const&, - aod::V0sLinked const&, - V0Full const&, aod::CascDataFull const& cascades, FilteredTrackAssocSel const& trackIndices, - TracksWithPVRefitAndDCA const& tracks) + aod::TracksWCovDca const& tracks, + aod::BCsWithTimestamps const&, + aod::V0sLinked const&, + V0Full const&) { for (const auto& collision : collisions) { @@ -2812,7 +3024,7 @@ struct HfTrackIndexSkimCreatorLfCascades { registry.fill(HIST("hCandidateCounter"), 0.5); // all candidates - auto trackXiDauCharged = casc.bachelor_as(); // pion <- xi track from TracksWithPVRefitAndDCA table + auto trackXiDauCharged = casc.bachelor_as(); // pion <- xi track from TracksWithPVRefitAndDCA table // cascade daughter - V0 if (!casc.v0_as().has_v0Data()) { // check that V0 data are stored continue; @@ -2821,9 +3033,9 @@ struct HfTrackIndexSkimCreatorLfCascades { auto v0index = casc.v0_as(); auto v0 = v0index.v0Data_as(); // V0 element from LF table containing V0 info // V0 positive daughter - auto trackV0DauPos = v0.posTrack_as(); // p <- V0 track (positive track) from TracksWithPVRefitAndDCA table + auto trackV0DauPos = v0.posTrack_as(); // p <- V0 track (positive track) from TracksWithPVRefitAndDCA table // V0 negative daughter - auto trackV0DauNeg = v0.negTrack_as(); // pion <- V0 track (negative track) from TracksWithPVRefitAndDCA table + auto trackV0DauNeg = v0.negTrack_as(); // pion <- V0 track (negative track) from TracksWithPVRefitAndDCA table // check that particles come from the same collision if (rejDiffCollTrack) { @@ -2870,8 +3082,8 @@ struct HfTrackIndexSkimCreatorLfCascades { continue; } - array pvecV0; // V0 - array pvecXiDauPion; // bach pion + std::array pvecV0; // V0 + std::array pvecXiDauPion; // bach pion dfc.getTrack(0).getPxPyPzGlo(pvecV0); dfc.getTrack(1).getPxPyPzGlo(pvecXiDauPion); @@ -2880,13 +3092,13 @@ struct HfTrackIndexSkimCreatorLfCascades { std::array covVtxCasc = dfc.calcPCACovMatrixFlat(); std::array pvecCascAsM = {pvecV0[0] + pvecXiDauPion[0], pvecV0[1] + pvecXiDauPion[1], pvecV0[2] + pvecXiDauPion[2]}; - auto trackCasc = o2::dataformats::V0(coordVtxCasc, pvecCascAsM, covVtxCasc, trackV0, trackParVarXiDauCharged, {0, 0}, {0, 0}); + auto trackCasc = o2::dataformats::V0(coordVtxCasc, pvecCascAsM, covVtxCasc, trackV0, trackParVarXiDauCharged); //-------------------combining cascade and pion tracks-------------------------- // first loop over positive tracks auto groupedBachTrackIndices = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); for (auto trackIdPion1 = groupedBachTrackIndices.begin(); trackIdPion1 != groupedBachTrackIndices.end(); ++trackIdPion1) { - auto trackPion1 = trackIdPion1.track_as(); + auto trackPion1 = trackIdPion1.track_as(); if ((rejDiffCollTrack) && (trackXiDauCharged.collisionId() != trackPion1.collisionId())) { continue; @@ -2909,7 +3121,7 @@ struct HfTrackIndexSkimCreatorLfCascades { if (do3Prong) { // second loop over positive tracks for (auto trackIdPion2 = trackIdPion1 + 1; trackIdPion2 != groupedBachTrackIndices.end(); ++trackIdPion2) { - auto trackPion2 = trackIdPion2.track_as(); + auto trackPion2 = trackIdPion2.track_as(); if ((rejDiffCollTrack) && (trackXiDauCharged.collisionId() != trackPion2.collisionId())) { continue; @@ -2955,7 +3167,7 @@ struct HfTrackIndexSkimCreatorLfCascades { registry.fill(HIST("hVtx3ProngY"), secondaryVertex3[1]); registry.fill(HIST("hVtx3ProngZ"), secondaryVertex3[2]); - array, 3> arr3Mom = {pVec1, pVec2, pVec3}; + std::array, 3> arr3Mom = {pVec1, pVec2, pVec3}; for (int iDecay3P = 0; iDecay3P < kN3ProngDecays; iDecay3P++) { auto mass3Prong = RecoDecay::m(arr3Mom, arrMass3Prong[iDecay3P][0]); switch (iDecay3P) { @@ -2990,7 +3202,7 @@ struct HfTrackIndexSkimCreatorLfCascades { registry.fill(HIST("hVtx2ProngY"), secondaryVertex2[1]); registry.fill(HIST("hVtx2ProngZ"), secondaryVertex2[2]); - array, 2> arrMom = {pVec1, pVec2}; + std::array, 2> arrMom = {pVec1, pVec2}; for (int iDecay2P = 0; iDecay2P < kN2ProngDecays; iDecay2P++) { auto mass2Prong = RecoDecay::m(arrMom, arrMass2Prong[iDecay2P][0]); switch (iDecay2P) { @@ -3006,7 +3218,8 @@ struct HfTrackIndexSkimCreatorLfCascades { } // loop over pion } // loop over cascade } // loop over collisions - } // process + } // processLfCascades + PROCESS_SWITCH(HfTrackIndexSkimCreatorLfCascades, processLfCascades, "Skim LF cascades", false); }; diff --git a/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx new file mode 100644 index 00000000000..ce4d0dc42a0 --- /dev/null +++ b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx @@ -0,0 +1,382 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file treeCreatorB0ToDPi.cxx +/// \brief Writer of B0 → D- π+ candidates in the form of flat tables to be stored in TTrees. +/// Intended for debug, local optimization of analysis on small samples or ML training. +/// In this file are defined and filled the output tables +/// +/// \author Alexandre Bigot , IPHC Strasbourg + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace full +{ +DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); //! Radius of secondary vertex (cm) +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! Momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); //! Normalised impact parameter of prong0 +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! Momentum of prong1 (in GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! Normalised impact parameter of prong1 +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(Ct, ct, float); //! Proper lifetime times c of candidate (cm) +// Events +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); //! Event rejection flag +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number +} // namespace full + +DECLARE_SOA_TABLE(HfCandB0Lites, "AOD", "HFCANDB0LITE", + hf_cand::Chi2PCA, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::PtProng0, + full::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + full::NSigTpcPi1, + full::NSigTofPi1, + full::CandidateSelFlag, + full::M, + full::Pt, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::Eta, + full::Phi, + full::Y, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec); + +DECLARE_SOA_TABLE(HfCandB0Fulls, "AOD", "HFCANDB0FULL", + collision::BCId, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + hf_cand::XSecondaryVertex, + hf_cand::YSecondaryVertex, + hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, + hf_cand::ErrorDecayLengthXY, + hf_cand::Chi2PCA, + full::RSecondaryVertex, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::ImpactParameterNormalised0, + full::PtProng0, + full::PProng0, + full::ImpactParameterNormalised1, + full::PtProng1, + full::PProng1, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ErrorImpactParameter0, + hf_cand::ErrorImpactParameter1, + full::NSigTpcPi1, + full::NSigTofPi1, + full::CandidateSelFlag, + full::M, + full::Pt, + full::P, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::Ct, + full::Eta, + full::Phi, + full::Y, + full::E, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec); + +DECLARE_SOA_TABLE(HfCandB0FullEvs, "AOD", "HFCANDB0FULLEV", + collision::BCId, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + full::IsEventReject, + full::RunNumber); + +DECLARE_SOA_TABLE(HfCandB0FullPs, "AOD", "HFCANDB0FULLP", + collision::BCId, + full::Pt, + full::Eta, + full::Phi, + full::Y, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcGen); +} // namespace o2::aod + +/// Writes the full information in an output TTree +struct HfTreeCreatorB0ToDPi { + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + Produces rowCandidateLite; + + Configurable selectionFlagB0{"selectionB0", 1, "Selection Flag for B0"}; + Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; + // parameters for production of training samples + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; + Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + + HfHelper hfHelper; + + using SelectedCandidatesMc = soa::Filtered>; + using TracksWPid = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0; + + Partition recSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); + Partition recBg = nabs(aod::hf_cand_b0::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); + + void init(InitContext const&) + { + } + + template + void fillEvent(const T& collision, int isEventReject, int runNumber) + { + rowCandidateFullEvents( + collision.bcId(), + collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ(), + isEventReject, + runNumber); + } + + template + void fillCandidateTable(const T& candidate, const U& prong1) + { + int8_t flagMc = 0; + int8_t originMc = 0; + if constexpr (doMc) { + flagMc = candidate.flagMcMatchRec(); + originMc = candidate.originMcRec(); + } + if (fillCandidateLiteTable) { + rowCandidateLite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + candidate.isSelB0ToDPi(), + hfHelper.invMassB0ToDPi(candidate), + candidate.pt(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yB0(candidate), + flagMc, + originMc); + } else { + rowCandidateFull( + prong1.collision().bcId(), + prong1.collision().numContrib(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.chi2PCA(), + candidate.rSecondaryVertex(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.impactParameterNormalised0(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.impactParameterNormalised1(), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + candidate.isSelB0ToDPi(), + hfHelper.invMassB0ToDPi(candidate), + candidate.pt(), + candidate.p(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + hfHelper.ctB0(candidate), + candidate.eta(), + candidate.phi(), + hfHelper.yB0(candidate), + hfHelper.eB0(candidate), + flagMc, + originMc); + } + } + + void processData(aod::Collisions const& collisions, + soa::Filtered> const& candidates, + TracksWPid const&) + { + // Filling event properties + rowCandidateFullEvents.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, 0, 1); + } + + // Filling candidate properties + rowCandidateFull.reserve(candidates.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + if (fillOnlyBackground) { + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + auto prong1 = candidate.prong1_as(); + fillCandidateTable(candidate, prong1); + } + } + + PROCESS_SWITCH(HfTreeCreatorB0ToDPi, processData, "Process data", true); + + void processMc(aod::Collisions const& collisions, + aod::McCollisions const&, + SelectedCandidatesMc const& candidates, + soa::Join const& particles, + TracksWPid const&) + { + // Filling event properties + rowCandidateFullEvents.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, 0, 1); + } + + // Filling candidate properties + if (fillOnlySignal) { + rowCandidateFull.reserve(recSig.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(recSig.size()); + } + for (const auto& candidate : recSig) { + auto prong1 = candidate.prong1_as(); + fillCandidateTable(candidate, prong1); + } + } else if (fillOnlyBackground) { + rowCandidateFull.reserve(recBg.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(recBg.size()); + } + for (const auto& candidate : recBg) { + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + auto prong1 = candidate.prong1_as(); + fillCandidateTable(candidate, prong1); + } + } else { + rowCandidateFull.reserve(candidates.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + auto prong1 = candidate.prong1_as(); + fillCandidateTable(candidate, prong1); + } + } + + // Filling particle properties + rowCandidateFullParticles.reserve(particles.size()); + for (const auto& particle : particles) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi)) { + rowCandidateFullParticles( + particle.mcCollision().bcId(), + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassB0), + particle.flagMcMatchGen(), + particle.originMcGen()); + } + } + } + + PROCESS_SWITCH(HfTreeCreatorB0ToDPi, processMc, "Process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx index 8e32045678d..18dc4843ae9 100644 --- a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx @@ -17,19 +17,16 @@ /// /// \author Antonio Palasciano , Università & INFN, Bari -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::aod; using namespace o2::framework; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_bplus; namespace o2::aod { @@ -95,11 +92,11 @@ DECLARE_SOA_COLUMN(NSigmaTPCTrk1Pi, nSigmaTPCTrk1Pi, float); // Events DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); -DECLARE_SOA_COLUMN(GlobalIndex, globalIndex, int); +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCandBplus, "_0"); } // namespace full // put the arguments into the table -DECLARE_SOA_TABLE(HfCandBplusFull, "AOD", "HFCANDBPFull", +DECLARE_SOA_TABLE(HfCandBpFulls, "AOD", "HFCANDBPFULL", full::RSecondaryVertex, full::PtProng0, full::PProng0, @@ -161,9 +158,9 @@ DECLARE_SOA_TABLE(HfCandBplusFull, "AOD", "HFCANDBPFull", full::NSigmaTOFTrk1Ka, full::NSigmaTPCTrk1Pi, full::NSigmaTPCTrk1Ka, - full::GlobalIndex); + full::CandidateId); -DECLARE_SOA_TABLE(HfCandBplusFullEvents, "AOD", "HFCANDBPFullE", +DECLARE_SOA_TABLE(HfCandBpFullEvs, "AOD", "HFCANDBPFULLEV", collision::BCId, collision::NumContrib, collision::PosX, @@ -172,40 +169,44 @@ DECLARE_SOA_TABLE(HfCandBplusFullEvents, "AOD", "HFCANDBPFullE", full::IsEventReject, full::RunNumber); -DECLARE_SOA_TABLE(HfCandBplusFullParticles, "AOD", "HFCANDBPFullP", +DECLARE_SOA_TABLE(HfCandBpFullPs, "AOD", "HFCANDBPFULLP", collision::BCId, full::Pt, full::Eta, full::Phi, full::Y, full::MCflag, - full::GlobalIndex); + full::CandidateId); } // namespace o2::aod /// Writes the full information in an output TTree struct HfTreeCreatorBplusToD0Pi { - Produces rowCandidateFull; - Produces rowCandidateFullEvents; - Produces rowCandidateFullParticles; + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; Configurable isSignal{"isSignal", 1, "save only MC matched candidates"}; + HfHelper hfHelper; + + using TracksWPid = soa::Join; + void init(InitContext const&) { } void process(aod::Collisions const& collisions, - aod::McCollisions const& mccollisions, + aod::McCollisions const&, soa::Join const& candidates, - soa::Join const& particles, - aod::BigTracksPID const& tracks, + soa::Join const& particles, + TracksWPid const&, aod::HfCand2Prong const&) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { rowCandidateFullEvents( collision.bcId(), collision.numContrib(), @@ -218,23 +219,23 @@ struct HfTreeCreatorBplusToD0Pi { // Filling candidate properties rowCandidateFull.reserve(candidates.size()); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { auto fillTable = [&](int CandFlag, // int FunctionSelection, float FunctionInvMass, float FunctionCt, float FunctionY) { auto d0Cand = candidate.prong0(); - auto piCand = candidate.prong1_as(); + auto piCand = candidate.prong1_as(); // adding D0 daughters to the table - auto d0Daughter0 = d0Cand.prong0_as(); - auto d0Daughter1 = d0Cand.prong1_as(); + auto d0Daughter0 = d0Cand.prong0_as(); + auto d0Daughter1 = d0Cand.prong1_as(); auto invMassD0 = 0.; if (piCand.sign() > 0) { - invMassD0 = o2::aod::hf_cand_2prong::invMassD0barToKPi(d0Cand); + invMassD0 = hfHelper.invMassD0barToKPi(d0Cand); } else if (piCand.sign() < 0) { - invMassD0 = o2::aod::hf_cand_2prong::invMassD0ToPiK(d0Cand); + invMassD0 = hfHelper.invMassD0ToPiK(d0Cand); } // if (FunctionSelection >= 1) { @@ -280,7 +281,7 @@ struct HfTreeCreatorBplusToD0Pi { invMassD0, d0Cand.ptProng0(), d0Cand.ptProng1(), - o2::aod::hf_cand_2prong::yD0(d0Cand), + hfHelper.yD0(d0Cand), d0Cand.eta(), d0Cand.cpa(), d0Cand.cpaXY(), @@ -306,20 +307,20 @@ struct HfTreeCreatorBplusToD0Pi { } }; - // fillTable(0, candidate.isSelBplusToD0Pi(), invMassBplusToD0Pi(candidate), ctBplus(candidate), yBplus(candidate)); - fillTable(0, invMassBplusToD0Pi(candidate), ctBplus(candidate), yBplus(candidate)); + // fillTable(0, candidate.isSelBplusToD0Pi(), hfHelper.invMassBplusToD0Pi(candidate), hfHelper.ctBplus(candidate), hfHelper.yBplus(candidate)); + fillTable(0, hfHelper.invMassBplusToD0Pi(candidate), hfHelper.ctBplus(candidate), hfHelper.yBplus(candidate)); } // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); - for (auto& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::BplusToD0Pi) { + for (const auto& particle : particles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_bplus::DecayType::BplusToD0Pi) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), particle.eta(), particle.phi(), - RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassBPlus), particle.flagMcMatchGen(), particle.globalIndex()); } diff --git a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx new file mode 100644 index 00000000000..ef842de5d01 --- /dev/null +++ b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx @@ -0,0 +1,371 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file treeCreatorBsToDsPi.cxx +/// \brief Writer of Bs0 → Ds- π+ candidates in the form of flat tables to be stored in TTrees. +/// Intended for debug, local optimization of analysis on small samples or ML training. +/// The output tables are defined and filled in this file. +/// \note Adapted from treeCreatorB0T0DPi.cxx +/// \author Phil Stahlhut + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace full +{ +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! Momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); //! Normalised impact parameter of prong0 +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! Momentum of prong1 (in GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! Normalised impact parameter of prong1 +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(Ct, ct, float); //! Proper lifetime time ctau of candidate (cm) +// Events +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); //! Event rejection flag +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number +} // namespace full + +DECLARE_SOA_TABLE(HfCandBsLites, "AOD", "HFCANDBSLITE", + hf_cand::Chi2PCA, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::PtProng0, + full::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + full::NSigTpcPi1, + full::NSigTofPi1, + full::CandidateSelFlag, + full::M, + full::Pt, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::Eta, + full::Phi, + full::Y, + hf_cand_bs::FlagMcMatchRec); + +DECLARE_SOA_TABLE(HfCandBsFulls, "AOD", "HFCANDBSFULL", + collision::BCId, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + hf_cand::XSecondaryVertex, + hf_cand::YSecondaryVertex, + hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, + hf_cand::ErrorDecayLengthXY, + hf_cand::Chi2PCA, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::ImpactParameterNormalised0, + full::PtProng0, + full::PProng0, + full::ImpactParameterNormalised1, + full::PtProng1, + full::PProng1, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ErrorImpactParameter0, + hf_cand::ErrorImpactParameter1, + full::NSigTpcPi1, + full::NSigTofPi1, + full::CandidateSelFlag, + full::M, + full::Pt, + full::P, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::Ct, + full::Eta, + full::Phi, + full::Y, + full::E, + hf_cand_bs::FlagMcMatchRec); + +DECLARE_SOA_TABLE(HfCandBsFullEvs, "AOD", "HFCANDBSFULLEV", + collision::BCId, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + full::IsEventReject, + full::RunNumber); + +DECLARE_SOA_TABLE(HfCandBsFullPs, "AOD", "HFCANDBSFULLP", + collision::BCId, + full::Pt, + full::Eta, + full::Phi, + full::Y, + hf_cand_bs::FlagMcMatchGen); +} // namespace o2::aod + +/// Writes the full information in an output TTree +struct HfTreeCreatorBsToDsPi { + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + Produces rowCandidateLite; + + Configurable selectionFlagBs{"selectionBs", 1, "Selection Flag for Bs"}; + Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; + // parameters for production of training samples + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; + Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + + HfHelper hfHelper; + + using SelectedCandidatesMc = soa::Filtered>; + using TracksWPid = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_bs::isSelBsToDsPi >= selectionFlagBs; + + Partition recSig = nabs(aod::hf_cand_bs::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); + Partition recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi); + + void init(InitContext const&) + { + } + + template + void fillEvent(const T& collision, int isEventReject, int runNumber) + { + rowCandidateFullEvents( + collision.bcId(), + collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ(), + isEventReject, + runNumber); + } + + template + void fillCandidateTable(const T& candidate, const U& prong1) + { + int8_t flagMc = 0; + if constexpr (doMc) { + flagMc = candidate.flagMcMatchRec(); + } + if (fillCandidateLiteTable) { + rowCandidateLite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + candidate.isSelBsToDsPi(), + hfHelper.invMassBsToDsPi(candidate), + candidate.pt(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.eta(), + candidate.phi(), + hfHelper.yBs(candidate), + flagMc); + } else { + rowCandidateFull( + prong1.collision().bcId(), + prong1.collision().numContrib(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.impactParameterNormalised0(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.impactParameterNormalised1(), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + candidate.isSelBsToDsPi(), + hfHelper.invMassBsToDsPi(candidate), + candidate.pt(), + candidate.p(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + hfHelper.ctBs(candidate), + candidate.eta(), + candidate.phi(), + hfHelper.yBs(candidate), + hfHelper.eBs(candidate), + flagMc); + } + } + + void processData(aod::Collisions const& collisions, + soa::Filtered> const& candidates, + TracksWPid const&) + { + // Filling event properties + rowCandidateFullEvents.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, 0, 1); + } + + // Filling candidate properties + rowCandidateFull.reserve(candidates.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + if (fillOnlyBackground && downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (pseudoRndm >= downSampleBkgFactor && candidate.pt() < ptMaxForDownSample) { + continue; + } + } + auto prong1 = candidate.prong1_as(); + fillCandidateTable(candidate, prong1); + } + } + + PROCESS_SWITCH(HfTreeCreatorBsToDsPi, processData, "Process data", true); + + void processMc(aod::Collisions const& collisions, + aod::McCollisions const&, + SelectedCandidatesMc const& candidates, + soa::Join const& particles, + TracksWPid const&) + { + // Filling event properties + rowCandidateFullEvents.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, 0, 1); + } + + // Filling candidate properties + if (fillOnlySignal) { + rowCandidateFull.reserve(recSig.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(recSig.size()); + } + for (const auto& candidate : recSig) { + auto prong1 = candidate.prong1_as(); + fillCandidateTable(candidate, prong1); + } + } else if (fillOnlyBackground) { + rowCandidateFull.reserve(recBg.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(recBg.size()); + } + for (const auto& candidate : recBg) { + float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + auto prong1 = candidate.prong1_as(); + fillCandidateTable(candidate, prong1); + } + } else { + rowCandidateFull.reserve(candidates.size()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + auto prong1 = candidate.prong1_as(); + fillCandidateTable(candidate, prong1); + } + } + + // Filling particle properties + rowCandidateFullParticles.reserve(particles.size()); + for (const auto& particle : particles) { + if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_bs::DecayTypeMc::BsToDsPiToKKPiPi)) { + rowCandidateFullParticles( + particle.mcCollision().bcId(), + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassBS), + particle.flagMcMatchGen()); + } + } + } + + PROCESS_SWITCH(HfTreeCreatorBsToDsPi, processMc, "Process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx index c3e64ea438c..c1a725ef54b 100644 --- a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx @@ -17,22 +17,22 @@ /// \author Nicolo' Jacazio , CERN /// \author Andrea Tavira García , IJCLab -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; -using namespace o2::aod::hf_cand_2prong; +using namespace o2::framework::expressions; namespace o2::aod { namespace full { +DECLARE_SOA_INDEX_COLUMN(Collision, collision); DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); DECLARE_SOA_COLUMN(PProng0, pProng0, float); @@ -62,21 +62,54 @@ DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); DECLARE_SOA_COLUMN(Cpa, cpa, float); DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); DECLARE_SOA_COLUMN(Ct, ct, float); DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // is prompt or non-prompt, reco level +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // is prompt or non-prompt, Gen level +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCand2Prong, "_0"); // Events DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); -DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // is prompt or non-prompt, reco level -DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // is prompt or non-prompt, Gen level -DECLARE_SOA_COLUMN(GlobalIndex, globalIndex, int); } // namespace full -DECLARE_SOA_TABLE(HfCand2ProngFull, "AOD", "HFCAND2PFull", - collision::BCId, - collision::NumContrib, +DECLARE_SOA_TABLE(HfCandD0Lites, "AOD", "HFCANDD0LITE", + hf_cand::Chi2PCA, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::PtProng0, + full::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + full::ImpactParameterNormalised0, + full::ImpactParameterNormalised1, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTofPi1, + full::NSigTofKa1, + full::CandidateSelFlag, + full::M, + full::Pt, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::ImpactParameterProduct, + full::Eta, + full::Phi, + full::Y, + full::FlagMc, + full::OriginMcRec) + +DECLARE_SOA_TABLE(HfCandD0Fulls, "AOD", "HFCANDD0FULL", + full::CollisionId, collision::PosX, collision::PosY, collision::PosZ, @@ -86,6 +119,7 @@ DECLARE_SOA_TABLE(HfCand2ProngFull, "AOD", "HFCAND2PFull", hf_cand::ErrorDecayLength, hf_cand::ErrorDecayLengthXY, hf_cand::Chi2PCA, + hf_cand::KfTopolChi2OverNdf, full::RSecondaryVertex, full::DecayLength, full::DecayLengthXY, @@ -117,6 +151,7 @@ DECLARE_SOA_TABLE(HfCand2ProngFull, "AOD", "HFCAND2PFull", full::NSigTofKa1, full::CandidateSelFlag, full::M, + full::MaxNormalisedDeltaIP, full::ImpactParameterProduct, full::CosThetaStar, full::Pt, @@ -130,10 +165,10 @@ DECLARE_SOA_TABLE(HfCand2ProngFull, "AOD", "HFCAND2PFull", full::E, full::FlagMc, full::OriginMcRec, - full::GlobalIndex); + full::CandidateId); -DECLARE_SOA_TABLE(HfCand2ProngFullEvents, "AOD", "HFCAND2PFullE", - collision::BCId, +DECLARE_SOA_TABLE(HfCandD0FullEvs, "AOD", "HFCANDD0FULLEV", + full::CollisionId, collision::NumContrib, collision::PosX, collision::PosY, @@ -141,33 +176,58 @@ DECLARE_SOA_TABLE(HfCand2ProngFullEvents, "AOD", "HFCAND2PFullE", full::IsEventReject, full::RunNumber); -DECLARE_SOA_TABLE(HfCand2ProngFullParticles, "AOD", "HFCAND2PFullP", - collision::BCId, +DECLARE_SOA_TABLE(HfCandD0FullPs, "AOD", "HFCANDD0FULLP", + full::CollisionId, full::Pt, full::Eta, full::Phi, full::Y, full::FlagMc, full::OriginMcGen, - full::GlobalIndex); + full::CandidateId); } // namespace o2::aod /// Writes the full information in an output TTree struct HfTreeCreatorD0ToKPi { - Produces rowCandidateFull; - Produces rowCandidateFullEvents; - Produces rowCandidateFullParticles; + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + Produces rowCandidateLite; + + Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; + // parameters for production of training samples + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + + HfHelper hfHelper; + + using TracksWPid = soa::Join; + using SelectedCandidatesMc = soa::Filtered>; + using SelectedCandidatesMcKf = soa::Filtered>; + using MatchedGenCandidatesMc = soa::Filtered>; + + Filter filterSelectCandidates = aod::hf_sel_candidate_d0::isSelD0 >= 1 || aod::hf_sel_candidate_d0::isSelD0bar >= 1; + Filter filterMcGenMatching = nabs(aod::hf_cand_2prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + + Partition reconstructedCandSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Partition reconstructedCandBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Partition reconstructedCandSigKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Partition reconstructedCandBkgKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); void init(InitContext const&) { + std::array doprocess{doprocessDataWithDCAFitterN, doprocessDataWithKFParticle, doprocessMcWithDCAFitterOnlySig, doprocessMcWithDCAFitterOnlyBkg, doprocessMcWithDCAFitterAll, doprocessMcWithKFParticleOnlySig, doprocessMcWithKFParticleOnlyBkg, doprocessMcWithKFParticleAll}; + if (std::accumulate(doprocess.begin(), doprocess.end(), 0) != 1) { + LOGP(fatal, "Only one process function can be enabled at a time."); + } } template void fillEvent(const T& collision, int isEventReject, int runNumber) { rowCandidateFullEvents( - collision.bcId(), + collision.globalIndex(), collision.numContrib(), collision.posX(), collision.posY(), @@ -177,13 +237,45 @@ struct HfTreeCreatorD0ToKPi { } template - auto fillTable(const T& candidate, const U& prong0, const U& prong1, int candFlag, int selection, double invMass, double cosThetaStar, + auto fillTable(const T& candidate, const U& prong0, const U& prong1, int candFlag, double invMass, double cosThetaStar, double topoChi2, double ct, double y, double e, int8_t flagMc, int8_t origin) { - if (selection >= 1) { + if (fillCandidateLiteTable) { + rowCandidateLite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameterNormalised0(), + candidate.impactParameterNormalised1(), + prong0.tpcNSigmaPi(), + prong0.tpcNSigmaKa(), + prong0.tofNSigmaPi(), + prong0.tofNSigmaKa(), + prong1.tpcNSigmaPi(), + prong1.tpcNSigmaKa(), + prong1.tofNSigmaPi(), + prong1.tofNSigmaKa(), + 1 << candFlag, + invMass, + candidate.pt(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.impactParameterProduct(), + candidate.eta(), + candidate.phi(), + y, + flagMc, + origin); + } else { rowCandidateFull( - prong0.collision().bcId(), - prong0.collision().numContrib(), + candidate.collisionId(), candidate.posX(), candidate.posY(), candidate.posZ(), @@ -193,6 +285,7 @@ struct HfTreeCreatorD0ToKPi { candidate.errorDecayLength(), candidate.errorDecayLengthXY(), candidate.chi2PCA(), + topoChi2, candidate.rSecondaryVertex(), candidate.decayLength(), candidate.decayLengthXY(), @@ -224,6 +317,7 @@ struct HfTreeCreatorD0ToKPi { prong1.tofNSigmaKa(), 1 << candFlag, invMass, + candidate.maxNormalisedDeltaIP(), candidate.impactParameterProduct(), cosThetaStar, candidate.pt(), @@ -241,65 +335,132 @@ struct HfTreeCreatorD0ToKPi { } } + template void processData(aod::Collisions const& collisions, - soa::Join const& candidates, - aod::BigTracksPID const&) + CandType const& candidates, + TracksWPid const&, aod::BCs const&) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto const& collision : collisions) { - fillEvent(collision, 0, 1); + for (const auto& collision : collisions) { + fillEvent(collision, 0, collision.bc().runNumber()); } // Filling candidate properties - rowCandidateFull.reserve(candidates.size()); - for (auto const& candidate : candidates) { - auto prong0 = candidate.prong0_as(); - auto prong1 = candidate.prong1_as(); - double yD = yD0(candidate); - double eD = eD0(candidate); - double ctD = ctD0(candidate); - fillTable(candidate, prong0, prong1, 0, candidate.isSelD0(), invMassD0ToPiK(candidate), cosThetaStarD0(candidate), ctD, yD, eD, 0, 0); - fillTable(candidate, prong0, prong1, 1, candidate.isSelD0bar(), invMassD0barToKPi(candidate), cosThetaStarD0bar(candidate), ctD, yD, eD, 0, 0); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + if (downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - (int64_t)(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + auto prong0 = candidate.template prong0_as(); + auto prong1 = candidate.template prong1_as(); + double yD = hfHelper.yD0(candidate); + double eD = hfHelper.eD0(candidate); + double ctD = hfHelper.ctD0(candidate); + float massD0, massD0bar; + float topolChi2PerNdf = -999.; + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + massD0 = candidate.kfGeoMassD0(); + massD0bar = candidate.kfGeoMassD0bar(); + topolChi2PerNdf = candidate.kfTopolChi2OverNdf(); + } else { + massD0 = hfHelper.invMassD0ToPiK(candidate); + massD0bar = hfHelper.invMassD0barToKPi(candidate); + } + if (candidate.isSelD0()) { + fillTable(candidate, prong0, prong1, 0, massD0, hfHelper.cosThetaStarD0(candidate), topolChi2PerNdf, ctD, yD, eD, 0, 0); + } + if (candidate.isSelD0bar()) { + fillTable(candidate, prong0, prong1, 1, massD0bar, hfHelper.cosThetaStarD0bar(candidate), topolChi2PerNdf, ctD, yD, eD, 0, 0); + } } } - PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processData, "Process data", true); + void processDataWithDCAFitterN(aod::Collisions const& collisions, + soa::Filtered> const& candidates, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processData(collisions, candidates, tracks, bcs); + } + PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processDataWithDCAFitterN, "Process data with DCAFitterN", true); + void processDataWithKFParticle(aod::Collisions const& collisions, + soa::Filtered> const& candidates, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processData(collisions, candidates, tracks, bcs); + } + PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processDataWithKFParticle, "Process data with KFParticle", false); + + template void processMc(aod::Collisions const& collisions, aod::McCollisions const&, - soa::Join const& candidates, - soa::Join const& particles, - aod::BigTracksPID const&) + CandType const& candidates, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const&, + aod::BCs const&) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto const& collision : collisions) { - fillEvent(collision, 0, 1); + for (const auto& collision : collisions) { + fillEvent(collision, 0, collision.bc().runNumber()); } // Filling candidate properties - rowCandidateFull.reserve(candidates.size()); - for (auto const& candidate : candidates) { - auto prong0 = candidate.prong0_as(); - auto prong1 = candidate.prong0_as(); - double yD = yD0(candidate); - double eD = eD0(candidate); - double ctD = ctD0(candidate); - fillTable(candidate, prong0, prong1, 0, candidate.isSelD0(), invMassD0ToPiK(candidate), cosThetaStarD0(candidate), ctD, yD, eD, candidate.flagMcMatchRec(), candidate.originMcRec()); - fillTable(candidate, prong0, prong1, 1, candidate.isSelD0bar(), invMassD0barToKPi(candidate), cosThetaStarD0bar(candidate), ctD, yD, eD, candidate.flagMcMatchRec(), candidate.originMcRec()); + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + if (onlyBkg && downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - (int64_t)(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + auto prong0 = candidate.template prong0_as(); + auto prong1 = candidate.template prong1_as(); + double yD = hfHelper.yD0(candidate); + double eD = hfHelper.eD0(candidate); + double ctD = hfHelper.ctD0(candidate); + float massD0, massD0bar; + float topolChi2PerNdf = -999.; + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + massD0 = candidate.kfGeoMassD0(); + massD0bar = candidate.kfGeoMassD0bar(); + topolChi2PerNdf = candidate.kfTopolChi2OverNdf(); + } else { + massD0 = hfHelper.invMassD0ToPiK(candidate); + massD0bar = hfHelper.invMassD0barToKPi(candidate); + } + if (candidate.isSelD0()) { + fillTable(candidate, prong0, prong1, 0, massD0, hfHelper.cosThetaStarD0(candidate), topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.originMcRec()); + } + if (candidate.isSelD0bar()) { + fillTable(candidate, prong0, prong1, 1, massD0bar, hfHelper.cosThetaStarD0bar(candidate), topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.originMcRec()); + } } // Filling particle properties - rowCandidateFullParticles.reserve(particles.size()); - for (auto const& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::D0ToPiK) { + rowCandidateFullParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { rowCandidateFullParticles( - particle.mcCollision().bcId(), + particle.mcCollisionId(), particle.pt(), particle.eta(), particle.phi(), - RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassD0), particle.flagMcMatchGen(), particle.originMcGen(), particle.globalIndex()); @@ -307,7 +468,71 @@ struct HfTreeCreatorD0ToKPi { } } - PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processMc, "Process MC", false); + void processMcWithDCAFitterOnlySig(aod::Collisions const& collisions, + aod::McCollisions const& mcCollisions, + SelectedCandidatesMc const&, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processMc(collisions, mcCollisions, reconstructedCandSig, mcParticles, tracks, bcs); + } + PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processMcWithDCAFitterOnlySig, "Process MC with DCAFitterN only for signals", false); + + void processMcWithDCAFitterOnlyBkg(aod::Collisions const& collisions, + aod::McCollisions const& mcCollisions, + SelectedCandidatesMc const&, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processMc(collisions, mcCollisions, reconstructedCandBkg, mcParticles, tracks, bcs); + } + PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processMcWithDCAFitterOnlyBkg, "Process MC with DCAFitterN only for background", false); + + void processMcWithDCAFitterAll(aod::Collisions const& collisions, + aod::McCollisions const& mcCollisions, + SelectedCandidatesMc const& candidates, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processMc(collisions, mcCollisions, candidates, mcParticles, tracks, bcs); + } + PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processMcWithDCAFitterAll, "Process MC with DCAFitterN", false); + + void processMcWithKFParticleOnlySig(aod::Collisions const& collisions, + aod::McCollisions const& mcCollisions, + SelectedCandidatesMcKf const&, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processMc(collisions, mcCollisions, reconstructedCandSigKF, mcParticles, tracks, bcs); + } + PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processMcWithKFParticleOnlySig, "Process MC with KFParticle only for signals", false); + + void processMcWithKFParticleOnlyBkg(aod::Collisions const& collisions, + aod::McCollisions const& mcCollisions, + SelectedCandidatesMcKf const&, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processMc(collisions, mcCollisions, reconstructedCandBkgKF, mcParticles, tracks, bcs); + } + PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processMcWithKFParticleOnlyBkg, "Process MC with KFParticle only for background", false); + + void processMcWithKFParticleAll(aod::Collisions const& collisions, + aod::McCollisions const& mcCollisions, + SelectedCandidatesMcKf const& candidates, + MatchedGenCandidatesMc const& mcParticles, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processMc(collisions, mcCollisions, candidates, mcParticles, tracks, bcs); + } + PROCESS_SWITCH(HfTreeCreatorD0ToKPi, processMcWithKFParticleAll, "Process MC with KFParticle", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index b565d4c8a8a..7f3ae9125c7 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -19,13 +19,13 @@ #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; namespace o2::aod { @@ -39,7 +39,7 @@ DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! Momentum of prong1 (in GeV/c) DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! Normalised impact parameter of prong1 DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); //! Transverse momentum of prong2 (GeV/c) -DECLARE_SOA_COLUMN(PProng2, pProng2, float); //! Transverse momentum of prong2 (GeV/c) +DECLARE_SOA_COLUMN(PProng2, pProng2, float); //! Momentum of prong2 (GeV/c) DECLARE_SOA_COLUMN(ImpactParameterNormalised2, impactParameterNormalised2, float); //! Normalised impact parameter of prong2 DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) @@ -74,7 +74,7 @@ DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); //! Event rejection flag DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number } // namespace full -DECLARE_SOA_TABLE(HfCand3ProngLite, "AOD", "HFCAND3PLite", +DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", hf_cand::Chi2PCA, full::DecayLength, full::DecayLengthXY, @@ -110,7 +110,7 @@ DECLARE_SOA_TABLE(HfCand3ProngLite, "AOD", "HFCAND3PLite", hf_cand_3prong::FlagMcMatchRec, hf_cand_3prong::OriginMcRec) -DECLARE_SOA_TABLE(HfCand3ProngFull, "AOD", "HFCAND3PFull", +DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", collision::BCId, collision::NumContrib, collision::PosX, @@ -178,7 +178,7 @@ DECLARE_SOA_TABLE(HfCand3ProngFull, "AOD", "HFCAND3PFull", hf_cand_3prong::FlagMcMatchRec, hf_cand_3prong::OriginMcRec); -DECLARE_SOA_TABLE(HfCand3ProngFullEvents, "AOD", "HFCAND3PFullE", +DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", collision::BCId, collision::NumContrib, collision::PosX, @@ -187,7 +187,7 @@ DECLARE_SOA_TABLE(HfCand3ProngFullEvents, "AOD", "HFCAND3PFullE", full::IsEventReject, full::RunNumber); -DECLARE_SOA_TABLE(HfCand3ProngFullParticles, "AOD", "HFCAND3PFullP", +DECLARE_SOA_TABLE(HfCandDpFullPs, "AOD", "HFCANDDPFULLP", collision::BCId, full::Pt, full::Eta, @@ -199,25 +199,30 @@ DECLARE_SOA_TABLE(HfCand3ProngFullParticles, "AOD", "HFCAND3PFullP", /// Writes the full information in an output TTree struct HfTreeCreatorDplusToPiKPi { - Produces rowCandidateFull; - Produces rowCandidateFullEvents; - Produces rowCandidateFullParticles; - Produces rowCandidateLite; + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + Produces rowCandidateLite; Configurable selectionFlagDplus{"selectionFlagDplus", 1, "Selection Flag for Dplus"}; Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; - // parameters for production of training samples Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; - Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + HfHelper hfHelper; + using SelectedCandidatesMc = soa::Filtered>; + using MatchedGenCandidatesMc = soa::Filtered>; + using TracksWPid = soa::Join; - Partition recSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi); - Partition recBg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi); + Filter filterSelectCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; + Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); + + Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); + Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi)); void init(InitContext const&) { @@ -236,8 +241,8 @@ struct HfTreeCreatorDplusToPiKPi { runNumber); } - template - void fillCandidateTable(const T& candidate, const U& prong0, const U& prong1, const U& prong2) + template + void fillCandidateTable(const T& candidate) { int8_t flagMc = 0; int8_t originMc = 0; @@ -245,6 +250,11 @@ struct HfTreeCreatorDplusToPiKPi { flagMc = candidate.flagMcMatchRec(); originMc = candidate.originMcRec(); } + + auto prong0 = candidate.template prong0_as(); + auto prong1 = candidate.template prong1_as(); + auto prong2 = candidate.template prong2_as(); + if (fillCandidateLiteTable) { rowCandidateLite( candidate.chi2PCA(), @@ -271,20 +281,20 @@ struct HfTreeCreatorDplusToPiKPi { prong2.tofNSigmaPi(), prong2.tofNSigmaKa(), candidate.isSelDplusToPiKPi(), - invMassDplusToPiKPi(candidate), + hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), candidate.cpa(), candidate.cpaXY(), candidate.maxNormalisedDeltaIP(), candidate.eta(), candidate.phi(), - yDplus(candidate), + hfHelper.yDplus(candidate), flagMc, originMc); } else { rowCandidateFull( - prong0.collision().bcId(), - prong0.collision().numContrib(), + candidate.collision().bcId(), + candidate.collision().numContrib(), candidate.posX(), candidate.posY(), candidate.posZ(), @@ -336,17 +346,17 @@ struct HfTreeCreatorDplusToPiKPi { prong2.tofNSigmaPi(), prong2.tofNSigmaKa(), candidate.isSelDplusToPiKPi(), - invMassDplusToPiKPi(candidate), + hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), candidate.p(), candidate.cpa(), candidate.cpaXY(), candidate.maxNormalisedDeltaIP(), - ctDplus(candidate), + hfHelper.ctDplus(candidate), candidate.eta(), candidate.phi(), - yDplus(candidate), - eDplus(candidate), + hfHelper.yDplus(candidate), + hfHelper.eDplus(candidate), flagMc, originMc); } @@ -354,30 +364,28 @@ struct HfTreeCreatorDplusToPiKPi { void processData(aod::Collisions const& collisions, soa::Filtered> const& candidates, - aod::BigTracksPID const&) + TracksWPid const&) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto const& collision : collisions) { + for (const auto& collision : collisions) { fillEvent(collision, 0, 1); } // Filling candidate properties - rowCandidateFull.reserve(candidates.size()); if (fillCandidateLiteTable) { rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); } - for (auto const& candidate : candidates) { - if (fillOnlyBackground) { + for (const auto& candidate : candidates) { + if (downSampleBkgFactor < 1.) { float pseudoRndm = candidate.ptProng0() * 1000. - (int64_t)(candidate.ptProng0() * 1000); if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { continue; } } - auto prong0 = candidate.prong0_as(); - auto prong1 = candidate.prong1_as(); - auto prong2 = candidate.prong2_as(); - fillCandidateTable(candidate, prong0, prong1, prong2); + fillCandidateTable(candidate); } } @@ -386,68 +394,62 @@ struct HfTreeCreatorDplusToPiKPi { void processMc(aod::Collisions const& collisions, aod::McCollisions const&, SelectedCandidatesMc const& candidates, - soa::Join const& particles, - aod::BigTracksPID const&) + MatchedGenCandidatesMc const& particles, + TracksWPid const&) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto const& collision : collisions) { + for (const auto& collision : collisions) { fillEvent(collision, 0, 1); } // Filling candidate properties if (fillOnlySignal) { - rowCandidateFull.reserve(recSig.size()); if (fillCandidateLiteTable) { - rowCandidateLite.reserve(recSig.size()); + rowCandidateLite.reserve(reconstructedCandSig.size()); + } else { + rowCandidateFull.reserve(reconstructedCandSig.size()); } - for (const auto& candidate : recSig) { - auto prong0 = candidate.prong0_as(); - auto prong1 = candidate.prong1_as(); - auto prong2 = candidate.prong2_as(); - fillCandidateTable(candidate, prong0, prong1, prong2); + for (const auto& candidate : reconstructedCandSig) { + fillCandidateTable(candidate); } } else if (fillOnlyBackground) { - rowCandidateFull.reserve(recBg.size()); if (fillCandidateLiteTable) { - rowCandidateLite.reserve(recBg.size()); + rowCandidateLite.reserve(reconstructedCandBkg.size()); + } else { + rowCandidateFull.reserve(reconstructedCandBkg.size()); } - for (const auto& candidate : recBg) { - float pseudoRndm = candidate.ptProng0() * 1000. - (int64_t)(candidate.ptProng0() * 1000); - if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { - continue; + for (const auto& candidate : reconstructedCandBkg) { + if (downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - (int64_t)(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } } - auto prong0 = candidate.prong0_as(); - auto prong1 = candidate.prong1_as(); - auto prong2 = candidate.prong2_as(); - fillCandidateTable(candidate, prong0, prong1, prong2); + fillCandidateTable(candidate); } } else { - rowCandidateFull.reserve(candidates.size()); if (fillCandidateLiteTable) { rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); } for (const auto& candidate : candidates) { - auto prong0 = candidate.prong0_as(); - auto prong1 = candidate.prong1_as(); - auto prong2 = candidate.prong2_as(); - fillCandidateTable(candidate, prong0, prong1, prong2); + fillCandidateTable(candidate); } } // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); - for (auto const& particle : particles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), DecayType::DplusToPiKPi)) { - rowCandidateFullParticles( - particle.mcCollision().bcId(), - particle.pt(), - particle.eta(), - particle.phi(), - RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())), - particle.flagMcMatchGen(), - particle.originMcGen()); - } + for (const auto& particle : particles) { + rowCandidateFullParticles( + particle.mcCollision().bcId(), + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassDPlus), + particle.flagMcMatchGen(), + particle.originMcGen()); } } diff --git a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx new file mode 100644 index 00000000000..d36515e053d --- /dev/null +++ b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx @@ -0,0 +1,523 @@ +// Copyright 2019-2023 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 treeCreatorDsToKKPi.cxx +/// \brief Writer of Ds to KKpi candidates in the form of flat tables to be stored in TTrees. +/// Intended for debug, local optimization of analysis on small samples, or ML training. +/// In this file are defined and filled the output tables +/// +/// \author Stefano Politanò , Politecnico & INFN, Torino +/// \author Fabio Catalano , CERN + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace full +{ +// Decay daughters +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! Momentum of prong0 (GeV/c) +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c) +DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! Momentum of prong1 (in GeV/c) +DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); //! Transverse momentum of prong2 (GeV/c) +DECLARE_SOA_COLUMN(PProng2, pProng2, float); //! Momentum of prong2 (GeV/c) +DECLARE_SOA_COLUMN(NSigTpcPi0, nSigTpcPi0, float); //! TPC Nsigma separation for prong0 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa0, nSigTpcKa0, float); //! TPC Nsigma separation for prong0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi0, nSigTofPi0, float); //! TOF Nsigma separation for prong0 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa0, nSigTofKa0, float); //! TOF Nsigma separation for prong0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); //! TPC Nsigma separation for prong1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); //! TOF Nsigma separation for prong1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcPi2, nSigTpcPi2, float); //! TPC Nsigma separation for prong2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKa2, nSigTpcKa2, float); //! TPC Nsigma separation for prong2 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); //! TOF Nsigma separation for prong2 with pion mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKa2, nSigTofKa2, float); //! TOF Nsigma separation for prong2 with kaon mass hypothesis +// Candidate +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate +DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate +DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate +DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) +DECLARE_SOA_COLUMN(Ct, ct, float); //! Proper lifetime times c of candidate (cm) +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm) +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(ImpactParameterXY, impactParameterXY, float); //! Transverse impact parameter of candidate (cm) +DECLARE_SOA_COLUMN(DeltaMassPhi, deltaMassPhi, float); //! Absolute mass difference between kaon-pair and phi-meson invariant mass (Gev/c2) +DECLARE_SOA_COLUMN(AbsCos3PiK, absCos3PiK, float); //! Cube of absolute value of the cosine of pion-kaon angle in the phi rest frame +// Events +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); //! Event rejection flag +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number +} // namespace full + +DECLARE_SOA_TABLE(HfCandDsLites, "AOD", "HFCANDDSLITE", + full::PtProng0, + full::PtProng1, + full::PtProng2, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ImpactParameter2, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTofPi1, + full::NSigTofKa1, + full::NSigTpcPi2, + full::NSigTpcKa2, + full::NSigTofPi2, + full::NSigTofKa2, + hf_sel_candidate_ds::IsSelDsToKKPi, + hf_sel_candidate_ds::IsSelDsToPiKK, + full::M, + full::Pt, + full::Eta, + full::Phi, + full::Y, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::ImpactParameterXY, + full::DeltaMassPhi, + full::AbsCos3PiK, + hf_cand::Chi2PCA, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec) + +DECLARE_SOA_TABLE(HfCandDsFulls, "AOD", "HFCANDDSFULL", + collision::BCId, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + full::PtProng0, + full::PProng0, + full::PtProng1, + full::PProng1, + full::PtProng2, + full::PProng2, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + hf_cand::PxProng2, + hf_cand::PyProng2, + hf_cand::PzProng2, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ImpactParameter2, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTofPi1, + full::NSigTofKa1, + full::NSigTpcPi2, + full::NSigTpcKa2, + full::NSigTofPi2, + full::NSigTofKa2, + hf_sel_candidate_ds::IsSelDsToKKPi, + hf_sel_candidate_ds::IsSelDsToPiKK, + hf_cand::XSecondaryVertex, + hf_cand::YSecondaryVertex, + hf_cand::ZSecondaryVertex, + full::M, + full::Pt, + full::P, + full::Ct, + full::Eta, + full::Phi, + full::Y, + full::E, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::Cpa, + full::CpaXY, + full::MaxNormalisedDeltaIP, + full::ImpactParameterXY, + full::DeltaMassPhi, + full::AbsCos3PiK, + hf_cand::Chi2PCA, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcRec); + +DECLARE_SOA_TABLE(HfCandDsFullEvs, "AOD", "HFCANDDSFULLEV", + collision::BCId, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + full::IsEventReject, + full::RunNumber); + +DECLARE_SOA_TABLE(HfCandDsFullPs, "AOD", "HFCANDDSFULLP", + collision::BCId, + full::Pt, + full::Eta, + full::Phi, + full::Y, + hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::OriginMcGen); +} // namespace o2::aod + +/// Writes the full information in an output TTree +struct HfTreeCreatorDsToKKPi { + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + Produces rowCandidateLite; + + Configurable decayChannel{"decayChannel", 1, "Switch between decay channels: 1 for Ds->PhiPi->KKpi, 2 for Ds->K0*K->KKPi"}; + Configurable selectionFlagDs{"selectionFlagDs", 1, "Selection flag for Ds"}; + Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; + // parameters for production of training samples + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; + Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; + + HfHelper hfHelper; + + using CandDsData = soa::Filtered>; + using CandDsMcReco = soa::Filtered>; + using CandDsMcGen = soa::Filtered>; + using TracksWPid = soa::Join; + + Filter filterSelectCandidates = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; + Filter filterMcGenMatching = nabs(o2::aod::hf_cand_3prong::flagMcMatchGen) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && aod::hf_cand_3prong::flagMcDecayChanGen == decayChannel; + + Partition selectedDsToKKPiCand = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlagDs; + Partition selectedDsToPiKKCand = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlagDs; + + Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)) && aod::hf_cand_3prong::flagMcDecayChanRec == decayChannel; + Partition reconstructedCandBkg = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi)); + + void init(InitContext const&) + { + } + + template + void fillEvent(const T& collision, int isEventReject, int runNumber) + { + rowCandidateFullEvents( + collision.bcId(), + collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ(), + isEventReject, + runNumber); + } + + /// Fill table accounting for MC information and mass hypothesis + /// \param doMc true to fill MC information + /// \param massHypo mass hypothesis considered: 0 = KKPi, 1 = PiKK + /// \param candidate is candidate + template + void fillCandidateTable(const T& candidate) + { + int8_t flagMc = 0; + int8_t originMc = 0; + if constexpr (doMc) { + flagMc = candidate.flagMcMatchRec(); + originMc = candidate.originMcRec(); + } + + float invMassDs = 0; + float deltaMassPhiKK = 0; + float absCos3PiKDs = 0; + if constexpr (massHypo == 0) { + invMassDs = hfHelper.invMassDsToKKPi(candidate); + deltaMassPhiKK = hfHelper.deltaMassPhiDsToKKPi(candidate); + absCos3PiKDs = std::abs(hfHelper.cos3PiKDsToKKPi(candidate)); + } else if constexpr (massHypo == 1) { + invMassDs = hfHelper.invMassDsToPiKK(candidate); + deltaMassPhiKK = hfHelper.deltaMassPhiDsToPiKK(candidate); + absCos3PiKDs = std::abs(hfHelper.cos3PiKDsToPiKK(candidate)); + } + + auto prong0 = candidate.template prong0_as(); + auto prong1 = candidate.template prong1_as(); + auto prong2 = candidate.template prong2_as(); + + if (fillCandidateLiteTable) { + rowCandidateLite( + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + prong0.tpcNSigmaPi(), + prong0.tpcNSigmaKa(), + prong0.tofNSigmaPi(), + prong0.tofNSigmaKa(), + prong1.tpcNSigmaPi(), + prong1.tpcNSigmaKa(), + prong1.tofNSigmaPi(), + prong1.tofNSigmaKa(), + prong2.tpcNSigmaPi(), + prong2.tpcNSigmaKa(), + prong2.tofNSigmaPi(), + prong2.tofNSigmaKa(), + candidate.isSelDsToKKPi(), + candidate.isSelDsToPiKK(), + invMassDs, + candidate.pt(), + candidate.eta(), + candidate.phi(), + hfHelper.yDs(candidate), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.impactParameterXY(), + deltaMassPhiKK, + absCos3PiKDs, + candidate.chi2PCA(), + flagMc, + originMc); + } else { + rowCandidateFull( + candidate.collision().bcId(), + candidate.collision().numContrib(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.ptProng2(), + RecoDecay::p(candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.pxProng2(), + candidate.pyProng2(), + candidate.pzProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + prong0.tpcNSigmaPi(), + prong0.tpcNSigmaKa(), + prong0.tofNSigmaPi(), + prong0.tofNSigmaKa(), + prong1.tpcNSigmaPi(), + prong1.tpcNSigmaKa(), + prong1.tofNSigmaPi(), + prong1.tofNSigmaKa(), + prong2.tpcNSigmaPi(), + prong2.tpcNSigmaKa(), + prong2.tofNSigmaPi(), + prong2.tofNSigmaKa(), + candidate.isSelDsToKKPi(), + candidate.isSelDsToPiKK(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + invMassDs, + candidate.pt(), + candidate.p(), + hfHelper.ctDs(candidate), + candidate.eta(), + candidate.phi(), + hfHelper.yDs(candidate), + hfHelper.eDs(candidate), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.cpa(), + candidate.cpaXY(), + candidate.maxNormalisedDeltaIP(), + candidate.impactParameterXY(), + deltaMassPhiKK, + absCos3PiKDs, + candidate.chi2PCA(), + flagMc, + originMc); + } + } + + void processData(aod::Collisions const& collisions, + CandDsData const& candidates, + TracksWPid const&) + { + // Filling event properties + rowCandidateFullEvents.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, 0, 1); + } + + // Filling candidate properties + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(selectedDsToKKPiCand.size() + selectedDsToPiKKCand.size()); + } else { + rowCandidateFull.reserve(selectedDsToKKPiCand.size() + selectedDsToPiKKCand.size()); + } + + for (const auto& candidate : selectedDsToKKPiCand) { + if (downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - (int64_t)(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + fillCandidateTable(candidate); + } + + for (const auto& candidate : selectedDsToPiKKCand) { + if (downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - (int64_t)(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + fillCandidateTable(candidate); + } + } + + PROCESS_SWITCH(HfTreeCreatorDsToKKPi, processData, "Process data", true); + + void processMc(aod::Collisions const& collisions, + aod::McCollisions const&, + CandDsMcReco const& candidates, + CandDsMcGen const& mcParticles, + TracksWPid const&) + { + // Filling event properties + rowCandidateFullEvents.reserve(collisions.size()); + for (const auto& collision : collisions) { + fillEvent(collision, 0, 1); + } + + // Filling candidate properties + if (fillOnlySignal) { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(reconstructedCandSig.size()); + } else { + rowCandidateFull.reserve(reconstructedCandSig.size()); + } + + for (const auto& candidate : reconstructedCandSig) { + if (candidate.isCandidateSwapped() == 0) { + fillCandidateTable(candidate); + } + if (candidate.isCandidateSwapped() == 1) { + fillCandidateTable(candidate); + } + } + } else if (fillOnlyBackground) { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(reconstructedCandBkg.size()); + } else { + rowCandidateFull.reserve(reconstructedCandBkg.size()); + } + + for (const auto& candidate : reconstructedCandBkg) { + if (downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - (int64_t)(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + // Bkg candidates are not matched to MC so rely on selections only + if (candidate.isSelDsToKKPi() >= selectionFlagDs) { + fillCandidateTable(candidate); + } + if (candidate.isSelDsToPiKK() >= selectionFlagDs) { + fillCandidateTable(candidate); + } + } + } else { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(reconstructedCandSig.size() + reconstructedCandBkg.size()); + } else { + rowCandidateFull.reserve(reconstructedCandSig.size() + reconstructedCandBkg.size()); + } + + for (const auto& candidate : reconstructedCandSig) { + if (candidate.isCandidateSwapped() == 0) { + fillCandidateTable(candidate); + } + if (candidate.isCandidateSwapped() == 1) { + fillCandidateTable(candidate); + } + } + + for (const auto& candidate : reconstructedCandBkg) { + // Bkg candidates are not matched to MC so rely on selections only + if (candidate.isSelDsToKKPi() >= selectionFlagDs) { + fillCandidateTable(candidate); + } + if (candidate.isSelDsToPiKK() >= selectionFlagDs) { + fillCandidateTable(candidate); + } + } + } + + // Filling particle properties + rowCandidateFullParticles.reserve(mcParticles.size()); + for (const auto& particle : mcParticles) { + rowCandidateFullParticles( + particle.mcCollision().bcId(), + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassDS), + particle.flagMcMatchGen(), + particle.originMcGen()); + } + } + + PROCESS_SWITCH(HfTreeCreatorDsToKKPi, processMc, "Process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx b/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx index b7e7fdfd492..42e8001022f 100644 --- a/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx @@ -18,22 +18,17 @@ /// \author Panos Christakoglou , Nikhef /// \author Maurice Jongerhuis , University Utrecht -#include "ALICE3/DataModel/RICH.h" -#include "Common/Core/TrackSelectorPID.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/PIDResponse.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/PID.h" +#include "ALICE3/DataModel/RICH.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_lb; namespace o2::aod { @@ -98,7 +93,7 @@ DECLARE_SOA_COLUMN(NSigTOFTrk3Pr, nSigTOFrk3Pr, float); } // namespace full // put the arguments into the table -DECLARE_SOA_TABLE(HfCandLbFull, "AOD", "HFCANDLbFull", +DECLARE_SOA_TABLE(HfCandLbFulls, "AOD", "HFCANDLBFULL", full::RSecondaryVertex, full::DecayLength, full::DecayLengthXY, @@ -186,35 +181,37 @@ DECLARE_SOA_INDEX_TABLE_USER(HfTrackIndexALICE3PID, Tracks, "HFTRKIDXA3PID", //! struct HfTreeCreatorLbToLcPiAlice3PidIndexBuilder { Builds index; - void init(o2::framework::InitContext&) {} + void init(InitContext&) {} }; /// Writes the full information in an output TTree struct HfTreeCreatorLbToLcPi { - Produces rowCandidateFull; + Produces rowCandidateFull; + + HfHelper hfHelper; - using TracksExtendedPID = soa::Join; + using TracksWPid = soa::Join; void process(soa::Join const& candidates, soa::Join const&, - TracksExtendedPID const&, + TracksWPid const&, aod::FRICHs const&, aod::RICHs const&) { // Filling candidate properties rowCandidateFull.reserve(candidates.size()); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { auto fillTable = [&](int FunctionSelection, float FunctionInvMass, float FunctionCt, float FunctionY) { if (FunctionSelection >= 1) { auto candLc = candidate.prong0_as>(); - auto track0 = candidate.prong1_as(); // daughter pion track - auto track1 = candLc.prong0_as(); // granddaughter tracks (lc decay particles) - auto track2 = candLc.prong1_as(); - auto track3 = candLc.prong2_as(); + auto track0 = candidate.prong1_as(); // daughter pion track + auto track1 = candLc.prong0_as(); // granddaughter tracks (lc decay particles) + auto track2 = candLc.prong1_as(); + auto track3 = candLc.prong2_as(); auto RICHTrk0Pi = -5000.0; auto RICHTrk1Pi = -5000.0; @@ -297,10 +294,10 @@ struct HfTreeCreatorLbToLcPi { track2.tofNSigmaKa(), track3.tofNSigmaPi(), track3.tofNSigmaPr(), - o2::aod::hf_cand_3prong::invMassLcToPKPi(candLc), - o2::aod::hf_cand_3prong::ctLc(candLc), - o2::aod::hf_cand_3prong::yLc(candLc), - o2::aod::hf_cand_3prong::eLc(candLc), + hfHelper.invMassLcToPKPi(candLc), + hfHelper.ctLc(candLc), + hfHelper.yLc(candLc), + hfHelper.eLc(candLc), candLc.eta(), candLc.cpa(), candLc.cpaXY(), @@ -325,7 +322,7 @@ struct HfTreeCreatorLbToLcPi { candidate.originMcRec()); } }; - fillTable(candidate.isSelLbToLcPi(), invMassLbToLcPi(candidate), ctLb(candidate), yLb(candidate)); + fillTable(candidate.isSelLbToLcPi(), hfHelper.invMassLbToLcPi(candidate), hfHelper.ctLb(candidate), hfHelper.yLb(candidate)); } } }; diff --git a/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx b/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx index e0f0c860b11..80f91610d86 100644 --- a/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx @@ -17,11 +17,10 @@ /// /// \author Daniel Samitz -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" @@ -76,7 +75,46 @@ DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); } // namespace full -DECLARE_SOA_TABLE(HfCandCascFull, "AOD", "HFCANDCASCFull", +DECLARE_SOA_TABLE(HfCandCascLites, "AOD", "HFCANDCASCLITE", + hf_cand::Chi2PCA, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::PtProng0, + full::PtProng1, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + full::ImpactParameterNormalised0, + full::ImpactParameterNormalised1, + full::V0Radius, + full::V0CosPA, + full::V0MLambda, + full::V0MAntiLambda, + full::V0MK0Short, + full::V0MGamma, + full::V0CtK0Short, + full::V0CtLambda, + v0data::DCAV0Daughters, + full::PtV0Pos, + full::PtV0Neg, + v0data::DCANegToPV, + v0data::DCAPosToPV, + full::NSigmaTPCPr0, + full::NSigmaTOFPr0, + full::M, + full::Pt, + full::CPA, + full::CPAXY, + full::Ct, + full::Eta, + full::Phi, + full::Y, + full::E, + full::FlagMc, + full::OriginMcRec); + +DECLARE_SOA_TABLE(HfCandCascFulls, "AOD", "HFCANDCASCFULL", collision::BCId, collision::NumContrib, collision::PosX, @@ -146,14 +184,14 @@ DECLARE_SOA_TABLE(HfCandCascFull, "AOD", "HFCANDCASCFull", full::FlagMc, full::OriginMcRec); -DECLARE_SOA_TABLE(HfCandCascFullEvents, "AOD", "HFCANDCASCFullE", +DECLARE_SOA_TABLE(HfCandCascFullEs, "AOD", "HFCANDCASCFULLE", collision::BCId, collision::NumContrib, collision::PosX, collision::PosY, collision::PosZ); -DECLARE_SOA_TABLE(HfCandCascFullParticles, "AOD", "HFCANDCASCFullP", +DECLARE_SOA_TABLE(HfCandCascFullPs, "AOD", "HFCANDCASCFULLP", collision::BCId, full::Pt, full::Eta, @@ -166,11 +204,18 @@ DECLARE_SOA_TABLE(HfCandCascFullParticles, "AOD", "HFCANDCASCFullP", /// Writes the full information in an output TTree struct HfTreeCreatorLcToK0sP { - Produces rowCandidateFull; - Produces rowCandidateFullEvents; - Produces rowCandidateFullParticles; + Produces rowCandidateLite; + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of candidates to store in the tree"}; + Configurable ptMaxForDownSample{"ptMaxForDownSample", 24., "Maximum pt for the application of the downsampling factor"}; + + HfHelper hfHelper; + + using TracksWPid = soa::Join; void init(InitContext const&) { @@ -179,77 +224,117 @@ struct HfTreeCreatorLcToK0sP { template void fillCandidate(const T& candidate, const U& bach, int8_t flagMc, int8_t originMcRec) { - rowCandidateFull( - bach.collision().bcId(), - bach.collision().numContrib(), - candidate.posX(), - candidate.posY(), - candidate.posZ(), - candidate.xSecondaryVertex(), - candidate.ySecondaryVertex(), - candidate.zSecondaryVertex(), - candidate.errorDecayLength(), - candidate.errorDecayLengthXY(), - candidate.chi2PCA(), - candidate.rSecondaryVertex(), - candidate.decayLength(), - candidate.decayLengthXY(), - candidate.decayLengthNormalised(), - candidate.decayLengthXYNormalised(), - candidate.impactParameterNormalised0(), - candidate.ptProng0(), - RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), - candidate.impactParameterNormalised1(), - candidate.ptProng1(), - RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), - candidate.pxProng0(), - candidate.pyProng0(), - candidate.pzProng0(), - candidate.pxProng1(), - candidate.pyProng1(), - candidate.pzProng1(), - candidate.impactParameter0(), - candidate.impactParameter1(), - candidate.errorImpactParameter0(), - candidate.errorImpactParameter1(), - candidate.v0x(), - candidate.v0y(), - candidate.v0z(), - candidate.v0radius(), - candidate.v0cosPA(), - candidate.mLambda(), - candidate.mAntiLambda(), - candidate.mK0Short(), - candidate.mGamma(), - o2::aod::hf_cand_casc::ctV0K0s(candidate), - o2::aod::hf_cand_casc::ctV0Lambda(candidate), - candidate.dcaV0daughters(), - candidate.pxpos(), - candidate.pypos(), - candidate.pzpos(), - candidate.ptV0Pos(), - candidate.dcapostopv(), - candidate.pxneg(), - candidate.pyneg(), - candidate.pzneg(), - candidate.ptV0Neg(), - candidate.dcanegtopv(), - bach.tpcNSigmaPr(), - bach.tofNSigmaPr(), - o2::aod::hf_cand_casc::invMassLcToK0sP(candidate), - candidate.pt(), - candidate.p(), - candidate.cpa(), - candidate.cpaXY(), - o2::aod::hf_cand_3prong::ctLc(candidate), - candidate.eta(), - candidate.phi(), - o2::aod::hf_cand_3prong::yLc(candidate), - o2::aod::hf_cand_3prong::eLc(candidate), - flagMc, - originMcRec); + if (fillCandidateLiteTable) { + rowCandidateLite( + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameterNormalised0(), + candidate.impactParameterNormalised1(), + candidate.v0radius(), + candidate.v0cosPA(), + candidate.mLambda(), + candidate.mAntiLambda(), + candidate.mK0Short(), + candidate.mGamma(), + hfHelper.ctV0K0s(candidate), + hfHelper.ctV0Lambda(candidate), + candidate.dcaV0daughters(), + candidate.ptV0Pos(), + candidate.ptV0Neg(), + candidate.dcanegtopv(), + candidate.dcapostopv(), + bach.tpcNSigmaPr(), + bach.tofNSigmaPr(), + hfHelper.invMassLcToK0sP(candidate), + candidate.pt(), + candidate.cpa(), + candidate.cpaXY(), + hfHelper.ctLc(candidate), + candidate.eta(), + candidate.phi(), + hfHelper.yLc(candidate), + hfHelper.eLc(candidate), + flagMc, + originMcRec); + } else { + rowCandidateFull( + bach.collision().bcId(), + bach.collision().numContrib(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.chi2PCA(), + candidate.rSecondaryVertex(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.impactParameterNormalised0(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.impactParameterNormalised1(), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + candidate.v0x(), + candidate.v0y(), + candidate.v0z(), + candidate.v0radius(), + candidate.v0cosPA(), + candidate.mLambda(), + candidate.mAntiLambda(), + candidate.mK0Short(), + candidate.mGamma(), + hfHelper.ctV0K0s(candidate), + hfHelper.ctV0Lambda(candidate), + candidate.dcaV0daughters(), + candidate.pxpos(), + candidate.pypos(), + candidate.pzpos(), + candidate.ptV0Pos(), + candidate.dcapostopv(), + candidate.pxneg(), + candidate.pyneg(), + candidate.pzneg(), + candidate.ptV0Neg(), + candidate.dcanegtopv(), + bach.tpcNSigmaPr(), + bach.tofNSigmaPr(), + hfHelper.invMassLcToK0sP(candidate), + candidate.pt(), + candidate.p(), + candidate.cpa(), + candidate.cpaXY(), + hfHelper.ctLc(candidate), + candidate.eta(), + candidate.phi(), + hfHelper.yLc(candidate), + hfHelper.eLc(candidate), + flagMc, + originMcRec); + } } - template void fillEvent(const T& collision) { @@ -262,39 +347,48 @@ struct HfTreeCreatorLcToK0sP { } void processMc(aod::Collisions const& collisions, - aod::McCollisions const& mccollisions, + aod::McCollisions const& mcCollisions, soa::Join const& candidates, soa::Join const& particles, - aod::BigTracksPID const& tracks) + TracksWPid const& tracks) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto const& collision : collisions) { + for (const auto& collision : collisions) { fillEvent(collision); } // Filling candidate properties - rowCandidateFull.reserve(candidates.size()); - for (auto const& candidate : candidates) { - auto bach = candidate.prong0_as(); // bachelor - double pseudoRndm = bach.pt() * 1000. - (int16_t)(bach.pt() * 1000); - if (candidate.isSelLcToK0sP() >= 1 && pseudoRndm < downSampleBkgFactor) { + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + auto bach = candidate.prong0_as(); // bachelor + if (downSampleBkgFactor < 1.) { + double pseudoRndm = bach.pt() * 1000. - (int16_t)(bach.pt() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + if (candidate.isSelLcToK0sP() >= 1) { fillCandidate(candidate, bach, candidate.flagMcMatchRec(), candidate.originMcRec()); } } // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); - for (auto const& particle : particles) { + for (const auto& particle : particles) { if (std::abs(particle.flagMcMatchGen()) == 1) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), particle.eta(), particle.phi(), - RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, - RecoDecay::getMassPDG(particle.pdgCode())), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, + o2::analysis::pdg::MassLambdaCPlus), particle.flagMcMatchGen(), particle.originMcGen()); } @@ -304,19 +398,23 @@ struct HfTreeCreatorLcToK0sP { void processData(aod::Collisions const& collisions, soa::Join const& candidates, - aod::BigTracksPID const& tracks) + TracksWPid const& tracks) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto const& collision : collisions) { + for (const auto& collision : collisions) { fillEvent(collision); } // Filling candidate properties - rowCandidateFull.reserve(candidates.size()); - for (auto const& candidate : candidates) { - auto bach = candidate.prong0_as(); // bachelor + if (fillCandidateLiteTable) { + rowCandidateLite.reserve(candidates.size()); + } else { + rowCandidateFull.reserve(candidates.size()); + } + for (const auto& candidate : candidates) { + auto bach = candidate.prong0_as(); // bachelor double pseudoRndm = bach.pt() * 1000. - (int16_t)(bach.pt() * 1000); if (candidate.isSelLcToK0sP() >= 1 && pseudoRndm < downSampleBkgFactor) { fillCandidate(candidate, bach, 0, 0); diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 46f377625d2..a7fff765d5b 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -16,22 +16,22 @@ /// /// \author Nicolo' Jacazio , CERN -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/DataModel/Multiplicity.h" using namespace o2; using namespace o2::framework; -using namespace o2::aod::hf_cand_3prong; namespace o2::aod { namespace full { +DECLARE_SOA_INDEX_COLUMN(Collision, collision); DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); DECLARE_SOA_COLUMN(PProng0, pProng0, float); @@ -50,44 +50,49 @@ DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(Y, y, float); DECLARE_SOA_COLUMN(E, e, float); -DECLARE_SOA_COLUMN(NSigTPCPi0, nsigTPCPi0, float); -DECLARE_SOA_COLUMN(NSigTPCKa0, nsigTPCKa0, float); -DECLARE_SOA_COLUMN(NSigTPCPr0, nsigTPCPr0, float); -DECLARE_SOA_COLUMN(NSigTOFPi0, nsigTOFPi0, float); -DECLARE_SOA_COLUMN(NSigTOFKa0, nsigTOFKa0, float); -DECLARE_SOA_COLUMN(NSigTOFPr0, nsigTOFPr0, float); -DECLARE_SOA_COLUMN(NSigTPCPi1, nsigTPCPi1, float); -DECLARE_SOA_COLUMN(NSigTPCKa1, nsigTPCKa1, float); -DECLARE_SOA_COLUMN(NSigTPCPr1, nsigTPCPr1, float); -DECLARE_SOA_COLUMN(NSigTOFPi1, nsigTOFPi1, float); -DECLARE_SOA_COLUMN(NSigTOFKa1, nsigTOFKa1, float); -DECLARE_SOA_COLUMN(NSigTOFPr1, nsigTOFPr1, float); -DECLARE_SOA_COLUMN(NSigTPCPi2, nsigTPCPi2, float); -DECLARE_SOA_COLUMN(NSigTPCKa2, nsigTPCKa2, float); -DECLARE_SOA_COLUMN(NSigTPCPr2, nsigTPCPr2, float); -DECLARE_SOA_COLUMN(NSigTOFPi2, nsigTOFPi2, float); -DECLARE_SOA_COLUMN(NSigTOFKa2, nsigTOFKa2, float); -DECLARE_SOA_COLUMN(NSigTOFPr2, nsigTOFPr2, float); +DECLARE_SOA_COLUMN(NSigTpcPi0, nSigTpcPi0, float); +DECLARE_SOA_COLUMN(NSigTpcKa0, nSigTpcKa0, float); +DECLARE_SOA_COLUMN(NSigTpcPr0, nSigTpcPr0, float); +DECLARE_SOA_COLUMN(NSigTofPi0, nSigTofPi0, float); +DECLARE_SOA_COLUMN(NSigTofKa0, nSigTofKa0, float); +DECLARE_SOA_COLUMN(NSigTofPr0, nSigTofPr0, float); +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); +DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); +DECLARE_SOA_COLUMN(NSigTpcPr1, nSigTpcPr1, float); +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); +DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); +DECLARE_SOA_COLUMN(NSigTofPr1, nSigTofPr1, float); +DECLARE_SOA_COLUMN(NSigTpcPi2, nSigTpcPi2, float); +DECLARE_SOA_COLUMN(NSigTpcKa2, nSigTpcKa2, float); +DECLARE_SOA_COLUMN(NSigTpcPr2, nSigTpcPr2, float); +DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); +DECLARE_SOA_COLUMN(NSigTofKa2, nSigTofKa2, float); +DECLARE_SOA_COLUMN(NSigTofPr2, nSigTofPr2, float); DECLARE_SOA_COLUMN(DecayLength, decayLength, float); DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); -DECLARE_SOA_COLUMN(CPA, cpa, float); -DECLARE_SOA_COLUMN(CPAXY, cpaXY, float); +DECLARE_SOA_COLUMN(Cpa, cpa, float); +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); DECLARE_SOA_COLUMN(Ct, ct, float); -DECLARE_SOA_COLUMN(MCflag, mcflag, int8_t); +DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCand3Prong, "_0"); // Events +DECLARE_SOA_INDEX_COLUMN(McCollision, mcCollision); DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); -DECLARE_SOA_COLUMN(GlobalIndex, globalIndex, int); +DECLARE_SOA_COLUMN(MultZeqFT0A, multZeqFT0A, float); +DECLARE_SOA_COLUMN(MultZeqFT0C, multZeqFT0C, float); +DECLARE_SOA_COLUMN(MultFT0M, multFT0M, float); +DECLARE_SOA_COLUMN(MultZeqFV0A, multZeqFV0A, float); +DECLARE_SOA_COLUMN(MultZeqNTracksPV, multZeqNTracksPV, float); } // namespace full -DECLARE_SOA_TABLE(HfCand3ProngFull, "AOD", "HFCAND3PFull", - collision::BCId, - collision::NumContrib, +DECLARE_SOA_TABLE(HfCandLcFulls, "AOD", "HFCANDLCFULL", + full::CollisionId, collision::PosX, collision::PosY, collision::PosZ, @@ -126,99 +131,115 @@ DECLARE_SOA_TABLE(HfCand3ProngFull, "AOD", "HFCAND3PFull", hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, - full::NSigTPCPi0, - full::NSigTPCKa0, - full::NSigTPCPr0, - full::NSigTOFPi0, - full::NSigTOFKa0, - full::NSigTOFPr0, - full::NSigTPCPi1, - full::NSigTPCKa1, - full::NSigTPCPr1, - full::NSigTOFPi1, - full::NSigTOFKa1, - full::NSigTOFPr1, - full::NSigTPCPi2, - full::NSigTPCKa2, - full::NSigTPCPr2, - full::NSigTOFPi2, - full::NSigTOFKa2, - full::NSigTOFPr2, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTpcPr0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTofPr0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTpcPr1, + full::NSigTofPi1, + full::NSigTofKa1, + full::NSigTofPr1, + full::NSigTpcPi2, + full::NSigTpcKa2, + full::NSigTpcPr2, + full::NSigTofPi2, + full::NSigTofKa2, + full::NSigTofPr2, full::CandidateSelFlag, full::M, full::Pt, full::P, - full::CPA, - full::CPAXY, + full::Cpa, + full::CpaXY, full::Ct, full::Eta, full::Phi, full::Y, full::E, - full::MCflag, + full::FlagMc, full::OriginMcRec, full::IsCandidateSwapped, - full::GlobalIndex); + full::CandidateId); -DECLARE_SOA_TABLE(HfCand3ProngFullEvents, "AOD", "HFCAND3PFullE", - collision::BCId, +DECLARE_SOA_TABLE(HfCandLcFullEvs, "AOD", "HFCANDLCFULLEV", + full::CollisionId, + full::McCollisionId, collision::NumContrib, collision::PosX, collision::PosY, collision::PosZ, full::IsEventReject, - full::RunNumber); + full::RunNumber, + full::MultZeqFT0A, + full::MultZeqFT0C, + full::MultFT0M, + full::MultZeqFV0A, + full::MultZeqNTracksPV); -DECLARE_SOA_TABLE(HfCand3ProngFullParticles, "AOD", "HFCAND3PFullP", - collision::BCId, +DECLARE_SOA_TABLE(HfCandLcFullPs, "AOD", "HFCANDLCFULLP", + full::McCollisionId, full::Pt, full::Eta, full::Phi, full::Y, - full::MCflag, + full::FlagMc, full::OriginMcGen, - full::GlobalIndex); + full::CandidateId); } // namespace o2::aod /// Writes the full information in an output TTree struct HfTreeCreatorLcToPKPi { - Produces rowCandidateFull; - Produces rowCandidateFullEvents; - Produces rowCandidateFullParticles; + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of candidates to store in the tree"}; + HfHelper hfHelper; + + using TracksWPid = soa::Join; + void init(InitContext const&) { } - void processMc(aod::Collisions const& collisions, - aod::McCollisions const& mccollisions, + void processMc(soa::Join const& collisions, + aod::McCollisions const& mcCollisions, soa::Join const& candidates, soa::Join const& particles, - aod::BigTracksPID const& tracks) + TracksWPid const& tracks, aod::BCs const&) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { rowCandidateFullEvents( - collision.bcId(), + collision.globalIndex(), + collision.mcCollisionId(), collision.numContrib(), collision.posX(), collision.posY(), collision.posZ(), 0, - 1); + collision.bc().runNumber(), + collision.multZeqFT0A(), + collision.multZeqFT0C(), + collision.multFT0M(), + collision.multZeqFV0A(), + collision.multZeqNTracksPV()); } // Filling candidate properties rowCandidateFull.reserve(candidates.size()); - for (auto& candidate : candidates) { - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) + for (const auto& candidate : candidates) { + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) auto fillTable = [&](int CandFlag, int FunctionSelection, float FunctionInvMass, @@ -228,8 +249,7 @@ struct HfTreeCreatorLcToPKPi { double pseudoRndm = trackPos1.pt() * 1000. - (int64_t)(trackPos1.pt() * 1000); if (FunctionSelection >= 1 && pseudoRndm < downSampleBkgFactor) { rowCandidateFull( - trackPos1.collision().bcId(), - trackPos1.collision().numContrib(), + candidate.collisionId(), candidate.posX(), candidate.posY(), candidate.posZ(), @@ -304,20 +324,20 @@ struct HfTreeCreatorLcToPKPi { } }; - fillTable(0, candidate.isSelLcToPKPi(), invMassLcToPKPi(candidate), ctLc(candidate), yLc(candidate), eLc(candidate)); - fillTable(1, candidate.isSelLcToPiKP(), invMassLcToPiKP(candidate), ctLc(candidate), yLc(candidate), eLc(candidate)); + fillTable(0, candidate.isSelLcToPKPi(), hfHelper.invMassLcToPKPi(candidate), hfHelper.ctLc(candidate), hfHelper.yLc(candidate), hfHelper.eLc(candidate)); + fillTable(1, candidate.isSelLcToPiKP(), hfHelper.invMassLcToPiKP(candidate), hfHelper.ctLc(candidate), hfHelper.yLc(candidate), hfHelper.eLc(candidate)); } // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); - for (auto& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::LcToPKPi) { + for (const auto& particle : particles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { rowCandidateFullParticles( - particle.mcCollision().bcId(), + particle.mcCollisionId(), particle.pt(), particle.eta(), particle.phi(), - RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassLambdaCPlus), particle.flagMcMatchGen(), particle.originMcGen(), particle.globalIndex()); @@ -326,30 +346,36 @@ struct HfTreeCreatorLcToPKPi { } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMc, "Process MC tree writer", true); - void processData(aod::Collisions const& collisions, + void processData(soa::Join const& collisions, soa::Join const& candidates, - aod::BigTracksPID const& tracks) + TracksWPid const& tracks, aod::BCs const&) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { rowCandidateFullEvents( - collision.bcId(), + collision.globalIndex(), + -1, collision.numContrib(), collision.posX(), collision.posY(), collision.posZ(), 0, - 1); + collision.bc().runNumber(), + collision.multZeqFT0A(), + collision.multZeqFT0C(), + collision.multFT0M(), + collision.multZeqFV0A(), + collision.multZeqNTracksPV()); } // Filling candidate properties rowCandidateFull.reserve(candidates.size()); - for (auto& candidate : candidates) { - auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) - auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) - auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) + for (const auto& candidate : candidates) { + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) auto fillTable = [&](int CandFlag, int FunctionSelection, float FunctionInvMass, @@ -359,8 +385,7 @@ struct HfTreeCreatorLcToPKPi { double pseudoRndm = trackPos1.pt() * 1000. - (int64_t)(trackPos1.pt() * 1000); if (FunctionSelection >= 1 && pseudoRndm < downSampleBkgFactor) { rowCandidateFull( - trackPos1.collision().bcId(), - trackPos1.collision().numContrib(), + candidate.collisionId(), candidate.posX(), candidate.posY(), candidate.posZ(), @@ -435,8 +460,8 @@ struct HfTreeCreatorLcToPKPi { } }; - fillTable(0, candidate.isSelLcToPKPi(), invMassLcToPKPi(candidate), ctLc(candidate), yLc(candidate), eLc(candidate)); - fillTable(1, candidate.isSelLcToPiKP(), invMassLcToPiKP(candidate), ctLc(candidate), yLc(candidate), eLc(candidate)); + fillTable(0, candidate.isSelLcToPKPi(), hfHelper.invMassLcToPKPi(candidate), hfHelper.ctLc(candidate), hfHelper.yLc(candidate), hfHelper.eLc(candidate)); + fillTable(1, candidate.isSelLcToPiKP(), hfHelper.invMassLcToPiKP(candidate), hfHelper.ctLc(candidate), hfHelper.yLc(candidate), hfHelper.eLc(candidate)); } } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processData, "Process data tree writer", false); diff --git a/PWGHF/TableProducer/treeCreatorToXiPi.cxx b/PWGHF/TableProducer/treeCreatorToXiPi.cxx index 45ef3041770..0fc439841d1 100644 --- a/PWGHF/TableProducer/treeCreatorToXiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorToXiPi.cxx @@ -15,18 +15,14 @@ /// /// \author Federica Zanone , Heidelberg University & GSI -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; -using namespace o2::aod::hf_cand_toxipi; -using namespace o2::aod::hf_sel_toxipi; namespace o2::aod { @@ -126,6 +122,8 @@ DECLARE_SOA_COLUMN(StatusInvMassLambda, statusInvMassLambda, bool); DECLARE_SOA_COLUMN(StatusInvMassCascade, statusInvMassCascade, bool); DECLARE_SOA_COLUMN(StatusInvMassOmegac, statusInvMassOmegac, bool); DECLARE_SOA_COLUMN(ResultSelections, resultSelections, bool); +DECLARE_SOA_COLUMN(PidTpcInfoStored, pidTpcInfoStored, int); +DECLARE_SOA_COLUMN(PidTofInfoStored, pidTofInfoStored, int); DECLARE_SOA_COLUMN(TpcNSigmaPiFromOmega, tpcNSigmaPiFromOmega, float); DECLARE_SOA_COLUMN(TpcNSigmaPiFromCasc, tpcNSigmaPiFromCasc, float); DECLARE_SOA_COLUMN(TpcNSigmaPiFromLambda, tpcNSigmaPiFromLambda, float); @@ -134,9 +132,10 @@ DECLARE_SOA_COLUMN(TofNSigmaPiFromOmega, tofNSigmaPiFromOmega, float); DECLARE_SOA_COLUMN(TofNSigmaPiFromCasc, tofNSigmaPiFromCasc, float); DECLARE_SOA_COLUMN(TofNSigmaPiFromLambda, tofNSigmaPiFromLambda, float); DECLARE_SOA_COLUMN(TofNSigmaPrFromLambda, tofNSigmaPrFromLambda, float); + } // namespace full -DECLARE_SOA_TABLE(HfToXiPiFull, "AOD", "HFTOXIPIFULL", +DECLARE_SOA_TABLE(HfToXiPiFulls, "AOD", "HFTOXIPIFULL", full::CollisionId, full::XPv, full::YPv, full::ZPv, collision::NumContrib, full::XDecayVtxOmegac, full::YDecayVtxOmegac, full::ZDecayVtxOmegac, full::XDecayVtxCascade, full::YDecayVtxCascade, full::ZDecayVtxCascade, @@ -163,12 +162,12 @@ DECLARE_SOA_TABLE(HfToXiPiFull, "AOD", "HFTOXIPIFULL", full::DcaZToPvV0Dau0, full::DcaZToPvV0Dau1, full::DcaZToPvCascDau, full::DcaCascDau, full::DcaV0Dau, full::DcaOmegacDau, full::StatusPidLambda, full::StatusPidCascade, full::StatusPidOmegac, - full::StatusInvMassLambda, full::StatusInvMassCascade, full::StatusInvMassOmegac, full::ResultSelections, + full::StatusInvMassLambda, full::StatusInvMassCascade, full::StatusInvMassOmegac, full::ResultSelections, full::PidTpcInfoStored, full::PidTofInfoStored, full::TpcNSigmaPiFromOmega, full::TpcNSigmaPiFromCasc, full::TpcNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, full::TofNSigmaPiFromOmega, full::TofNSigmaPiFromCasc, full::TofNSigmaPiFromLambda, full::TofNSigmaPrFromLambda, full::FlagMcMatchRec, full::DebugMcRec); -DECLARE_SOA_TABLE(HfToXiPiEvents, "AOD", "HFTOXIPIEVENTS", +DECLARE_SOA_TABLE(HfToXiPiEvents, "AOD", "HFTOXIPIEVENT", collision::NumContrib, collision::PosX, collision::PosY, @@ -178,7 +177,7 @@ DECLARE_SOA_TABLE(HfToXiPiEvents, "AOD", "HFTOXIPIEVENTS", /// Writes the full information in an output TTree struct HfTreeCreatorToXiPi { - Produces rowCandidateFull; + Produces rowCandidateFull; Produces rowCandidateEvents; void init(InitContext const&) @@ -289,6 +288,8 @@ struct HfTreeCreatorToXiPi { candidate.statusInvMassCascade(), candidate.statusInvMassOmegac(), candidate.resultSelections(), + candidate.pidTpcInfoStored(), + candidate.pidTofInfoStored(), candidate.tpcNSigmaPiFromOmega(), candidate.tpcNSigmaPiFromCasc(), candidate.tpcNSigmaPiFromLambda(), @@ -307,13 +308,13 @@ struct HfTreeCreatorToXiPi { // Filling event properties rowCandidateEvents.reserve(collisions.size()); - for (auto const& collision : collisions) { + for (const auto& collision : collisions) { fillEvent(collision); } // Filling candidate properties rowCandidateFull.reserve(candidates.size()); - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { fillCandidate(candidate, -7, -7); } } @@ -325,13 +326,13 @@ struct HfTreeCreatorToXiPi { // Filling event properties rowCandidateEvents.reserve(collisions.size()); - for (auto const& collision : collisions) { + for (const auto& collision : collisions) { fillEvent(collision); } // Filling candidate properties rowCandidateFull.reserve(candidates.size()); - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec()); } } diff --git a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx new file mode 100644 index 00000000000..b18d1c44470 --- /dev/null +++ b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx @@ -0,0 +1,453 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file treeCreatorXicToPKPi.cxx +/// \brief Writer of XiC -> pKpi candidates in the form of flat tables to be stored in TTrees. +/// inspired from file treeCreatorLcToPKPi.cxx + +/// \author Himanshu Sharma , INFN Padova + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +using namespace o2; +using namespace o2::framework; + +namespace o2::aod +{ +namespace full +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); +DECLARE_SOA_COLUMN(PProng0, pProng0, float); +DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); +DECLARE_SOA_COLUMN(PProng1, pProng1, float); +DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); +DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); +DECLARE_SOA_COLUMN(PProng2, pProng2, float); +DECLARE_SOA_COLUMN(ImpactParameterNormalised2, impactParameterNormalised2, float); +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int8_t); +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(P, p, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(E, e, float); +DECLARE_SOA_COLUMN(NSigTpcPi0, nSigTpcPi0, float); +DECLARE_SOA_COLUMN(NSigTpcKa0, nSigTpcKa0, float); +DECLARE_SOA_COLUMN(NSigTpcPr0, nSigTpcPr0, float); +DECLARE_SOA_COLUMN(NSigTofPi0, nSigTofPi0, float); +DECLARE_SOA_COLUMN(NSigTofKa0, nSigTofKa0, float); +DECLARE_SOA_COLUMN(NSigTofPr0, nSigTofPr0, float); +DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); +DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); +DECLARE_SOA_COLUMN(NSigTpcPr1, nSigTpcPr1, float); +DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); +DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); +DECLARE_SOA_COLUMN(NSigTofPr1, nSigTofPr1, float); +DECLARE_SOA_COLUMN(NSigTpcPi2, nSigTpcPi2, float); +DECLARE_SOA_COLUMN(NSigTpcKa2, nSigTpcKa2, float); +DECLARE_SOA_COLUMN(NSigTpcPr2, nSigTpcPr2, float); +DECLARE_SOA_COLUMN(NSigTofPi2, nSigTofPi2, float); +DECLARE_SOA_COLUMN(NSigTofKa2, nSigTofKa2, float); +DECLARE_SOA_COLUMN(NSigTofPr2, nSigTofPr2, float); +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); +DECLARE_SOA_COLUMN(Cpa, cpa, float); +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); +DECLARE_SOA_COLUMN(Ct, ct, float); +DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); +DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCand3Prong, "_0"); +// Events +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +} // namespace full + +DECLARE_SOA_TABLE(HfCandXicFulls, "AOD", "HFCANDXICFULL", + full::CollisionId, + collision::PosX, + collision::PosY, + collision::PosZ, + hf_cand::XSecondaryVertex, + hf_cand::YSecondaryVertex, + hf_cand::ZSecondaryVertex, + hf_cand::ErrorDecayLength, + hf_cand::ErrorDecayLengthXY, + hf_cand::Chi2PCA, + full::RSecondaryVertex, + full::DecayLength, + full::DecayLengthXY, + full::DecayLengthNormalised, + full::DecayLengthXYNormalised, + full::ImpactParameterNormalised0, + full::PtProng0, + full::PProng0, + full::ImpactParameterNormalised1, + full::PtProng1, + full::PProng1, + full::ImpactParameterNormalised2, + full::PtProng2, + full::PProng2, + hf_cand::PxProng0, + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, + hf_cand::PyProng1, + hf_cand::PzProng1, + hf_cand::PxProng2, + hf_cand::PyProng2, + hf_cand::PzProng2, + hf_cand::ImpactParameter0, + hf_cand::ImpactParameter1, + hf_cand::ImpactParameter2, + hf_cand::ErrorImpactParameter0, + hf_cand::ErrorImpactParameter1, + hf_cand::ErrorImpactParameter2, + full::NSigTpcPi0, + full::NSigTpcKa0, + full::NSigTpcPr0, + full::NSigTofPi0, + full::NSigTofKa0, + full::NSigTofPr0, + full::NSigTpcPi1, + full::NSigTpcKa1, + full::NSigTpcPr1, + full::NSigTofPi1, + full::NSigTofKa1, + full::NSigTofPr1, + full::NSigTpcPi2, + full::NSigTpcKa2, + full::NSigTpcPr2, + full::NSigTofPi2, + full::NSigTofKa2, + full::NSigTofPr2, + full::CandidateSelFlag, + full::M, + full::Pt, + full::P, + full::Cpa, + full::CpaXY, + full::Ct, + full::Eta, + full::Phi, + full::Y, + full::E, + full::FlagMc, + full::OriginMcRec, + full::IsCandidateSwapped, + full::CandidateId); + +DECLARE_SOA_TABLE(HfCandXicFullEvs, "AOD", "HFCANDXICFULLEV", + full::CollisionId, + collision::BCId, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + full::IsEventReject, + full::RunNumber); + +DECLARE_SOA_TABLE(HfCandXicFullPs, "AOD", "HFCANDXICFULLP", + full::CollisionId, + collision::BCId, + full::Pt, + full::Eta, + full::Phi, + full::Y, + full::FlagMc, + full::OriginMcGen, + full::CandidateId); + +} // namespace o2::aod + +/// Writes the full information in an output TTree +struct HfTreeCreatorXicToPKPi { + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + + Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of candidates to store in the tree"}; + + HfHelper hfHelper; + + using TracksWPid = soa::Join; + + void init(InitContext const&) + { + } + + void processMc(aod::Collisions const& collisions, + aod::McCollisions const& mcCollisions, + soa::Join const& candidates, + soa::Join const& particles, + TracksWPid const& tracks) + { + // Filling event properties + rowCandidateFullEvents.reserve(collisions.size()); + for (const auto& collision : collisions) { + rowCandidateFullEvents( + collision.globalIndex(), + collision.bcId(), + collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ(), + 0, + 1); + } + + // Filling candidate properties + rowCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) + auto fillTable = [&](int CandFlag, + int FunctionSelection, + float FunctionInvMass, + float FunctionCt, + float FunctionY, + float FunctionE) { + double pseudoRndm = trackPos1.pt() * 1000. - (int64_t)(trackPos1.pt() * 1000); + if (FunctionSelection >= 1 && pseudoRndm < downSampleBkgFactor) { + rowCandidateFull( + candidate.collisionId(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.chi2PCA(), + candidate.rSecondaryVertex(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.impactParameterNormalised0(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.impactParameterNormalised1(), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.impactParameterNormalised2(), + candidate.ptProng2(), + RecoDecay::p(candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.pxProng2(), + candidate.pyProng2(), + candidate.pzProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + candidate.errorImpactParameter2(), + trackPos1.tpcNSigmaPi(), + trackPos1.tpcNSigmaKa(), + trackPos1.tpcNSigmaPr(), + trackPos1.tofNSigmaPi(), + trackPos1.tofNSigmaKa(), + trackPos1.tofNSigmaPr(), + trackNeg.tpcNSigmaPi(), + trackNeg.tpcNSigmaKa(), + trackNeg.tpcNSigmaPr(), + trackNeg.tofNSigmaPi(), + trackNeg.tofNSigmaKa(), + trackNeg.tofNSigmaPr(), + trackPos2.tpcNSigmaPi(), + trackPos2.tpcNSigmaKa(), + trackPos2.tpcNSigmaPr(), + trackPos2.tofNSigmaPi(), + trackPos2.tofNSigmaKa(), + trackPos2.tofNSigmaPr(), + 1 << CandFlag, + FunctionInvMass, + candidate.pt(), + candidate.p(), + candidate.cpa(), + candidate.cpaXY(), + FunctionCt, + candidate.eta(), + candidate.phi(), + FunctionY, + FunctionE, + candidate.flagMcMatchRec(), + candidate.originMcRec(), + candidate.isCandidateSwapped(), + candidate.globalIndex()); + } + }; + + fillTable(0, candidate.isSelXicToPKPi(), hfHelper.invMassXicToPKPi(candidate), hfHelper.ctXic(candidate), hfHelper.yXic(candidate), hfHelper.eXic(candidate)); + fillTable(1, candidate.isSelXicToPiKP(), hfHelper.invMassXicToPiKP(candidate), hfHelper.ctXic(candidate), hfHelper.yXic(candidate), hfHelper.eXic(candidate)); + } + + // Filling particle properties + rowCandidateFullParticles.reserve(particles.size()); + for (const auto& particle : particles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::XicToPKPi) { + rowCandidateFullParticles( + particle.mcCollision().globalIndex(), + particle.mcCollision().bcId(), + particle.pt(), + particle.eta(), + particle.phi(), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassXiCPlus), + particle.flagMcMatchGen(), + particle.originMcGen(), + particle.globalIndex()); + } + } + } + PROCESS_SWITCH(HfTreeCreatorXicToPKPi, processMc, "Process MC tree writer", true); + + void processData(aod::Collisions const& collisions, + soa::Join const& candidates, + TracksWPid const& tracks) + { + + // Filling event properties + rowCandidateFullEvents.reserve(collisions.size()); + for (const auto& collision : collisions) { + rowCandidateFullEvents( + collision.globalIndex(), + collision.bcId(), + collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ(), + 0, + 1); + } + + // Filling candidate properties + rowCandidateFull.reserve(candidates.size()); + for (const auto& candidate : candidates) { + auto trackPos1 = candidate.prong0_as(); // positive daughter (negative for the antiparticles) + auto trackNeg = candidate.prong1_as(); // negative daughter (positive for the antiparticles) + auto trackPos2 = candidate.prong2_as(); // positive daughter (negative for the antiparticles) + auto fillTable = [&](int CandFlag, + int FunctionSelection, + float FunctionInvMass, + float FunctionCt, + float FunctionY, + float FunctionE) { + double pseudoRndm = trackPos1.pt() * 1000. - (int64_t)(trackPos1.pt() * 1000); + if (FunctionSelection >= 1 && pseudoRndm < downSampleBkgFactor) { + rowCandidateFull( + candidate.collisionId(), + candidate.posX(), + candidate.posY(), + candidate.posZ(), + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.chi2PCA(), + candidate.rSecondaryVertex(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.impactParameterNormalised0(), + candidate.ptProng0(), + RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()), + candidate.impactParameterNormalised1(), + candidate.ptProng1(), + RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()), + candidate.impactParameterNormalised2(), + candidate.ptProng2(), + RecoDecay::p(candidate.pxProng2(), candidate.pyProng2(), candidate.pzProng2()), + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.pxProng2(), + candidate.pyProng2(), + candidate.pzProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.errorImpactParameter0(), + candidate.errorImpactParameter1(), + candidate.errorImpactParameter2(), + trackPos1.tpcNSigmaPi(), + trackPos1.tpcNSigmaKa(), + trackPos1.tpcNSigmaPr(), + trackPos1.tofNSigmaPi(), + trackPos1.tofNSigmaKa(), + trackPos1.tofNSigmaPr(), + trackNeg.tpcNSigmaPi(), + trackNeg.tpcNSigmaKa(), + trackNeg.tpcNSigmaPr(), + trackNeg.tofNSigmaPi(), + trackNeg.tofNSigmaKa(), + trackNeg.tofNSigmaPr(), + trackPos2.tpcNSigmaPi(), + trackPos2.tpcNSigmaKa(), + trackPos2.tpcNSigmaPr(), + trackPos2.tofNSigmaPi(), + trackPos2.tofNSigmaKa(), + trackPos2.tofNSigmaPr(), + 1 << CandFlag, + FunctionInvMass, + candidate.pt(), + candidate.p(), + candidate.cpa(), + candidate.cpaXY(), + FunctionCt, + candidate.eta(), + candidate.phi(), + FunctionY, + FunctionE, + 0., + 0., + 0., + candidate.globalIndex()); + } + }; + + fillTable(0, candidate.isSelXicToPKPi(), hfHelper.invMassXicToPKPi(candidate), hfHelper.ctXic(candidate), hfHelper.yXic(candidate), hfHelper.eXic(candidate)); + fillTable(1, candidate.isSelXicToPiKP(), hfHelper.invMassXicToPiKP(candidate), hfHelper.ctXic(candidate), hfHelper.yXic(candidate), hfHelper.eXic(candidate)); + } + } + PROCESS_SWITCH(HfTreeCreatorXicToPKPi, processData, "Process data tree writer", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow; + workflow.push_back(adaptAnalysisTask(cfgc)); + return workflow; +} diff --git a/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx b/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx index 2002109acfd..c3472b9aa06 100644 --- a/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx @@ -17,18 +17,15 @@ /// /// \author Jinjoo Seo , Inha University -#include "Common/Core/trackUtilities.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; using namespace o2::framework; -using namespace o2::aod::hf_cand; -using namespace o2::aod::hf_cand_xicc; namespace o2::aod { @@ -84,7 +81,7 @@ DECLARE_SOA_COLUMN(RunNumber, runNumber, int); } // namespace full // put the arguments into the table -DECLARE_SOA_TABLE(HfCandXiccFull, "AOD", "HFCANDXiccFull", +DECLARE_SOA_TABLE(HfCandXiccFulls, "AOD", "HFCANDXICCFULL", full::RSecondaryVertex, full::DecayLength, full::DecayLengthXY, @@ -138,7 +135,7 @@ DECLARE_SOA_TABLE(HfCandXiccFull, "AOD", "HFCANDXiccFull", full::MCflag, full::OriginMcRec); -DECLARE_SOA_TABLE(HfCandXiccFullEvents, "AOD", "HFCANDXiccFullE", +DECLARE_SOA_TABLE(HfCandXiccFullEs, "AOD", "HFCANDXICCFULLE", collision::BCId, collision::NumContrib, collision::PosX, @@ -147,7 +144,7 @@ DECLARE_SOA_TABLE(HfCandXiccFullEvents, "AOD", "HFCANDXiccFullE", full::IsEventReject, full::RunNumber); -DECLARE_SOA_TABLE(HfCandXiccFullParticles, "AOD", "HFCANDXiccFullP", +DECLARE_SOA_TABLE(HfCandXiccFullPs, "AOD", "HFCANDXICCFULLP", collision::BCId, full::Pt, full::Eta, @@ -160,25 +157,29 @@ DECLARE_SOA_TABLE(HfCandXiccFullParticles, "AOD", "HFCANDXiccFullP", /// Writes the full information in an output TTree struct HfTreeCreatorXiccToPKPiPi { - Produces rowCandidateFull; - Produces rowCandidateFullEvents; - Produces rowCandidateFullParticles; + Produces rowCandidateFull; + Produces rowCandidateFullEvents; + Produces rowCandidateFullParticles; + + HfHelper hfHelper; + + using TracksWPid = soa::Join; void init(InitContext const&) { } void process(aod::Collisions const& collisions, - aod::McCollisions const& mccollisions, + aod::McCollisions const& mcCollisions, soa::Join const& candidates, soa::Join const& particles, - aod::BigTracksPID const& tracks, + TracksWPid const& tracks, aod::HfCand3Prong const&) { // Filling event properties rowCandidateFullEvents.reserve(collisions.size()); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { rowCandidateFullEvents( collision.bcId(), collision.numContrib(), @@ -191,7 +192,7 @@ struct HfTreeCreatorXiccToPKPiPi { // Filling candidate properties rowCandidateFull.reserve(candidates.size()); - for (auto& candidate : candidates) { + for (const auto& candidate : candidates) { auto fillTable = [&](int CandFlag, int FunctionSelection, float FunctionInvMass, @@ -219,16 +220,16 @@ struct HfTreeCreatorXiccToPKPiPi { candidate.pyProng1(), candidate.pzProng1(), candidate.chi2PCA(), - candidate.prong1_as().tofNSigmaPi(), + candidate.prong1_as().tofNSigmaPi(), candidate.impactParameter0(), candidate.impactParameter1(), candidate.errorImpactParameter0(), candidate.errorImpactParameter1(), candidate.impactParameterProduct(), - o2::aod::hf_cand_3prong::invMassXicToPKPi(xicCand), - o2::aod::hf_cand_3prong::ctXic(xicCand), - o2::aod::hf_cand_3prong::yXic(xicCand), - o2::aod::hf_cand_3prong::eXic(xicCand), + hfHelper.invMassXicToPKPi(xicCand), + hfHelper.ctXic(xicCand), + hfHelper.yXic(xicCand), + hfHelper.eXic(xicCand), xicCand.eta(), xicCand.cpa(), xicCand.cpaXY(), @@ -236,11 +237,11 @@ struct HfTreeCreatorXiccToPKPiPi { xicCand.decayLength(), xicCand.decayLengthXY(), xicCand.decayLengthXYNormalised(), - xicCand.prong0_as().tofNSigmaPr(), - xicCand.prong0_as().tofNSigmaPi(), - xicCand.prong1_as().tofNSigmaKa(), - xicCand.prong2_as().tofNSigmaPr(), - xicCand.prong2_as().tofNSigmaPi(), + xicCand.prong0_as().tofNSigmaPr(), + xicCand.prong0_as().tofNSigmaPi(), + xicCand.prong1_as().tofNSigmaKa(), + xicCand.prong2_as().tofNSigmaPr(), + xicCand.prong2_as().tofNSigmaPi(), 1 << CandFlag, FunctionInvMass, candidate.pt(), @@ -256,19 +257,19 @@ struct HfTreeCreatorXiccToPKPiPi { } }; - fillTable(0, candidate.isSelXiccToPKPiPi(), invMassXiccToXicPi(candidate), ctXicc(candidate), yXicc(candidate)); + fillTable(0, candidate.isSelXiccToPKPiPi(), hfHelper.invMassXiccToXicPi(candidate), hfHelper.ctXicc(candidate), hfHelper.yXicc(candidate)); } // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); - for (auto& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::XiccToXicPi) { + for (const auto& particle : particles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_xicc::DecayType::XiccToXicPi) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), particle.eta(), particle.phi(), - RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())), + RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassXiCCPlusPlus), particle.flagMcMatchGen(), particle.originMcGen()); } diff --git a/PWGHF/Tasks/CMakeLists.txt b/PWGHF/Tasks/CMakeLists.txt index d1117624912..4a100752765 100644 --- a/PWGHF/Tasks/CMakeLists.txt +++ b/PWGHF/Tasks/CMakeLists.txt @@ -11,20 +11,20 @@ o2physics_add_dpl_workflow(task-lc-centrality SOURCES taskLcCentrality.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-mc-efficiency SOURCES taskMcEfficiency.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-mc-validation SOURCES taskMcValidation.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-sel-optimisation SOURCES taskSelOptimisation.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGHF/Tasks/taskLcCentrality.cxx b/PWGHF/Tasks/taskLcCentrality.cxx index 387a6386005..149d33e738b 100644 --- a/PWGHF/Tasks/taskLcCentrality.cxx +++ b/PWGHF/Tasks/taskLcCentrality.cxx @@ -16,18 +16,19 @@ /// \author Luigi Dello Stritto , University and INFN SALERNO /// \author Vít Kučera , CERN -#include "Common/DataModel/Centrality.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Common/DataModel/Centrality.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_3prong; -using namespace o2::analysis::hf_cuts_lc_to_p_k_pi; void customize(std::vector& workflowOptions) { @@ -43,6 +44,8 @@ struct HfTaskLcCentrality { Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); HistogramRegistry registry{ @@ -53,7 +56,7 @@ struct HfTaskLcCentrality { {"hPtProng2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{100, 0., 10.}}}}, {"hCentrality", "centrality;centrality percentile;entries", {HistType::kTH1F, {{100, 0., 100.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hMass", "3-prong candidates;inv. mass (p K #pi) (GeV/#it{c}^{2}); p_{T}; centrality", {HistType::kTH3F, {{500, 1.6, 3.1}, {vbins, "#it{p}_{T} (GeV/#it{c})"}, {100, 0., 100.}}}); @@ -72,23 +75,24 @@ struct HfTaskLcCentrality { // FIXME: Add ALICE 2/3 switch! // void process(aod::HfCand3Prong const& candidates) - void process(soa::Join::iterator const& collision, soa::Filtered> const& candidates) + void process(soa::Join::iterator const& collision, + soa::Filtered> const& candidates) { float centrality = collision.centRun2V0M(); registry.fill(HIST("hCentrality"), centrality); - for (auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { continue; } - if (yCandMax >= 0. && std::abs(yLc(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yLc(candidate)) > yCandMax) { continue; } if (candidate.isSelLcToPKPi() >= selectionFlagLc) { - registry.fill(HIST("hMass"), invMassLcToPKPi(candidate), candidate.pt(), centrality); + registry.fill(HIST("hMass"), hfHelper.invMassLcToPKPi(candidate), candidate.pt(), centrality); } if (candidate.isSelLcToPiKP() >= selectionFlagLc) { - registry.fill(HIST("hMass"), invMassLcToPiKP(candidate), candidate.pt(), centrality); + registry.fill(HIST("hMass"), hfHelper.invMassLcToPiKP(candidate), candidate.pt(), centrality); } registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hPtProng0"), candidate.ptProng0()); @@ -98,7 +102,7 @@ struct HfTaskLcCentrality { registry.fill(HIST("hd0Prong0"), candidate.impactParameter0(), candidate.pt()); registry.fill(HIST("hd0Prong1"), candidate.impactParameter1(), candidate.pt()); registry.fill(HIST("hd0Prong2"), candidate.impactParameter2(), candidate.pt()); - registry.fill(HIST("hCt"), ctLc(candidate), candidate.pt()); + registry.fill(HIST("hCt"), hfHelper.ctLc(candidate), candidate.pt()); registry.fill(HIST("hCPA"), candidate.cpa(), candidate.pt()); registry.fill(HIST("hEta"), candidate.eta(), candidate.pt()); registry.fill(HIST("hSelectionStatus"), candidate.isSelLcToPKPi(), candidate.pt()); @@ -118,6 +122,8 @@ struct HfTaskLcCentralityMc { Configurable yCandMax{"yCandMax", -1., "max. cand. rapidity"}; Configurable> binsPt{"binsPt", std::vector{hf_cuts_lc_to_p_k_pi::vecBinsPt}, "pT bin limits"}; + HfHelper hfHelper; + Filter filterSelectCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); HistogramRegistry registry{ @@ -128,7 +134,7 @@ struct HfTaskLcCentralityMc { {"hEtaRecBg", "3-prong candidates (unmatched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}, {"hEtaGen", "MC particles (matched);#it{#eta};entries", {HistType::kTH1F, {{100, -2., 2.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { auto vbins = (std::vector)binsPt; registry.add("hPtRecSig", "3-prong candidates (matched);#it{p}_{T}^{rec.} (GeV/#it{c});entries", {HistType::kTH1F, {{vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -142,21 +148,21 @@ struct HfTaskLcCentralityMc { } void process(soa::Filtered> const& candidates, - soa::Join const& particlesMC, aod::BigTracksMC const& tracks) + soa::Join const& mcParticles, + aod::TracksWMc const& tracks) { // MC rec. - // Printf("MC Candidates: %d", candidates.size()); - for (auto& candidate : candidates) { - if (!(candidate.hfflag() & 1 << DecayType::LcToPKPi)) { + for (const auto& candidate : candidates) { + if (!(candidate.hfflag() & 1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) { continue; } - if (yCandMax >= 0. && std::abs(yLc(candidate)) > yCandMax) { + if (yCandMax >= 0. && std::abs(hfHelper.yLc(candidate)) > yCandMax) { continue; } - if (std::abs(candidate.flagMcMatchRec()) == 1 << DecayType::LcToPKPi) { + if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { // Get the corresponding MC particle. - auto indexMother = RecoDecay::getMother(particlesMC, candidate.prong0_as().mcParticle_as>(), pdg::Code::kLambdaCPlus, true); - auto particleMother = particlesMC.rawIteratorAt(indexMother); + auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong0_as().mcParticle_as>(), pdg::Code::kLambdaCPlus, true); + auto particleMother = mcParticles.rawIteratorAt(indexMother); registry.fill(HIST("hPtGenSig"), particleMother.pt()); // gen. level pT auto ptRec = candidate.pt(); registry.fill(HIST("hPtRecSig"), ptRec); // rec. level pT @@ -174,10 +180,9 @@ struct HfTaskLcCentralityMc { } } // MC gen. - // Printf("MC Particles: %d", particlesMC.size()); - for (auto& particle : particlesMC) { - if (std::abs(particle.flagMcMatchGen()) == 1 << DecayType::LcToPKPi) { - if (yCandMax >= 0. && std::abs(RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode()))) > yCandMax) { + for (const auto& particle : mcParticles) { + if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_3prong::DecayType::LcToPKPi) { + if (yCandMax >= 0. && std::abs(RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, o2::analysis::pdg::MassLambdaCPlus)) > yCandMax) { continue; } auto ptGen = particle.pt(); diff --git a/PWGHF/Tasks/taskMcEfficiency.cxx b/PWGHF/Tasks/taskMcEfficiency.cxx index 1a35ecb6476..f6b67fb0ad1 100644 --- a/PWGHF/Tasks/taskMcEfficiency.cxx +++ b/PWGHF/Tasks/taskMcEfficiency.cxx @@ -14,19 +14,22 @@ /// /// \author Jan Fiete Grosse-Oetringhaus, CERN -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; struct HfTaskMcEfficiency { Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; @@ -34,12 +37,15 @@ struct HfTaskMcEfficiency { ConfigurableAxis axisPt{"axisPt", {10, 0, 10}, "pT axis"}; ConfigurableAxis axisMass{"axisMass", {120, 1.5848, 2.1848}, "m_inv axis"}; - ConfigurableAxis axisPdg{"axisPdg", {VARIABLE_WIDTH, -4122.5, -421.5, 0, 421.5, 4122.5}, "PDG code axis"}; + ConfigurableAxis axisPdg{"axisPdg", {VARIABLE_WIDTH, -4122.5, -431.5, -421.5, -411.5, 0, 411.5, 421.5, 431.5, 4122.5}, "PDG code axis"}; ConfigurableAxis axisCPA{"axisCPA", {102, -1.02, 1.02}, "Cosine of pointing angle axis"}; Configurable mcAcceptancePt{"mcAcceptancePt", 0.1, "MC Acceptance: lower pt limit"}; Configurable mcAcceptanceEta{"mcAcceptanceEta", 0.8, "MC Acceptance: upper eta limit"}; + Service pdg; + HfHelper hfHelper; + enum HFStep { kHFStepMC = 0, kHFStepMcInRapidity, // MC mothers in rapidity |y| < 0.5 kHFStepAcceptance, // MC mothers where all prongs are in the acceptance @@ -93,7 +99,7 @@ struct HfTaskMcEfficiency { return track.isGlobalTrackWoDCA(); } - template + template void candidate3ProngLoop(T1& candidates, T2& tracks, T3& mcParticles, std::vector pdgCodes) { using TracksType = std::decay_t; @@ -107,7 +113,17 @@ struct HfTaskMcEfficiency { auto decayType = -1; std::array pdgDaughters; - if (pdgCode == pdg::kLambdaCPlus) { + if (pdgCode == pdg::kDPlus) { + decayType = 1 << aod::hf_cand_3prong::DecayType::DplusToPiKPi; + pdgDaughters[0] = +kPiPlus; + pdgDaughters[1] = -kKPlus; + pdgDaughters[2] = +kPiPlus; + } else if (pdgCode == pdg::kDS) { + decayType = 1 << aod::hf_cand_3prong::DecayType::DsToKKPi; + pdgDaughters[0] = +kKPlus; + pdgDaughters[1] = -kKPlus; + pdgDaughters[2] = +kPiPlus; + } else if (pdgCode == pdg::kLambdaCPlus) { decayType = 1 << aod::hf_cand_3prong::DecayType::LcToPKPi; pdgDaughters[0] = +kProton; pdgDaughters[1] = -kKPlus; @@ -128,18 +144,30 @@ struct HfTaskMcEfficiency { bool isHypoMass2TrackStep = true; bool isHypoMass1SelStep = false; bool isHypoMass2SelStep = false; - if (pdgCode == pdg::kLambdaCPlus) { - isHypoMass1SelStep = candidate.isSelLcToPKPi(); /// from candidate selector! - isHypoMass2SelStep = candidate.isSelLcToPiKP(); /// from candidate selector! + /// selections from candidate selectors + if constexpr (hasDplus) { + if (pdgCode == pdg::kDPlus) { + isHypoMass1SelStep = candidate.isSelDplusToPiKPi(); // only one mass hypo for D+ + } + } + if constexpr (hasDs) { + if (pdgCode == pdg::kDS) { + isHypoMass1SelStep = candidate.isSelDsToKKPi(); + isHypoMass2SelStep = candidate.isSelDsToPiKK(); + } } + if constexpr (hasLc) { + if (pdgCode == pdg::kLambdaCPlus) { + isHypoMass1SelStep = candidate.isSelLcToPKPi(); + isHypoMass2SelStep = candidate.isSelLcToPiKP(); + } + } + bool collisionMatched = false; int origin = RecoDecay::OriginType::None; if constexpr (mc) { /// info MC used int8_t sign = 0; - int indexRec = -999; - if (pdgCode == pdg::kLambdaCPlus) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, std::array{trackPos, trackNeg, trackThird}, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); - } + int indexRec = RecoDecay::getMatchedMCRec(mcParticles, std::array{trackPos, trackNeg, trackThird}, pdgCode, pdgDaughters, true, &sign, 2); if (indexRec < 0) { continue; @@ -176,13 +204,19 @@ struct HfTaskMcEfficiency { /// all candidates if (isHypoMass1TrackStep) { if (pdgCode == pdg::kLambdaCPlus) { - massHypo1 = invMassLcToPKPi(candidate); + massHypo1 = hfHelper.invMassLcToPKPi(candidate); + } else if (pdgCode == pdg::kDPlus) { + massHypo1 = hfHelper.invMassDplusToPiKPi(candidate); + } else if (pdgCode == pdg::kDS) { + massHypo1 = hfHelper.invMassDsToKKPi(candidate); } hCandidates->Fill(kHFStepTracked, pt, massHypo1, pdgCode, cpa, collisionMatched, origin); } if (isHypoMass2TrackStep) { if (pdgCode == pdg::kLambdaCPlus) { - massHypo2 = invMassLcToPiKP(candidate); + massHypo2 = hfHelper.invMassLcToPiKP(candidate); + } else if (pdgCode == pdg::kDS) { + massHypo2 = hfHelper.invMassDsToPiKK(candidate); } hCandidates->Fill(kHFStepTracked, pt, massHypo2, pdgCode, cpa, collisionMatched, origin); } @@ -234,7 +268,7 @@ struct HfTaskMcEfficiency { } template - void candidate2ProngLoop(T1& candidates, T2& tracks, T3& mcParticles, std::vector pdgCodes) + void candidate2ProngLoop(T1 const& candidates, T2 const& tracks, T3 const& mcParticles, std::vector pdgCodes) { using TracksType = std::decay_t; @@ -284,10 +318,10 @@ struct HfTaskMcEfficiency { float pt = candidate.pt(); bool selected = false; if (pdgCode == pdg::kD0) { - mass = invMassD0ToPiK(candidate); + mass = hfHelper.invMassD0ToPiK(candidate); selected = candidate.isSelD0() >= selectionFlagD0; } else if (pdgCode == pdg::kD0Bar) { - mass = invMassD0barToKPi(candidate); + mass = hfHelper.invMassD0barToKPi(candidate); selected = candidate.isSelD0bar() >= selectionFlagD0bar; } LOGP(debug, "Candidate {} has prong {} and prong {} and pT {} and mass {}", candidate.globalIndex(), candidate.prong0Id(), candidate.prong1Id(), candidate.pt(), mass); @@ -333,7 +367,7 @@ struct HfTaskMcEfficiency { } template - void candidate2ProngMcLoop(C& candidates, TracksWithSelectionMC& tracks, aod::McParticles& mcParticles, aod::McCollisionLabels& colls, std::vector pdgCodes) + void candidate2ProngMcLoop(C const& candidates, TracksWithSelectionMC const& tracks, aod::McParticles const& mcParticles, aod::McCollisionLabels const& colls, std::vector pdgCodes) { candidate2ProngLoop(candidates, tracks, mcParticles, pdgCodes); @@ -361,7 +395,7 @@ struct HfTaskMcEfficiency { } for (const auto pdgCode : pdgCodes) { - auto mass = RecoDecay::getMassPDG(pdgCode); + auto mass = pdg->Mass(pdgCode); for (const auto& mcParticle : mcParticles) { if (mcParticle.pdgCode() != pdgCode) { @@ -369,7 +403,7 @@ struct HfTaskMcEfficiency { } /// check if we end-up with the correct final state using MC info int8_t sign = 0; - if (std::abs(mcParticle.pdgCode()) == pdg::kD0 && !RecoDecay::isMatchedMCGen(mcParticles, mcParticle, pdg::Code::kD0, array{+kPiPlus, -kKPlus}, true, &sign)) { + if (std::abs(mcParticle.pdgCode()) == pdg::kD0 && !RecoDecay::isMatchedMCGen(mcParticles, mcParticle, pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) { /// check if we have D0(bar) → π± K∓ continue; } @@ -445,10 +479,10 @@ struct HfTaskMcEfficiency { /// 3-prong analyses - template - void candidate3ProngMcLoop(C& candidates, TracksWithSelectionMC& tracks, aod::McParticles& mcParticles, aod::McCollisionLabels& colls, std::vector pdgCodes) + template + void candidate3ProngMcLoop(C const& candidates, TracksWithSelectionMC const& tracks, aod::McParticles const& mcParticles, aod::McCollisionLabels const& colls, std::vector pdgCodes) { - candidate3ProngLoop(candidates, tracks, mcParticles, pdgCodes); + candidate3ProngLoop(candidates, tracks, mcParticles, pdgCodes); auto hCandidates = registry.get(HIST("hCandidates")); auto hTrackablePtEta = registry.get(HIST("hTrackablePtEta")); @@ -474,21 +508,40 @@ struct HfTaskMcEfficiency { } for (const auto pdgCode : pdgCodes) { /// loop over PDG codes - auto mass = RecoDecay::getMassPDG(pdgCode); + auto mass = pdg->Mass(pdgCode); for (const auto& mcParticle : mcParticles) { /// loop over MC particles ////////////////////////// /// Step kHFStepMC /// ////////////////////////// - if (std::abs(mcParticle.pdgCode()) != pdgCode) { /// abs. value because only "kLambdaCPlus" is defined, not "kAntiLambdaCPlus" + auto absPdg = std::abs(mcParticle.pdgCode()); + if (absPdg != pdgCode) { /// abs. value because only "kLambdaCPlus" is defined, not "kAntiLambdaCPlus" continue; } + + std::array pdgDaughters; + if (pdgCode == pdg::kDPlus) { + pdgDaughters[0] = +kPiPlus; + pdgDaughters[1] = -kKPlus; + pdgDaughters[2] = +kPiPlus; + } else if (pdgCode == pdg::kDS) { + pdgDaughters[0] = +kKPlus; + pdgDaughters[1] = -kKPlus; + pdgDaughters[2] = +kPiPlus; + } else if (pdgCode == pdg::kLambdaCPlus) { + pdgDaughters[0] = +kProton; + pdgDaughters[1] = -kKPlus; + pdgDaughters[2] = +kPiPlus; + } else { + LOGP(fatal, "Not implemented for PDG {}", pdgCode); + } + /// check if we end-up with the correct final state using MC info int8_t sign = 0; std::unique_ptr> listIndexDaughters(new std::vector{}); - if (std::abs(mcParticle.pdgCode()) == pdg::kLambdaCPlus && !RecoDecay::isMatchedMCGen(mcParticles, mcParticle, pdg::Code::kLambdaCPlus, array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, listIndexDaughters.get())) { - /// check if we have Λc± → p± K∓ π± (either direct or resonant) + if (!RecoDecay::isMatchedMCGen(mcParticles, mcParticle, pdgCode, pdgDaughters, true, &sign, 2, listIndexDaughters.get())) { + /// check if we have Λc± → p± K∓ π± (either direct or resonant), or D± → π± K∓ π± (either direct or resonant) or Ds± → K± K∓ π± (either direct or resonant) continue; } @@ -594,34 +647,150 @@ struct HfTaskMcEfficiency { } /// end candidate3ProngMcLoop // process functions for data - void processDataD0(soa::Join& candidates, TracksWithSelection& tracks) + void processDataD0(soa::Join const& candidates, + TracksWithSelection const& tracks) { std::vector pdgCodes{pdg::kD0Bar, pdg::kD0}; candidate2ProngLoop(candidates, tracks, tracks, pdgCodes); // NOTE third argument has to be provided but is not used as template argument is } PROCESS_SWITCH(HfTaskMcEfficiency, processDataD0, "Process D0 data (no MC information needed)", false); - void processDataLc(soa::Join& candidates, TracksWithSelection& tracks) + void processDataDplus(soa::Join const& candidates, + TracksWithSelection const& tracks) + { + std::vector pdgCodes{pdg::kDPlus}; + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processDataDplus, "Process D+ data (no MC information needed)", false); + + void processDataDs(soa::Join const& candidates, + TracksWithSelection const& tracks) + { + std::vector pdgCodes{pdg::kDS}; + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processDataDs, "Process Ds+ data (no MC information needed)", false); + + void processDataLc(soa::Join const& candidates, + TracksWithSelection const& tracks) { std::vector pdgCodes{pdg::kLambdaCPlus}; - candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processDataLc, "Process Lc data (no MC information needed)", false); + void processDataDplusDs(soa::Join const& candidates, + TracksWithSelection const& tracks) + { + std::vector pdgCodes{pdg::kDPlus, pdg::kDS}; + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processDataDplusDs, "Process D+ and Ds+ data (no MC information needed)", false); + + void processDataDplusDsLc(soa::Join const& candidates, + TracksWithSelection const& tracks) + { + std::vector pdgCodes{pdg::kDPlus, pdg::kDS, pdg::kLambdaCPlus}; + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processDataDplusDsLc, "Process D+, Ds+, and Lc data (no MC information needed)", false); + + void processDataDplusLc(soa::Join const& candidates, + TracksWithSelection const& tracks) + { + std::vector pdgCodes{pdg::kDPlus, pdg::kLambdaCPlus}; + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processDataDplusLc, "Process D+ and Lc data (no MC information needed)", false); + + void processDataDsLc(soa::Join const& candidates, + TracksWithSelection const& tracks) + { + std::vector pdgCodes{pdg::kDPlus, pdg::kDS, pdg::kLambdaCPlus}; + candidate3ProngLoop(candidates, tracks, tracks, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processDataDsLc, "Process Ds+ and Lc data (no MC information needed)", false); + // process functions for MC - void processMcD0(soa::Join& candidates, TracksWithSelectionMC& tracks, aod::McParticles& mcParticles, aod::McCollisionLabels& colls) + void processMcD0(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) { std::vector pdgCodes{pdg::kD0Bar, pdg::kD0}; candidate2ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcD0, "Process MC for D0 signal", true); - void processMcLc(soa::Join& candidates, TracksWithSelectionMC& tracks, aod::McParticles& mcParticles, aod::McCollisionLabels& colls) + void processMcDplus(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) + { + std::vector pdgCodes{pdg::kDPlus}; + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processMcDplus, "Process MC for D+ signal", false); + + void processMcDs(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) + { + std::vector pdgCodes{pdg::kDS}; + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processMcDs, "Process MC for Ds+ signal", false); + + void processMcLc(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) { std::vector pdgCodes{pdg::kLambdaCPlus}; - candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); } PROCESS_SWITCH(HfTaskMcEfficiency, processMcLc, "Process MC for Lc signal", false); + + void processMcDplusDs(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) + { + std::vector pdgCodes{pdg::kDPlus, pdg::kDS}; + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processMcDplusDs, "Process MC for D+ and Ds+ signals", false); + + void processMcDplusDsLc(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) + { + std::vector pdgCodes{pdg::kDPlus, pdg::kDS, pdg::kLambdaCPlus}; + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processMcDplusDsLc, "Process MC for D+, Ds+, and Lc signals", false); + + void processMcDplusLc(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) + { + std::vector pdgCodes{pdg::kDPlus, pdg::kLambdaCPlus}; + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processMcDplusLc, "Process MC for D+ and Lc signals", false); + + void processMcDsLc(soa::Join const& candidates, + TracksWithSelectionMC const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisionLabels const& colls) + { + std::vector pdgCodes{pdg::kDS, pdg::kLambdaCPlus}; + candidate3ProngMcLoop(candidates, tracks, mcParticles, colls, pdgCodes); + } + PROCESS_SWITCH(HfTaskMcEfficiency, processMcDsLc, "Process MC for Ds+ and Lc signals", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index 88952be04eb..530d0c11108 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -17,20 +17,20 @@ /// \author Vít Kučera , CERN /// \author Fabrizio Grosa , CERN -#include "Common/DataModel/CollisionAssociationTables.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Common/DataModel/CollisionAssociationTables.h" + #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" using namespace o2; +using namespace o2::analysis; +using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_3prong; namespace { @@ -117,7 +117,7 @@ struct HfTaskMcValidationGen { {"hNonPromptCharmHadronsYDistr", "Y distribution vs non-prompt charm hadron; ; #it{y}^{gen}", {HistType::kTH2F, {axisSpecies, axisY}}}, {"hNonPromptCharmHadronsDecLenDistr", "Decay length distribution vs non-prompt charm hadron; ; decay length (#mum)", {HistType::kTH2F, {axisSpecies, axisDecLen}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { for (auto iBin = 1; iBin <= nCharmHadrons; ++iBin) { registry.get(HIST("hPromptCharmHadronsPtDistr"))->GetXaxis()->SetBinLabel(iBin, labels[iBin - 1].data()); @@ -130,7 +130,7 @@ struct HfTaskMcValidationGen { } /// Primary-vertex selection - /// \param collision mccollision table row + /// \param collision mcCollision table row template bool selectVertex(const Col& collision) { @@ -149,9 +149,10 @@ struct HfTaskMcValidationGen { return true; } - void process(aod::McCollision const& mccollision, aod::McParticles const& particlesMC) + void process(aod::McCollision const& mcCollision, + aod::McParticles const& mcParticles) { - if (!selectVertex(mccollision)) { + if (!selectVertex(mcCollision)) { return; } @@ -162,7 +163,7 @@ struct HfTaskMcValidationGen { std::array counterPrompt{0}, counterNonPrompt{0}; bool hasSignal = false; - for (auto& particle : particlesMC) { + for (const auto& particle : mcParticles) { if (!particle.has_mothers()) { continue; } @@ -209,7 +210,7 @@ struct HfTaskMcValidationGen { double sumPzDau = 0.; bool momentumCheck = true; for (std::size_t iDau = 0; iDau < listDaughters.size(); ++iDau) { - auto daughter = particlesMC.rawIteratorAt(listDaughters.at(iDau) - particlesMC.offset()); + auto daughter = mcParticles.rawIteratorAt(listDaughters.at(iDau) - mcParticles.offset()); sumPxDau += daughter.px(); sumPyDau += daughter.py(); sumPzDau += daughter.pz(); @@ -234,7 +235,7 @@ struct HfTaskMcValidationGen { } hasSignal = true; - int origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle); + int origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle); if (origin == RecoDecay::OriginType::Prompt) { counterPrompt[iD]++; } else if (origin == RecoDecay::OriginType::NonPrompt) { @@ -243,7 +244,7 @@ struct HfTaskMcValidationGen { auto daughter0 = particle.daughters_as().begin(); double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; - double vertexPrimary[3] = {mccollision.posX(), mccollision.posY(), mccollision.posZ()}; + double vertexPrimary[3] = {mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()}; auto decayLength = RecoDecay::distance(vertexPrimary, vertexDau); if (origin == RecoDecay::OriginType::Prompt) { if (std::abs(particle.y()) < 0.5) { @@ -310,7 +311,7 @@ struct HfTaskMcValidationRec { using HfCand2ProngWithMCRec = soa::Join; using HfCand3ProngWithMCRec = soa::Join; using CollisionsWithMCLabels = soa::Join; - using TracksWithSel = soa::Join; + using TracksWithSel = soa::Join; using McCollisionWithHFSignalInfo = soa::Join; Partition tracksFilteredGlobalTrackWoDCA = requireGlobalTrackWoDCAInFilter(); @@ -356,7 +357,7 @@ struct HfTaskMcValidationRec { return stdev; } - void init(o2::framework::InitContext&) + void init(InitContext&) { histOriginTracks[0] = registry.add("histOriginNonAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks not associated to any collision histOriginTracks[1] = registry.add("histOriginAssociatedTracks", ";origin;#it{p}_{T}^{reco} (GeV/#it{c});#it{#eta}^{reco};#it{Z}_{vtx}^{reco}#minus#it{Z}_{vtx}^{gen} (cm); is PV contributor; has TOF; number of ITS hits", HistType::kTHnSparseF, {axisOrigin, axisPt, axisEta, axisDeltaVtx, axisDecision, axisDecision, axisITShits}); // tracks associasted to a collision @@ -404,7 +405,7 @@ struct HfTaskMcValidationRec { void process(HfCand2ProngWithMCRec const& cand2Prongs, HfCand3ProngWithMCRec const& cand3Prongs, TracksWithSel const& tracks, - aod::McParticles const& particlesMC, + aod::McParticles const& mcParticles, McCollisionWithHFSignalInfo const& mcCollisions, CollisionsWithMCLabels const& collisions, aod::BCs const&) @@ -427,7 +428,7 @@ struct HfTaskMcValidationRec { registry.fill(HIST("histNtracks"), tracksGlobalWoDCAColl1.size()); auto tracksColl1 = tracksInAcc->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); int nContributors = 0, nGoodContributors = 0; - for (auto& track : tracksColl1) { + for (const auto& track : tracksColl1) { if (!track.isPVContributor()) { continue; } @@ -449,20 +450,20 @@ struct HfTaskMcValidationRec { float radColl1 = std::sqrt(collision.posX() * collision.posX() + collision.posY() * collision.posY()); float radColl2 = std::sqrt(collision2.posX() * collision2.posX() + collision2.posY() * collision2.posY()); int nFromBeautyColl1 = 0, nFromBeautyColl2 = 0; - for (auto& trackColl1 : tracksColl1) { + for (const auto& trackColl1 : tracksColl1) { if (trackColl1.has_mcParticle() && trackColl1.isPVContributor()) { auto particleColl1 = trackColl1.mcParticle(); - auto origin = RecoDecay::getCharmHadronOrigin(particlesMC, particleColl1, true); + auto origin = RecoDecay::getCharmHadronOrigin(mcParticles, particleColl1, true); if (origin == RecoDecay::NonPrompt) { nFromBeautyColl1++; } } } auto tracksColl2 = tracksInAcc->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); - for (auto& trackColl2 : tracksColl2) { + for (const auto& trackColl2 : tracksColl2) { if (trackColl2.has_mcParticle() && trackColl2.isPVContributor()) { auto particleColl2 = trackColl2.mcParticle(); - auto origin = RecoDecay::getCharmHadronOrigin(particlesMC, particleColl2, true); + auto origin = RecoDecay::getCharmHadronOrigin(mcParticles, particleColl2, true); if (origin == RecoDecay::NonPrompt) { nFromBeautyColl2++; } @@ -475,7 +476,7 @@ struct HfTaskMcValidationRec { } // loop over tracks - for (auto& track : tracksFilteredGlobalTrackWoDCA) { + for (const auto& track : tracksFilteredGlobalTrackWoDCA) { // check number of ITS hits int nITSlayers = 0; uint8_t ITSHitMap = track.itsClusterMap(); @@ -493,14 +494,14 @@ struct HfTaskMcValidationRec { continue; } } - auto origin = RecoDecay::getCharmHadronOrigin(particlesMC, particle, true); + auto origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, true); histTracks->Fill(origin, track.pt()); bool isAmbiguous = (track.compatibleCollIds().size() != 1); if (isAmbiguous) { registry.fill(HIST("histAmbiguousTrackNumCollisions"), track.compatibleCollIds().size()); histAmbiguousTracks->Fill(origin, track.pt()); std::vector ambCollPosZ{}; - for (auto const& collIdx : track.compatibleCollIds()) { + for (const auto& collIdx : track.compatibleCollIds()) { auto ambCollision = collisions.rawIteratorAt(collIdx); ambCollPosZ.push_back(ambCollision.posZ()); } @@ -518,7 +519,7 @@ struct HfTaskMcValidationRec { histOriginTracks[index + 1]->Fill(origin, track.pt(), track.eta(), deltaZ, track.isPVContributor(), track.hasTOF(), nITSlayers); } else { // if the default associated collision is not the good one, check if the tracks is ambiguous if (isAmbiguous) { - for (auto const& collIdx : track.compatibleCollIds()) { + for (const auto& collIdx : track.compatibleCollIds()) { auto ambCollision = collisions.rawIteratorAt(collIdx); if (ambCollision.has_mcCollision() && ambCollision.mcCollisionId() == particle.mcCollisionId()) { @@ -543,7 +544,7 @@ struct HfTaskMcValidationRec { } // loop over 2-prong candidates - for (auto& cand2Prong : cand2Prongs) { + for (const auto& cand2Prong : cand2Prongs) { // determine which kind of candidate it is bool isD0Sel = TESTBIT(cand2Prong.hfflag(), o2::aod::hf_cand_2prong::DecayType::D0ToPiK); @@ -567,9 +568,9 @@ struct HfTaskMcValidationRec { if (whichHad >= 0 && whichOrigin >= 0) { int indexParticle = 0; if (cand2Prong.prong0_as().has_mcParticle()) { - indexParticle = RecoDecay::getMother(particlesMC, cand2Prong.prong0_as().mcParticle(), PDGArrayParticle[whichHad], true); + indexParticle = RecoDecay::getMother(mcParticles, cand2Prong.prong0_as().mcParticle(), PDGArrayParticle[whichHad], true); } - auto mother = particlesMC.rawIteratorAt(indexParticle); + auto mother = mcParticles.rawIteratorAt(indexParticle); histDeltaPt[whichHad]->Fill(cand2Prong.pt() - mother.pt()); histDeltaPx[whichHad]->Fill(cand2Prong.px() - mother.px()); histDeltaPy[whichHad]->Fill(cand2Prong.py() - mother.py()); @@ -601,7 +602,7 @@ struct HfTaskMcValidationRec { } // end loop on 2-prong candidates // loop over 3-prong candidates - for (auto& cand3Prong : cand3Prongs) { + for (const auto& cand3Prong : cand3Prongs) { // determine which kind of candidate it is bool isDPlusSel = TESTBIT(cand3Prong.hfflag(), o2::aod::hf_cand_3prong::DecayType::DplusToPiKPi); @@ -632,9 +633,9 @@ struct HfTaskMcValidationRec { if (whichHad >= 0) { int indexParticle = 0; if (cand3Prong.prong0_as().has_mcParticle()) { - indexParticle = RecoDecay::getMother(particlesMC, cand3Prong.prong0_as().mcParticle(), PDGArrayParticle[whichHad], true); + indexParticle = RecoDecay::getMother(mcParticles, cand3Prong.prong0_as().mcParticle(), PDGArrayParticle[whichHad], true); } - auto mother = particlesMC.rawIteratorAt(indexParticle); + auto mother = mcParticles.rawIteratorAt(indexParticle); histDeltaPt[whichHad]->Fill(cand3Prong.pt() - mother.pt()); histDeltaPx[whichHad]->Fill(cand3Prong.px() - mother.px()); histDeltaPy[whichHad]->Fill(cand3Prong.py() - mother.py()); diff --git a/PWGHF/Tasks/taskSelOptimisation.cxx b/PWGHF/Tasks/taskSelOptimisation.cxx index 70507e798a5..128ef6ac0c8 100644 --- a/PWGHF/Tasks/taskSelOptimisation.cxx +++ b/PWGHF/Tasks/taskSelOptimisation.cxx @@ -105,8 +105,6 @@ struct HfSelOptimisation { Configurable> cutsToTestMinDcaXY{"cutsToTestMinDcaXY", std::vector{vecCutsMinDCAxy}, "min DCA xy cut values to test"}; Configurable> cutsToTestMinTrackPt{"cutsToTestMinTrackPt", std::vector{vecCutsMinTrackPt}, "min track pT cut values to test"}; - using ExtendedTracks = soa::Join; - ConfigurableAxis ptBinning{"ptBinning", {0, 0., 2., 5., 20.}, "pT bin limits"}; AxisSpec axisPt = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; @@ -259,13 +257,13 @@ struct HfSelOptimisation { void process(soa::Join const& cand2Prongs, soa::Join const& cand3Prongs, - ExtendedTracks const&) + aod::TracksWDca const&) { // looping over 2-prong candidates for (const auto& cand2Prong : cand2Prongs) { - auto trackPos = cand2Prong.prong0_as(); // positive daughter - auto trackNeg = cand2Prong.prong1_as(); // negative daughter + auto trackPos = cand2Prong.prong0_as(); // positive daughter + auto trackNeg = cand2Prong.prong1_as(); // negative daughter std::array tracks = {trackPos, trackNeg}; bool isPrompt = false, isNonPrompt = false, isBkg = false; @@ -319,9 +317,9 @@ struct HfSelOptimisation { // looping over 3-prong candidates for (const auto& cand3Prong : cand3Prongs) { - auto trackFirst = cand3Prong.prong0_as(); // first daughter - auto trackSecond = cand3Prong.prong1_as(); // second daughter - auto trackThird = cand3Prong.prong2_as(); // third daughter + auto trackFirst = cand3Prong.prong0_as(); // first daughter + auto trackSecond = cand3Prong.prong1_as(); // second daughter + auto trackThird = cand3Prong.prong2_as(); // third daughter std::array tracks = {trackFirst, trackSecond, trackThird}; bool isPrompt = false, isNonPrompt = false, isBkg = false; diff --git a/PWGHF/Utils/utilsAnalysis.h b/PWGHF/Utils/utilsAnalysis.h new file mode 100644 index 00000000000..d5b2b725091 --- /dev/null +++ b/PWGHF/Utils/utilsAnalysis.h @@ -0,0 +1,41 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file utilsAnalysis.h +/// \brief Utilities for HF analyses + +#ifndef PWGHF_UTILS_UTILSANALYSIS_H_ +#define PWGHF_UTILS_UTILSANALYSIS_H_ + +#include // std::upper_bound +#include // std::distance + +namespace o2::analysis +{ +/// Finds pT bin in an array. +/// \param bins array of pT bins +/// \param value pT +/// \return index of the pT bin +/// \note Accounts for the offset so that pt bin array can be used to also configure a histogram axis. +template +int findBin(T1 const& binsPt, T2 value) +{ + if (value < binsPt->front()) { + return -1; + } + if (value >= binsPt->back()) { + return -1; + } + return std::distance(binsPt->begin(), std::upper_bound(binsPt->begin(), binsPt->end(), value)) - 1; +} +} // namespace o2::analysis + +#endif // PWGHF_UTILS_UTILSANALYSIS_H_ diff --git a/PWGHF/Utils/utilsBfieldCCDB.h b/PWGHF/Utils/utilsBfieldCCDB.h index 25eda9713ac..d4f2146f732 100644 --- a/PWGHF/Utils/utilsBfieldCCDB.h +++ b/PWGHF/Utils/utilsBfieldCCDB.h @@ -16,7 +16,7 @@ #ifndef PWGHF_UTILS_UTILSBFIELDCCDB_H_ #define PWGHF_UTILS_UTILSBFIELDCCDB_H_ -#include +#include // std::string #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" diff --git a/PWGHF/Utils/utilsDebugLcToK0sP.h b/PWGHF/Utils/utilsDebugLcToK0sP.h index 1da9ce89072..0a470c2fc14 100644 --- a/PWGHF/Utils/utilsDebugLcToK0sP.h +++ b/PWGHF/Utils/utilsDebugLcToK0sP.h @@ -22,8 +22,9 @@ /// listLabelsK0SNeg = {730, 2867, 4755, 5458, 6892, 7825, 9244, 9811, 10389, 12666, 13831, 17461, 19956, 21787, 23320, 24011, 26235, 28714, 30700, 32057, 34867, 37076, 39315, 40288, 41618, 43791, 44869, 45253, 46588, 47867, 48993, 53535, 57212, 58161, 59356, 61020, 62004, 63581, 65692, 68165, 69722, 70853, 73168, 75332, 76642, 78189, 79596, 80679, 81614, 84312, 86377, 86841, 87375, 89999, 95079, 96095, 97426, 100158, 101789, 103469, 104647, 106156, 108697, 110389, 111356, 111349, 112713, 113579, 114557, 114551, 116433, 117767, 118797, 118791, 119767, 120729, 121873, 124028, 125408, 127285, 129069, 129925, 131454, 132457, 132437, 133267, 134085, 135471, 136208, 137447, 138617, 139218, 141833, 143514, 144417, 145019, 145703, 147140, 148509, 149291, 149738, 153272, 154516, 155207, 158201, 159060, 160083, 161141, 162209, 163778, 165875, 167002, 168853, 174034, 174028, 175502, 177397, 177266, 178384, 179596, 179581, 181169, 187327, 188609, 189129, 191592, 193026, 194171, 195825, 197473, 201906, 202665, 203164, 203836, 205557, 207839, 208867, 211655, 216313, 217133, 217555, 218617, 219504, 219997, 223355, 224714, 224708, 225483, 227208, 230563, 231325, 232084, 232810, 234775, 235893, 236901, 238039, 239630, 241518, 243461, 244882, 245554, 246722, 249673, 250590, 251883, 253035, 254544, 254540, 255942, 256809, 258808, 261613, 262888, 264474, 264472, 268913, 270024, 271999, 274082, 276126, 276953, 278531, 279614, 280447, 282153, 282035, 283409, 284754, 286616, 288038, 289737, 291010, 292337, 293566, 296530, 300565} /// -#include -#include +#include // std::any_of +#include // std::runtime_error +#include // std::vector inline bool isK0SfromLcFunc(int labelK0SPos, int labelK0SNeg, std::vector listLabelsK0SPos, std::vector listLabelsK0SNeg) { diff --git a/PWGJE/Core/JetFinder.cxx b/PWGJE/Core/JetFinder.cxx index d83896e4694..32339b2aed3 100644 --- a/PWGJE/Core/JetFinder.cxx +++ b/PWGJE/Core/JetFinder.cxx @@ -18,10 +18,15 @@ /// Sets the jet finding parameters void JetFinder::setParams() { + if (jetEtaDefault) { - if (!isReclustering && !isTriggering) { - jetEtaMin = etaMin + jetR; //in aliphysics this was (-etaMax + 0.95*jetR) + jetEtaMin = etaMin + jetR; // in aliphysics this was (-etaMax + 0.95*jetR) jetEtaMax = etaMax - jetR; + + if (isReclustering || isTriggering) { + jetEtaMin -= jetR; + jetEtaMax += jetR; + } } if (isReclustering) { jetR = 5.0 * jetR; @@ -92,6 +97,7 @@ fastjet::ClusterSequenceArea JetFinder::findJets(std::vector fastjet::ClusterSequenceArea clusterSeq(inputParticles, jetDef, areaDef); jets = sub ? (*sub)(clusterSeq.inclusive_jets()) : clusterSeq.inclusive_jets(); jets = selJets(jets); + jets = sorted_by_pt(jets); if (isReclustering) { jetR = jetR / 5.0; } diff --git a/PWGJE/Core/JetFinder.h b/PWGJE/Core/JetFinder.h index de6d30fd72a..24dce04cb6f 100644 --- a/PWGJE/Core/JetFinder.h +++ b/PWGJE/Core/JetFinder.h @@ -69,6 +69,7 @@ class JetFinder float jetPhiMax; float jetEtaMin; float jetEtaMax; + bool jetEtaDefault; float ghostEtaMin; float ghostEtaMax; @@ -119,8 +120,9 @@ class JetFinder jetPtMax(1000.0), jetPhiMin(phi_Min), jetPhiMax(phi_Max), - jetEtaMin(eta_Min), - jetEtaMax(eta_Max), + jetEtaMin(-99.0), + jetEtaMax(99.0), + jetEtaDefault(false), ghostEtaMin(eta_Min), ghostEtaMax(eta_Max), ghostArea(0.005), diff --git a/PWGJE/DataModel/Jet.h b/PWGJE/DataModel/Jet.h index 1d8917c510c..e1ecd36efa2 100644 --- a/PWGJE/DataModel/Jet.h +++ b/PWGJE/DataModel/Jet.h @@ -73,39 +73,42 @@ DECLARE_SOA_DYNAMIC_COLUMN(P, p, } // namespace o2::aod // Defines the jet table definition -#define DECLARE_JET_TABLE(_collision_name_, _jet_type_, _name_, _description_) \ - namespace _name_##util \ - { \ - DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_##s, dummy##_jet_type##s, \ - []() -> int { return 0; }); \ - } \ - DECLARE_SOA_TABLE(_jet_type_##s, "AOD", _description_, \ - o2::soa::Index<>, \ - jet::_collision_name_##Id, \ - jet::Pt, \ - jet::Eta, \ - jet::Phi, \ - jet::Energy, \ - jet::Mass, \ - jet::Area, \ - jet::R, \ - jet::Px, \ - jet::Py, \ - jet::Pz, \ - jet::P, \ - _name_##util::Dummy##_jet_type_##s<>); \ - namespace _name_##matchingGeo \ - { \ - DECLARE_SOA_INDEX_COLUMN_FULL(_jet_type_, matchedJetGeo, int32_t, _jet_type_##s, "_geo"); \ - } \ - namespace _name_##matchingPt \ - { \ - DECLARE_SOA_INDEX_COLUMN_FULL(_jet_type_, matchedJetPt, int32_t, _jet_type_##s, "_pt"); \ - } \ - namespace _name_##matchingCand \ - { \ - DECLARE_SOA_INDEX_COLUMN_FULL(_jet_type_, matchedJetCand, int32_t, _jet_type_##s, "_hf"); \ +#define DECLARE_JET_TABLE(_collision_name_, _jet_type_, _name_, _description_) \ + namespace _name_##util \ + { \ + DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_##s, dummy##_jet_type##s, \ + []() -> int { return 0; }); \ + } \ + DECLARE_SOA_TABLE(_jet_type_##s, "AOD", _description_, \ + o2::soa::Index<>, \ + jet::_collision_name_##Id, \ + jet::Pt, \ + jet::Eta, \ + jet::Phi, \ + jet::Energy, \ + jet::Mass, \ + jet::Area, \ + jet::R, \ + jet::Px, \ + jet::Py, \ + jet::Pz, \ + jet::P, \ + _name_##util::Dummy##_jet_type_##s<>); \ + namespace _name_##matchingGeo \ + { \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_jet_type_, matchedJetGeo, int32_t, _jet_type_##s, "_geo"); \ + } \ + namespace _name_##matchingPt \ + { \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_jet_type_, matchedJetPt, int32_t, _jet_type_##s, "_pt"); \ + } \ + namespace _name_##matchingCand \ + { \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_jet_type_, matchedJetCand, int32_t, _jet_type_##s, "_hf"); \ } + // DECLARE_SOA_INDEX_COLUMN_FULL(_jet_type_, matchedJetGeo, int32_t, _jet_type_##s, "_geo"); + // DECLARE_SOA_INDEX_COLUMN_FULL(_jet_type_, matchedJetPt, int32_t, _jet_type_##s, "_pt"); + // DECLARE_SOA_INDEX_COLUMN_FULL(_jet_type_, matchedJetCand, int32_t, _jet_type_##s, "_hf"); #define DECLARE_CONSTITUENTS_TABLE(_jet_type_, _name_, _Description_, _track_type_, _cand_type_) \ namespace _name_##constituents \ @@ -149,9 +152,9 @@ DECLARE_SOA_DYNAMIC_COLUMN(P, p, #define DECLARE_JETMATCHING_TABLE(_jet_type_base_, _jet_type_tag_, _description_) \ DECLARE_SOA_TABLE(_jet_type_base_##JetsMatchedTo##_jet_type_tag_##Jets, "AOD", _description_, \ - _jet_type_tag_##jetmatchingGeo::_jet_type_tag_##JetId, \ - _jet_type_tag_##jetmatchingPt::_jet_type_tag_##JetId, \ - _jet_type_tag_##jetmatchingCand::_jet_type_tag_##JetId); \ + _jet_type_tag_##jetmatchingGeo::_jet_type_tag_##JetIds, \ + _jet_type_tag_##jetmatchingPt::_jet_type_tag_##JetIds, \ + _jet_type_tag_##jetmatchingCand::_jet_type_tag_##JetIds); \ using _jet_type_base_##JetsMatchedTo##_jet_type_tag_##Jet = _jet_type_base_##JetsMatchedTo##_jet_type_tag_##Jets::iterator; #define DECLARE_MCEVENTWEIGHT_TABLE(_jet_type_, _name_, _description_) \ diff --git a/PWGJE/DataModel/JetSubstructure.h b/PWGJE/DataModel/JetSubstructure.h index 59f48dbd62f..15ccb7d78d7 100644 --- a/PWGJE/DataModel/JetSubstructure.h +++ b/PWGJE/DataModel/JetSubstructure.h @@ -37,29 +37,48 @@ DECLARE_SOA_COLUMN(Nsd, nsd, float); //! namespace jetoutput { +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! +DECLARE_SOA_INDEX_COLUMN(McCollision, mcCollision); //! DECLARE_SOA_COLUMN(JetPt, jetPt, float); //! DECLARE_SOA_COLUMN(JetPhi, jetPhi, float); //! DECLARE_SOA_COLUMN(JetEta, jetEta, float); //! +DECLARE_SOA_COLUMN(JetR, jetR, float); //! DECLARE_SOA_COLUMN(JetNConstituents, jetNConstituents, int); //! } // namespace jetoutput // Defines the jet substrcuture table definition -#define JETSUBSTRUCTURE_TABLE_DEF(_jet_type_, _cand_type_, _name_, _description_) \ - namespace _name_##substructure \ - { \ - DECLARE_SOA_INDEX_COLUMN(_jet_type_, jet); \ - DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, _cand_type_, "_0"); \ - DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_, dummy##_jet_type_, []() -> int { return 0; }); \ - } \ - DECLARE_SOA_TABLE(_jet_type_##Substructures, "AOD", _description_ "SS", jetsubstructure::Zg, jetsubstructure::Rg, jetsubstructure::Nsd, _name_##substructure::Dummy##_jet_type_<>); \ - DECLARE_SOA_TABLE(_jet_type_##Output, "AOD", _description_ "O", _name_##substructure::_jet_type_##Id, _name_##substructure::Candidate##Id, jetoutput::JetPt, jetoutput::JetPhi, jetoutput::JetEta, jetoutput::JetNConstituents); \ +#define JETSUBSTRUCTURE_TABLE_DEF(_collision_type_, _jet_type_, _matched_jet_type_, _cand_type_, _name_, _description_) \ + namespace _name_##substructure \ + { \ + DECLARE_SOA_INDEX_COLUMN(_jet_type_, jet); \ + DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, _cand_type_, "_0"); \ + DECLARE_SOA_DYNAMIC_COLUMN(Dummy##_jet_type_, dummy##_jet_type_, []() -> int { return 0; }); \ + } \ + \ + namespace _name_##geomatched \ + { \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_matched_jet_type_, matchedJetGeo, int32_t, _matched_jet_type_##s, "_geo"); \ + } \ + \ + namespace _name_##ptmatched \ + { \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_matched_jet_type_, matchedJetPt, int32_t, _matched_jet_type_##s, "_pt"); \ + } \ + \ + namespace _name_##candmatched \ + { \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_matched_jet_type_, matchedJetCand, int32_t, _matched_jet_type_##s, "_hf"); \ + } \ + \ + DECLARE_SOA_TABLE(_jet_type_##Substructures, "AOD", _description_ "SS", jetsubstructure::Zg, jetsubstructure::Rg, jetsubstructure::Nsd, _name_##substructure::Dummy##_jet_type_<>); \ + DECLARE_SOA_TABLE(_jet_type_##Output, "AOD", _description_ "O", jetoutput::_collision_type_##Id, _name_##substructure::_jet_type_##Id, _name_##substructure::Candidate##Id, _name_##geomatched::_matched_jet_type_##Ids, _name_##ptmatched::_matched_jet_type_##Ids, _name_##candmatched::_matched_jet_type_##Ids, jetoutput::JetPt, jetoutput::JetPhi, jetoutput::JetEta, jetoutput::JetR, jetoutput::JetNConstituents); \ DECLARE_SOA_TABLE(_jet_type_##SubstructureOutput, "AOD", _description_ "SSO", _name_##substructure::_jet_type_##Id, jetsubstructure::Zg, jetsubstructure::Rg, jetsubstructure::Nsd); -#define JETSUBSTRUCTURE_TABLES_DEF(_jet_type_, _cand_type_, _description_) \ - JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##Jet, _cand_type_, _jet_type_##jet, _description_) \ - JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##MCDetectorLevelJet, _cand_type_, _jet_type_##mcdetectorleveljet, _description_ "MCD") \ - JETSUBSTRUCTURE_TABLE_DEF(_jet_type_##MCParticleLevelJet, McParticles, _jet_type_##mcparticleleveljet, _description_ "MCP") +#define JETSUBSTRUCTURE_TABLES_DEF(_jet_type_, _cand_type_, _description_) \ + JETSUBSTRUCTURE_TABLE_DEF(Collision, _jet_type_##Jet, _jet_type_##Jet, _cand_type_, _jet_type_##jet, _description_) \ + JETSUBSTRUCTURE_TABLE_DEF(Collision, _jet_type_##MCDetectorLevelJet, _jet_type_##MCParticleLevelJet, _cand_type_, _jet_type_##mcdetectorleveljet, _description_ "MCD") \ + JETSUBSTRUCTURE_TABLE_DEF(McCollision, _jet_type_##MCParticleLevelJet, _jet_type_##MCDetectorLevelJet, McParticles, _jet_type_##mcparticleleveljet, _description_ "MCP") JETSUBSTRUCTURE_TABLES_DEF(Charged, HfCand2Prong, "C"); JETSUBSTRUCTURE_TABLES_DEF(D0Charged, HfCand2Prong, "D0"); diff --git a/PWGJE/DataModel/TrackJetQa.h b/PWGJE/DataModel/TrackJetQa.h new file mode 100644 index 00000000000..770040c1b51 --- /dev/null +++ b/PWGJE/DataModel/TrackJetQa.h @@ -0,0 +1,171 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file JetTrackQa.h +/// \author Johanna Lömker +/// \since 2023-10-02 +/// \brief Header for the trackJetQa task for the analysis of the tracks for jets. +/// + +#ifndef PWGJE_DATAMODEL_TRACKJETQA_H_ +#define PWGJE_DATAMODEL_TRACKJETQA_H_ + +// O2 includes +#include "ReconstructionDataFormats/Track.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGJE/DataModel/Jet.h" +#include "Framework/StaticFor.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" + +using namespace o2; +using namespace o2::track; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// Derived data model for cut variation +namespace o2::aod +{ +namespace spectra +{ + +template +typename binningType::binned_t packInTable(const float& valueToBin) +{ + if (valueToBin <= binningType::binned_min) { + return (binningType::underflowBin); + } else if (valueToBin >= binningType::binned_max) { + return (binningType::overflowBin); + } else if (valueToBin >= 0) { + return (static_cast((valueToBin / binningType::bin_width) + 0.5f)); + } else { + return (static_cast((valueToBin / binningType::bin_width) - 0.5f)); + } +} +// Function to unpack a binned value into a float +template +float unPack(const typename binningType::binned_t& valueToUnpack) +{ + return binningType::bin_width * static_cast(valueToUnpack); +} + +struct binningDCA { + public: + typedef int16_t binned_t; + static constexpr int nbins = (1 << 8 * sizeof(binned_t)) - 2; + static constexpr binned_t overflowBin = nbins >> 1; + static constexpr binned_t underflowBin = -(nbins >> 1); + static constexpr float binned_max = 6.0; + static constexpr float binned_min = -6.0; + static constexpr float bin_width = (binned_max - binned_min) / nbins; +}; + +// Collision info +DECLARE_SOA_INDEX_COLUMN(BC, bc); //! Most probably BC to where this collision has occurred +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +DECLARE_SOA_COLUMN(Sel8, sel8, bool); +// DECLARE_SOA_COLUMN(MultNTracksPVeta1, multNTracksPVeta1, int); +// Track info +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! Index to the collision +DECLARE_SOA_COLUMN(PtSigned, ptSigned, float); //! Pt (signed) of the track +DECLARE_SOA_COLUMN(Eta, eta, float); //! Eta of the track +DECLARE_SOA_COLUMN(Phi, phi, float); //! Phi of the track +DECLARE_SOA_COLUMN(Sigma1Pt, sigma1Pt, float); +// DECLARE_SOA_COLUMN(EvTimeT0AC, evTimeT0AC, float); //! Event time of the track computed with the T0AC +// DECLARE_SOA_COLUMN(EvTimeT0ACErr, evTimeT0ACErr, float); //! Resolution of the event time of the track computed with the T0AC +DECLARE_SOA_COLUMN(IsPVContributor, isPVContributor, bool); //! IsPVContributor +// DECLARE_SOA_COLUMN(LastTRDCluster, lastTRDCluster, int8_t); //! Index of the last cluster in the TRD, -1 if no TRD information +DECLARE_SOA_COLUMN(HasTRD, hasTRD, bool); //! Has or not the TRD match + +DECLARE_SOA_COLUMN(DCAxyStore, dcaxyStore, binningDCA::binned_t); //! Stored binned dcaxy +DECLARE_SOA_COLUMN(DCAzStore, dcazStore, binningDCA::binned_t); //! Stored binned dcaz +DECLARE_SOA_DYNAMIC_COLUMN(DCAxy, dcaXY, //! Unpacked dcaxy + [](binningDCA::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(DCAz, dcaZ, //! Unpacked dcaz + [](binningDCA::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! Absolute value of signed pT + [](float signedPt) -> float { return std::abs(signedPt); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float signedpt, float eta) -> float { return std::abs(signedpt) * cosh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackType, trackType, [](float v) -> uint8_t { return o2::aod::track::TrackTypeEnum::Track; }); +DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, bool); // if a track passed the isGlobalTrack requirement +DECLARE_SOA_COLUMN(IsGlobalTrackWoDCA, isGlobalTrackWoDCA, bool); // if a track passed the isGlobalTrackWoDCA requirement +DECLARE_SOA_COLUMN(IsGlobalTrackWoPtEta, isGlobalTrackWoPtEta, bool); // if a track passed the isGlobalTrackWoDCA requirement +DECLARE_SOA_DYNAMIC_COLUMN(Flags, flags, [](float v) -> uint32_t { return 0; }); // Dummy +DECLARE_SOA_DYNAMIC_COLUMN(TRDPattern, trdPattern, [](float v) -> uint8_t { return 0; }); // Dummy +DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, //! Track rapidity, computed under the mass assumption given as input + [](float signedPt, float eta, float mass) -> float { + const auto pt = std::abs(signedPt); + const auto p = std::abs(signedPt) * cosh(eta); + const auto pz = std::sqrt(p * p - pt * pt); + const auto energy = sqrt(p * p + mass * mass); + return 0.5f * log((energy + pz) / (energy - pz)); + }); +DECLARE_SOA_DYNAMIC_COLUMN(IsQualityTrackITS, isQualityTrackITS, [](float v) -> bool { return false; }); // Dummy +DECLARE_SOA_DYNAMIC_COLUMN(IsQualityTrackTPC, isQualityTrackTPC, [](float v) -> bool { return false; }); // Dummy + +} // namespace spectra + +DECLARE_SOA_TABLE(SpColls, "AOD", "SPCOLLS", + o2::soa::Index<>, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + spectra::Sel8, + spectra::RunNumber); +using SpColl = SpColls::iterator; + +DECLARE_SOA_TABLE(SpTracks, "AOD", "SPTRACKS", + o2::soa::Index<>, + spectra::CollisionId, + spectra::PtSigned, spectra::Eta, spectra::Phi, + spectra::Sigma1Pt, + track::Length, + track::TPCSignal, + track::TPCChi2NCl, track::ITSChi2NCl, track::TOFChi2, + track::TPCNClsShared, + track::TPCNClsFindable, + track::TPCNClsFindableMinusFound, + track::TPCNClsFindableMinusCrossedRows, + spectra::IsPVContributor, + track::ITSClusterMap, + spectra::HasTRD, + spectra::DCAxyStore, + spectra::DCAzStore, + spectra::DCAxy, + spectra::DCAz, + spectra::IsGlobalTrack, + spectra::IsGlobalTrackWoDCA, + spectra::IsGlobalTrackWoPtEta, + spectra::Pt, + track::Sign, + spectra::P, + spectra::Rapidity, + spectra::Flags, + spectra::TrackType, + spectra::IsQualityTrackITS, + spectra::IsQualityTrackTPC, + track::ITSNCls, track::ITSNClsInnerBarrel, + track::TPCFractionSharedCls, + track::TPCNClsFound, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls); +} // namespace o2::aod + +#endif // PWGJE_DATAMODEL_TRACKJETQA_H_ diff --git a/PWGJE/TableProducer/CMakeLists.txt b/PWGJE/TableProducer/CMakeLists.txt index f0c5b62056c..918516bdfe2 100644 --- a/PWGJE/TableProducer/CMakeLists.txt +++ b/PWGJE/TableProducer/CMakeLists.txt @@ -16,8 +16,23 @@ o2physics_add_dpl_workflow(jet-finder PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(jet-finder-hf - SOURCES jetfinderhf.cxx +o2physics_add_dpl_workflow(jet-finder-d0-data-charged + SOURCES jetfinderD0DataCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-d0-mcd-charged + SOURCES jetfinderD0MCDCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-d0-mcp-charged + SOURCES jetfinderD0MCPCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-lc-data-charged + SOURCES jetfinderLcDataCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) @@ -40,6 +55,11 @@ o2physics_add_dpl_workflow(jet-eventweight-mcp SOURCES jeteventweightmcp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-track-derived + SOURCES jettrackderived.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) endif() diff --git a/PWGJE/TableProducer/jetfinder.cxx b/PWGJE/TableProducer/jetfinder.cxx index d2b5807e782..77d3326c60a 100644 --- a/PWGJE/TableProducer/jetfinder.cxx +++ b/PWGJE/TableProducer/jetfinder.cxx @@ -38,7 +38,8 @@ struct JetFinderTask { Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - Configurable evSel{"evSel", "evSel8", "choose event selection"}; + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // cluster level configurables Configurable clusterDefinitionS{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; @@ -55,7 +56,8 @@ struct JetFinderTask { Configurable> jetRadius{"jetRadius", {0.4}, "jet resolution parameters"}; Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT"}; Configurable jetPtMax{"jetPtMax", 1000.0, "maximum jet pT"}; - Configurable jetTypeParticleLevel{"jetTypeParticleLevel", 1, "Type of stored jets at MC particle leevel. 0 = full, 1 = charged, 2 = neutral"}; + Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; + Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; Configurable jetAlgorithm{"jetAlgorithm", 2, "jet clustering algorithm. 0 = kT, 1 = C/A, 2 = Anti-kT"}; Configurable jetRecombScheme{"jetRecombScheme", 0, "jet recombination scheme. 0 = E-scheme, 1 = pT-scheme, 2 = pT2-scheme"}; Configurable jetGhostArea{"jetGhostArea", 0.005, "jet ghost area"}; @@ -64,8 +66,10 @@ struct JetFinderTask { Configurable DoRhoAreaSub{"DoRhoAreaSub", false, "do rho area subtraction"}; Configurable DoConstSub{"DoConstSub", false, "do constituent subtraction"}; - Service pdg; + Service pdg; std::string trackSelection; + std::string eventSelection; + std::string particleSelection; JetFinder jetFinder; std::vector inputParticles; @@ -73,6 +77,8 @@ struct JetFinderTask { void init(InitContext const&) { trackSelection = static_cast(trackSelections); + eventSelection = static_cast(eventSelections); + particleSelection = static_cast(particleSelections); if (DoRhoAreaSub) { jetFinder.setBkgSubMode(JetFinder::BkgSubMode::rhoAreaSub); @@ -85,6 +91,11 @@ struct JetFinderTask { jetFinder.etaMax = trackEtaMax; jetFinder.jetPtMin = jetPtMin; jetFinder.jetPtMax = jetPtMax; + jetFinder.jetEtaMin = jetEtaMin; + jetFinder.jetEtaMax = jetEtaMax; + if (jetEtaMin < -98.0) { + jetFinder.jetEtaDefault = true; + } jetFinder.algorithm = static_cast(static_cast(jetAlgorithm)); jetFinder.recombScheme = static_cast(static_cast(jetRecombScheme)); jetFinder.ghostArea = jetGhostArea; @@ -97,7 +108,7 @@ struct JetFinderTask { o2::aod::EMCALClusterDefinition clusterDefinition = o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); Filter collisionFilter = nabs(aod::collision::posZ) < vertexZCut; Filter trackCuts = (aod::track::pt >= trackPtMin && aod::track::pt < trackPtMax && aod::track::eta > trackEtaMin && aod::track::eta < trackEtaMax && aod::track::phi >= trackPhiMin && aod::track::phi <= trackPhiMax); // do we need eta cut both here and in globalselection? - Filter partCuts = (aod::mcparticle::pt >= trackPtMin && aod::mcparticle::pt < trackPtMax); + Filter partCuts = (aod::mcparticle::pt >= trackPtMin && aod::mcparticle::pt < trackPtMax && aod::mcparticle::eta > trackEtaMin && aod::mcparticle::eta < trackEtaMax); Filter clusterFilter = (o2::aod::emcalcluster::definition == static_cast(clusterDefinition) && aod::emcalcluster::eta > clusterEtaMin && aod::emcalcluster::eta < clusterEtaMax && aod::emcalcluster::phi >= clusterPhiMin && aod::emcalcluster::phi <= clusterPhiMax && aod::emcalcluster::energy >= clusterEnergyMin && aod::emcalcluster::time > clusterTimeMin && aod::emcalcluster::time < clusterTimeMax && (clusterRejectExotics && aod::emcalcluster::isExotic != true)); void processDummy(aod::Collisions const& collision) @@ -109,7 +120,7 @@ struct JetFinderTask { void processChargedJets(soa::Filtered>::iterator const& collision, JetTracks const& tracks) { - if (!selectCollision(collision, evSel)) { + if (!selectCollision(collision, eventSelection)) { return; } inputParticles.clear(); @@ -122,7 +133,7 @@ struct JetFinderTask { void processNeutralJets(soa::Filtered>::iterator const& collision, JetClusters const& clusters) { - if (!collision.alias_bit(kTVXinEMC)) { + if (!hasEMCAL(collision)) { return; } inputParticles.clear(); @@ -135,7 +146,7 @@ struct JetFinderTask { JetTracks const& tracks, JetClusters const& clusters) { - if (!collision.alias_bit(kTVXinEMC)) { + if (!hasEMCAL(collision)) { return; } inputParticles.clear(); @@ -143,17 +154,32 @@ struct JetFinderTask { analyseClusters(inputParticles, &clusters); findJets(jetFinder, inputParticles, jetRadius, collision, jetsTable, constituentsTable, constituentsSubTable, DoConstSub); } - PROCESS_SWITCH(JetFinderTask, processFullJets, "Data jet finding for full and neutral jets", false); - void processParticleLevelJets(aod::McCollision const& collision, aod::McParticles const& particles) + void processParticleLevelChargedJets(aod::McCollision const& collision, soa::Filtered const& particles) + { + // TODO: MC event selection? + analyseParticles, soa::Filtered::iterator>(inputParticles, particleSelection, 1, particles, pdg->Instance()); + findJets(jetFinder, inputParticles, jetRadius, collision, jetsTable, constituentsTable, constituentsSubTable, DoConstSub); + } + PROCESS_SWITCH(JetFinderTask, processParticleLevelChargedJets, "Particle level charged jet finding", false); + + void processParticleLevelNeutralJets(aod::McCollision const& collision, soa::Filtered const& particles) + { + // TODO: MC event selection? + analyseParticles, soa::Filtered::iterator>(inputParticles, particleSelection, 2, particles, pdg->Instance()); + findJets(jetFinder, inputParticles, jetRadius, collision, jetsTable, constituentsTable, constituentsSubTable, DoConstSub); + } + PROCESS_SWITCH(JetFinderTask, processParticleLevelNeutralJets, "Particle level neutral jet finding", false); + + void processParticleLevelFullJets(aod::McCollision const& collision, soa::Filtered const& particles) { // TODO: MC event selection? - analyseParticles(inputParticles, trackEtaMin, trackEtaMax, jetTypeParticleLevel, particles, pdg->Instance()); + analyseParticles, soa::Filtered::iterator>(inputParticles, particleSelection, 0, particles, pdg->Instance()); findJets(jetFinder, inputParticles, jetRadius, collision, jetsTable, constituentsTable, constituentsSubTable, DoConstSub); } - PROCESS_SWITCH(JetFinderTask, processParticleLevelJets, "Particle level jet finding", false); + PROCESS_SWITCH(JetFinderTask, processParticleLevelFullJets, "Particle level full jet finding", false); }; using JetFinderDataCharged = JetFinderTask; diff --git a/PWGJE/TableProducer/jetfinder.h b/PWGJE/TableProducer/jetfinder.h index c3c6ac32970..2bf01698def 100644 --- a/PWGJE/TableProducer/jetfinder.h +++ b/PWGJE/TableProducer/jetfinder.h @@ -16,6 +16,7 @@ #ifndef PWGJE_TABLEPRODUCER_JETFINDER_H_ #define PWGJE_TABLEPRODUCER_JETFINDER_H_ +#include #include #include @@ -40,21 +41,21 @@ #include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" -using JetTracks = soa::Filtered>; +using JetTracks = o2::soa::Filtered>; using JetClusters = o2::soa::Filtered; -using JetParticles2Prong = soa::Filtered>; -using JetParticles3Prong = soa::Filtered>; -using JetParticlesBplus = soa::Filtered>; +using ParticlesD0 = o2::soa::Filtered>; +using ParticlesLc = o2::soa::Filtered>; +using ParticlesBplus = o2::soa::Filtered>; -using CandidateD0Data = soa::Filtered>; -using CandidateD0MC = soa::Filtered>; +using CandidatesD0Data = o2::soa::Filtered>; +using CandidatesD0MCD = o2::soa::Filtered>; -using CandidateBplusData = soa::Filtered>; -using CandidateBplusMC = soa::Filtered>; +using CandidatesBplusData = o2::soa::Filtered>; +using CandidatesBplusMCD = o2::soa::Filtered>; -using CandidateLcData = soa::Filtered>; -using CandidateLcMC = soa::Filtered>; +using CandidatesLcData = o2::soa::Filtered>; +using CandidatesLcMCD = o2::soa::Filtered>; // functions for track, cluster and candidate selection @@ -62,12 +63,12 @@ using CandidateLcMC = soa::Filtered bool selectTrack(T const& track, std::string trackSelection) { - if (trackSelection == "globalTracks" && !track.isGlobalTrackWoPtEta()) { - return false; - } else if (trackSelection == "QualityTracks" && !track.isQualityTrack()) { - return false; - } else if (trackSelection == "hybridTracksJE" && !track.trackCutFlagFb5()) { - return false; + if (trackSelection == "globalTracks") { + return track.isGlobalTrackWoPtEta(); + } else if (trackSelection == "QualityTracks") { + return track.isQualityTrack(); + } else if (trackSelection == "hybridTracksJE") { + return track.trackCutFlagFb5(); } else { return true; } @@ -83,20 +84,20 @@ void analyseTracks(std::vector& inputParticles, T const& tra } if (candidate != std::nullopt) { auto cand = candidate.value(); - if constexpr (std::is_same_v, CandidateD0Data::iterator> || std::is_same_v, CandidateD0Data::filtered_iterator> || std::is_same_v, CandidateD0MC::iterator> || std::is_same_v, CandidateD0MC::filtered_iterator>) { + if constexpr (std::is_same_v, CandidatesD0Data::iterator> || std::is_same_v, CandidatesD0Data::filtered_iterator> || std::is_same_v, CandidatesD0MCD::iterator> || std::is_same_v, CandidatesD0MCD::filtered_iterator>) { if (cand.template prong0_as().globalIndex() == track.globalIndex() || cand.template prong1_as().globalIndex() == track.globalIndex()) { continue; } } - if constexpr (std::is_same_v, CandidateLcData::iterator> || std::is_same_v, CandidateLcData::filtered_iterator> || std::is_same_v, CandidateLcMC::iterator> || std::is_same_v, CandidateLcMC::filtered_iterator>) { + if constexpr (std::is_same_v, CandidatesLcData::iterator> || std::is_same_v, CandidatesLcData::filtered_iterator> || std::is_same_v, CandidatesLcMCD::iterator> || std::is_same_v, CandidatesLcMCD::filtered_iterator>) { if (cand.template prong0_as().globalIndex() == track.globalIndex() || cand.template prong1_as().globalIndex() == track.globalIndex() || cand.template prong2_as().globalIndex() == track.globalIndex()) { continue; } } - if constexpr (std::is_same_v, CandidateBplusData::iterator> || std::is_same_v, CandidateBplusData::filtered_iterator> || std::is_same_v, CandidateBplusMC::iterator> || std::is_same_v, CandidateBplusMC::filtered_iterator>) { - if (cand.template prong0_as().template prong0_as().globalIndex() == track.globalIndex() || cand.template prong0_as().template prong1_as().globalIndex() == track.globalIndex() || cand.template prong1_as().globalIndex() == track.globalIndex()) { + if constexpr (std::is_same_v, CandidatesBplusData::iterator> || std::is_same_v, CandidatesBplusData::filtered_iterator> || std::is_same_v, CandidatesBplusMCD::iterator> || std::is_same_v, CandidatesBplusMCD::filtered_iterator>) { + if (cand.template prong0_as().template prong0_as().globalIndex() == track.globalIndex() || cand.template prong0_as().template prong1_as().globalIndex() == track.globalIndex() || cand.template prong1_as().globalIndex() == track.globalIndex()) { continue; } } @@ -166,7 +167,7 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic std::vector trackconst; std::vector candconst; std::vector clusterconst; - jetsTable(collision, jet.pt(), jet.eta(), jet.phi(), + jetsTable(collision.globalIndex(), jet.pt(), jet.eta(), jet.phi(), jet.E(), jet.m(), jet.area(), std::round(R * 100)); for (const auto& constituent : sorted_by_pt(jet.constituents())) { // need to add seperate thing for constituent subtraction @@ -186,7 +187,6 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic } } constituentsTable(jetsTable.lastIndex(), trackconst, clusterconst, candconst); - break; } } } @@ -195,7 +195,7 @@ void findJets(JetFinder& jetFinder, std::vector& inputPartic template bool checkDaughters(T const& particle, int globalIndex) { - for (auto daughter : particle.template daughters_as()) { + for (auto daughter : particle.template daughters_as()) { if (daughter.globalIndex() == globalIndex) { return true; } @@ -207,15 +207,17 @@ bool checkDaughters(T const& particle, int globalIndex) } template -void analyseParticles(std::vector& inputParticles, float particleEtaMin, float particleEtaMax, int jetTypeParticleLevel, T const& particles, TDatabasePDG* pdg, std::optional const& candidate = std::nullopt) +void analyseParticles(std::vector& inputParticles, std::string particleSelection, int jetTypeParticleLevel, T const& particles, TDatabasePDG* pdg, std::optional const& candidate = std::nullopt) { inputParticles.clear(); for (auto& particle : particles) { - // TODO: can we do this through the filter? - if (particle.eta() < particleEtaMin || particle.eta() > particleEtaMax) { + if (particleSelection == "PhysicalPrimary" && !particle.isPhysicalPrimary()) { // CHECK : Does this exclude the HF hadron? continue; - } - if (particle.getGenStatusCode() != 1) { // CHECK : Does this exclude the HF hadron? + } else if (particleSelection == "HepMCStatus" && particle.getHepMCStatusCode() != 1) { // do we need isPhysicalPrimary as well? Note: Might give unforseen results if the generator isnt PYTHIA + continue; + } else if (particleSelection == "GenStatus" && particle.getGenStatusCode() != 1) { + continue; + } else if (particleSelection == "PhysicalPrimaryAndHepMCStatus" && (!particle.isPhysicalPrimary() || particle.getHepMCStatusCode() != 1)) { continue; } auto pdgParticle = pdg->GetParticle(particle.pdgCode()); @@ -237,18 +239,30 @@ void analyseParticles(std::vector& inputParticles, float par } template -bool selectCollision(T const& collision, std::string evSel) +bool selectCollision(T const& collision, std::string eventSelection) { - if (evSel == "evSel8" & !collision.sel8()) { - return false; - } - if (evSel == "evSel7" & !collision.sel7()) { - return false; - } - if (evSel == "None") { + if (eventSelection == "sel8") { + return collision.sel8(); + } else if (eventSelection == "sel7") { + return collision.sel7(); + } else { return true; } - return true; +} + +template +bool hasEMCAL(T const& collision) +{ + // Check for EMCAL in readout requires any of the EMCAL trigger classes (including EMC in MB trigger) to fire + std::array selectAliases = {{triggerAliases::kTVXinEMC, triggerAliases::kEMC7, triggerAliases::kDMC7, triggerAliases::kEG1, triggerAliases::kEG2, triggerAliases::kDG1, triggerAliases::kDG2, triggerAliases::kEJ1, triggerAliases::kEJ2, triggerAliases::kDJ1, triggerAliases::kDJ2}}; + bool found = false; + for (auto alias : selectAliases) { + if (collision.alias_bit(alias)) { + found = true; + break; + } + } + return found; } #endif // PWGJE_TABLEPRODUCER_JETFINDER_H_ diff --git a/PWGJE/TableProducer/jetfinderD0DataCharged.cxx b/PWGJE/TableProducer/jetfinderD0DataCharged.cxx new file mode 100644 index 00000000000..3ae0705d661 --- /dev/null +++ b/PWGJE/TableProducer/jetfinderD0DataCharged.cxx @@ -0,0 +1,29 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// jet finder d0 data charged task +// +// Authors: Nima Zardoshti + +#include "PWGJE/TableProducer/jetfinderhf.cxx" + +using JetFinderD0DataCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-d0-data-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/jetfinderD0MCDCharged.cxx b/PWGJE/TableProducer/jetfinderD0MCDCharged.cxx new file mode 100644 index 00000000000..bfe986396a8 --- /dev/null +++ b/PWGJE/TableProducer/jetfinderD0MCDCharged.cxx @@ -0,0 +1,29 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// jet finder d0 mcd charged task +// +// Authors: Nima Zardoshti + +#include "PWGJE/TableProducer/jetfinderhf.cxx" + +using JetFinderD0MCDetectorLevelCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-d0-mcd-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/jetfinderD0MCPCharged.cxx b/PWGJE/TableProducer/jetfinderD0MCPCharged.cxx new file mode 100644 index 00000000000..ceae1330947 --- /dev/null +++ b/PWGJE/TableProducer/jetfinderD0MCPCharged.cxx @@ -0,0 +1,29 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// jet finder d0 mcp charged task +// +// Authors: Nima Zardoshti + +#include "PWGJE/TableProducer/jetfinderhf.cxx" + +using JetFinderD0MCParticleLevelCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-d0-mcp-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/jetfinderLcDataCharged.cxx b/PWGJE/TableProducer/jetfinderLcDataCharged.cxx new file mode 100644 index 00000000000..096f48fdded --- /dev/null +++ b/PWGJE/TableProducer/jetfinderLcDataCharged.cxx @@ -0,0 +1,29 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// jet finder lc data charged task +// +// Authors: Nima Zardoshti + +#include "PWGJE/TableProducer/jetfinderhf.cxx" + +using JetFinderLcDataCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-lc-data-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/jetfinderhf.cxx b/PWGJE/TableProducer/jetfinderhf.cxx index 0b07fe58ec5..bbc7b2fc841 100644 --- a/PWGJE/TableProducer/jetfinderhf.cxx +++ b/PWGJE/TableProducer/jetfinderhf.cxx @@ -16,13 +16,30 @@ #include "PWGJE/TableProducer/jetfinder.h" using namespace o2; +using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; +/* +void customize(std::vector& workflowOptions) +{ + std::vector hfjetworkflows{{"d0-data-charged", VariantType::Int, 1, {"D0 jets charged data"}}, + {"d0-mcd-charged", VariantType::Int, 0, {"D0 jets charged MCD"}}, + {"d0-mcp-charged", VariantType::Int, 0, {"D0 jets charged MCD"}}, + {"bplus-data-charged", VariantType::Int, 0, {"B+ jets charged MCD"}}, + {"bplus-mcd-charged", VariantType::Int, 0, {"B+ jets charged MCD"}}, + {"bplus-mcp-charged", VariantType::Int, 0, {"B+ jets charged MCD"}}, + {"lc-data-charged", VariantType::Int, 0, {"Lc jets charged MCD"}}, + {"lc-mcd-charged", VariantType::Int, 0, {"Lc jets charged MCD"}}, + {"lc-mcp-charged", VariantType::Int, 0, {"Lc jets charged MCD"}}}; + std::swap(workflowOptions, hfjetworkflows); +} +*/ + // NB: runDataProcessing.h must be included after customize! #include "Framework/runDataProcessing.h" -template +template struct JetFinderHFTask { Produces jetsTable; Produces constituentsTable; @@ -39,7 +56,8 @@ struct JetFinderHFTask { Configurable trackPhiMin{"trackPhiMin", -999, "minimum track phi"}; Configurable trackPhiMax{"trackPhiMax", 999, "maximum track phi"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - Configurable evSel{"evSel", "evSel8", "choose event selection"}; + Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; + Configurable particleSelections{"particleSelections", "PhysicalPrimary", "set particle selections"}; // cluster level configurables Configurable clusterDefinitionS{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; @@ -49,8 +67,6 @@ struct JetFinderHFTask { Configurable clusterPhiMax{"clusterPhiMax", 999, "maximum cluster phi"}; // HF candidate level configurables - Configurable candSpecie_s{"candSpecie_s", "D0", "options are D0, Lc, Bplus"}; - Configurable candDecayChannel_s{"candDecayChannel_s", "default", "look up in task"}; Configurable candPtMin{"candPtMin", 0.0, "minimum candidate pT"}; Configurable candPtMax{"candPtMax", 100.0, "maximum candidate pT"}; Configurable candYMin{"candYMin", -0.8, "minimum candidate eta"}; @@ -67,6 +83,8 @@ struct JetFinderHFTask { Configurable> jetRadius{"jetRadius", {0.4}, "jet resolution parameters"}; Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT"}; Configurable jetPtMax{"jetPtMax", 1000.0, "maximum jet pT"}; + Configurable jetEtaMin{"jetEtaMin", -99.0, "minimum jet pseudorapidity"}; + Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; Configurable jetTypeParticleLevel{"jetTypeParticleLevel", 1, "Type of stored jets. 0 = full, 1 = charged, 2 = neutral"}; Configurable jetAlgorithm{"jetAlgorithm", 2, "jet clustering algorithm. 0 = kT, 1 = C/A, 2 = Anti-kT"}; Configurable jetRecombScheme{"jetRecombScheme", 0, "jet recombination scheme. 0 = E-scheme, 1 = pT-scheme, 2 = pT2-scheme"}; @@ -75,8 +93,10 @@ struct JetFinderHFTask { Configurable DoRhoAreaSub{"DoRhoAreaSub", false, "do rho area subtraction"}; Configurable DoConstSub{"DoConstSub", false, "do constituent subtraction"}; - Service pdg; + Service pdg; std::string trackSelection; + std::string eventSelection; + std::string particleSelection; JetFinder jetFinder; std::vector inputParticles; @@ -87,6 +107,8 @@ struct JetFinderHFTask { void init(InitContext const&) { trackSelection = static_cast(trackSelections); + eventSelection = static_cast(eventSelections); + particleSelection = static_cast(particleSelections); if (DoRhoAreaSub) { jetFinder.setBkgSubMode(JetFinder::BkgSubMode::rhoAreaSub); @@ -99,34 +121,28 @@ struct JetFinderHFTask { jetFinder.etaMax = trackEtaMax; jetFinder.jetPtMin = jetPtMin; jetFinder.jetPtMax = jetPtMax; + jetFinder.jetEtaMin = jetEtaMin; + jetFinder.jetEtaMax = jetEtaMax; + if (jetEtaMin < -98.0) { + jetFinder.jetEtaDefault = true; + } jetFinder.algorithm = static_cast(static_cast(jetAlgorithm)); jetFinder.recombScheme = static_cast(static_cast(jetRecombScheme)); jetFinder.ghostArea = jetGhostArea; jetFinder.ghostRepeatN = ghostRepeat; - auto candSpecie = static_cast(candSpecie_s); - auto candDecayChannel = static_cast(candDecayChannel_s); - if (candSpecie == "D0") { + if constexpr (std::is_same_v, CandidatesD0Data>) { // Note : need to be careful if configurable workflow options are added later candPDG = static_cast(pdg::Code::kD0); candDecay = static_cast(aod::hf_cand_2prong::DecayType::D0ToPiK); } - if (candSpecie == "Bplus") { + if constexpr (std::is_same_v, CandidatesBplusData>) { candPDG = static_cast(pdg::Code::kBPlus); candDecay = static_cast(aod::hf_cand_bplus::DecayType::BplusToD0Pi); } - if (candSpecie == "Lc") { + if constexpr (std::is_same_v, CandidatesLcData>) { candPDG = static_cast(pdg::Code::kLambdaCPlus); candDecay = static_cast(aod::hf_cand_3prong::DecayType::LcToPKPi); } - if (candSpecie == "JPsi") { - candPDG = static_cast(pdg::Code::kJPsi); - if (candDecayChannel == "default" || candDecayChannel == "ee") { - candDecay = static_cast(aod::hf_cand_2prong::DecayType::JpsiToEE); - } - if (candDecayChannel == "mumu") { - candDecay = static_cast(aod::hf_cand_2prong::DecayType::JpsiToMuMu); - } - } } o2::aod::EMCALClusterDefinition clusterDefinition = o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); @@ -143,7 +159,7 @@ struct JetFinderHFTask { template void analyseData(T const& collision, U const& tracks, M const& candidates) { - if (!selectCollision(collision, evSel)) { + if (!selectCollision(collision, eventSelection)) { return; } @@ -161,7 +177,7 @@ struct JetFinderHFTask { template void analyseMCD(T const& collision, U const& tracks, M const& candidates) { - if (!selectCollision(collision, evSel)) { + if (!selectCollision(collision, eventSelection)) { return; } @@ -176,12 +192,16 @@ struct JetFinderHFTask { } // function that generalically processes gen level events - template - void analyseMCGenParticles(T const& collision, U const& particles, M& candidates) + template + void analyseMCP(T const& collision, U const& particles) { + inputParticles.clear(); + std::vector candidates; + candidates.clear(); + for (auto const& particle : particles) { if (std::abs(particle.flagMcMatchGen()) & (1 << candDecay)) { - auto particleY = RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); + auto particleY = RecoDecay::y(std::array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())); if (particleY < candYMin || particleY > candYMax) { continue; } @@ -192,96 +212,43 @@ struct JetFinderHFTask { } } for (auto& candidate : candidates) { - analyseParticles(inputParticles, trackEtaMin, trackEtaMax, jetTypeParticleLevel, particles, pdg->Instance(), std::optional{candidate}); + analyseParticles(inputParticles, particleSelection, jetTypeParticleLevel, particles, pdg->Instance(), std::optional{candidate}); FastJetUtilities::fillTracks(candidate, inputParticles, candidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(candidate.pdgCode())); findJets(jetFinder, inputParticles, jetRadius, collision, jetsTable, constituentsTable, constituentsSubTable, DoConstSub, true); } } - // check if type JetParticles2Prong can be templated. then you can just use one function everywhere - // function that is called for gen level events with 2 prong candidates - template - void analyseMCGen2Prong(T const& collision, U const& particles) - { - inputParticles.clear(); - std::vector candidates; - candidates.clear(); - analyseMCGenParticles(collision, particles, candidates); - } - // function that is called for gen level events with 3 prong candidates - template - void analyseMCGen3Prong(T const& collision, U const& particles) - { - inputParticles.clear(); - std::vector candidates; - analyseMCGenParticles(collision, particles, candidates); - } - // function that is called for gen level events with B+ candidates - template - void analyseMCGenBplus(T const& collision, U const& particles) - { - inputParticles.clear(); - std::vector candidates; - candidates.clear(); - analyseMCGenParticles(collision, particles, candidates); - } - void processDummy(aod::Collisions const& collision) { } PROCESS_SWITCH(JetFinderHFTask, processDummy, "Dummy process function turned on by default", true); - void processD0ChargedJetsData(soa::Filtered>::iterator const& collision, JetTracks const& tracks, CandidateD0Data const& candidates) { analyseData(collision, tracks, candidates); } - PROCESS_SWITCH(JetFinderHFTask, processD0ChargedJetsData, "D0 jet finding on data", false); - - void processD0ChargedJetsMCD(soa::Join::iterator const& collision, JetTracks const& tracks, CandidateD0MC const& candidates) { analyseMCD(collision, tracks, candidates); } - PROCESS_SWITCH(JetFinderHFTask, processD0ChargedJetsMCD, "D0 finding on MC detector level", false); - - void processBplusChargedJetsData(soa::Filtered>::iterator const& collision, JetTracks const& tracks, CandidateBplusData const& candidates, aod::HfCand2Prong const& HFdaughters) { analyseData(collision, tracks, candidates); } - PROCESS_SWITCH(JetFinderHFTask, processBplusChargedJetsData, "B+ jet finding on data", false); - - void processBplusChargedJetsMCD(soa::Join::iterator const& collision, JetTracks const& tracks, CandidateBplusMC const& candidates, aod::HfCand2Prong const& HFdaughters) { analyseMCD(collision, tracks, candidates); } - PROCESS_SWITCH(JetFinderHFTask, processBplusChargedJetsMCD, "B+ finding on MC detector level", false); - - void processLcChargedJetsData(soa::Filtered>::iterator const& collision, JetTracks const& tracks, CandidateLcData const& candidates) { analyseData(collision, tracks, candidates); } - PROCESS_SWITCH(JetFinderHFTask, processLcChargedJetsData, "Lc jet finding on data", false); + void processChargedJetsData(soa::Filtered>::iterator const& collision, JetTracks const& tracks, CandidateTableData const& candidates) { analyseData(collision, tracks, candidates); } + PROCESS_SWITCH(JetFinderHFTask, processChargedJetsData, "charged hf jet finding on data", false); - void processLcChargedJetsMCD(soa::Join::iterator const& collision, JetTracks const& tracks, CandidateLcMC const& candidates) { analyseMCD(collision, tracks, candidates); } - PROCESS_SWITCH(JetFinderHFTask, processLcChargedJetsMCD, "Lc finding on MC detector level", false); - - void process2ProngJetsMCP(aod::McCollision const& collision, - JetParticles2Prong const& particles) - { - analyseMCGen2Prong(collision, particles); - } - PROCESS_SWITCH(JetFinderHFTask, process2ProngJetsMCP, "2-prong HF jet finding on MC particle level", false); - - void process3ProngJetsMCP(aod::McCollision const& collision, - JetParticles3Prong const& particles) - { - analyseMCGen3Prong(collision, particles); - } - PROCESS_SWITCH(JetFinderHFTask, process3ProngJetsMCP, "3-prong HF jet finding on MC particle level", false); + void processChargedJetsMCD(soa::Join::iterator const& collision, JetTracks const& tracks, CandidateTableMCD const& candidates) { analyseMCD(collision, tracks, candidates); } + PROCESS_SWITCH(JetFinderHFTask, processChargedJetsMCD, "charged hf jet finding on MC detector level", false); - void processBplusJetsMCP(aod::McCollision const& collision, - JetParticlesBplus const& particles) + void processChargedJetsMCP(aod::McCollision const& collision, + ParticleTable const& particles) { - analyseMCGenBplus(collision, particles); + analyseMCP(collision, particles); } - PROCESS_SWITCH(JetFinderHFTask, processBplusJetsMCP, "B+ HF jet finding on MC particle level", false); + PROCESS_SWITCH(JetFinderHFTask, processChargedJetsMCP, "hf jet finding on MC particle level", false); }; +/* -using JetFinderD0DataCharged = JetFinderHFTask; -using JetFinderD0MCDetectorLevelCharged = JetFinderHFTask; -using JetFinderD0MCParticleLevelCharged = JetFinderHFTask; +using JetFinderD0DataCharged = JetFinderHFTask; +using JetFinderD0MCDetectorLevelCharged = JetFinderHFTask; +using JetFinderD0MCParticleLevelCharged = JetFinderHFTask; -using JetFinderBplusDataCharged = JetFinderHFTask; -using JetFinderBplusMCDetectorLevelCharged = JetFinderHFTask; -using JetFinderBplusMCParticleLevelCharged = JetFinderHFTask; +using JetFinderBplusDataCharged = JetFinderHFTask; +using JetFinderBplusMCDetectorLevelCharged = JetFinderHFTask; +using JetFinderBplusMCParticleLevelCharged = JetFinderHFTask; -using JetFinderLcDataCharged = JetFinderHFTask; -using JetFinderLcMCDetectorLevelCharged = JetFinderHFTask; -using JetFinderLcMCParticleLevelCharged = JetFinderHFTask; +using JetFinderLcDataCharged = JetFinderHFTask; +using JetFinderLcMCDetectorLevelCharged = JetFinderHFTask; +using JetFinderLcMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { @@ -325,3 +292,39 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) return WorkflowSpec{tasks}; } +*/ +/* +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + auto workflow = WorkflowSpec{adaptAnalysisTask(cfgc)}; + workflow.clear(); + if (cfgc.hfjetworkflows().get("d0-data-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + if (cfgc.hfjetworkflows().get("d0-mcd-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + if (cfgc.hfjetworkflows().get("d0-mcp-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + if (cfgc.hfjetworkflows().get("bplus-data-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + if (cfgc.hfjetworkflows().get("bplus-mcd-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + if (cfgc.hfjetworkflows().get("bplus-mcp-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + if (cfgc.hfjetworkflows().get("lc-data-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + if (cfgc.hfjetworkflows().get("lc-mcd-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + if (cfgc.hfjetworkflows().get("lc-mcp-charged")) { + workflow.push_back(adaptAnalysisTask(cfgc)); + } + return workflow; +} +*/ diff --git a/PWGJE/TableProducer/jetmatching.cxx b/PWGJE/TableProducer/jetmatching.cxx index 180f74d3be0..47ac42ad7ed 100644 --- a/PWGJE/TableProducer/jetmatching.cxx +++ b/PWGJE/TableProducer/jetmatching.cxx @@ -16,6 +16,7 @@ /// /// \author Raymond Ehlers , ORNL /// \author Jochen Klein +/// \author Aimeric Lanodu #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" @@ -36,6 +37,7 @@ using namespace o2::framework::expressions; template struct JetMatching { + Configurable doMatchingGeo{"doMatchingGeo", true, "Enable geometric matching"}; Configurable doMatchingPt{"doMatchingPt", true, "Enable pt matching"}; Configurable doMatchingHf{"doMatchingHf", true, "Enable HF matching"}; @@ -51,9 +53,14 @@ struct JetMatching { Preslice baseJetsPerCollision = jetsBaseIsMC ? aod::jet::mcCollisionId : aod::jet::collisionId; Preslice tagJetsPerCollision = jetsTagIsMC ? aod::jet::mcCollisionId : aod::jet::collisionId; - using Collisions = soa::Join; + using Collisions = soa::Join; + PresliceUnsorted CollisionsCollectionPerMcCollision = aod::mccollisionlabel::mcCollisionId; using Tracks = soa::Join; + // initialise objects used to store the matching index arrays (array in case a mcCollision is split) before filling the matching tables + std::vector> geojetidBaseToTag, ptjetidBaseToTag, hfjetidBaseToTag; + std::vector> geojetidTagToBase, ptjetidTagToBase, hfjetidTagToBase; + static constexpr int8_t getHfFlag() { if (std::is_same::value && @@ -75,148 +82,352 @@ struct JetMatching { { } - void processDummy(aod::McCollisions const& mcCollisions) + // function that does the geometric matching of jets from jetsBasePerColl and jets from jetsTagPerColl + template + void MatchGeo(T const& jetsBasePerColl, U const& jetsTagPerColl, std::vector& baseToTagGeo, std::vector& tagToBaseGeo) { + std::vector jetsBasePhi; + std::vector jetsBaseEta; + for (const auto& jet : jetsBasePerColl) { + jetsBasePhi.emplace_back(jet.phi()); + jetsBaseEta.emplace_back(jet.eta()); + } + std::vector jetsTagPhi; + std::vector jetsTagEta; + for (const auto& jet : jetsTagPerColl) { + jetsTagPhi.emplace_back(jet.phi()); + jetsTagEta.emplace_back(jet.eta()); + } + std::tie(baseToTagGeo, tagToBaseGeo) = JetUtilities::MatchJetsGeometrically(jetsBasePhi, jetsBaseEta, jetsTagPhi, jetsTagEta, maxMatchingDistance); + LOGF(debug, "geometric matching: %d - %d jets", baseToTagGeo.size(), tagToBaseGeo.size()); + for (std::size_t i = 0; i < baseToTagGeo.size(); ++i) { + LOGF(debug, "bjet %i -> %i", i, baseToTagGeo[i]); + } + for (std::size_t i = 0; i < tagToBaseGeo.size(); ++i) { + LOGF(debug, "tjet %i -> %i", i, tagToBaseGeo[i]); + } } - PROCESS_SWITCH(JetMatching, processDummy, "Dummy process", true); - // for now: - // BaseJetCollection must contain detector level jets - // TagJetCollection must contain particle level jets - void processJets(Collisions::iterator const& collision, aod::McCollisions const& mcCollisions, - BaseJetCollection const& jetsBase, TagJetCollection const& jetsTag, - Tracks const& tracks, McParticles const& particlesMC, - HfCandidates const& hfcandidates) + // function that does the HF matching of jets from jetsBasePerColl and jets from jetsTagPerColl + template + void MatchHF(T const& jetsBasePerColl, U const& jetsTagPerColl, std::vector& baseToTagHF, std::vector& tagToBaseHF) { - // TODO: check whether we need to handle jets in MC collisions without a reconstructed collision - - // waiting for framework fix to make sliced collection of same type as original collection: - // const auto jetsBasePerColl = jetsBaseIsMC ? jetsBase.sliceBy(baseJetsPerCollision, collision.mcCollisionId()); - const auto jetsBasePerColl = jetsBase; - const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, jetsTagIsMC ? collision.mcCollisionId() : collision.globalIndex()); + int index_bjet = 0; + int index_tjet = 0; + for (const auto& bjet : jetsBasePerColl) { + LOGF(debug, "jet index: %d (coll %d, pt %g, phi %g) with %d tracks, %d HF candidates", + bjet.index(), bjet.collisionId(), bjet.pt(), bjet.phi(), bjet.tracks().size(), bjet.hfcandidates().size()); + const auto hfcand = bjet.template hfcandidates_first_as(); + if (hfcand.flagMcMatchRec() & getHfFlag()) { + const auto hfCandMC = hfcand.template prong0_as().template mcParticle_as(); + const auto hfCandMcId = hfCandMC.template mothers_first_as().globalIndex(); + for (const auto& tjet : jetsTagPerColl) { + const auto cand = tjet.template hfcandidates_first_as(); + if (cand.globalIndex() == hfCandMcId) { + LOGF(debug, "Found HF match: %d (pt %g) <-> %d (pt %g)", + bjet.globalIndex(), bjet.pt(), tjet.globalIndex(), tjet.pt()); + baseToTagHF[index_bjet] = index_tjet; + tagToBaseHF[index_tjet] = index_bjet; + } + index_tjet++; + } + } + index_bjet++; + } + } - // geometric matching - std::vector baseToTagGeo(jetsBasePerColl.size(), -1); - std::vector tagToBaseGeo(jetsTagPerColl.size(), -1); - if (doMatchingGeo) { - LOGF(info, "performing geometric matching for collision %d (%d / %d jets)", - collision.globalIndex(), jetsBasePerColl.size(), jetsTagPerColl.size()); - std::vector jetsBasePhi; - std::vector jetsBaseEta; - for (const auto& jet : jetsBasePerColl) { - jetsBasePhi.emplace_back(jet.phi()); - jetsBaseEta.emplace_back(jet.eta()); + template + float getPtSum_FirstArgIsMC(T const& btracks, U const& ttracks) + { + float ptSum = 0; + for (const auto& btrack : btracks) { + for (const auto& ttrack : ttracks) { + if (ttrack.has_mcParticle() && btrack.globalIndex() == ttrack.template mcParticle_as().globalIndex()) { + ptSum += ttrack.pt(); + break; + } } - std::vector jetsTagPhi; - std::vector jetsTagEta; - for (const auto& jet : jetsTagPerColl) { - jetsTagPhi.emplace_back(jet.phi()); - jetsTagEta.emplace_back(jet.eta()); + } + return ptSum; + } + template + float getPtSum_SecondArgIsMC(T const& btracks, U const& ttracks) + { + float ptSum = 0; + for (const auto& btrack : btracks) { + for (const auto& ttrack : ttracks) { + if (btrack.has_mcParticle() && ttrack.globalIndex() == btrack.template mcParticle_as().globalIndex()) { + ptSum += ttrack.pt(); + break; + } } - std::tie(baseToTagGeo, tagToBaseGeo) = JetUtilities::MatchJetsGeometrically(jetsBasePhi, jetsBaseEta, jetsTagPhi, jetsTagEta, maxMatchingDistance); - LOGF(debug, "geometric matching: %d - %d jets", baseToTagGeo.size(), tagToBaseGeo.size()); - for (std::size_t i = 0; i < baseToTagGeo.size(); ++i) { - LOGF(debug, "bjet %i -> %i", i, baseToTagGeo[i]); + } + return ptSum; + } + + // function that does the pT matching of jets from jetsBasePerColl and jets from jetsTagPerColl + template + void MatchPt(T const& jetsBasePerColl, U const& jetsTagPerColl, std::vector& baseToTagPt, std::vector& tagToBasePt) + { + float ptSum; + int index_bjet = 0; + int index_tjet = 0; + + for (const auto& bjet : jetsBasePerColl) { + for (const auto& tjet : jetsTagPerColl) { + auto btracksMcParts = bjet.template tracks_as(); + auto btracksTracks = bjet.template tracks_as(); + auto ttracksMcParts = tjet.template tracks_as(); + auto ttracksTracks = tjet.template tracks_as(); + + jetsBaseIsMC ? ptSum = getPtSum_FirstArgIsMC(btracksMcParts, ttracksTracks) : ptSum = getPtSum_SecondArgIsMC(btracksTracks, ttracksMcParts); + + if (ptSum > tjet.pt() * minPtFraction) { + LOGF(debug, "Found pt match: %d (pt %g) <-> %d (pt %g)", + bjet.globalIndex(), bjet.pt(), tjet.globalIndex(), tjet.pt()); + baseToTagPt[index_bjet] = index_tjet; + } else { + LOGF(debug, "DID NOT find pt match: %d (pt %g) <-> %d (pt %g)", + bjet.globalIndex(), bjet.pt(), tjet.globalIndex(), tjet.pt()); + } + index_tjet++; } - for (std::size_t i = 0; i < tagToBaseGeo.size(); ++i) { - LOGF(debug, "tjet %i -> %i", i, tagToBaseGeo[i]); + index_bjet++; + } + + index_bjet = 0; + index_tjet = 0; + for (const auto& tjet : jetsTagPerColl) { + for (const auto& bjet : jetsBasePerColl) { + auto btracksMcParts = bjet.template tracks_as(); + auto btracksTracks = bjet.template tracks_as(); + auto ttracksMcParts = tjet.template tracks_as(); + auto ttracksTracks = tjet.template tracks_as(); + + jetsBaseIsMC ? ptSum = getPtSum_SecondArgIsMC(ttracksTracks, btracksMcParts) : ptSum = getPtSum_FirstArgIsMC(ttracksMcParts, btracksTracks); + + if (ptSum > bjet.pt() * minPtFraction) { + LOGF(debug, "Found pt match: %d (pt %g) <-> %d (pt %g)", + tjet.globalIndex(), tjet.pt(), bjet.globalIndex(), bjet.pt()); + tagToBasePt[index_tjet] = index_bjet; + } else { + LOGF(debug, "DID NOT find pt match: %d (pt %g) <-> %d (pt %g)", + bjet.globalIndex(), bjet.pt(), tjet.globalIndex(), tjet.pt()); + } + index_bjet++; } + index_tjet++; } + } + // // old pt matching function taken as is from jochen initial matching workflow; it assumed bjet was mcd and tjet was mcp + // template + // void MatchPt(T const& jetsBasePerColl, U const& jetsTagPerColl, std::vector & baseToTagPt, std::vector & tagToBasePt) + // { + // int index_bjet = 0; + // int index_tjet = 0; + // for (const auto& bjet : jetsBasePerColl) { + // for (const auto& tjet : jetsTagPerColl) { + // float ptSum = 0; + // for (const auto& btrack : bjet.template tracks_as()) { // assumes bjet is mcd and tjet is mcp? + // for (const auto& ttrack : tjet.template tracks_as()) { + // if (btrack.has_mcParticle() && + // ttrack.globalIndex() == btrack.template mcParticle_as().globalIndex()) { + // ptSum += ttrack.pt(); + // break; + // } + // } + // } + // if (ptSum > tjet.pt() * minPtFraction) { + // LOGF(debug, "Found pt match: %d (pt %g) <-> %d (pt %g)", + // bjet.globalIndex(), bjet.pt(), tjet.globalIndex(), tjet.pt()); + // baseToTagPt[index_bjet] = index_tjet; + // } + // index_tjet++; + // } + // index_bjet++; + // } + + // index_bjet = 0; + // index_tjet = 0; + // for (const auto& tjet : jetsTagPerColl) { + // for (const auto& bjet : jetsBasePerColl) { + // float ptSum = 0; + // for (const auto& ttrack : tjet.template tracks_as()) { + // for (const auto& btrack : bjet.template tracks_as()) { // assumes bjet is mcd and tjet is mcp?s + // if (btrack.has_mcParticle() && + // ttrack.globalIndex() == btrack.template mcParticle_as().globalIndex()) { + // ptSum += btrack.pt(); + // break; + // } + // } + // } + // if (ptSum > bjet.pt() * minPtFraction) { + // LOGF(debug, "Found pt match: %d (pt %g) <-> %d (pt %g)", + // tjet.globalIndex(), tjet.pt(), bjet.globalIndex(), bjet.pt()); + // tagToBasePt[index_tjet] = index_bjet; + // } + // index_bjet++; + // } + // index_tjet++; + // } + // for (std::size_t i = 0; i < baseToTagPt.size(); ++i) { + // LOGF(debug, "pt matched base table: bjet %i -> %i", i, baseToTagPt[i]); + // } + // for (std::size_t i = 0; i < tagToBasePt.size(); ++i) { + // LOGF(debug, "pt matched tag table: tjet %i -> %i", i, tagToBasePt[i]); + // } + // } + + // function that calls all the Match functions + template + void doAllMatching(T const& jetsBasePerColl, U const& jetsTagPerColl, std::vector& baseToTagGeo, std::vector& baseToTagHF, std::vector& baseToTagPt, std::vector& tagToBaseGeo, std::vector& tagToBaseHF, std::vector& tagToBasePt) + { + // geometric matching + if (doMatchingGeo) { + MatchGeo(jetsBasePerColl, jetsTagPerColl, baseToTagGeo, tagToBaseGeo); + } // HF matching - std::vector baseToTagHF(jetsBasePerColl.size(), -1); - std::vector tagToBaseHF(jetsTagPerColl.size(), -1); if constexpr (getHfFlag() > 0) { if (doMatchingHf) { - LOGF(info, "performing HF matching for collision %d", collision.globalIndex()); - for (const auto& bjet : jetsBasePerColl) { - LOGF(info, "jet index: %d (coll %d, pt %g, phi %g) with %d tracks, %d HF candidates", - bjet.index(), bjet.collisionId(), bjet.pt(), bjet.phi(), bjet.tracks().size(), bjet.hfcandidates().size()); - - const auto hfcand = bjet.template hfcandidates_first_as(); - if (hfcand.flagMcMatchRec() & getHfFlag()) { - const auto hfCandMC = hfcand.template prong0_as().template mcParticle_as(); - const auto hfCandMcId = hfCandMC.template mothers_first_as().globalIndex(); - for (const auto& tjet : jetsTagPerColl) { - const auto cand = tjet.template hfcandidates_first_as(); - if (cand.globalIndex() == hfCandMcId) { - LOGF(info, "Found HF match: %d (pt %g) <-> %d (pt %g)", - bjet.globalIndex(), bjet.pt(), tjet.globalIndex(), tjet.pt()); - baseToTagHF[bjet.index()] = tjet.globalIndex(); - tagToBaseHF[tjet.index()] = bjet.globalIndex(); - } - } - } - } + MatchHF(jetsBasePerColl, jetsTagPerColl, baseToTagHF, tagToBaseHF); } } - // pt matching - std::vector baseToTagPt(jetsBasePerColl.size(), -1); - std::vector tagToBasePt(jetsTagPerColl.size(), -1); if (doMatchingPt) { - LOGF(info, "performing pt matching for collision %d", collision.globalIndex()); - for (const auto& bjet : jetsBasePerColl) { - for (const auto& tjet : jetsTagPerColl) { - float ptSum = 0; - for (const auto& btrack : bjet.template tracks_as()) { - for (const auto& ttrack : tjet.template tracks_as()) { - if (btrack.has_mcParticle() && - ttrack.globalIndex() == btrack.template mcParticle_as().globalIndex()) { - ptSum += ttrack.pt(); - break; - } - } - } - if (ptSum > tjet.pt() * minPtFraction) { - LOGF(info, "Found pt match: %d (pt %g) <-> %d (pt %g)", - bjet.globalIndex(), bjet.pt(), tjet.globalIndex(), tjet.pt()); - baseToTagPt[bjet.index()] = tjet.globalIndex(); - } - } - } + MatchPt(jetsBasePerColl, jetsTagPerColl, baseToTagPt, tagToBasePt); + } + } - for (const auto& tjet : jetsTagPerColl) { - for (const auto& bjet : jetsBasePerColl) { - float ptSum = 0; - for (const auto& ttrack : tjet.template tracks_as()) { - for (const auto& btrack : bjet.template tracks_as()) { - if (btrack.has_mcParticle() && - ttrack.globalIndex() == btrack.template mcParticle_as().globalIndex()) { - ptSum += btrack.pt(); - break; - } - } - } - if (ptSum > bjet.pt() * minPtFraction) { - LOGF(info, "Found pt match: %d (pt %g) <-> %d (pt %g)", - tjet.globalIndex(), tjet.pt(), bjet.globalIndex(), bjet.pt()); - tagToBasePt[tjet.index()] = bjet.globalIndex(); - } - } + // function that fills the jetidTagToBase vectors, where the vector that is the i-th entry (corresponding to the tag jet with global index i) sees added to itself the global index of the matched base jet + template + void fillJetIdArraysTagToBase(T const& jetsBasePerColl, U const& jetsTagPerColl, std::vector const& tagToBaseGeo, std::vector const& tagToBasePt, std::vector const& tagToBaseHF) + { + int geojetidTemp; + int ptjetidTemp; + int hfjetidTemp; + std::vector geojetidTempVector; + std::vector ptjetidTempVector; + std::vector hfjetidTempVector; + for (const auto& jet : jetsTagPerColl) { + geojetidTemp = tagToBaseGeo[jet.index()]; + if (geojetidTemp > -1 && geojetidTemp < jetsBasePerColl.size()) { + geojetidTemp = jetsBasePerColl.iteratorAt(geojetidTemp).globalIndex(); + geojetidTagToBase[jet.globalIndex()].push_back(geojetidTemp); + } else { + geojetidTemp = -1; + } + // Pt matching + ptjetidTemp = tagToBasePt[jet.index()]; + if (ptjetidTemp > -1 && ptjetidTemp < jetsBasePerColl.size()) { + ptjetidTemp = jetsBasePerColl.iteratorAt(ptjetidTemp).globalIndex(); + ptjetidTagToBase[jet.globalIndex()].push_back(ptjetidTemp); + } else { + ptjetidTemp = -1; } + // HF matching + hfjetidTemp = tagToBaseHF[jet.index()]; + if (hfjetidTemp > -1 && hfjetidTemp < jetsBasePerColl.size()) { + hfjetidTemp = jetsBasePerColl.iteratorAt(hfjetidTemp).globalIndex(); + hfjetidTagToBase[jet.globalIndex()].push_back(hfjetidTemp); + } + LOGF(debug, "registering matches for tag jet %d (%d): geo -> %d (%d), pT -> %d (%d), HF -> %d", + jet.index(), jet.globalIndex(), geojetidTemp, tagToBaseGeo[jet.index()], ptjetidTemp, tagToBasePt[jet.index()], tagToBaseHF[jet.index()]); } + } + // function that fills the jetidBaseToTag vectors, where the vector that is the i-th entry (corresponding to the base jet with global index i) sees added to itself the global index of the matched tag jet + template + void fillJetIdArraysBaseToTag(T const& jetsBasePerColl, U const& jetsTagPerColl, std::vector const& baseToTagGeo, std::vector const& baseToTagPt, std::vector const& baseToTagHF) + { + int geojetidTemp; + int ptjetidTemp; + int hfjetidTemp; + std::vector geojetidTempVector; + std::vector ptjetidTempVector; + std::vector hfjetidTempVector; for (const auto& jet : jetsBasePerColl) { - int geojetid = baseToTagGeo[jet.index()]; - if (geojetid > -1 && geojetid < jetsTagPerColl.size()) - geojetid = jetsTagPerColl.iteratorAt(geojetid).globalIndex(); - else - geojetid = -1; - LOGF(info, "registering matches for base jet %d (%d): geo -> %d (%d), HF -> %d", - jet.index(), jet.globalIndex(), geojetid, baseToTagGeo[jet.index()], baseToTagHF[jet.index()]); - jetsBaseToTag(geojetid, baseToTagPt[jet.index()], baseToTagHF[jet.index()]); + geojetidTemp = baseToTagGeo[jet.index()]; + if (geojetidTemp > -1 && geojetidTemp < jetsTagPerColl.size()) { + geojetidTemp = jetsTagPerColl.iteratorAt(geojetidTemp).globalIndex(); + geojetidBaseToTag[jet.globalIndex()].push_back(geojetidTemp); + } else { + geojetidTemp = -1; + } + // Pt matching + ptjetidTemp = baseToTagPt[jet.index()]; + if (ptjetidTemp > -1 && ptjetidTemp < jetsTagPerColl.size()) { + ptjetidTemp = jetsTagPerColl.iteratorAt(ptjetidTemp).globalIndex(); + ptjetidBaseToTag[jet.globalIndex()].push_back(ptjetidTemp); + } + // HF matching + hfjetidTemp = baseToTagHF[jet.index()]; + if (hfjetidTemp > -1 && hfjetidTemp < jetsTagPerColl.size()) { + hfjetidTemp = jetsTagPerColl.iteratorAt(hfjetidTemp).globalIndex(); + hfjetidBaseToTag[jet.globalIndex()].push_back(hfjetidTemp); + } + LOGF(debug, "registering matches for base jet %d (%d): geo -> %d (%d), pT -> %d (%d), HF -> %d", + jet.index(), jet.globalIndex(), geojetidTemp, baseToTagGeo[jet.index()], ptjetidTemp, baseToTagPt[jet.index()], baseToTagHF[jet.index()]); } + } - for (const auto& jet : jetsTagPerColl) { - int geojetid = tagToBaseGeo[jet.index()]; - if (geojetid > -1 && geojetid < jetsBasePerColl.size()) - geojetid = jetsBasePerColl.iteratorAt(geojetid).globalIndex(); - else - geojetid = -1; - LOGF(info, "registering matches for tag jet %d (%d): geo -> %d (%d), HF -> %d", - jet.index(), jet.globalIndex(), geojetid, tagToBaseGeo[jet.index()], tagToBaseHF[jet.index()]); - jetsTagToBase(geojetid, tagToBasePt[jet.index()], tagToBaseHF[jet.index()]); + void processDummy(aod::McCollisions const& mcCollisions) + { + } + PROCESS_SWITCH(JetMatching, processDummy, "Dummy process", true); + + // for now: + // BaseJetCollection and TagJetCollection must have MC info + void processJets(aod::McCollisions const& mcCollisions, Collisions const& collisions, + BaseJetCollection const& jetsBase, TagJetCollection const& jetsTag, McParticles const& particlesMC, + Tracks const& tracks, HfCandidates const& hfcandidates) + { + // waiting for framework fix to make sliced collection of same type as original collection: + geojetidBaseToTag.assign(jetsBase.size(), {}); + ptjetidBaseToTag.assign(jetsBase.size(), {}); + hfjetidBaseToTag.assign(jetsBase.size(), {}); + geojetidTagToBase.assign(jetsTag.size(), {}); + ptjetidTagToBase.assign(jetsTag.size(), {}); + hfjetidTagToBase.assign(jetsTag.size(), {}); + + for (const auto& mcCollision : mcCollisions) { + + const auto collisionsPerMcColl = collisions.sliceBy(CollisionsCollectionPerMcCollision, mcCollision.globalIndex()); + + int i_collision = 0; + for (const auto& collision : collisionsPerMcColl) { + ++i_collision; + + const auto jetsBasePerColl = jetsBase.sliceBy(baseJetsPerCollision, jetsBaseIsMC ? mcCollision.globalIndex() : collision.globalIndex()); + const auto jetsTagPerColl = jetsTag.sliceBy(tagJetsPerCollision, jetsTagIsMC ? mcCollision.globalIndex() : collision.globalIndex()); + + // mini jet matching tables for the collection of jets from the current mcCollision (if mcp jet) or collision (if mcd or data jet) + std::vector baseToTagGeo(jetsBasePerColl.size(), -1), baseToTagHF(jetsBasePerColl.size(), -1), baseToTagPt(jetsBasePerColl.size(), -1); + std::vector tagToBaseGeo(jetsTagPerColl.size(), -1), tagToBaseHF(jetsTagPerColl.size(), -1), tagToBasePt(jetsTagPerColl.size(), -1); + + LOGF(debug, "performing geometric matching for mcCollision %d and collision %d (%d / %d jets)", + mcCollision.globalIndex(), collision.globalIndex(), jetsBasePerColl.size(), jetsTagPerColl.size()); + + doAllMatching(jetsBasePerColl, jetsTagPerColl, baseToTagGeo, baseToTagHF, baseToTagPt, tagToBaseGeo, tagToBaseHF, tagToBasePt); + + // time to fill the tables + if (i_collision == 1) { // do this once regardless; if both tag and base are MC, or if one is MC and the other is not and there is no split vertex: it's the only iteration + fillJetIdArraysBaseToTag(jetsBasePerColl, jetsTagPerColl, baseToTagGeo, baseToTagPt, baseToTagHF); + fillJetIdArraysTagToBase(jetsBasePerColl, jetsTagPerColl, tagToBaseGeo, tagToBasePt, tagToBaseHF); + } + if (i_collision > 1) { // collision is split + if (!jetsBaseIsMC || !jetsTagIsMC) { // if both are MC, allowing those two lines below to happen would make duplicates in the matching table; this is why thie i_collision>1 case is not treated the same way as the i_collision==1 case + fillJetIdArraysBaseToTag(jetsBasePerColl, jetsTagPerColl, baseToTagGeo, baseToTagPt, baseToTagHF); + fillJetIdArraysTagToBase(jetsBasePerColl, jetsTagPerColl, tagToBaseGeo, tagToBasePt, tagToBaseHF); + } + } + } + } + for (std::size_t i = 0; i < jetsTag.size(); i++) { + jetsTagToBase(geojetidTagToBase[i], ptjetidTagToBase[i], hfjetidTagToBase[i]); // is (and needs to) be filled in order + } + for (std::size_t i = 0; i < jetsBase.size(); ++i) { + jetsBaseToTag(geojetidBaseToTag[i], ptjetidBaseToTag[i], hfjetidBaseToTag[i]); // is (and needs to) be filled in order } } PROCESS_SWITCH(JetMatching, processJets, "Perform jet matching", false); @@ -227,7 +438,14 @@ using ChargedJetMatching = JetMatching; + aod::FwdTracks>; +// using ChargedJetMatching = JetMatching, // test of the mcd <-> mcp switch in the base/tag categories +// soa::Join, +// aod::ChargedMCParticleLevelJetsMatchedToChargedMCDetectorLevelJets, +// aod::ChargedMCDetectorLevelJetsMatchedToChargedMCParticleLevelJets, +// aod::McParticles, +// aod::DummyTracks>; + using D0ChargedJetMatching = JetMatching, soa::Join, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCParticleLevelJets, @@ -251,7 +469,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { std::vector tasks; - tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-ch"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-matching-ch"})); tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-d0-ch"})); tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-lc-ch"})); tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-bplus-ch"})); diff --git a/PWGJE/TableProducer/jettrackderived.cxx b/PWGJE/TableProducer/jettrackderived.cxx new file mode 100644 index 00000000000..72d24085684 --- /dev/null +++ b/PWGJE/TableProducer/jettrackderived.cxx @@ -0,0 +1,175 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file for derived process JetTrackQa.h and .cxx +/// \author Johanna Lömker +/// \since 2023-10-02 +/// \brief Header for the trackJetQa task for the analysis of the tracks for jets.. +/// + +// O2 includes +#include "ReconstructionDataFormats/Track.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/AnalysisDataModel.h" +#include "PWGJE/DataModel/Jet.h" +#include "Framework/StaticFor.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "PWGJE/DataModel/TrackJetQa.h" + +using namespace o2; +using namespace o2::track; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct spectraDerivedMaker { + Configurable nBins{"nBins", 200, "N bins in histos"}; + + Configurable ValVtx{"ValVtx", 10, "Value of the vertex position"}; + Configurable ValCutEta{"ValCutEta", 0.8f, "Eta range for tracks"}; + Configurable ValCutY{"ValCutY", 0.5f, "Y range for tracks"}; + Configurable fractionOfEvents{"fractionOfEvents", 2.f, "Downsampling factor for the events for derived data"}; + // Custom track cuts for the cut variation study + TrackSelection customTrackCuts; + Configurable itsPattern{"itsPattern", 1, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable requireITS{"requireITS", true, "Additional cut on the ITS requirement"}; + Configurable requireTPC{"requireTPC", true, "Additional cut on the TPC requirement"}; + Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 60.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.7f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 7.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Additional cut on the maximum value of the DCA xy (multiplicative factor)"}; + Configurable maxDcaZ{"maxDcaZ", 3.f, "Additional cut on the maximum value of the DCA z"}; + Configurable minTPCNClsFound{"minTPCNClsFound", 0.f, "Additional cut on the minimum value of the number of found clusters in the TPC"}; + + // Histograms + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + // Custom track cuts + LOG(info) << "Using custom track cuts from values:"; + LOG(info) << "\trequireITS=" << requireITS.value; + LOG(info) << "\trequireTPC=" << requireTPC.value; + LOG(info) << "\trequireGoldenChi2=" << requireGoldenChi2.value; + LOG(info) << "\tmaxChi2PerClusterTPC=" << maxChi2PerClusterTPC.value; + LOG(info) << "\tminNCrossedRowsTPC=" << minNCrossedRowsTPC.value; + LOG(info) << "\tminTPCNClsFound=" << minTPCNClsFound.value; + LOG(info) << "\tmaxChi2PerClusterITS=" << maxChi2PerClusterITS.value; + LOG(info) << "\tmaxDcaZ=" << maxDcaZ.value; + + customTrackCuts = getGlobalTrackSelectionRun3ITSMatch(itsPattern.value); + LOG(info) << "Customizing track cuts:"; + customTrackCuts.SetRequireITSRefit(requireITS.value); + customTrackCuts.SetRequireTPCRefit(requireTPC.value); + customTrackCuts.SetRequireGoldenChi2(requireGoldenChi2.value); + customTrackCuts.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); + customTrackCuts.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); + customTrackCuts.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); + customTrackCuts.SetMinNClustersTPC(minTPCNClsFound.value); + customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + customTrackCuts.SetMaxDcaXYPtDep([](float pt) { return 10.f; }); // No DCAxy cut will be used, this is done via the member function of the task + customTrackCuts.SetMaxDcaZ(maxDcaZ.value); + customTrackCuts.print(); + + // event property histograms + histos.add("EventProp/collisionVtxZ", "Collsion Vertex Z;#it{Vtx}_{z} [cm];number of entries", HistType::kTH1F, {{nBins, -20, 20}}); + histos.add("EventProp/collisionVtxZnoSel", "Collsion Vertex Z without event selection;#it{Vtx}_{z} [cm];number of entries", HistType::kTH1F, {{nBins, -20, 20}}); + histos.add("EventProp/collisionVtxZSel8", "Collsion Vertex Z with event selection;#it{Vtx}_{z} [cm];number of entries", HistType::kTH1F, {{nBins, -20, 20}}); + histos.add("EventProp/sampledvertexz", "Sampled collsion Vertex Z with event selection;#it{Vtx}_{z} [cm];number of entries", HistType::kTH1F, {{nBins, -20, 20}}); + } + + template + bool isEventSelected(CollisionType const& collision, TrackType const& tracks) + { + // here we could already fill some histos fo cross checks + if (!collision.sel8()) { + return false; + } + + if (abs(collision.posZ()) > ValVtx) { + return false; + } + histos.fill(HIST("EventProp/collisionVtxZ"), collision.posZ()); // test fill + // Last thing, check the sampling + if (fractionOfEvents < 1.f && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > fractionOfEvents) { // Skip events that are not sampled + return false; + } + histos.fill(HIST("EventProp/sampledvertexz"), collision.posZ()); + return true; + } + + template + bool isTrackSelected(TrackType const& track) // add trackselections and corresponding histos for cross checks to derived table + { + if (!track.isGlobalTrackWoPtEta()) { // in principle we would liek to check all these cuts + return false; + } + return true; + } + + using CollisionCandidate = soa::Join; + using TrackCandidates = soa::Join; + + Produces tableColl; + Produces tableTrack; + unsigned int randomSeed = 0; + void processData(CollisionCandidate::iterator const& collision, + TrackCandidates const& tracks, + aod::BCs const&) + { + if (!isEventSelected(collision, tracks)) { + return; + } + + tableColl(collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ(), + collision.sel8(), + collision.bc().runNumber()); + + tableTrack.reserve(tracks.size()); + for (const auto& trk : tracks) { + if (!isTrackSelected(trk)) { + return; + } + + tableTrack(tableColl.lastIndex(), + trk.pt() * trk.sign(), trk.eta(), trk.phi(), + trk.sigma1Pt(), + o2::aod::spectra::packInTable(trk.dcaXY()), + o2::aod::spectra::packInTable(trk.dcaZ()), + trk.length(), + trk.tpcSignal(), + trk.tpcChi2NCl(), trk.itsChi2NCl(), trk.tofChi2(), + trk.tpcNClsShared(), + trk.tpcNClsFindable(), + trk.tpcNClsFindableMinusFound(), + trk.tpcNClsFindableMinusCrossedRows(), + trk.isPVContributor(), + trk.itsClusterMap(), + trk.hasTRD(), + trk.isGlobalTrack(), + trk.isGlobalTrackWoDCA(), + trk.isGlobalTrackWoPtEta()); + } + } + PROCESS_SWITCH(spectraDerivedMaker, processData, "Process data for derived dataset production", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index 1fa2cec97d3..9f0c19e32a3 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -56,6 +56,10 @@ if(FastJet_FOUND) SOURCES jetfinderhfQA.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(trigger-correlations + SOURCES triggerCorrelations.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-charged-trigger-qa SOURCES ChJetTriggerQATask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -80,4 +84,12 @@ if(FastJet_FOUND) SOURCES jetTutorialSkeleton.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(track-jet-qa + SOURCES trackJetqa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-nsubjettiness + SOURCES nSubjettiness.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) endif() \ No newline at end of file diff --git a/PWGJE/Tasks/FullJetTriggerQATask.cxx b/PWGJE/Tasks/FullJetTriggerQATask.cxx index 1434cd45e19..f1092345742 100644 --- a/PWGJE/Tasks/FullJetTriggerQATask.cxx +++ b/PWGJE/Tasks/FullJetTriggerQATask.cxx @@ -14,6 +14,7 @@ // Author: Gijs van Weelden // #include +#include #include "TH1F.h" #include "TTree.h" @@ -34,22 +35,39 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using selectedClusters = o2::soa::Filtered; struct JetTriggerQA { + using selectedClusters = o2::soa::Filtered; + using fullJetInfos = soa::Join; + using neutralJetInfos = soa::Join; + using collisionWithTrigger = soa::Join::iterator; enum TriggerType_t { kMinBias, - kEmcal, + kEmcalAny, + kEmcalMB, kEmcalJetFull, + kEmcalJetFullLow, kEmcalJetNeutral, + kEmcalJetNeutralLow, + kEmcalGammaVeryHigh, + kDcalGammaVeryHigh, kEmcalGammaHigh, kDcalGammaHigh, kEmcalGammaLow, kDcalGammaLow, + kEmcalGammaVeryLow, + kDcalGammaVeryLow, kNTriggers }; + enum EMCALHardwareTrigger { + TRG_MB, + TRG_EMC7, + TRG_DMC7, + TRG_NTriggers + }; + // Preslice perJetTrackConstituents = o2::aod::jetconstituents::jetId; // Preslice perJetClusterConstituents = o2::aod::jetconstituents::jetId; @@ -122,24 +140,25 @@ struct JetTriggerQA { registry.add("jetRPtEtaPhiNoFiducial", "JetRPtEtaPhiNoFiducial", hJetRPtEtaPhiNoFiducial); registry.add("jetRMaxPtEtaPhiNoFiducial", "JetRMaxPtEtaPhiNoFiducial", hJetRMaxPtEtaPhiNoFiducial); - registry.add("hProcessedEvents", "Processed events", HistType::kTH1I, {{14, -0.5, 13.5, "Trigger type"}}); + registry.add("hProcessedEvents", "Processed events", HistType::kTH1D, {{15, -0.5, 14.5, "Trigger type"}}); auto histProcessed = registry.get(HIST("hProcessedEvents")); histProcessed->GetXaxis()->SetBinLabel(1, "MB"); - histProcessed->GetXaxis()->SetBinLabel(2, "EMC"); - histProcessed->GetXaxis()->SetBinLabel(3, "Selected Full Jet"); - histProcessed->GetXaxis()->SetBinLabel(4, "Selected Neutral Jet"); - histProcessed->GetXaxis()->SetBinLabel(5, "Selected Gamma high EMCAL"); - histProcessed->GetXaxis()->SetBinLabel(6, "Selected Gamma high DCAL"); - histProcessed->GetXaxis()->SetBinLabel(7, "Selected Gamma low EMCAL"); - histProcessed->GetXaxis()->SetBinLabel(8, "Selected Gamma low DCAL"); - histProcessed->GetXaxis()->SetBinLabel(9, "Selected full jet and Gamma high EMCAL"); - histProcessed->GetXaxis()->SetBinLabel(10, "Selected full jet and Gamma high DCAL"); - histProcessed->GetXaxis()->SetBinLabel(11, "Selected neutral jet and Gamma high EMCAL"); - histProcessed->GetXaxis()->SetBinLabel(12, "Selected neutral jet and Gamma high DCAL"); - histProcessed->GetXaxis()->SetBinLabel(13, "Selected Gamma high EMCAL and high Gamma DCAL"); - histProcessed->GetXaxis()->SetBinLabel(14, "Selected full jet and neutral jet"); - - std::array triggerlabels = {{"MB", "EMC", "EMC jet full", "EMC jet neutral", "EMC gamma high", "DCL gamma high", "EMC gamma low", "DCL gamma low"}}; + histProcessed->GetXaxis()->SetBinLabel(2, "Any EMC trigger"); + histProcessed->GetXaxis()->SetBinLabel(3, "EMC Min. bias"); + histProcessed->GetXaxis()->SetBinLabel(4, "Selected Full Jet high"); + histProcessed->GetXaxis()->SetBinLabel(5, "Selected Full Jet low"); + histProcessed->GetXaxis()->SetBinLabel(6, "Selected Neutral Jet high"); + histProcessed->GetXaxis()->SetBinLabel(7, "Selected Neutral Jet low"); + histProcessed->GetXaxis()->SetBinLabel(8, "Selected Gamma very high EMCAL"); + histProcessed->GetXaxis()->SetBinLabel(9, "Selected Gamma very high DCAL"); + histProcessed->GetXaxis()->SetBinLabel(10, "Selected Gamma high EMCAL"); + histProcessed->GetXaxis()->SetBinLabel(11, "Selected Gamma high DCAL"); + histProcessed->GetXaxis()->SetBinLabel(12, "Selected Gamma low EMCAL"); + histProcessed->GetXaxis()->SetBinLabel(13, "Selected Gamma low DCAL"); + histProcessed->GetXaxis()->SetBinLabel(14, "Selected Gamma very low EMCAL"); + histProcessed->GetXaxis()->SetBinLabel(15, "Selected Gamma very low DCAL"); + + std::array triggerlabels = {{"MB", "EMC Any", "EMC MB", "EMC jet full high", "EMC jet full low", "EMC jet neutral high", "EMC jet neutral low", "EMC gamma very high", "DCL gamma very high", "EMC gamma high", "DCL gamma high", "EMC gamma low", "DCL gamma low", "EMC gamma very low", "DCL gamma very low"}}; registry.add("hTriggerCorrelation", "Correlation between EMCAL triggers", HistType::kTH2D, {{TriggerType_t::kNTriggers, -0.5, TriggerType_t::kNTriggers - 0.5, "Main trigger"}, {TriggerType_t::kNTriggers, -0.5, TriggerType_t::kNTriggers - 0.5, "Associated trigger"}}); auto triggerCorrelation = registry.get(HIST("hTriggerCorrelation")); for (std::size_t triggertype = 0; triggertype < TriggerType_t::kNTriggers; triggertype++) { @@ -152,13 +171,28 @@ struct JetTriggerQA { registry.add("hJetRPtPhi", "Jets #it{p}_{T} and #phi", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); registry.add("hJetRMaxPtEta", "Leading jets #it{p}_{T} and #eta", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); registry.add("hJetRMaxPtPhi", "Leading jets #it{p}_{T} and #phi", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); - registry.add("hClusterPtEta", Form("Cluster %s and #eta", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hClusterPtPhi", Form("Cluster %s and #phi", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); + registry.add("hJetRMaxPtEtaMinBias", "Leading jets #it{p}_{T} and #eta (min. bias)", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); + registry.add("hJetRMaxPtPhiMinBias", "Leading jets #it{p}_{T} and #phi (min. bias)", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); + registry.add("hJetRMaxPtEtaLevel0", "Leading jets #it{p}_{T} and #eta (level0)", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); + registry.add("hJetRMaxPtPhiLevel0", "Leading jets #it{p}_{T} and #phi (level0)", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); registry.add("hClusterPtEtaPhi", Form("Cluster %s, #eta and #phi", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hClusterPtEtaPhiMinBias", Form("Cluster %s (Min. bias trigger), #eta and #phi", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hClusterPtEtaPhiLevel0", Form("Cluster %s (Level-0 trigger), #eta and #phi", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); registry.add("hClusterEMCALMaxPtEtaPhi", Form("Leading cluster %s, #eta and #phi (EMCAL)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hClusterEMCALMaxPtEtaPhiMinBias", Form("Leading cluster %s, #eta and #phi (EMCAL, min. bias trigger)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hClusterEMCALMaxPtEtaPhiLevel0", Form("Leading cluster %s, #eta and #phi (EMCAL, Level-0 trigger)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); registry.add("hClusterDCALMaxPtEtaPhi", Form("Leading cluster %s, #eta and #phi (DCAL)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); - registry.add("hClusterMaxPtEta", Form("Leading clusters %s and #eta", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hClusterMaxPtPhi", Form("Leading clusters %s and #phi", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); + registry.add("hClusterDCALMaxPtEtaPhiMinBias", Form("Leading cluster %s, #eta and #phi (DCAL, min, bias trigger)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hClusterDCALMaxPtEtaPhiLevel0", Form("Leading cluster %s, #eta and #phi (DCAL, Level-0 trigger)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hEventsNoMaxClusterEMCAL", "Events with no max. cluster in EMCAL", HistType::kTH1D, {{1, 0.5, 1.5}}); + registry.add("hEventsNoMaxClusterEMCALMinBias", "Events with no max. cluster in EMCAL (min. bias trigger)", HistType::kTH1D, {{1, 0.5, 1.5}}); + registry.add("hEventsNoMaxClusterEMCALLevel0", "Events with no max. cluster in EMCAL (level0 trigger)", HistType::kTH1D, {{1, 0.5, 1.5}}); + registry.add("hEventsNoMaxClusterDCAL", ("Events with no max. cluster in DCAL"), HistType::kTH1D, {{1, 0.5, 1.5}}); + registry.add("hEventsNoMaxClusterDCALMinBias", "Events with no max. cluster in DCAL (min. bias trigger)", HistType::kTH1D, {{1, 0.5, 1.5}}); + registry.add("hEventsNoMaxClusterDCALLevel0", "Events with no max. cluster in DCAL (level0 trigger)", HistType::kTH1D, {{1, 0.5, 1.5}}); + registry.add("hEventsNoMaxJet", "Events with no max. jet", HistType::kTH1D, {{rAxis}}); + registry.add("hEventsNoMaxJetMinBias", "Events with no max. jet (min. bias trigger)", HistType::kTH1D, {{rAxis}}); + registry.add("hEventsNoMaxJetLevel0", "Events with no max. jet (level0 trigger)", HistType::kTH1D, {{rAxis}}); registry.add("hJetRPtTrackPt", "Jets", HistType::kTH3F, {rAxis, jetPtAxis, ptAxisTrackInJet}); registry.add("hJetRPtClusterPt", "Jets", HistType::kTH3F, {rAxis, jetPtAxis, ptAxisClusterInJet}); registry.add("hJetRPtPtd", "Jets", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "p_{t,D}"}}); @@ -170,16 +204,14 @@ struct JetTriggerQA { registry.add("hJetRMaxPtClusterMaxPt", "Leading jets and clusters", HistType::kTH3F, {rAxis, jetPtAxis, observableAxisCluster}); // Histograms for triggered events - registry.add("hSelectedJetRPtEta", "Selected jets #it{p}_{T} and #eta", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); - registry.add("hSelectedJetRPtPhi", "Selected jets #it{p}_{T} and #phi", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); - registry.add("hSelectedJetRMaxPtEta", "Leading selected jets #it{p}_{T} and #eta", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); - registry.add("hSelectedJetRMaxPtPhi", "Leading selected jets #it{p}_{T} and #phi", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); - registry.add("hSelectedClusterPtEta", Form("Selected Cluster %s and #eta", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedClusterPtPhi", Form("Selected Cluster %s and #phi", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); registry.add("hSelectedClusterPtEtaPhi", Form("Selected cluster %s, #eta and #phi", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); registry.add("hSelectedClusterMaxPtEtaPhi", Form("Leading Selected cluster %s, #eta and #phi", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); - registry.add("hSelectedClusterMaxPtEta", Form("Leading selected clusters %s and #eta", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedClusterMaxPtPhi", Form("Leading selected clusters %s and #phi", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); + + // Jet high trigger + registry.add("hSelectedJetRMaxPtEta", "Leading selected jets #it{p}_{T} and #eta", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); + registry.add("hSelectedJetRMaxPtPhi", "Leading selected jets #it{p}_{T} and #phi", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); + registry.add("hSelectedJetRPtEta", "Selected jets #it{p}_{T} and #eta", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); + registry.add("hSelectedJetRPtPhi", "Selected jets #it{p}_{T} and #phi", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); registry.add("hSelectedJetRPtTrackPt", "Selected jets", HistType::kTH3F, {rAxis, jetPtAxis, ptAxisTrackInJet}); registry.add("hSelectedJetRPtClusterPt", "Selected jets", HistType::kTH3F, {rAxis, jetPtAxis, ptAxisClusterInJet}); registry.add("hSelectedJetRPtPtd", "Selected jets", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "p_{t,D}"}}); @@ -188,32 +220,54 @@ struct JetTriggerQA { registry.add("hSelectedJetRPtZTheta", "Selected jets", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "z#theta"}}); registry.add("hSelectedJetRPtZSqTheta", "Selected jets", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "z^{2} #theta"}}); registry.add("hSelectedJetRPtZThetaSq", "Selected jets", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "z #theta^{2}"}}); - registry.add("hSelectedGammaEMCALPtEta", Form("Selected Gamma %s and #eta (EMCAL, high threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedGammaEMCALPtPhi", Form("Selected Gamma %s and #phi (EMCAL, high threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); - registry.add("hSelectedGammaDCALPtEta", Form("Selected Gamma %s and #eta (DCAL, high threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedGammaDCALPtPhi", Form("Selected Gamma %s and #phi (DCAL, high threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); + + // Jet low trigger + registry.add("hSelectedJetLowRMaxPtEta", "Leading selected jets (low threshold) #it{p}_{T} and #eta", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); + registry.add("hSelectedJetLowRMaxPtPhi", "Leading selected jets (low threshold) #it{p}_{T} and #phi", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); + registry.add("hSelectedJetLowRPtEta", "Selected jets (low threshold) #it{p}_{T} and #eta", HistType::kTH3F, {rAxis, jetPtAxis, etaAxis}); + registry.add("hSelectedJetLowRPtPhi", "Selected jets (low threshold) #it{p}_{T} and #phi", HistType::kTH3F, {rAxis, jetPtAxis, phiAxis}); + registry.add("hSelectedJetLowRPtTrackPt", "Selected jets (low threshold)", HistType::kTH3F, {rAxis, jetPtAxis, ptAxisTrackInJet}); + registry.add("hSelectedJetLowRPtClusterPt", "Selected jets (low threshold)", HistType::kTH3F, {rAxis, jetPtAxis, ptAxisClusterInJet}); + registry.add("hSelectedJetLowRPtPtd", "Selected jets (low threshold)", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "p_{t,D}"}}); + registry.add("hSelectedJetLowRPtChargeFrag", "Selected jets (low threshold)", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "z"}}); + registry.add("hSelectedJetLowRPtNEF", "Selected jets (low threshold)", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "NEF"}}); + registry.add("hSelectedJetLowRPtZTheta", "Selected jets (low threshold)", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "z#theta"}}); + registry.add("hSelectedJetLowRPtZSqTheta", "Selected jets (low threshold)", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "z^{2} #theta"}}); + registry.add("hSelectedJetLowRPtZThetaSq", "Selected jets (low threshold)", HistType::kTH3F, {rAxis, jetPtAxis, {nPtBins / 2, 0., 1., "z #theta^{2}"}}); + + // EMCAL gamma very-high trigger + registry.add("hSelectedGammaEMCALPtEtaPhiVeryHigh", Form("Selected Gamma %s, #eta and #phi (EMCAL, very high threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hSelectedGammaEMCALMaxPtEtaPhiVeryHigh", Form("Leading selected gamma %s, #eta and #phi (EMCAL, very high treshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + + // DCAL gamma very-high trigger + registry.add("hSelectedGammaDCALPtEtaPhiVeryHigh", Form("Selected gamma %s, #eta and #phi (DCAL, very high treshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hSelectedGammaDCALMaxPtEtaPhiVeryHigh", Form("Leading selected gamma %s, #eta and #phi (DCAL, very high treshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + + // EG1 trigger registry.add("hSelectedGammaEMCALPtEtaPhi", Form("Selected Gamma %s, #eta and #phi (EMCAL, high threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); registry.add("hSelectedGammaEMCALMaxPtEtaPhi", Form("Leading selected gamma %s, #eta and #phi (EMCAL, high treshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); - registry.add("hSelectedGammaEMCALMaxPtEta", Form("Leading selected gamma %s and #eta (EMCAL, high threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedGammaEMCALMaxPtPhi", Form("Leading selected gamma %s and #phi (EMCAL, high threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); - registry.add("hSelectedGammaDCALMaxPtEta", Form("Leading selected gamma %s and #eta (DCAL, high threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedGammaDCALMaxPtPhi", Form("Leading selected gamma %s and #phi (DCAL, high threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); + + // DG1 trigger registry.add("hSelectedGammaDCALPtEtaPhi", Form("Selected gamma %s, #eta and #phi (DCAL, high treshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); registry.add("hSelectedGammaDCALMaxPtEtaPhi", Form("Leading selected gamma %s, #eta and #phi (DCAL, high treshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); - registry.add("hSelectedGammaEMCALPtEtaLow", Form("Selected Gamma %s and #eta (EMCAL, low threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedGammaEMCALPtPhiLow", Form("Selected Gamma %s and #phi (EMCAL, low threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); - registry.add("hSelectedGammaDCALPtEtaLow", Form("Selected Gamma %s and #eta (DCAL, low threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedGammaDCALPtPhiLow", Form("Selected Gamma %s and #phi (DCAL, low threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); + + // EG2 trigger registry.add("hSelectedGammaEMCALPtEtaPhiLow", Form("Selected gamma %s, #eta and #phi (EMCAL, low threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); registry.add("hSelectedGammaEMCALMaxPtEtaPhiLow", Form("Leading selected gamma %s, #eta and #phi (EMCAL, low threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); - registry.add("hSelectedGammaEMCALMaxPtEtaLow", Form("Leading selected gamma %s and #eta (EMCAL, low threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedGammaEMCALMaxPtPhiLow", Form("Leading selected gamma %s and #phi (EMCAL, low threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); - registry.add("hSelectedGammaDCALMaxPtEtaLow", Form("Leading selected gamma %s and #eta (DCAL, low threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, etaAxis}); - registry.add("hSelectedGammaDCALMaxPtPhiLow", Form("Leading selected gamma %s and #phi (DCAL, low threshold)", observableName.data()), HistType::kTH2F, {observableAxisCluster, phiAxis}); + + // DG2 trigger registry.add("hSelectedGammaDCALPtEtaPhiLow", Form("Selected gamma %s, #eta and #phi (DCAL, low threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); registry.add("hSelectedGammaDCALMaxPtEtaPhiLow", Form("Leading selected gamma %s, #eta and #phi (DCAL, low threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); - registry.add("hSelectedJetRMaxPtClusterMaxPt", "Leading selected jets and clusters", HistType::kTH3F, {rAxis, jetPtAxis, observableAxisCluster}); + // EMCAL gamma very-low trigger + registry.add("hSelectedGammaEMCALPtEtaPhiVeryLow", Form("Selected gamma %s, #eta and #phi (EMCAL, very low threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hSelectedGammaEMCALMaxPtEtaPhiVeryLow", Form("Leading selected gamma %s, #eta and #phi (EMCAL, very low threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + + // DCAL gamma very-low trigger + registry.add("hSelectedGammaDCALPtEtaPhiVeryLow", Form("Selected gamma %s, #eta and #phi (DCAL, low threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + registry.add("hSelectedGammaDCALMaxPtEtaPhiVeryLow", Form("Leading selected gamma %s, #eta and #phi (DCAL, low threshold)", observableName.data()), HistType::kTH3F, {observableAxisCluster, etaAxis, phiAxis}); + + registry.add("hSelectedJetRMaxPtClusterMaxPt", "Leading selected jets and clusters", HistType::kTH3F, {rAxis, jetPtAxis, observableAxisCluster}); registry.add("hJetRMaxPtJetPt", "Leading jet #it{p}_{T} vs jet #it{p}_{T}", HistType::kTH3F, {rAxis, jetMaxPtAxis, jetPtAxis}); registry.add("hJetRMaxPtJetPtNoFiducial", "Leading jet #it{p}_{T} vs jet #it{p}_{T} (no fiducial cut)", HistType::kTH3F, {rAxis, jetMaxPtAxis, jetPtAxis}); registry.add("hClusterEMCALMaxPtClusterEMCALPt", Form("Leading clusterEMCAL %s vs clusterEMCAL %s", observableName.data(), observableName.data()), HistType::kTH2F, {observableAxisMaxCluster, observableAxisCluster}); @@ -232,6 +286,10 @@ struct JetTriggerQA { registry.get(HIST("hJetRPtZThetaSq"))->SetTitle("Jets (in emcal only)"); registry.get(HIST("hJetRMaxPtEta"))->SetTitle("Leading jets (in emcal only) #it{p}_{T} and #eta"); registry.get(HIST("hJetRMaxPtPhi"))->SetTitle("Leading jets (in emcal only) #it{p}_{T} and #phi"); + registry.get(HIST("hJetRMaxPtEtaMinBias"))->SetTitle("Leading jets (in emcal only, min. bias) #it{p}_{T} and #eta"); + registry.get(HIST("hJetRMaxPtPhiMinBias"))->SetTitle("Leading jets (in emcal only, min. bias) #it{p}_{T} and #phi"); + registry.get(HIST("hJetRMaxPtEtaLevel0"))->SetTitle("Leading jets (in emcal only, level-0) #it{p}_{T} and #eta"); + registry.get(HIST("hJetRMaxPtPhiLevel0"))->SetTitle("Leading jets (in emcal only, level-0) #it{p}_{T} and #phi"); registry.get(HIST("hJetRMaxPtClusterMaxPt"))->SetTitle("Leading jets (in emcal only) and clusters"); registry.get(HIST("hSelectedJetRPtEta"))->SetTitle("Selected jets (in emcal only) #it{p}_{T} and #eta"); @@ -244,6 +302,18 @@ struct JetTriggerQA { registry.get(HIST("hSelectedJetRPtZTheta"))->SetTitle("Selected jets (in emcal only)"); registry.get(HIST("hSelectedJetRPtZSqTheta"))->SetTitle("Selected jets (in emcal only)"); registry.get(HIST("hSelectedJetRPtZThetaSq"))->SetTitle("Selected jets (in emcal only)"); + + registry.get(HIST("hSelectedJetLowRPtEta"))->SetTitle("Selected jets (low threshold, in emcal only) #it{p}_{T} and #eta"); + registry.get(HIST("hSelectedJetLowRPtPhi"))->SetTitle("Selected jets (low threshold, in emcal only) #it{p}_{T} and #phi"); + registry.get(HIST("hSelectedJetLowRPtTrackPt"))->SetTitle("Selected jets (low threshold, in emcal only)"); + registry.get(HIST("hSelectedJetLowRPtClusterPt"))->SetTitle("Selected jets (low threshold, in emcal only)"); + registry.get(HIST("hSelectedJetLowRPtPtd"))->SetTitle("Selected jets (low threshold, in emcal only)"); + registry.get(HIST("hSelectedJetLowRPtChargeFrag"))->SetTitle("Selected jets (low threshold, in emcal only)"); + registry.get(HIST("hSelectedJetLowRPtNEF"))->SetTitle("Selected jets (low threshold, in emcal only)"); + registry.get(HIST("hSelectedJetLowRPtZTheta"))->SetTitle("Selected jets (low threshold, in emcal only)"); + registry.get(HIST("hSelectedJetLowRPtZSqTheta"))->SetTitle("Selected jets (low threshold, in emcal only)"); + registry.get(HIST("hSelectedJetLowRPtZThetaSq"))->SetTitle("Selected jets (low threshold, in emcal only)"); + registry.get(HIST("hSelectedJetRMaxPtEta"))->SetTitle("Leading selected jets (in emcal only) #it{p}_{T} and #eta"); registry.get(HIST("hSelectedJetRMaxPtPhi"))->SetTitle("Leading selected jets (in emcal only) #it{p}_{T} and #phi"); registry.get(HIST("hSelectedJetRMaxPtClusterMaxPt"))->SetTitle("Leading selected jets (in emcal only) and clusters"); @@ -255,7 +325,7 @@ struct JetTriggerQA { o2::aod::EMCALClusterDefinition clusDef = o2::aod::emcalcluster::getClusterDefinitionFromString(mClusterDefinition.value); Filter clusterDefinitionSelection = o2::aod::emcalcluster::definition == static_cast(clusDef); - double check_dphi(double dphi) + double check_dphi(double dphi) const { if (dphi > TMath::Pi()) { dphi -= TMath::Pi(); @@ -276,6 +346,19 @@ struct JetTriggerQA { return false; } + bool hasEMCAL(collisionWithTrigger const& collision) const + { + std::array selectAliases = {{triggerAliases::kTVXinEMC, triggerAliases::kEMC7, triggerAliases::kDMC7, triggerAliases::kEG1, triggerAliases::kEG2, triggerAliases::kDG1, triggerAliases::kDG2, triggerAliases::kEJ1, triggerAliases::kEJ2, triggerAliases::kDJ1, triggerAliases::kDJ2}}; + bool found = false; + for (auto alias : selectAliases) { + if (collision.alias_bit(alias)) { + found = true; + break; + } + } + return found; + } + Bool_t isClusterInEmcal(selectedClusters::iterator const& cluster) { if (cluster.phi() < f_PhiEmcalOrDcal) { @@ -311,101 +394,163 @@ struct JetTriggerQA { registry.fill(HIST("hTriggerCorrelation"), mainTrigger, assocTrigger); } - void process(soa::Join::iterator const& collision, - soa::Join const& jets, - aod::Tracks const& tracks, - selectedClusters const& clusters) + std::pair fillGammaQA(const selectedClusters& clusters, std::bitset hwtrg, const std::bitset& triggerstatus) { - std::bitset triggerstatus; auto isTrigger = [&triggerstatus](TriggerType_t triggertype) -> bool { return triggerstatus.test(triggertype); }; - auto setTrigger = [&triggerstatus](TriggerType_t triggertype) { - triggerstatus.set(triggertype, true); - }; - fillEventSelectionCounter(0); - setTrigger(TriggerType_t::kMinBias); + double maxClusterObservableEMCAL = -1., maxClusterObservableDCAL = -1.; + selectedClusters::iterator maxClusterEMCAL, maxClusterDCAL; - // fill event counters and correlation matrix without constraint on the EMCAL trigger flag - if (collision.alias_bit(kTVXinEMC)) { - fillEventSelectionCounter(1); - setTrigger(TriggerType_t::kEmcal); - } + struct ClusterData { + float mTriggerObservable; + float mEta; + float mPhi; + bool mEMCALcluster; + }; + std::vector analysedClusters; - bool isEvtSelected = false, isEventSelectedNeutralJet = false, isEvtSelectedGammaEMCAL = false, isEvtSelectedGammaDCAL = false, isEvtSelectedGammaLowEMCAL = false, isEvtSelectedGammaLowDCAL = false; - if (collision.hasJetFullHighPt()) { - isEvtSelected = true; - fillEventSelectionCounter(2); - setTrigger(TriggerType_t::kEmcalJetFull); - } - if (collision.hasJetNeutralHighPt()) { - isEventSelectedNeutralJet = true; - fillEventSelectionCounter(3); - setTrigger(TriggerType_t::kEmcalJetNeutral); - } - if (collision.hasGammaHighPtEMCAL()) { - isEvtSelectedGammaEMCAL = true; - fillEventSelectionCounter(4); - setTrigger(TriggerType_t::kEmcalGammaHigh); - } - if (collision.hasGammaHighPtDCAL()) { - isEvtSelectedGammaDCAL = true; - fillEventSelectionCounter(5); - setTrigger(TriggerType_t::kDcalGammaHigh); - } - if (collision.hasGammaLowPtEMCAL()) { - isEvtSelectedGammaLowEMCAL = true; - fillEventSelectionCounter(6); - setTrigger(TriggerType_t::kEmcalGammaLow); - } - if (collision.hasGammaLowPtDCAL()) { - isEvtSelectedGammaLowDCAL = true; - fillEventSelectionCounter(7); - setTrigger(TriggerType_t::kDcalGammaLow); - } - if (collision.hasJetFullHighPt() && collision.hasGammaHighPtEMCAL()) { - fillEventSelectionCounter(8); - } - if (collision.hasJetFullHighPt() && collision.hasGammaHighPtDCAL()) { - fillEventSelectionCounter(9); - } - if (collision.hasJetNeutralHighPt() && collision.hasGammaHighPtEMCAL()) { - fillEventSelectionCounter(10); - } - if (collision.hasJetNeutralHighPt() && collision.hasGammaHighPtDCAL()) { - fillEventSelectionCounter(11); - } - if (collision.hasJetFullHighPt() && collision.hasJetNeutralHighPt()) { - fillEventSelectionCounter(12); - } - if (collision.hasGammaHighPtEMCAL() && collision.hasGammaHighPtDCAL()) { - fillEventSelectionCounter(13); - } + for (const auto& cluster : clusters) { + if (b_RejectExoticClusters && cluster.isExotic()) { + continue; + } + if (cluster.time() < f_minClusterTime || cluster.time() > f_maxClusterTime) { + continue; + } + bool emcalCluster = isClusterInEmcal(cluster); + double clusterObservable = (f_GammaObservable == 0) ? cluster.energy() : cluster.energy() / std::cosh(cluster.eta()); + analysedClusters.push_back({static_cast(clusterObservable), cluster.eta(), cluster.phi(), emcalCluster}); - // Create correlationMatrix - for (std::size_t maintriggertype = 0; maintriggertype < TriggerType_t::kNTriggers; maintriggertype++) { - if (isTrigger(static_cast(maintriggertype))) { - for (std::size_t assoctriggertype = 0; assoctriggertype < TriggerType_t::kNTriggers; assoctriggertype++) { - if (isTrigger(static_cast(assoctriggertype))) { - fillCorrelationMatrix(static_cast(maintriggertype), static_cast(assoctriggertype)); - } + if (emcalCluster && (clusterObservable > maxClusterObservableEMCAL)) { + maxClusterObservableEMCAL = clusterObservable; + maxClusterEMCAL = cluster; + } + if (!emcalCluster && (clusterObservable > maxClusterObservableDCAL)) { + maxClusterObservableDCAL = clusterObservable; + maxClusterDCAL = cluster; + } + registry.fill(HIST("hClusterPtEtaPhi"), clusterObservable, cluster.eta(), cluster.phi()); + if (hwtrg.test(EMCALHardwareTrigger::TRG_MB)) { + registry.fill(HIST("hClusterPtEtaPhiMinBias"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (hwtrg.test(EMCALHardwareTrigger::TRG_EMC7) || hwtrg.test(EMCALHardwareTrigger::TRG_DMC7)) { + registry.fill(HIST("hClusterPtEtaPhiLevel0"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kEmcalJetFull) || isTrigger(TriggerType_t::kEmcalJetNeutral)) { + registry.fill(HIST("hSelectedClusterPtEtaPhi"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kEmcalGammaVeryHigh) && isClusterInEmcal(cluster)) { // Only fill EMCAL clusters + registry.fill(HIST("hSelectedGammaEMCALPtEtaPhiVeryHigh"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kDcalGammaVeryHigh) && !isClusterInEmcal(cluster)) { // Only fill DCAL clusters + registry.fill(HIST("hSelectedGammaDCALPtEtaPhiVeryHigh"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kEmcalGammaHigh) && isClusterInEmcal(cluster)) { // Only fill EMCAL clusters + registry.fill(HIST("hSelectedGammaEMCALPtEtaPhi"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kDcalGammaHigh) && !isClusterInEmcal(cluster)) { // Only fill DCAL clusters + registry.fill(HIST("hSelectedGammaDCALPtEtaPhi"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kEmcalGammaLow) && isClusterInEmcal(cluster)) { // Only fill EMCAL clusters + registry.fill(HIST("hSelectedGammaEMCALPtEtaPhiLow"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kDcalGammaLow) && !isClusterInEmcal(cluster)) { // Only fill DCAL clusters + registry.fill(HIST("hSelectedGammaDCALPtEtaPhiLow"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kEmcalGammaVeryLow) && isClusterInEmcal(cluster)) { // Only fill EMCAL clusters + registry.fill(HIST("hSelectedGammaEMCALPtEtaPhiVeryLow"), clusterObservable, cluster.eta(), cluster.phi()); + } + if (isTrigger(TriggerType_t::kDcalGammaVeryLow) && !isClusterInEmcal(cluster)) { // Only fill DCAL clusters + registry.fill(HIST("hSelectedGammaDCALPtEtaPhiVeryLow"), clusterObservable, cluster.eta(), cluster.phi()); + } + } // for clusters + + if (maxClusterObservableEMCAL > 0) { + registry.fill(HIST("hClusterEMCALMaxPtEtaPhi"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); + if (hwtrg.test(EMCALHardwareTrigger::TRG_MB)) { + registry.fill(HIST("hClusterEMCALMaxPtEtaPhiMinBias"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); + } + if (hwtrg.test(EMCALHardwareTrigger::TRG_EMC7)) { + registry.fill(HIST("hClusterEMCALMaxPtEtaPhiLevel0"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); + } + for (const auto& cluster : analysedClusters) { + if (cluster.mEMCALcluster) { + registry.fill(HIST("hClusterEMCALMaxPtClusterEMCALPt"), maxClusterObservableEMCAL, cluster.mTriggerObservable); } } + if (isTrigger(TriggerType_t::kEmcalJetFull) || isTrigger(TriggerType_t::kEmcalJetNeutral)) { + registry.fill(HIST("hSelectedClusterMaxPtEtaPhi"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); + } + if (isTrigger(TriggerType_t::kEmcalGammaVeryHigh)) { + registry.fill(HIST("hSelectedGammaEMCALMaxPtEtaPhiVeryHigh"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); + } + if (isTrigger(TriggerType_t::kEmcalGammaHigh)) { + registry.fill(HIST("hSelectedGammaEMCALMaxPtEtaPhi"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); + } + if (isTrigger(TriggerType_t::kEmcalGammaLow)) { + registry.fill(HIST("hSelectedGammaEMCALMaxPtEtaPhiLow"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); + } + if (isTrigger(TriggerType_t::kEmcalGammaVeryLow)) { + registry.fill(HIST("hSelectedGammaEMCALMaxPtEtaPhiVeryLow"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); + } + } else { + // count events where max. cluster has not been found + registry.fill(HIST("hEventsNoMaxClusterEMCAL"), 1.); + if (hwtrg.test(EMCALHardwareTrigger::TRG_MB)) { + registry.fill(HIST("hEventsNoMaxClusterEMCALMinBias"), 1.); + } + if (hwtrg.test(EMCALHardwareTrigger::TRG_EMC7)) { + registry.fill(HIST("hEventsNoMaxClusterEMCALLevel0"), 1.); + } } - - // Discard collisions without EMCAL if it is not respecifically required to discard the the EMCAL flag - // If ignore is true, we don't check for the flag and accept all events - if (!b_IgnoreEmcalFlag) { - if (!collision.alias_bit(kTVXinEMC)) { - return; // Only consider events where EMCAL is live + if (maxClusterObservableDCAL > 0) { + registry.fill(HIST("hClusterDCALMaxPtEtaPhi"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); + if (hwtrg.test(EMCALHardwareTrigger::TRG_MB)) { + registry.fill(HIST("hClusterDCALMaxPtEtaPhiMinBias"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); + } + if (hwtrg.test(EMCALHardwareTrigger::TRG_DMC7)) { + registry.fill(HIST("hClusterDCALMaxPtEtaPhiLevel0"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); + } + for (const auto& cluster : analysedClusters) { + if (!cluster.mEMCALcluster) { + registry.fill(HIST("hClusterDCALMaxPtClusterDCALPt"), maxClusterObservableDCAL, cluster.mTriggerObservable); + } + } + if (isTrigger(TriggerType_t::kDcalGammaVeryHigh)) { + registry.fill(HIST("hSelectedGammaDCALMaxPtEtaPhiVeryHigh"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); + } + if (isTrigger(TriggerType_t::kDcalGammaHigh)) { + registry.fill(HIST("hSelectedGammaDCALMaxPtEtaPhi"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); + } + if (isTrigger(TriggerType_t::kDcalGammaLow)) { + registry.fill(HIST("hSelectedGammaDCALMaxPtEtaPhiLow"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); + } + if (isTrigger(TriggerType_t::kDcalGammaVeryLow)) { + registry.fill(HIST("hSelectedGammaDCALMaxPtEtaPhiVeryLow"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); + } + } else { + registry.fill(HIST("hEventsNoMaxClusterDCAL"), 1.); + // count events where max. cluster has not been found + if (hwtrg.test(EMCALHardwareTrigger::TRG_MB)) { + registry.fill(HIST("hEventsNoMaxClusterDCALMinBias"), 1.); + } + if (hwtrg.test(EMCALHardwareTrigger::TRG_DMC7)) { + registry.fill(HIST("hEventsNoMaxClusterDCALLevel0"), 1.); } } + return std::make_pair(maxClusterObservableEMCAL, maxClusterObservableDCAL); + } - double maxClusterObservableEMCAL = -1., maxClusterObservableDCAL = -1.; - selectedClusters::iterator maxClusterEMCAL, maxClusterDCAL; - std::vector::iterator> vecMaxJet; - std::vector::iterator> vecMaxJetNoFiducial; + template + std::pair, std::vector> fillJetQA(const JetCollection& jets, aod::Tracks const& tracks, selectedClusters const& clusters, std::bitset hwtrg, const std::bitset& triggerstatus) + { + auto isTrigger = [&triggerstatus](TriggerType_t triggertype) -> bool { + return triggerstatus.test(triggertype); + }; + + std::vector vecMaxJet; + std::vector vecMaxJetNoFiducial; for (const auto& jet : jets) { double jetPt = jet.pt(), jetR = jet.r() * 1e-2; @@ -422,7 +567,7 @@ struct JetTriggerQA { // This gives us access to all jet substructure information // auto tracksInJet = jetTrackConstituents.sliceBy(perJetTrackConstituents, jet.globalIndex()); // for (const auto& trackList : tracksInJet) { - for (auto& track : jet.tracks_as()) { + for (auto& track : jet.template tracks_as()) { auto trackPt = track.pt(); auto chargeFrag = track.px() * jet.px() + track.py() * jet.py() + track.pz() * jet.pz(); chargeFrag /= (jet.p() * jet.p()); @@ -436,15 +581,19 @@ struct JetTriggerQA { ptD += z * z; registry.fill(HIST("hJetRPtTrackPt"), jetR, jetPt, trackPt); registry.fill(HIST("hJetRPtChargeFrag"), jetR, jetPt, chargeFrag); - if (isEvtSelected || isEventSelectedNeutralJet) { + if (isTrigger(TriggerType_t::kEmcalJetFull) || isTrigger(TriggerType_t::kEmcalJetNeutral)) { registry.fill(HIST("hSelectedJetRPtTrackPt"), jetR, jetPt, trackPt); registry.fill(HIST("hSelectedJetRPtChargeFrag"), jetR, jetPt, chargeFrag); } + if (isTrigger(TriggerType_t::kEmcalJetFullLow) || isTrigger(TriggerType_t::kEmcalJetNeutralLow)) { + registry.fill(HIST("hSelectedJetLowRPtTrackPt"), jetR, jetPt, trackPt); + registry.fill(HIST("hSelectedJetLowRPtChargeFrag"), jetR, jetPt, chargeFrag); + } } // for tracks in jet // auto clustersInJet = jetClusterConstituents.sliceBy(perJetClusterConstituents, jet.globalIndex()); // for (const auto& clusterList : clustersInJet) { - for (auto& cluster : jet.clusters_as()) { + for (auto& cluster : jet.template clusters_as()) { auto clusterPt = cluster.energy() / std::cosh(cluster.eta()); neutralEnergyFraction += cluster.energy(); auto z = clusterPt / jetPt; @@ -456,9 +605,12 @@ struct JetTriggerQA { zThetaSq += z * dR * dR / (jetR * jetR); ptD += z * z; registry.fill(HIST("hJetRPtClusterPt"), jetR, jetPt, clusterPt); - if (isEvtSelected || isEventSelectedNeutralJet) { + if (isTrigger(TriggerType_t::kEmcalJetFull) || isTrigger(TriggerType_t::kEmcalJetNeutral)) { registry.fill(HIST("hSelectedJetRPtClusterPt"), jetR, jetPt, clusterPt); } + if (isTrigger(TriggerType_t::kEmcalJetFullLow) || isTrigger(TriggerType_t::kEmcalJetNeutralLow)) { + registry.fill(HIST("hSelectedJetLowRPtClusterPt"), jetR, jetPt, clusterPt); + } } // for clusters in jet neutralEnergyFraction /= jet.energy(); ptD = TMath::Sqrt(ptD); @@ -472,7 +624,7 @@ struct JetTriggerQA { registry.fill(HIST("hJetRPtZSqTheta"), jetR, jetPt, zSqTheta); registry.fill(HIST("hJetRPtZThetaSq"), jetR, jetPt, zThetaSq); registry.get(HIST("jetRPtEtaPhi"))->Fill(jetR, jetPt, jet.eta(), jet.phi()); - if (isEvtSelected || isEventSelectedNeutralJet) { + if (isTrigger(TriggerType_t::kEmcalJetFull) || isTrigger(TriggerType_t::kEmcalJetNeutral)) { registry.fill(HIST("hSelectedJetRPtEta"), jetR, jetPt, jet.eta()); registry.fill(HIST("hSelectedJetRPtPhi"), jetR, jetPt, jet.phi()); registry.fill(HIST("hSelectedJetRPtPtd"), jetR, jetPt, ptD); @@ -481,122 +633,157 @@ struct JetTriggerQA { registry.fill(HIST("hSelectedJetRPtZSqTheta"), jetR, jetPt, zSqTheta); registry.fill(HIST("hSelectedJetRPtZThetaSq"), jetR, jetPt, zThetaSq); } + if (isTrigger(TriggerType_t::kEmcalJetFullLow) || isTrigger(TriggerType_t::kEmcalJetNeutralLow)) { + registry.fill(HIST("hSelectedJetLowRPtEta"), jetR, jetPt, jet.eta()); + registry.fill(HIST("hSelectedJetLowRPtPhi"), jetR, jetPt, jet.phi()); + registry.fill(HIST("hSelectedJetLowRPtPtd"), jetR, jetPt, ptD); + registry.fill(HIST("hSelectedJetLowRPtNEF"), jetR, jetPt, neutralEnergyFraction); + registry.fill(HIST("hSelectedJetLowRPtZTheta"), jetR, jetPt, zTheta); + registry.fill(HIST("hSelectedJetLowRPtZSqTheta"), jetR, jetPt, zSqTheta); + registry.fill(HIST("hSelectedJetLowRPtZThetaSq"), jetR, jetPt, zThetaSq); + } } // for jets + return std::make_pair(vecMaxJet, vecMaxJetNoFiducial); + } - struct ClusterData { - float mTriggerObservable; - float mEta; - float mPhi; - bool mEMCALcluster; + template + void runQA(collisionWithTrigger const& collision, + JetCollection const& jets, + aod::Tracks const& tracks, + selectedClusters const& clusters) + { + std::bitset triggerstatus; + auto isTrigger = [&triggerstatus](TriggerType_t triggertype) -> bool { + return triggerstatus.test(triggertype); + }; + auto setTrigger = [&triggerstatus](TriggerType_t triggertype) { + triggerstatus.set(triggertype, true); }; - std::vector analysedClusters; - for (const auto& cluster : clusters) { - if (b_RejectExoticClusters && cluster.isExotic()) { - continue; - } - if (cluster.time() < f_minClusterTime || cluster.time() > f_maxClusterTime) { - continue; - } - bool emcalCluster = isClusterInEmcal(cluster); - double clusterObservable = (f_GammaObservable == 0) ? cluster.energy() : cluster.energy() / std::cosh(cluster.eta()); - analysedClusters.push_back({static_cast(clusterObservable), cluster.eta(), cluster.phi(), emcalCluster}); + std::bitset hardwaretriggers; + if (collision.alias_bit(triggerAliases::kTVXinEMC)) { + hardwaretriggers.set(EMCALHardwareTrigger::TRG_MB); + } + if (collision.alias_bit(triggerAliases::kEMC7)) { + hardwaretriggers.set(EMCALHardwareTrigger::TRG_EMC7); + } + if (collision.alias_bit(triggerAliases::kDMC7)) { + hardwaretriggers.set(EMCALHardwareTrigger::TRG_DMC7); + } - if (emcalCluster && (clusterObservable > maxClusterObservableEMCAL)) { - maxClusterObservableEMCAL = clusterObservable; - maxClusterEMCAL = cluster; - } - if (!emcalCluster && (clusterObservable > maxClusterObservableDCAL)) { - maxClusterObservableDCAL = clusterObservable; - maxClusterDCAL = cluster; - } - registry.fill(HIST("hClusterPtEta"), clusterObservable, cluster.eta()); - registry.fill(HIST("hClusterPtPhi"), clusterObservable, cluster.phi()); - registry.fill(HIST("hClusterPtEtaPhi"), clusterObservable, cluster.eta(), cluster.phi()); - if (isEvtSelected || isEventSelectedNeutralJet) { - registry.fill(HIST("hSelectedClusterPtEta"), clusterObservable, cluster.eta()); - registry.fill(HIST("hSelectedClusterPtPhi"), clusterObservable, cluster.phi()); - registry.fill(HIST("hSelectedClusterPtEtaPhi"), clusterObservable, cluster.eta(), cluster.phi()); - } - if (isEvtSelectedGammaEMCAL && isClusterInEmcal(cluster)) { // Only fill EMCAL clusters - registry.fill(HIST("hSelectedGammaEMCALPtEta"), clusterObservable, cluster.eta()); - registry.fill(HIST("hSelectedGammaEMCALPtPhi"), clusterObservable, cluster.phi()); - registry.fill(HIST("hSelectedGammaEMCALPtEtaPhi"), clusterObservable, cluster.eta(), cluster.phi()); - } - if (isEvtSelectedGammaDCAL && !isClusterInEmcal(cluster)) { // Only fill DCAL clusters - registry.fill(HIST("hSelectedGammaDCALPtEta"), clusterObservable, cluster.eta()); - registry.fill(HIST("hSelectedGammaDCALPtPhi"), clusterObservable, cluster.phi()); - registry.fill(HIST("hSelectedGammaDCALPtEtaPhi"), clusterObservable, cluster.eta(), cluster.phi()); - } - if (isEvtSelectedGammaLowEMCAL && isClusterInEmcal(cluster)) { // Only fill EMCAL clusters - registry.fill(HIST("hSelectedGammaEMCALPtEtaLow"), clusterObservable, cluster.eta()); - registry.fill(HIST("hSelectedGammaEMCALPtPhiLow"), clusterObservable, cluster.phi()); - registry.fill(HIST("hSelectedGammaEMCALPtEtaPhiLow"), clusterObservable, cluster.eta(), cluster.phi()); - } - if (isEvtSelectedGammaLowDCAL && !isClusterInEmcal(cluster)) { // Only fill DCAL clusters - registry.fill(HIST("hSelectedGammaDCALPtEtaLow"), clusterObservable, cluster.eta()); - registry.fill(HIST("hSelectedGammaDCALPtPhiLow"), clusterObservable, cluster.phi()); - registry.fill(HIST("hSelectedGammaDCALPtEtaPhiLow"), clusterObservable, cluster.eta(), cluster.phi()); - } - } // for clusters + fillEventSelectionCounter(0); + setTrigger(TriggerType_t::kMinBias); - if (maxClusterObservableEMCAL > 0) { - // hClusterMaxPtEta->Fill(maxClusterPt, maxCluster.eta()); - // hClusterMaxPtPhi->Fill(maxClusterPt, maxCluster.phi()); - registry.fill(HIST("hClusterEMCALMaxPtEtaPhi"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); - for (const auto& cluster : analysedClusters) { - if (cluster.mEMCALcluster) { - registry.fill(HIST("hClusterEMCALMaxPtClusterEMCALPt"), maxClusterObservableEMCAL, cluster.mTriggerObservable); - } - } - if (isEvtSelected) { - registry.fill(HIST("hSelectedClusterMaxPtEta"), maxClusterObservableEMCAL, maxClusterEMCAL.eta()); - registry.fill(HIST("hSelectedClusterMaxPtPhi"), maxClusterObservableEMCAL, maxClusterEMCAL.phi()); - registry.fill(HIST("hSelectedClusterMaxPtEtaPhi"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); - } - if (isEvtSelectedGammaEMCAL) { - registry.fill(HIST("hSelectedGammaEMCALMaxPtEta"), maxClusterObservableEMCAL, maxClusterEMCAL.eta()); - registry.fill(HIST("hSelectedGammaEMCALMaxPtPhi"), maxClusterObservableEMCAL, maxClusterEMCAL.phi()); - registry.fill(HIST("hSelectedGammaEMCALMaxPtEtaPhi"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); - } - if (isEvtSelectedGammaLowEMCAL) { - registry.fill(HIST("hSelectedGammaEMCALMaxPtEtaLow"), maxClusterObservableEMCAL, maxClusterEMCAL.eta()); - registry.fill(HIST("hSelectedGammaEMCALMaxPtPhiLow"), maxClusterObservableEMCAL, maxClusterEMCAL.phi()); - registry.fill(HIST("hSelectedGammaEMCALMaxPtEtaPhiLow"), maxClusterObservableEMCAL, maxClusterEMCAL.eta(), maxClusterEMCAL.phi()); - } + if (hasEMCAL(collision)) { + fillEventSelectionCounter(1); + setTrigger(TriggerType_t::kEmcalAny); } - if (maxClusterObservableDCAL > 0) { - registry.fill(HIST("hClusterDCALMaxPtEtaPhi"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); - for (const auto& cluster : analysedClusters) { - if (!cluster.mEMCALcluster) { - registry.fill(HIST("hClusterDCALMaxPtClusterDCALPt"), maxClusterObservableDCAL, cluster.mTriggerObservable); + + // fill event counters and correlation matrix without constraint on the EMCAL trigger flag + if (collision.alias_bit(kTVXinEMC)) { + fillEventSelectionCounter(2); + setTrigger(TriggerType_t::kEmcalMB); + } + + if (collision.hasJetFullHighPt()) { + fillEventSelectionCounter(3); + setTrigger(TriggerType_t::kEmcalJetFull); + } + if (collision.hasJetFullLowPt()) { + fillEventSelectionCounter(4); + setTrigger(TriggerType_t::kEmcalJetFullLow); + } + if (collision.hasJetNeutralHighPt()) { + fillEventSelectionCounter(5); + setTrigger(TriggerType_t::kEmcalJetNeutral); + } + if (collision.hasJetNeutralLowPt()) { + fillEventSelectionCounter(6); + setTrigger(TriggerType_t::kEmcalJetNeutralLow); + } + if (collision.hasGammaVeryHighPtEMCAL()) { + fillEventSelectionCounter(7); + setTrigger(TriggerType_t::kEmcalGammaVeryHigh); + } + if (collision.hasGammaVeryHighPtDCAL()) { + fillEventSelectionCounter(8); + setTrigger(TriggerType_t::kDcalGammaVeryHigh); + } + if (collision.hasGammaHighPtEMCAL()) { + fillEventSelectionCounter(9); + setTrigger(TriggerType_t::kEmcalGammaHigh); + } + if (collision.hasGammaHighPtDCAL()) { + fillEventSelectionCounter(10); + setTrigger(TriggerType_t::kDcalGammaHigh); + } + if (collision.hasGammaLowPtEMCAL()) { + fillEventSelectionCounter(11); + setTrigger(TriggerType_t::kEmcalGammaLow); + } + if (collision.hasGammaLowPtDCAL()) { + fillEventSelectionCounter(12); + setTrigger(TriggerType_t::kDcalGammaLow); + } + if (collision.hasGammaVeryLowPtEMCAL()) { + fillEventSelectionCounter(13); + setTrigger(TriggerType_t::kEmcalGammaVeryLow); + } + if (collision.hasGammaVeryLowPtDCAL()) { + fillEventSelectionCounter(14); + setTrigger(TriggerType_t::kDcalGammaVeryLow); + } + + // Create correlationMatrix + for (std::size_t maintriggertype = 0; maintriggertype < TriggerType_t::kNTriggers; maintriggertype++) { + if (isTrigger(static_cast(maintriggertype))) { + for (std::size_t assoctriggertype = 0; assoctriggertype < TriggerType_t::kNTriggers; assoctriggertype++) { + if (isTrigger(static_cast(assoctriggertype))) { + fillCorrelationMatrix(static_cast(maintriggertype), static_cast(assoctriggertype)); + } } } - if (isEvtSelectedGammaDCAL) { - registry.fill(HIST("hSelectedGammaDCALMaxPtEta"), maxClusterObservableDCAL, maxClusterDCAL.eta()); - registry.fill(HIST("hSelectedGammaDCALMaxPtPhi"), maxClusterObservableDCAL, maxClusterDCAL.phi()); - registry.fill(HIST("hSelectedGammaDCALMaxPtEtaPhi"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); - } - if (isEvtSelectedGammaLowDCAL) { - registry.fill(HIST("hSelectedGammaDCALMaxPtEtaLow"), maxClusterObservableDCAL, maxClusterDCAL.eta()); - registry.fill(HIST("hSelectedGammaDCALMaxPtPhiLow"), maxClusterObservableDCAL, maxClusterDCAL.phi()); - registry.fill(HIST("hSelectedGammaDCALMaxPtEtaPhiLow"), maxClusterObservableDCAL, maxClusterDCAL.eta(), maxClusterDCAL.phi()); + } + + // Discard collisions without EMCAL if it is not respecifically required to discard the the EMCAL flag + // If ignore is true, we don't check for the flag and accept all events + if (!b_IgnoreEmcalFlag) { + if (!isTrigger(TriggerType_t::kEmcalAny)) { + return; // Only consider events where EMCAL is live } } + auto [maxClusterObservableEMCAL, maxClusterObservableDCAL] = fillGammaQA(clusters, hardwaretriggers, triggerstatus); + auto [vecMaxJet, vecMaxJetNoFiducial] = fillJetQA(jets, tracks, clusters, hardwaretriggers, triggerstatus); + + std::array foundMaxJet; + std::fill(foundMaxJet.begin(), foundMaxJet.end(), false); for (auto maxJet : vecMaxJet) { double jetR = maxJet.r() * 1e-2, jetPt = maxJet.pt(), jetEta = maxJet.eta(), jetPhi = maxJet.phi(); + foundMaxJet[static_cast(maxJet.r() * 1e-1) - 2] = true; registry.fill(HIST("hJetRMaxPtEta"), jetR, jetPt, jetEta); registry.fill(HIST("hJetRMaxPtPhi"), jetR, jetPt, jetPhi); + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_MB)) { + registry.fill(HIST("hJetRMaxPtEtaMinBias"), jetR, jetPt, jetEta); + registry.fill(HIST("hJetRMaxPtPhiMinBias"), jetR, jetPt, jetPhi); + } + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_EMC7)) { + registry.fill(HIST("hJetRMaxPtEtaLevel0"), jetR, jetPt, jetEta); + registry.fill(HIST("hJetRMaxPtPhiLevel0"), jetR, jetPt, jetPhi); + } // hJetRMaxPtEtaPhi->Fill(jetR, jetPt, jetEta, jetPhi); registry.get(HIST("jetRMaxPtEtaPhi"))->Fill(jetR, jetPt, jetEta, jetPhi); - if (isEvtSelected) { + if (isTrigger(TriggerType_t::kEmcalJetFull) || isTrigger(TriggerType_t::kEmcalJetNeutral)) { registry.fill(HIST("hSelectedJetRMaxPtEta"), jetR, jetPt, jetEta); registry.fill(HIST("hSelectedJetRMaxPtPhi"), jetR, jetPt, jetPhi); } + if (isTrigger(TriggerType_t::kEmcalJetFullLow) || isTrigger(TriggerType_t::kEmcalJetNeutralLow)) { + registry.fill(HIST("hSelectedJetLowRMaxPtEta"), jetR, jetPt, jetEta); + registry.fill(HIST("hSelectedJetLowRMaxPtPhi"), jetR, jetPt, jetPhi); + } if (maxClusterObservableEMCAL > 0) { registry.fill(HIST("hJetRMaxPtClusterMaxPt"), jetR, jetPt, maxClusterObservableEMCAL); - if (isEvtSelected) { + if (isTrigger(TriggerType_t::kEmcalJetFull) || isTrigger(TriggerType_t::kEmcalJetNeutral)) { registry.fill(HIST("hSelectedJetRMaxPtClusterMaxPt"), jetR, jetPt, maxClusterObservableEMCAL); } } // if maxClusterPt @@ -608,6 +795,19 @@ struct JetTriggerQA { } // for jets } // if maxJet.r() == std::round(f_jetR * 100) } // for maxJet + // Fill counters for events without max jets + for (std::size_t ir = 0; ir < foundMaxJet.size(); ir++) { + if (!foundMaxJet[ir]) { + double rval = static_cast(ir) / 10.; + registry.fill(HIST("hEventsNoMaxJet"), rval); + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_MB)) { + registry.fill(HIST("hEventsNoMaxJetMinBias"), rval); + } + if (hardwaretriggers.test(EMCALHardwareTrigger::TRG_EMC7)) { + registry.fill(HIST("hEventsNoMaxJetLevel0"), rval); + } + } + } for (auto maxJet : vecMaxJetNoFiducial) { double jetR = maxJet.r() * 1e-2, jetPt = maxJet.pt(), jetEta = maxJet.eta(), jetPhi = maxJet.phi(); // hJetRMaxPtEtaPhiNoFiducial->Fill(jetR, jetPt, jetEta, jetPhi); @@ -618,8 +818,28 @@ struct JetTriggerQA { } // for jets } // if maxJet.r() == std::round(f_jetR * 100) } // for maxjet no fiducial - } // process + + } // process + + void processFullJets(collisionWithTrigger const& collision, + fullJetInfos const& jets, + aod::Tracks const& tracks, + selectedClusters const& clusters) + { + runQA(collision, jets, tracks, clusters); + } + PROCESS_SWITCH(JetTriggerQA, processFullJets, "Run QA for full jets", true); + + void processNeutralJets(collisionWithTrigger const& collision, + neutralJetInfos const& jets, + aod::Tracks const& tracks, + selectedClusters const& clusters) + { + runQA(collision, jets, tracks, clusters); + } + PROCESS_SWITCH(JetTriggerQA, processNeutralJets, "Run QA for neutral jets", false); }; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ diff --git a/PWGJE/Tasks/emccellmonitor.cxx b/PWGJE/Tasks/emccellmonitor.cxx index 56f4a15374d..bb1d8fb3f9f 100644 --- a/PWGJE/Tasks/emccellmonitor.cxx +++ b/PWGJE/Tasks/emccellmonitor.cxx @@ -23,6 +23,7 @@ #include "Framework/ASoA.h" #include "Framework/HistogramRegistry.h" +#include "DataFormatsEMCAL/Constants.h" #include "EMCALBase/Geometry.h" #include "EMCALCalib/BadChannelMap.h" #include "CommonDataFormat/InteractionRecord.h" @@ -94,7 +95,9 @@ struct CellMonitor { mHistManager.add("cellMasking", "Monitoring for masked cells", o2HistType::kTH1F, {cellAxis}); mHistManager.add("cellFrequency", "Frequency of cell firing", o2HistType::kTH1F, {cellAxis}); mHistManager.add("cellAmplitude", "Energy distribution per cell", o2HistType::kTH2F, {amplitudeAxis, cellAxis}); - mHistManager.add("cellAmplitudeCut", "Energy distribution per cell", o2HistType::kTH2F, {amplitudeAxis, cellAxis}); + mHistManager.add("cellAmplitudeHG", "Energy distribution per cell high gain", o2HistType::kTH2F, {amplitudeAxis, cellAxis}); + mHistManager.add("cellAmplitudeLG", "Energy distribution per cell low gain", o2HistType::kTH2F, {amplitudeAxis, cellAxis}); + mHistManager.add("cellAmplitudeCut", "Energy distribution per cell cut", o2HistType::kTH2F, {amplitudeAxis, cellAxis}); mHistManager.add("cellTime", "Time distribution per cell", o2HistType::kTH2F, {timeAxisLarge, cellAxis}); mHistManager.add("cellTimeMain", "Time distribution per cell for the main bunch", o2HistType::kTH2F, {timeAxisMainBunch, cellAxis}); mHistManager.add("cellAmplitudeBC", "Cell amplitude vs. bunch crossing ID", o2HistType::kTH2F, {bcAxis, amplitudeAxis}); @@ -169,6 +172,12 @@ struct CellMonitor { mHistManager.fill(HIST("cellBCAll"), cellIR.bc); mHistManager.fill(HIST("cellBCSelected"), cellIR.bc); mHistManager.fill(HIST("cellAmplitude"), cell.amplitude(), cell.cellNumber()); + if (cell.cellType() == o2::emcal::channelTypeToInt(o2::emcal::ChannelType_t::HIGH_GAIN)) { + mHistManager.fill(HIST("cellAmplitudeHG"), cell.amplitude(), cell.cellNumber()); + } else if (cell.cellType() == o2::emcal::channelTypeToInt(o2::emcal::ChannelType_t::LOW_GAIN)) { + mHistManager.fill(HIST("cellAmplitudeLG"), cell.amplitude(), cell.cellNumber()); + } + if (cell.amplitude() < mMinCellAmplitude) continue; mHistManager.fill(HIST("cellAmplitudeCut"), cell.amplitude(), cell.cellNumber()); diff --git a/PWGJE/Tasks/emceventselectionqa.cxx b/PWGJE/Tasks/emceventselectionqa.cxx index 3da8b918dca..330cc8ca11b 100644 --- a/PWGJE/Tasks/emceventselectionqa.cxx +++ b/PWGJE/Tasks/emceventselectionqa.cxx @@ -44,12 +44,48 @@ struct EmcEventSelectionQA { o2Axis matchingAxis{3, -0.5, 2.5, "matchingStatus", "Matching status"}, // 0, no vertex,1 vertex found , 2 multiple vertices found bcAxis{4001, -0.5, 4000.5, "bcid", "BC ID"}; - mHistManager.add("hCollisionMatching", "hCollisionMatching", o2HistType::kTH1F, {matchingAxis}); - mHistManager.add("hCollisionMatchingReadout", "hCollisionMatching", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatching", "Collision Status", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingReadout", "Collision Status EMCAL Readout", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingMB", "Collision Status EMCAL MB", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatching0EMC", "Collision Status EMCAL L0 trigger", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatching0DMC", "Collision Status DCAL L0 tr", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingEG1", "Collision Status EG1 trigger", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingDG1", "Collision Status DG1 trigger", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingEG2", "Collision Status EG2 trigger", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingDG2", "Collision Status DG2 trigger", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingEJ1", "Collision Status EJ1 trigger", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingDJ1", "Collision Status DJ1 trigger", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingEJ2", "Collision Status EJ2 trigger", o2HistType::kTH1F, {matchingAxis}); + mHistManager.add("hCollisionMatchingDJ2", "Collision Status DJ2 trigger", o2HistType::kTH1F, {matchingAxis}); mHistManager.add("hBCCollisions", "Bunch crossings of found collisions", o2HistType::kTH1F, {bcAxis}); mHistManager.add("hBCEmcalReadout", "Bunch crossings with EMCAL trigger from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalMB", "Bunch crossings with EMCAL MB from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcal0EMC", "Bunch crossings with EMCAL L0 from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcal0DMC", "Bunch crossings with DCAL L0 from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalEG1", "Bunch crossings with EG1 trigger from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalDG1", "Bunch crossings with DG1 trigger from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalEG2", "Bunch crossings with EG1 trigger from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalDG2", "Bunch crossings with DG2 trigger from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalEJ1", "Bunch crossings with EJ1 trigger from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalDJ1", "Bunch crossings with DJ1 trigger from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalEJ2", "Bunch crossings with EJ2 trigger from CTP", o2HistType::kTH1F, {bcAxis}); + mHistManager.add("hBCEmcalDJ2", "Bunch crossings with DJ2 trigger from CTP", o2HistType::kTH1F, {bcAxis}); mHistManager.add("hBCTVX", "Bunch crossings with FIT TVX trigger from CTP", o2HistType::kTH1F, {bcAxis}); mHistManager.add("hBCEmcalCellContent", "Bunch crossings with non-0 EMCAL cell content", o2HistType::kTH1F, {bcAxis}); + + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatching")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingReadout")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingMB")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatching0EMC")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatching0DMC")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingEG1")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingDG1")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingEG2")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingDG2")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingEJ1")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingDJ1")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingEJ2")).get()); + initCollisionHistogram(mHistManager.get(HIST("hCollisionMatchingDJ2")).get()); } PresliceUnsorted perFoundBC = aod::evsel::foundBCId; @@ -76,7 +112,7 @@ struct EmcEventSelectionQA { if (bc.runNumber() > 300000) { // in case of run3 not all BCs contain EMCAL data, require trigger selection also for min. bias // in addition select also L0/L1 triggers as triggers with EMCAL in reaodut - if (bc.alias_bit(kTVXinEMC) || bc.alias_bit(kEMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2)) { + if (bc.alias_bit(kTVXinEMC) || bc.alias_bit(kEMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kDG1) || bc.alias_bit(kDG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2) || bc.alias_bit(kDJ1) || bc.alias_bit(kDJ2)) { isEMCALreadout = true; } } else { @@ -90,9 +126,43 @@ struct EmcEventSelectionQA { // Monitoring BCs with EMCAL trigger / readout / FIT trigger if (isEMCALreadout) { mHistManager.fill(HIST("hBCEmcalReadout"), bcID); + // various triggers + if (bc.alias_bit(kTVXinEMC)) { + mHistManager.fill(HIST("hBCEmcalMB"), bcID); + } + if (bc.alias_bit(kEMC7)) { + mHistManager.fill(HIST("hBCEmcal0EMC"), bcID); + } + if (bc.alias_bit(kDMC7)) { + mHistManager.fill(HIST("hBCEmcal0DMC"), bcID); + } + if (bc.alias_bit(kEG1)) { + mHistManager.fill(HIST("hBCEmcalEG1"), bcID); + } + if (bc.alias_bit(kDG1)) { + mHistManager.fill(HIST("hBCEmcalDG1"), bcID); + } + if (bc.alias_bit(kEG2)) { + mHistManager.fill(HIST("hBCEmcalEG2"), bcID); + } + if (bc.alias_bit(kDG2)) { + mHistManager.fill(HIST("hBCEmcalDG2"), bcID); + } + if (bc.alias_bit(kEJ1)) { + mHistManager.fill(HIST("hBCEmcalEJ1"), bcID); + } + if (bc.alias_bit(kDJ1)) { + mHistManager.fill(HIST("hBCEmcalDJ1"), bcID); + } + if (bc.alias_bit(kEJ2)) { + mHistManager.fill(HIST("hBCEmcalEJ2"), bcID); + } + if (bc.alias_bit(kDJ2)) { + mHistManager.fill(HIST("hBCEmcalDJ2"), bcID); + } } - if (bc.selection_bit(kIsTriggerTVX)) { + if (bc.selection_bit(aod::evsel::kIsTriggerTVX)) { mHistManager.fill(HIST("hBCTVX"), bcID); } @@ -119,6 +189,40 @@ struct EmcEventSelectionQA { mHistManager.fill(HIST("hCollisionMatching"), collisionStatus); if (isEMCALreadout) { mHistManager.fill(HIST("hCollisionMatchingReadout"), collisionStatus); + // various triggers + if (bc.alias_bit(kTVXinEMC)) { + mHistManager.fill(HIST("hCollisionMatchingMB"), collisionStatus); + } + if (bc.alias_bit(kEMC7)) { + mHistManager.fill(HIST("hCollisionMatching0EMC"), collisionStatus); + } + if (bc.alias_bit(kDMC7)) { + mHistManager.fill(HIST("hCollisionMatching0DMC"), collisionStatus); + } + if (bc.alias_bit(kEG1)) { + mHistManager.fill(HIST("hCollisionMatchingEG1"), collisionStatus); + } + if (bc.alias_bit(kDG1)) { + mHistManager.fill(HIST("hCollisionMatchingDG1"), collisionStatus); + } + if (bc.alias_bit(kEG2)) { + mHistManager.fill(HIST("hCollisionMatchingEG2"), collisionStatus); + } + if (bc.alias_bit(kDG2)) { + mHistManager.fill(HIST("hCollisionMatchingDG2"), collisionStatus); + } + if (bc.alias_bit(kEJ1)) { + mHistManager.fill(HIST("hCollisionMatchingEJ1"), collisionStatus); + } + if (bc.alias_bit(kDJ1)) { + mHistManager.fill(HIST("hCollisionMatchingDJ1"), collisionStatus); + } + if (bc.alias_bit(kEJ2)) { + mHistManager.fill(HIST("hCollisionMatchingEJ2"), collisionStatus); + } + if (bc.alias_bit(kDJ2)) { + mHistManager.fill(HIST("hCollisionMatchingDJ2"), collisionStatus); + } } } if (collisionStatus > 0) { @@ -126,6 +230,16 @@ struct EmcEventSelectionQA { } } } + + void initCollisionHistogram(TH1* hist) + { + // Beautify collision type lables + hist->GetXaxis()->SetTitle("Collision status"); + hist->GetXaxis()->SetBinLabel(1, "No vertex"); + hist->GetXaxis()->SetBinLabel(2, "1 vertex"); + hist->GetXaxis()->SetBinLabel(3, "Pileup"); + hist->GetYaxis()->SetTitle("Number of BCs"); + } }; o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/emctmmonitor.cxx b/PWGJE/Tasks/emctmmonitor.cxx index 615e47d65c7..c210a42f169 100644 --- a/PWGJE/Tasks/emctmmonitor.cxx +++ b/PWGJE/Tasks/emctmmonitor.cxx @@ -79,6 +79,12 @@ struct TrackMatchingMonitor { Configurable minTime{"minTime", -25., "Minimum cluster time for time cut"}; Configurable maxTime{"maxTime", +20., "Maximum cluster time for time cut"}; Configurable minM02{"minM02", 0.1, "Minimum M02 for M02 cut"}; + Configurable maxM02{"maxM02", 0.9, "Maximum M02 for M02 cut"}; + Configurable maxM02HighPt{"maxM02HighPt", 0.6, "Maximum M02 for M02 cut for high pT"}; + Configurable M02highPt{"M02highPt", 15., "pT threshold for maxM02HighPt cut. Set to negative value to disable it!"}; + Configurable minDEta{"minDEta", 0.01, "Minimum dEta between track and cluster"}; + Configurable minDPhi{"minDPhi", 0.01, "Minimum dPhi between track and cluster"}; + Configurable> eOverPRange{"eOverPRange", {0.9, 1.2}, "E/p range where one would search for electrons (first <= E/p <= second)"}; std::vector mVetoBCIDs; std::vector mSelectBCIDs; @@ -98,13 +104,14 @@ struct TrackMatchingMonitor { const o2Axis bcAxis{3501, -0.5, 3500.5}; const o2Axis energyAxis{makeEnergyBinningAliPhysics(), "E_{clus} (GeV)"}; const o2Axis amplitudeAxisLarge{1000, 0., 100., "amplitudeLarge", "Amplitude (GeV)"}; - const o2Axis dEtaAxis{100, -0.4, 0.4, "d#it{#eta}"}; - const o2Axis dPhiAxis{100, -0.4, 0.4, "d#it{#varphi} (rad)"}; - const o2Axis dRAxis{100, 0.0, 0.4, "d#it{R}"}; + const o2Axis dEtaAxis{100, -0.01, 0.01, "d#it{#eta}"}; + const o2Axis dPhiAxis{100, -0.01, 0.01, "d#it{#varphi} (rad)"}; + const o2Axis dRAxis{150, 0.0, 0.015, "d#it{R}"}; const o2Axis eoverpAxis{500, 0, 10, "#it{E}_{cluster}/#it{p}_{track}"}; - const o2Axis trackptAxis{200, 0, 100, "#it{p}_{T,track}"}; + const o2Axis nSigmaAxis{130, -10., +3., "N#sigma"}; + const o2Axis trackptAxis{makePtBinning(), "#it{p}_{T,track}"}; const o2Axis trackpAxis{200, 0, 100, "#it{p}_{track}"}; - const o2Axis clusterptAxis{200, 0, 100, "#it{p}_{T}"}; + const o2Axis clusterptAxis{makePtBinning(), "#it{p}_{T}"}; o2Axis timeAxis{mClusterTimeBinning, "t_{cl} (ns)"}; int MaxMatched = 20; // maximum number of matched tracks, hardcoded in emcalCorrectionTask.cxx! @@ -144,11 +151,17 @@ struct TrackMatchingMonitor { mHistManager.add("clusterTM_EoverP_E", "E/p ", o2HistType::kTH3F, {eoverpAxis, energyAxis, nmatchedtrack}); // E/p vs p for the Nth closest track mHistManager.add("clusterTM_EoverP_Pt", "E/p vs track pT", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E/p vs track pT for the Nth closest track mHistManager.add("clusterTM_EvsP", "cluster E/track p", o2HistType::kTH3F, {energyAxis, trackpAxis, nmatchedtrack}); // E vs p for the Nth closest track - mHistManager.add("clusterTM_EoverP_ep", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track - mHistManager.add("clusterTM_EoverP_e", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron track - mHistManager.add("clusterTM_EoverP_p", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positron track - mHistManager.add("clusterTM_EoverP_electron_ASide", "cluster E/electron p in A-Side", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in A-Side - mHistManager.add("clusterTM_EoverP_electron_CSide", "cluster E/electron p in C-Side", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in C-Side + mHistManager.add("clusterTM_EoverP_ep", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track + mHistManager.add("clusterTM_EoverP_e", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron track + mHistManager.add("clusterTM_EoverP_p", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positron track + mHistManager.add("clusterTM_EoverP_electron_ASide", "cluster E/electron p in A-Side", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in A-Side + mHistManager.add("clusterTM_EoverP_electron_CSide", "cluster E/electron p in C-Side", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in C-Side + mHistManager.add("clusterTM_NSigma", "electron NSigma for matched track", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track + mHistManager.add("clusterTM_NSigma_cut", "electron NSigma for matched track with cuts", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track with cuts on E/p and cluster cuts + mHistManager.add("clusterTM_NSigma_e", "NSigma electron", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track + mHistManager.add("clusterTM_NSigma_p", "NSigma positron", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track + mHistManager.add("clusterTM_NSigma_electron_ASide", "NSigma electron in A-Side", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in A-Side + mHistManager.add("clusterTM_NSigma_electron_CSide", "NSigma positron in C-Side", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in C-Side mHistManager.add("clusterTM_EoverP_hadron", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track mHistManager.add("clusterTM_EoverP_hn", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest negative hadron track mHistManager.add("clusterTM_EoverP_hp", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positive hadron track @@ -180,7 +193,7 @@ struct TrackMatchingMonitor { // define cluster filter. It selects only those clusters which are of the type // sadly passing of the string at runtime is not possible for technical region so cluster definition is // an integer instead - Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == mClusterDefinition) && (o2::aod::emcalcluster::time >= minTime) && (o2::aod::emcalcluster::time <= maxTime) && (o2::aod::emcalcluster::m02 > minM02); + Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == mClusterDefinition) && (o2::aod::emcalcluster::time >= minTime) && (o2::aod::emcalcluster::time <= maxTime) && (o2::aod::emcalcluster::m02 > minM02) && (o2::aod::emcalcluster::m02 < maxM02); /// \brief Process EMCAL clusters that are matched to a collisions void processCollisions(collisionEvSelIt const& theCollision, selectedClusters const& clusters, o2::aod::EMCALClusterCells const& emccluscells, o2::aod::Calos const& allcalos, o2::aod::EMCALMatchedTracks const& matchedtracks, tracksPID const& alltrack) @@ -258,6 +271,9 @@ struct TrackMatchingMonitor { // In this example the counter t is just used to only look at the closest match double dEta, dPhi, pT, abs_p; pT = cluster.energy() / cosh(cluster.eta()); + if (M02highPt > 0. && cluster.m02() >= maxM02HighPt && pT >= M02highPt) { // high pT M02 cut + continue; + } auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, cluster.globalIndex()); int t = 0; int tAli = 0; @@ -273,15 +289,24 @@ struct TrackMatchingMonitor { dEta = match.track_as().eta() - cluster.eta(); dPhi = match.track_as().phi() - cluster.phi(); } + if (fabs(dEta) >= minDEta || fabs(dPhi) >= minDPhi) { // dEta and dPhi cut + continue; + } + double eOverP = cluster.energy() / abs_p; + double NSigmaEl = match.track_as().tpcNSigmaEl(); mHistManager.fill(HIST("clusterTM_dEtaTN"), dEta, t); mHistManager.fill(HIST("clusterTM_dPhiTN"), dPhi, t); mHistManager.fill(HIST("clusterTM_dRTN"), std::sqrt(dPhi * dPhi + dEta * dEta), t); - mHistManager.fill(HIST("clusterTM_EoverP_E"), cluster.energy() / abs_p, cluster.energy(), t); + mHistManager.fill(HIST("clusterTM_EoverP_E"), eOverP, cluster.energy(), t); mHistManager.fill(HIST("clusterTM_dEtadPhi"), dEta, dPhi, t); mHistManager.fill(HIST("clusterEMatched"), cluster.energy(), t); mHistManager.fill(HIST("clusterTM_dEtaPt"), dEta, pT, t); mHistManager.fill(HIST("clusterTM_EvsP"), cluster.energy(), abs_p, t); - mHistManager.fill(HIST("clusterTM_EoverP_Pt"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_Pt"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma"), NSigmaEl, match.track_as().pt(), t); + if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { + mHistManager.fill(HIST("clusterTM_NSigma_cut"), NSigmaEl, match.track_as().pt(), t); + } // A- and C-side if (match.track_as().eta() > 0.0) { mHistManager.fill(HIST("clusterTM_dEtadPhi_ASide"), dEta, dPhi, t); @@ -310,43 +335,51 @@ struct TrackMatchingMonitor { mHistManager.fill(HIST("clusterTM_NegdEtadPhi_0_75leqPl1_25"), dEta, dPhi, t); } } - if (tpcNsigmaElectron->at(0) <= match.track_as().tpcNSigmaEl() && match.track_as().tpcNSigmaEl() <= tpcNsigmaElectron->at(1)) { // E/p for e+/e- + if (tpcNsigmaElectron->at(0) <= NSigmaEl && NSigmaEl <= tpcNsigmaElectron->at(1)) { // E/p for e+/e- if (usePionRejection && (tpcNsigmaPion->at(0) <= match.track_as().tpcNSigmaPi() || match.track_as().tpcNSigmaPi() <= tpcNsigmaPion->at(1))) { // with pion rejection - mHistManager.fill(HIST("clusterTM_EoverP_ep"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), NSigmaEl, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), NSigmaEl, match.track_as().pt(), t); } if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_e"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e"), NSigmaEl, match.track_as().pt(), t); } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_p"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p"), NSigmaEl, match.track_as().pt(), t); } } else { // without pion rejection - mHistManager.fill(HIST("clusterTM_EoverP_ep"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), NSigmaEl, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), NSigmaEl, match.track_as().pt(), t); } if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_e"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e"), NSigmaEl, match.track_as().pt(), t); } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_p"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p"), NSigmaEl, match.track_as().pt(), t); } } - } else if (tpcNsigmaBack->at(0) <= match.track_as().tpcNSigmaEl() && match.track_as().tpcNSigmaEl() <= tpcNsigmaBack->at(1)) { // E/p for hadrons / background - mHistManager.fill(HIST("clusterTM_EoverP_hadron"), cluster.energy() / abs_p, match.track_as().pt(), t); + } else if (tpcNsigmaBack->at(0) <= NSigmaEl && NSigmaEl <= tpcNsigmaBack->at(1)) { // E/p for hadrons / background + mHistManager.fill(HIST("clusterTM_EoverP_hadron"), eOverP, match.track_as().pt(), t); if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_hadron_ASide"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_hadron_ASide"), eOverP, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_hadron_CSide"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_hadron_CSide"), eOverP, match.track_as().pt(), t); } if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_hn"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_hn"), eOverP, match.track_as().pt(), t); } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_hp"), cluster.energy() / abs_p, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_hp"), eOverP, match.track_as().pt(), t); } } if ((fabs(dEta) <= 0.01 + pow(match.track_as().pt() + 4.07, -2.5)) && @@ -418,6 +451,33 @@ struct TrackMatchingMonitor { } return result; } + + /// \brief Create binning for pT axis (variable bin size) + /// direct port from binning often used in AliPhysics for debugging + /// \return vector with bin limits + std::vector makePtBinning() const + { + std::vector result; + result.reserve(1000); + double epsilon = 1e-6; + double valGammaPt = 0; + for (int i = 0; i < 1000; ++i) { + result.push_back(valGammaPt); + if (valGammaPt < 1.0 - epsilon) + valGammaPt += 0.1; + else if (valGammaPt < 5 - epsilon) + valGammaPt += 0.2; + else if (valGammaPt < 10 - epsilon) + valGammaPt += 0.5; + else if (valGammaPt < 50 - epsilon) + valGammaPt += 1; + else if (valGammaPt < 100 - epsilon) + valGammaPt += 5; + else + break; + } + return result; + } }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetTutorial.cxx b/PWGJE/Tasks/jetTutorial.cxx index d033f1f92b4..ba0b1bfb8c8 100644 --- a/PWGJE/Tasks/jetTutorial.cxx +++ b/PWGJE/Tasks/jetTutorial.cxx @@ -197,8 +197,7 @@ struct JetTutorialTask { void processMCMatched(aod::Collision const& collision, MCDJetTable const& MCDjets, MCPJetTable const& MCPjets) { for (const auto& MCDjet : MCDjets) { - if (MCDjet.has_matchedJetGeo() && MCDjet.matchedJetGeoId() >= 0) { - const auto& MCPjet = MCDjet.matchedJetGeo_as(); + for (auto& MCPjet : MCDjet.matchedJetGeo_as()) { registry.fill(HIST("h_matched_jets_pt"), MCPjet.pt(), MCDjet.pt()); registry.fill(HIST("h_matched_jets_pt"), MCPjet.phi(), MCDjet.phi()); registry.fill(HIST("h_matched_jets_pt"), MCPjet.eta(), MCDjet.eta()); diff --git a/PWGJE/Tasks/jetfinderQA.cxx b/PWGJE/Tasks/jetfinderQA.cxx index bc295a66c13..af9d6e2d5e4 100644 --- a/PWGJE/Tasks/jetfinderQA.cxx +++ b/PWGJE/Tasks/jetfinderQA.cxx @@ -9,18 +9,15 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// jet finder hf QA task +// jet finder QA task // // Authors: Nima Zardoshti -#include - #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "TDatabasePDG.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" @@ -29,9 +26,6 @@ #include "Common/Core/RecoDecay.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - #include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" @@ -41,76 +35,23 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; #include "Framework/runDataProcessing.h" struct JetFinderQATask { - AxisSpec weightAxis = {{VARIABLE_WIDTH, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1.0, 10.0}, "weights"}; - HistogramRegistry registry{"registry", - {{"h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}, true}, - {"h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_jet_eta", ";#it{p}_{T,jet} (GeV/#it{c}); #eta_{jet}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_pt_jet_phi", ";#it{p}_{T,jet} (GeV/#it{c}); #phi_{jet}", {HistType::kTH2F, {{200, 0.0, 200}, {80, -1.0, 7.}}}, true}, - {"h2_jet_pt_jet_ntracks", ";#it{p}_{T,jet} (GeV/#it{c}); N_{jet tracks}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_r_jet_pt", ";#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{10, 0.05, 1.05}, {200, 0.0, 200}}}, true}, - {"h2_jet_r_jet_eta", ";#it{R}_{jet}; #eta_{jet}", {HistType::kTH2F, {{10, 0.05, 1.05}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_r_jet_phi", ";#it{R}_{jet}; #phi_{jet}", {HistType::kTH2F, {{10, 0.05, 1.05}, {80, -1.0, 7.}}}, true}, - {"h2_jet_r_jet_ntracks", ";#it{R}_{jet}; N_{jet tracks}", {HistType::kTH2F, {{10, 0.05, 1.05}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_track_pt", ";#it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200.0}}}, true}, - {"h2_jet_pt_track_eta", ";#it{p}_{T,jet} (GeV/#it{c}); #eta_{track}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_pt_track_phi", ";#it{p}_{T,jet} (GeV/#it{c}); #phi_{track}", {HistType::kTH2F, {{200, 0.0, 200}, {80, -1.0, 7.}}}, true}, - {"h2_jet_pt_leadingtrack_pt", ";#it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,leading track} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200.0}}}, true}, - {"h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}, true}, - {"h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_track_phi", "track #phi;#phi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}, true}, - {"h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_jet_phi_part", "jet #phi;#phi_{jet}^{part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_jet_ntracks_part", "jet N tracks;N_{jet tracks}^{part};entries", {HistType::kTH1F, {{100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_part_jet_eta_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #eta_{jet}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_pt_part_jet_phi_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #phi_{jet}", {HistType::kTH2F, {{200, 0.0, 200}, {80, -1.0, 7.}}}, true}, - {"h2_jet_pt_part_jet_ntracks_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); N_{jet tracks}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_r_part_jet_pt_part", ";#it{R}_{jet}^{part}; #it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{10, 0.05, 1.05}, {200, 0.0, 200}}}, true}, - {"h2_jet_r_part_jet_eta_part", ";#it{R}_{jet}^{part}; #eta_{jet}^{part}", {HistType::kTH2F, {{10, 0.05, 1.05}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_r_part_jet_phi_part", ";#it{R}_{jet}^{part}; #phi_{jet}^{part}", {HistType::kTH2F, {{10, 0.05, 1.05}, {80, -1.0, 7.}}}, true}, - {"h2_jet_r_part_jet_ntracks_part", ";#it{R}_{jet}^{part}; N_{jet tracks}^{part}", {HistType::kTH2F, {{10, 0.05, 1.05}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_part_track_pt_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,track}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200.0}}}, true}, - {"h2_jet_pt_part_track_eta_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #eta_{track}^{part}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_pt_part_track_phi_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #phi_{track}^{part}", {HistType::kTH2F, {{200, 0.0, 200}, {80, -1.0, 7.}}}, true}, - {"h_track_pt_part", "track pT;#it{p}_{T,track}^{part} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}, true}, - {"h_track_eta_part", "track #eta;#eta_{track}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_track_phi_part", "track #phi;#phi_{track}^{part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h2_jet_pt_part_jet_pt", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200}}}, true}, - {"h2_jet_eta_part_jet_eta", ";#eta_{jet}^{part}; #eta_{jet}", {HistType::kTH2F, {{100, -1.0, 1.0}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_phi_part_jet_phi", ";#phi_{jet}^{part}; #phi_{jet}", {HistType::kTH2F, {{80, -1.0, 7.}, {80, -1.0, 7.}}}, true}, - {"h2_jet_ntracks_part_jet_ntracks", ";N_{jet tracks}^{part}; N_{jet tracks}", {HistType::kTH2F, {{100, -0.5, 99.5}, {100, -0.5, 99.5}}}, true}, - {"h3_jet_pt_part_jet_eta_part_jet_eta", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #eta_{jet}^{part}; #eta_{jet}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}, true}, - {"h3_jet_pt_part_jet_phi_part_jet_phi", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #phi_{jet}^{part}; #phi_{jet}", {HistType::kTH3F, {{200, 0.0, 200}, {80, -1.0, 7.}, {80, -1.0, 7.}}}, true}, - {"h3_jet_pt_part_jet_ntracks_part_jet_ntracks", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); N_{jet tracks}^{part}; N_{jet tracks}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -0.5, 99.5}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_part_jet_pt_diff", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); (#it{p}_{T,jet}^{part} (GeV/#it{c}) - #it{p}_{T,jet} (GeV/#it{c})) / #it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {1000, -5.0, 5.0}}}, true}, - {"h_collision_trigger_events", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}, true}, - {"h_track_pt_MB", "track pT for MB events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}, true}, - {"h_track_eta_MB", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_track_phi_MB", "track #phi for MB events;#phi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_track_pt_Triggered", "track pT for Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}, true}, - {"h_track_eta_Triggered", "track #eta for Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_track_phi_Triggered", "track #phi for Triggered events;#phi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_collision_eventweight_part", "event weight;event weight;entries", {HistType::kTH1F, {weightAxis}}}}}; - - Configurable triggeredJetsRadius{"triggeredJetsRadius", 0.6, "resolution parameter for triggered jets"}; + HistogramRegistry registry; + + Configurable selectedJetsRadius{"selectedJetsRadius", 0.4, "resolution parameter for histograms without radius"}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; - Configurable> jetRadii{"jetRadii", std::vector{0.2, 0.3, 0.4, 0.5, 0.6}, "jet resolution parameters"}; + Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum eta acceptance for tracks"}; Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum eta acceptance for tracks"}; Configurable trackPtMin{"trackPtMin", 0.15, "minimum pT acceptance for tracks"}; Configurable trackPtMax{"trackPtMax", 100.0, "maximum pT acceptance for tracks"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; std::string trackSelection; - std::vector minJetPt; + std::vector filledJetR; std::vector jetRadiiValues; void init(o2::framework::InitContext&) @@ -118,8 +59,8 @@ struct JetFinderQATask { trackSelection = static_cast(trackSelections); jetRadiiValues = (std::vector)jetRadii; - for (auto iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { - minJetPt.push_back(0.0); + for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { + filledJetR.push_back(0.0); } auto jetRadiiBins = (std::vector)jetRadii; if (jetRadiiBins.size() > 1) { @@ -127,22 +68,78 @@ struct JetFinderQATask { } else { jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); } - registry.add("h3_jet_radius_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#phi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#phi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#phi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#phi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#phi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#phi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {2, 0.0, 2.0}}}); - registry.add("h3_jet_radius_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {2, 0.0, 2.0}}}); - registry.add("h3_jet_radius_jet_phi_collision", "#it{R}_{jet};#phi_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {80, -1.0, 7.}, {2, 0.0, 2.0}}}); - registry.add("h2_jet_radius_jet_pT_triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h3_jet_radius_jet_pt_track_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_radius_jet_pt_track_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_track_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_pt_track_pt_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_radius_jet_pt_track_eta_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_track_phi_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + + if (doprocessJetsData || doprocessJetsMCD || doprocessJetsMCDWeighted) { + registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_phi", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -0.5, 99.5}}}); + registry.add("h3_jet_r_jet_pt_track_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + } + + if (doprocessJetsMCP || doprocessJetsMCPWeighted) { + registry.add("h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_phi_part", "jet #varphi;#varphi_{jet}^{part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("h_jet_ntracks_part", "jet N tracks;N_{jet tracks}^{part};entries", {HistType::kTH1F, {{100, -0.5, 99.5}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_ntracks_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});N_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -0.5, 99.5}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet tracks}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + } + + if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWeighted) { + registry.add("h3_jet_r_jet_pt_part_jet_pt", "#it{R}_{jet};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_eta_part_jet_eta", "#it{R}_{jet};#eta_{jet}^{part};#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_phi_part_jet_phi", "#it{R}_{jet};#varphi_{jet}^{part};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_ntracks_part_jet_ntracks", "#it{R}_{jet};N_{jet tracks}^{part};N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -0.5, 99.5}, {100, -0.5, 99.5}}}); + registry.add("h3_jet_r_jet_pt_part_jet_pt_diff", "#it{R}_{jet};#it{p}_{T,jet}^{part} (GeV/#it{c}); (#it{p}_{T,jet}^{part} (GeV/#it{c}) - #it{p}_{T,jet} (GeV/#it{c})) / #it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_part_jet_eta_diff", "#it{R}_{jet};#it{p}_{T,jet}^{part} (GeV/#it{c}); (#eta_{jet}^{part} - #eta_{jet}) / #eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_part_jet_phi_diff", "#it{R}_{jet};#it{p}_{T,jet}^{part} (GeV/#it{c}); (#varphi_{jet}^{part} - #varphi_{jet}) / #varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_part_jet_eta_part_jet_eta", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #eta_{jet}^{part}; #eta_{jet}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_pt_part_jet_phi_part_jet_phi", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #varphi_{jet}^{part}; #varphi_{jet}", {HistType::kTH3F, {{200, 0.0, 200}, {80, -1.0, 7.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_pt_part_jet_ntracks_part_jet_ntracks", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); N_{jet tracks}^{part}; N_{jet tracks}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -0.5, 99.5}, {100, -0.5, 99.5}}}); + } + + if (doprocessTriggeredData) { + registry.add("h_collision_trigger_events", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h_track_pt_MB", "track pT for MB events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); + registry.add("h_track_eta_MB", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_phi_MB", "track #varphi for MB events;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("h_track_pt_Triggered", "track pT for Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); + registry.add("h_track_eta_Triggered", "track #eta for Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_phi_Triggered", "track #varphi for Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {2, -0.5, 1.5}}}); + registry.add("h3_jet_r_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {2, -0.5, 1.5}}}); + registry.add("h3_jet_r_jet_phi_collision", "#it{R}_{jet};#varphi_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {80, -1.0, 7.}, {2, -0.5, 1.5}}}); + registry.add("h2_jet_r_jet_pT_triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + } + if (doprocessTracks) { + registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_phi", "track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + } + + if (doprocessMCCollisionsWeighted) { + AxisSpec weightAxis = {{VARIABLE_WIDTH, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1.0, 10.0}, "weights"}; + registry.add("h_collision_eventweight_part", "event weight;event weight;entries", {HistType::kTH1F, {weightAxis}}); + } } using JetTracks = soa::Join; @@ -150,119 +147,92 @@ struct JetFinderQATask { template bool selectTrack(T const& track) { - if (trackSelection == "globalTracks" && !track.isGlobalTrackWoPtEta()) { - return false; - } - if (trackSelection == "globalTracks" && (track.pt() < trackPtMin || track.pt() >= trackPtMax || track.eta() < trackEtaMin || track.eta() >= trackEtaMax)) { - return false; + if (trackSelection == "globalTracks") { + if (track.pt() >= trackPtMin && track.pt() < trackPtMax && track.eta() >= trackEtaMin && track.eta() <= trackEtaMax) { + return track.isGlobalTrackWoPtEta(); + } else { + return false; + } } - if (trackSelection == "QualityTracks" && !track.isQualityTrack()) { - return false; + if (trackSelection == "QualityTracks") { + return track.isQualityTrack(); } - if (trackSelection == "hybridTracksJE" && !track.trackCutFlagFb5()) { // isQualityTrack - return false; + if (trackSelection == "hybridTracksJE") { // isQualityTrack + return track.trackCutFlagFb5(); } return true; } + template void fillHistograms(T const& jet, float weight = 1.0) { + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h_jet_pt"), jet.pt(), weight); + registry.fill(HIST("h_jet_eta"), jet.eta(), weight); + registry.fill(HIST("h_jet_phi"), jet.phi(), weight); + registry.fill(HIST("h_jet_ntracks"), jet.tracks().size(), weight); + } - registry.fill(HIST("h_jet_pt"), jet.pt(), weight); - registry.fill(HIST("h_jet_eta"), jet.eta(), weight); - registry.fill(HIST("h_jet_phi"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks"), jet.tracks().size(), weight); - - registry.fill(HIST("h2_jet_pt_jet_eta"), jet.pt(), jet.eta(), weight); - registry.fill(HIST("h2_jet_pt_jet_phi"), jet.pt(), jet.phi(), weight); - registry.fill(HIST("h2_jet_pt_jet_ntracks"), jet.pt(), jet.tracks().size(), weight); - - registry.fill(HIST("h2_jet_r_jet_pt"), jet.r() / 100.0, jet.pt(), weight); - registry.fill(HIST("h2_jet_r_jet_eta"), jet.r() / 100.0, jet.eta(), weight); - registry.fill(HIST("h2_jet_r_jet_phi"), jet.r() / 100.0, jet.phi(), weight); - registry.fill(HIST("h2_jet_r_jet_ntracks"), jet.r() / 100.0, jet.tracks().size(), weight); - - registry.fill(HIST("h3_jet_radius_jet_pt_jet_eta"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); - registry.fill(HIST("h3_jet_radius_jet_pt_jet_phi"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); - registry.fill(HIST("h3_jet_radius_jet_eta_jet_phi"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_eta"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_phi"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_eta_jet_phi"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks"), jet.r() / 100.0, jet.pt(), jet.tracks().size(), weight); for (auto& constituent : jet.template tracks_as()) { - registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), constituent.pt(), weight); - registry.fill(HIST("h2_jet_pt_track_eta"), jet.pt(), constituent.eta(), weight); - registry.fill(HIST("h2_jet_pt_track_phi"), jet.pt(), constituent.phi(), weight); - registry.fill(HIST("h_track_pt"), constituent.pt(), weight); - registry.fill(HIST("h_track_eta"), constituent.eta(), weight); - registry.fill(HIST("h_track_phi"), constituent.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_pt"), jet.r() / 100.0, jet.pt(), constituent.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_eta"), jet.r() / 100.0, jet.pt(), constituent.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_phi"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } } template void fillMCPHistograms(T const& jet, float weight = 1.0) { + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h_jet_pt_part"), jet.pt(), weight); + registry.fill(HIST("h_jet_eta_part"), jet.eta(), weight); + registry.fill(HIST("h_jet_phi_part"), jet.phi(), weight); + registry.fill(HIST("h_jet_ntracks_part"), jet.tracks().size(), weight); + } - registry.fill(HIST("h_jet_pt_part"), jet.pt(), weight); - registry.fill(HIST("h_jet_eta_part"), jet.eta(), weight); - registry.fill(HIST("h_jet_phi_part"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks_part"), jet.tracks().size(), weight); - - registry.fill(HIST("h2_jet_pt_part_jet_eta_part"), jet.pt(), jet.eta(), weight); - registry.fill(HIST("h2_jet_pt_part_jet_phi_part"), jet.pt(), jet.phi(), weight); - registry.fill(HIST("h2_jet_pt_part_jet_ntracks_part"), jet.pt(), jet.tracks().size(), weight); - - registry.fill(HIST("h2_jet_r_part_jet_pt_part"), jet.r() / 100.0, jet.pt(), weight); - registry.fill(HIST("h2_jet_r_part_jet_eta_part"), jet.r() / 100.0, jet.eta(), weight); - registry.fill(HIST("h2_jet_r_part_jet_phi_part"), jet.r() / 100.0, jet.phi(), weight); - registry.fill(HIST("h2_jet_r_part_jet_ntracks_part"), jet.r() / 100.0, jet.tracks().size(), weight); - - registry.fill(HIST("h3_jet_radius_part_jet_pt_part_jet_eta_part"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); - registry.fill(HIST("h3_jet_radius_part_jet_pt_part_jet_phi_part"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); - registry.fill(HIST("h3_jet_radius_part_jet_eta_part_jet_phi_part"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_eta_part"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_phi_part"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_eta_part_jet_phi_part"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_ntracks_part"), jet.r() / 100.0, jet.pt(), jet.tracks().size(), weight); for (auto& constituent : jet.template tracks_as()) { - registry.fill(HIST("h2_jet_pt_part_track_pt_part"), jet.pt(), constituent.pt(), weight); - registry.fill(HIST("h2_jet_pt_part_track_eta_part"), jet.pt(), constituent.eta(), weight); - registry.fill(HIST("h2_jet_pt_part_track_phi_part"), jet.pt(), constituent.phi(), weight); - registry.fill(HIST("h_track_pt_part"), constituent.pt(), weight); - registry.fill(HIST("h_track_eta_part"), constituent.eta(), weight); - registry.fill(HIST("h_track_phi_part"), constituent.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_pt_part"), jet.r() / 100.0, jet.pt(), constituent.pt(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_eta_part"), jet.r() / 100.0, jet.pt(), constituent.eta(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_phi_part"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } } - template + template void fillMCMatchedHistograms(T const& mcdjet, float weight = 1.0) { - - if (mcdjet.has_matchedJetGeo()) { - const auto& mcpjet = mcdjet.template matchedJetGeo_as>(); - - registry.fill(HIST("h2_jet_pt_part_jet_pt"), mcpjet.pt(), mcdjet.pt(), weight); - registry.fill(HIST("h2_jet_eta_part_jet_eta"), mcpjet.eta(), mcdjet.eta(), weight); - registry.fill(HIST("h2_jet_phi_part_jet_phi"), mcpjet.phi(), mcdjet.phi(), weight); - registry.fill(HIST("h2_jet_ntracks_part_jet_ntracks"), mcpjet.tracks().size(), mcdjet.tracks().size(), weight); - registry.fill(HIST("h3_jet_pt_part_jet_eta_part_jet_eta"), mcpjet.pt(), mcpjet.eta(), mcdjet.eta(), weight); - registry.fill(HIST("h3_jet_pt_part_jet_phi_part_jet_phi"), mcpjet.pt(), mcpjet.phi(), mcdjet.phi(), weight); - registry.fill(HIST("h3_jet_pt_part_jet_ntracks_part_jet_ntracks"), mcpjet.pt(), mcpjet.tracks().size(), mcdjet.tracks().size(), weight); - registry.fill(HIST("h2_jet_pt_part_jet_pt_diff"), mcpjet.pt(), (mcpjet.pt() - mcdjet.pt()) / mcpjet.pt(), weight); + for (auto& mcpjet : mcdjet.template matchedJetGeo_as>()) { + + registry.fill(HIST("h3_jet_r_jet_pt_part_jet_pt"), mcdjet.r() / 100.0, mcpjet.pt(), mcdjet.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_eta_part_jet_eta"), mcdjet.r() / 100.0, mcpjet.eta(), mcdjet.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_phi_part_jet_phi"), mcdjet.r() / 100.0, mcpjet.phi(), mcdjet.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_part_jet_ntracks"), mcdjet.r() / 100.0, mcpjet.tracks().size(), mcdjet.tracks().size(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_part_jet_pt_diff"), mcdjet.r() / 100.0, mcpjet.pt(), (mcpjet.pt() - mcdjet.pt()) / mcpjet.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_part_jet_eta_diff"), mcdjet.r() / 100.0, mcpjet.pt(), (mcpjet.eta() - mcdjet.eta()) / mcpjet.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_part_jet_phi_diff"), mcdjet.r() / 100.0, mcpjet.pt(), (mcpjet.phi() - mcdjet.phi()) / mcpjet.phi(), weight); + + if (mcdjet.r() == round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h3_jet_pt_part_jet_eta_part_jet_eta"), mcpjet.pt(), mcpjet.eta(), mcdjet.eta(), weight); + registry.fill(HIST("h3_jet_pt_part_jet_phi_part_jet_phi"), mcpjet.pt(), mcpjet.phi(), mcdjet.phi(), weight); + registry.fill(HIST("h3_jet_pt_part_jet_ntracks_part_jet_ntracks"), mcpjet.pt(), mcpjet.tracks().size(), mcdjet.tracks().size(), weight); + } } } - void processDummy(aod::Tracks const& track) {} - PROCESS_SWITCH(JetFinderQATask, processDummy, "Dummy process function turned on by default", true); - void processJetsData(soa::Join::iterator const& jet, JetTracks const& tracks) { fillHistograms(jet); - auto leadingTrackpT = -1.0; - for (auto const& track : tracks) { - if (!selectTrack(track)) { - continue; - } - if (track.pt() > leadingTrackpT) - leadingTrackpT = track.pt(); - } - registry.fill(HIST("h2_jet_pt_leadingtrack_pt"), jet.pt(), leadingTrackpT); } PROCESS_SWITCH(JetFinderQATask, processJetsData, "jet finder QA data", false); @@ -298,7 +268,7 @@ struct JetFinderQATask { JetTracks const& tracks, aod::McParticles const& particles) { for (const auto& mcdjet : mcdjets) { - fillMCMatchedHistograms(mcdjet); + fillMCMatchedHistograms::iterator, soa::Join>(mcdjet); } } PROCESS_SWITCH(JetFinderQATask, processJetsMCPMCDMatched, "jet finder QA matched mcp and mcd", false); @@ -309,7 +279,7 @@ struct JetFinderQATask { JetTracks const& tracks, aod::McParticles const& particles) { for (const auto& mcdjet : mcdjets) { - fillMCMatchedHistograms(mcdjet, mcdjet.eventWeight()); + fillMCMatchedHistograms::iterator, soa::Join>(mcdjet, mcdjet.eventWeight()); } } PROCESS_SWITCH(JetFinderQATask, processJetsMCPMCDMatchedWeighted, "jet finder QA matched mcp and mcd with weighted events", false); @@ -335,17 +305,15 @@ struct JetFinderQATask { if (collision.hasJetChHighPt() >= 1) registry.fill(HIST("h_collision_trigger_events"), 3.5); // events with triggered jets - for (auto iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { - minJetPt[iJetRadius] = 0.0; + for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { + filledJetR[iJetRadius] = false; } for (auto& jet : jets) { - for (auto iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { - if (jet.r() == round(jetRadiiValues[iJetRadius] * 100.0f)) { - for (double pt = jet.pt(); pt > minJetPt[iJetRadius]; pt -= 1.0) { - registry.fill(HIST("h2_jet_radius_jet_pT_triggered"), jet.r() / 100.0, pt); - } - if (jet.pt() > minJetPt[iJetRadius]) { - minJetPt[iJetRadius] = jet.pt(); + for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { + if (jet.r() == round(jetRadiiValues[iJetRadius] * 100.0f) && !filledJetR[iJetRadius]) { + filledJetR[iJetRadius] = true; + for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { + registry.fill(HIST("h2_jet_r_jet_pT_triggered"), jet.r() / 100.0, pt); } break; } @@ -354,18 +322,18 @@ struct JetFinderQATask { if ((jet.eta() < (trackEtaMin + jet.r() / 100.0)) || (jet.eta() > (trackEtaMax - jet.r() / 100.0))) { continue; } - registry.fill(HIST("h3_jet_radius_jet_pt_collision"), jet.r() / 100.0, jet.pt(), collision.hasJetChHighPt()); - registry.fill(HIST("h3_jet_radius_jet_eta_collision"), jet.r() / 100.0, jet.eta(), collision.hasJetChHighPt()); - registry.fill(HIST("h3_jet_radius_jet_phi_collision"), jet.r() / 100.0, jet.phi(), collision.hasJetChHighPt()); + registry.fill(HIST("h3_jet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), collision.hasJetChHighPt()); + registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), collision.hasJetChHighPt()); + registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), collision.hasJetChHighPt()); for (auto& constituent : jet.template tracks_as()) { - registry.fill(HIST("h3_jet_radius_jet_pt_track_pt_MB"), jet.r() / 100.0, jet.pt(), constituent.pt()); - registry.fill(HIST("h3_jet_radius_jet_pt_track_eta_MB"), jet.r() / 100.0, jet.pt(), constituent.eta()); - registry.fill(HIST("h3_jet_radius_jet_pt_track_phi_MB"), jet.r() / 100.0, jet.pt(), constituent.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_track_pt_MB"), jet.r() / 100.0, jet.pt(), constituent.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_track_eta_MB"), jet.r() / 100.0, jet.pt(), constituent.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_track_phi_MB"), jet.r() / 100.0, jet.pt(), constituent.phi()); if (collision.hasJetChHighPt() >= 1) { - registry.fill(HIST("h3_jet_radius_jet_pt_track_pt_Triggered"), jet.r() / 100.0, jet.pt(), constituent.pt()); - registry.fill(HIST("h3_jet_radius_jet_pt_track_eta_Triggered"), jet.r() / 100.0, jet.pt(), constituent.eta()); - registry.fill(HIST("h3_jet_radius_jet_pt_track_phi_Triggered"), jet.r() / 100.0, jet.pt(), constituent.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_track_pt_Triggered"), jet.r() / 100.0, jet.pt(), constituent.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_track_eta_Triggered"), jet.r() / 100.0, jet.pt(), constituent.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_track_phi_Triggered"), jet.r() / 100.0, jet.pt(), constituent.phi()); } } } @@ -384,8 +352,27 @@ struct JetFinderQATask { } } } - PROCESS_SWITCH(JetFinderQATask, processTriggeredData, "QA for charged jet trigger", false); + + void processTracks(soa::Join::iterator const& collision, + JetTracks const& tracks) + { + + registry.fill(HIST("h_collisions"), 0.5); + if (!collision.sel8()) { + return; + } + registry.fill(HIST("h_collisions"), 1.5); + for (auto const& track : tracks) { + if (!selectTrack(track)) { + continue; + } + registry.fill(HIST("h_track_pt"), track.pt()); + registry.fill(HIST("h_track_eta"), track.eta()); + registry.fill(HIST("h_track_phi"), track.phi()); + } + } + PROCESS_SWITCH(JetFinderQATask, processTracks, "QA for charged tracks", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-finder-qa"})}; } diff --git a/PWGJE/Tasks/jetfinderhfQA.cxx b/PWGJE/Tasks/jetfinderhfQA.cxx index ae2ad48f703..5315d8c3628 100644 --- a/PWGJE/Tasks/jetfinderhfQA.cxx +++ b/PWGJE/Tasks/jetfinderhfQA.cxx @@ -27,11 +27,10 @@ #include "Common/Core/RecoDecay.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" #include "EventFiltering/filterTables.h" @@ -39,90 +38,30 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; #include "Framework/runDataProcessing.h" +template struct JetFinderHFQATask { + HistogramRegistry registry; - AxisSpec weightAxis = {{VARIABLE_WIDTH, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1.0, 10.0}, "weights"}; - HistogramRegistry registry{"registry", - {{"h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}, true}, - {"h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_jet_phi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_jet_eta", ";#it{p}_{T,jet} (GeV/#it{c}); #eta_{jet}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_pt_jet_phi", ";#it{p}_{T,jet} (GeV/#it{c}); #phi_{jet}", {HistType::kTH2F, {{200, 0.0, 200}, {80, -1.0, 7.}}}, true}, - {"h2_jet_pt_jet_ntracks", ";#it{p}_{T,jet} (GeV/#it{c}); N_{jet tracks}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_r_jet_pt", ";#it{R}_{jet}; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{10, 0.05, 1.05}, {200, 0.0, 200}}}, true}, - {"h2_jet_r_jet_eta", ";#it{R}_{jet}; #eta_{jet}", {HistType::kTH2F, {{10, 0.05, 1.05}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_r_jet_phi", ";#it{R}_{jet}; #phi_{jet}", {HistType::kTH2F, {{10, 0.05, 1.05}, {80, -1.0, 7.}}}, true}, - {"h2_jet_r_jet_ntracks", ";#it{R}_{jet}; N_{jet tracks}", {HistType::kTH2F, {{10, 0.05, 1.05}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_track_pt", ";#it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200.0}}}, true}, - {"h2_jet_pt_track_eta", ";#it{p}_{T,jet} (GeV/#it{c}); #eta_{track}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_pt_track_phi", ";#it{p}_{T,jet} (GeV/#it{c}); #phi_{track}", {HistType::kTH2F, {{200, 0.0, 200}, {80, -1.0, 7.}}}, true}, - {"h2_jet_pt_leadingtrack_pt", ";#it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,leading track} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200.0}}}, true}, - {"h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}, true}, - {"h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_track_phi", "track #phi;#phi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_candidate_pt", "candidate pT;#it{p}_{T,candidate} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}}, - {"h_candidate_eta", "candidate #eta;#eta_{candidate};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"h_candidate_phi", "candidate #phi;#phi_{candidate};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, - {"h_candidate_y", "candidate y;y_{candidate};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"h2_jet_pt_candidate_pt", ";#it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200}}}}, - {"h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}, true}, - {"h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_jet_phi_part", "jet #phi;#phi_{jet}^{part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_jet_ntracks_part", "jet N tracks;N_{jet tracks}^{part};entries", {HistType::kTH1F, {{100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_part_jet_eta_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #eta_{jet}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_pt_part_jet_phi_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #phi_{jet}", {HistType::kTH2F, {{200, 0.0, 200}, {80, -1.0, 7.}}}, true}, - {"h2_jet_pt_part_jet_ntracks_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); N_{jet tracks}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_r_part_jet_pt_part", ";#it{R}_{jet}^{part}; #it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{10, 0.05, 1.05}, {200, 0.0, 200}}}, true}, - {"h2_jet_r_part_jet_eta_part", ";#it{R}_{jet}^{part}; #eta_{jet}^{part}", {HistType::kTH2F, {{10, 0.05, 1.05}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_r_part_jet_phi_part", ";#it{R}_{jet}^{part}; #phi_{jet}^{part}", {HistType::kTH2F, {{10, 0.05, 1.05}, {80, -1.0, 7.}}}, true}, - {"h2_jet_r_part_jet_ntracks_part", ";#it{R}_{jet}^{part}; N_{jet tracks}^{part}", {HistType::kTH2F, {{10, 0.05, 1.05}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_part_track_pt_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,track}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200.0}}}, true}, - {"h2_jet_pt_part_track_eta_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #eta_{track}^{part}", {HistType::kTH2F, {{200, 0.0, 200}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_pt_part_track_phi_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #phi_{track}^{part}", {HistType::kTH2F, {{200, 0.0, 200}, {80, -1.0, 7.}}}, true}, - {"h_track_pt_part", "track pT;#it{p}_{T,track}^{part} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}, true}, - {"h_track_eta_part", "track #eta;#eta_{track}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_track_phi_part", "track #phi;#phi_{track}^{part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_candidate_pt_part", "candidate pT;#it{p}_{T,candidate}^{part} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}}, - {"h_candidate_eta_part", "candidate #eta;#eta_{candidate}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"h_candidate_phi_part", "candidate #phi;#phi_{candidate}^{part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}}, - {"h_candidate_y_part", "candidate y;y_{candidate}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, - {"h2_jet_pt_part_candidate_pt_part", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,candidate}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200}}}}, - {"h2_jet_pt_part_jet_pt", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200}}}, true}, - {"h2_jet_eta_part_jet_eta", ";#eta_{jet}^{part}; #eta_{jet}", {HistType::kTH2F, {{100, -1.0, 1.0}, {100, -1.0, 1.0}}}, true}, - {"h2_jet_phi_part_jet_phi", ";#phi_{jet}^{part}; #phi_{jet}", {HistType::kTH2F, {{80, -1.0, 7.}, {80, -1.0, 7.}}}, true}, - {"h2_jet_ntracks_part_jet_ntracks", ";N_{jet tracks}^{part}; N_{jet tracks}", {HistType::kTH2F, {{100, -0.5, 99.5}, {100, -0.5, 99.5}}}, true}, - {"h2_candidate_pt_part_candidate_pt", ";#it{p}_{T,candidate}^{part} (GeV/#it{c}); #it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {200, 0.0, 200}}}}, - {"h2_candidate_eta_part_candidate_eta", ";#eta_{candidate}^{part}; #eta_{candidate}", {HistType::kTH2F, {{100, -1.0, 1.0}, {100, -1.0, 1.0}}}}, - {"h2_candidate_phi_part_candidate_phi", ";#phi_{candidate}^{part}; #phi_{candidate}", {HistType::kTH2F, {{80, -1.0, 7.}, {80, -1.0, 7.}}}}, - {"h2_candidate_y_part_candidate_y", ";#y_{candidate}^{part}; #y_{candidate}", {HistType::kTH2F, {{100, -1.0, 1.0}, {100, -1.0, 1.0}}}}, - {"h3_jet_pt_part_jet_eta_part_jet_eta", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #eta_{jet}^{part}; #eta_{jet}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}, true}, - {"h3_jet_pt_part_jet_phi_part_jet_phi", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #phi_{jet}^{part}; #phi_{jet}", {HistType::kTH3F, {{200, 0.0, 200}, {80, -1.0, 7.}, {80, -1.0, 7.}}}, true}, - {"h3_jet_pt_part_jet_ntracks_part_jet_ntracks", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); N_{jet tracks}^{part}; N_{jet tracks}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -0.5, 99.5}, {100, -0.5, 99.5}}}, true}, - {"h2_jet_pt_part_jet_pt_diff", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); (#it{p}_{T,jet}^{part} (GeV/#it{c}) - #it{p}_{T,jet} (GeV/#it{c})) / #it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0.0, 200}, {1000, -5.0, 5.0}}}, true}, - {"h_collision_trigger_events", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}, true}, - {"h_track_pt_MB", "track pT for MB events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}, true}, - {"h_track_eta_MB", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_track_phi_MB", "track #phi for MB events;#phi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_track_pt_Triggered", "track pT for Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}, true}, - {"h_track_eta_Triggered", "track #eta for Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}, true}, - {"h_track_phi_Triggered", "track #phi for Triggered events;#phi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}, true}, - {"h_collision_eventweight_part", "event weight;event weight;entries", {HistType::kTH1F, {weightAxis}}}}}; - - Configurable triggeredJetsRadius{"triggeredJetsRadius", 0.6, "resolution parameter for triggered jets"}; + Configurable selectedJetsRadius{"selectedJetsRadius", 0.4, "resolution parameter for histograms without radius"}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; - Configurable> jetRadii{"jetRadii", std::vector{0.2, 0.3, 0.4, 0.5, 0.6}, "jet resolution parameters"}; + Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; Configurable trackEtaMin{"trackEtaMin", -0.9, "minimum eta acceptance for tracks"}; Configurable trackEtaMax{"trackEtaMax", 0.9, "maximum eta acceptance for tracks"}; Configurable trackPtMin{"trackPtMin", 0.15, "minimum pT acceptance for tracks"}; Configurable trackPtMax{"trackPtMax", 100.0, "maximum pT acceptance for tracks"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; + Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; + Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; + Configurable selectionFlagLcToPKPi{"selectionFlagLcToPKPi", 1, "Selection Flag for Lc->PKPi"}; + Configurable selectionFlagLcToPiPK{"selectionFlagLcToPiPK", 1, "Selection Flag for Lc->PiPK"}; + Configurable selectionFlagBplus{"selectionFlagBplus", 1, "Selection Flag for B+"}; + + HfHelper hfHelper; std::string trackSelection; - std::vector minJetPt; + std::vector filledJetR; std::vector jetRadiiValues; void init(o2::framework::InitContext&) @@ -130,8 +69,8 @@ struct JetFinderHFQATask { trackSelection = static_cast(trackSelections); jetRadiiValues = (std::vector)jetRadii; - for (auto iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { - minJetPt.push_back(0.0); + for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { + filledJetR.push_back(0.0); } auto jetRadiiBins = (std::vector)jetRadii; if (jetRadiiBins.size() > 1) { @@ -139,210 +78,237 @@ struct JetFinderHFQATask { } else { jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); } - registry.add("h3_jet_radius_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#phi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#phi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#phi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#phi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#phi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#phi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {2, 0.0, 2.0}}}); - registry.add("h3_jet_radius_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {2, 0.0, 2.0}}}); - registry.add("h3_jet_radius_jet_phi_collision", "#it{R}_{jet};#phi_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {80, -1.0, 7.}, {2, 0.0, 2.0}}}); - registry.add("h2_jet_radius_jet_pT_triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); - registry.add("h3_jet_radius_jet_pt_track_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_radius_jet_pt_track_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_track_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_pt_track_pt_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_radius_jet_pt_track_eta_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_track_phi_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_pt_candidate_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_radius_jet_pt_candidate_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_candidate_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_pt_candidate_y_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_candidate_pt_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h3_jet_radius_jet_pt_candidate_eta_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); - registry.add("h3_jet_radius_jet_pt_candidate_phi_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); - registry.add("h3_jet_radius_jet_pt_candidate_y_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + + if (doprocessJetsData || doprocessJetsMCD || doprocessJetsMCDWeighted) { + registry.add("h_jet_pt", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_jet_eta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_phi", "jet #varphi;#varphi_{jet};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("h_jet_ntracks", "jet N tracks;N_{jet tracks};entries", {HistType::kTH1F, {{200, -0.5, 199.5}}}); + registry.add("h3_jet_r_jet_pt_jet_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_jet_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_eta_jet_phi", "#it{R}_{jet};#eta_{jet};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_jet_ntracks", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -0.5, 99.5}}}); + registry.add("h3_jet_r_jet_pt_track_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_leadingtrack_pt", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c}); #it{p}_{T,leading track} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200.0}, {200, 0.0, 200.0}}}); + registry.add("h3_candidate_invmass_jet_pt_candidate_pt", ";#it{m}_{inv, candidate} (GeV/#it{c}^{2}); #it{p}_{T,jet} (GeV/#it{c}) ;#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{500, 0.0, 5.0}, {200, 0.0, 200.0}, {200, 0.0, 200.0}}}); + registry.add("h3_candidatebar_invmass_jet_pt_candidate_pt", ";#it{m}_{inv, candidate bar} (GeV/#it{c}^{2}); #it{p}_{T,jet} (GeV/#it{c}) ;#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{500, 0.0, 5.0}, {200, 0.0, 200.0}, {200, 0.0, 200.0}}}); + } + + if (doprocessJetsMCP || doprocessJetsMCPWeighted) { + registry.add("h_jet_pt_part", "jet pT;#it{p}_{T,jet}^{part}(GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_jet_eta_part", "jet #eta;#eta_{jet}^{part};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_jet_phi_part", "jet #varphi;#varphi_{jet}^{part};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("h_jet_ntracks_part", "jet N tracks;N_{jet tracks}^{part};entries", {HistType::kTH1F, {{100, -0.5, 99.5}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_eta_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_phi_part", ";#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_eta_part_jet_phi_part", ";#it{R}_{jet}^{part};#eta_{jet}^{part};#varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_jet_ntracks_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});N_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -0.5, 99.5}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet tracks}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_track_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi_{jet tracks}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_candidate_pt_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,candidate}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_part_jet_pt_part_candidate_eta_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#eta_{candidate}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_part_jet_pt_part_candidate_phi_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});#varphi{candidate}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_part_jet_pt_part_candidate_y_part", "#it{R}_{jet}^{part};#it{p}_{T,jet}^{part} (GeV/#it{c});y_{candidate}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + } + + if (doprocessJetsMCPMCDMatched || doprocessJetsMCPMCDMatchedWeighted) { + registry.add("h3_jet_r_jet_pt_part_jet_pt", "#it{R}_{jet};#it{p}_{T,jet}^{part} (GeV/#it{c});#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_eta_part_jet_eta", "#it{R}_{jet};#eta_{jet}^{part};#eta_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_phi_part_jet_phi", "#it{R}_{jet};#varphi_{jet}^{part};#varphi_{jet}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_ntracks_part_jet_ntracks", "#it{R}_{jet};N_{jet tracks}^{part};N_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -0.5, 99.5}, {100, -0.5, 99.5}}}); + registry.add("h3_jet_r_candidate_pt_part_candidate_pt", "#it{R}_{jet};#it{p}_{T,candidate}^{part} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_candidate_eta_part_candidate_eta", "#it{R}_{jet};#eta_{candidate}^{part};#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_candidate_phi_part_candidate_phi", "#it{R}_{jet};#varphi_{candidate}^{part};#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_candidate_y_part_candidate_y", "#it{R}_{jet};#y_{candidate}^{part};#y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_part_jet_pt_diff", "#it{R}_{jet};#it{p}_{T,jet}^{part} (GeV/#it{c}); (#it{p}_{T,jet}^{part} (GeV/#it{c}) - #it{p}_{T,jet} (GeV/#it{c})) / #it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_part_jet_eta_diff", "#it{R}_{jet};#it{p}_{T,jet}^{part} (GeV/#it{c}); (#eta_{jet}^{part} - #eta_{jet}) / #eta_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_r_jet_pt_part_jet_phi_diff", "#it{R}_{jet};#it{p}_{T,jet}^{part} (GeV/#it{c}); (#varphi_{jet}^{part} - #varphi_{jet}) / #varphi_{jet}^{part}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0.0, 200}, {1000, -5.0, 5.0}}}); + registry.add("h3_jet_pt_part_jet_eta_part_jet_eta", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #eta_{jet}^{part}; #eta_{jet}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -1.0, 1.0}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_pt_part_jet_phi_part_jet_phi", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); #varphi_{jet}^{part}; #varphi_{jet}", {HistType::kTH3F, {{200, 0.0, 200}, {80, -1.0, 7.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_pt_part_jet_ntracks_part_jet_ntracks", ";#it{p}_{T,jet}^{part} (GeV/#it{c}); N_{jet tracks}^{part}; N_{jet tracks}", {HistType::kTH3F, {{200, 0.0, 200}, {100, -0.5, 99.5}, {100, -0.5, 99.5}}}); + } + + if (doprocessTriggeredData) { + registry.add("h_collision_trigger_events", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h_track_pt_MB", "track pT for MB events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); + registry.add("h_track_eta_MB", "track #eta for MB events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_phi_MB", "track #varphi for MB events;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("h_track_pt_Triggered", "track pT for Triggered events;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0.0, 200.0}}}); + registry.add("h_track_eta_Triggered", "track #eta for Triggered events;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_phi_Triggered", "track #varphi for Triggered events;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_collision", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {2, -0.5, 1.5}}}); + registry.add("h3_jet_r_jet_eta_collision", "#it{R}_{jet};#eta_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {100, -1.0, 1.0}, {2, -0.5, 1.5}}}); + registry.add("h3_jet_r_jet_phi_collision", "#it{R}_{jet};#varphi_{jet};collision trigger status", {HistType::kTH3F, {{jetRadiiBins, ""}, {80, -1.0, 7.}, {2, -0.5, 1.5}}}); + registry.add("h2_jet_r_jet_pT_triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{jetRadiiBins, ""}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_track_pt_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,jet tracks} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_track_eta_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_track_phi_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{jet tracks}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_MB", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_pt_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#it{p}_{T,candidate} (GeV/#it{c})", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h3_jet_r_jet_pt_candidate_eta_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#eta_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + registry.add("h3_jet_r_jet_pt_candidate_phi_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});#varphi_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {80, -1.0, 7.}}}); + registry.add("h3_jet_r_jet_pt_candidate_y_Triggered", "#it{R}_{jet};#it{p}_{T,jet} (GeV/#it{c});y_{candidate}", {HistType::kTH3F, {{jetRadiiBins, ""}, {200, 0., 200.}, {100, -1.0, 1.0}}}); + } + + if (doprocessTracks) { + registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h_track_pt", "track pT;#it{p}_{T,track} (GeV/#it{c});entries", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("h_track_eta", "track #eta;#eta_{track};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + registry.add("h_track_phi", "track #varphi;#varphi_{track};entries", {HistType::kTH1F, {{80, -1.0, 7.}}}); + } + + if (doprocessMCCollisionsWeighted) { + AxisSpec weightAxis = {{VARIABLE_WIDTH, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1.0, 10.0}, "weights"}; + registry.add("h_collision_eventweight_part", "event weight;event weight;entries", {HistType::kTH1F, {weightAxis}}); + } } using JetTracks = soa::Join; - using CandidateD0Data = soa::Join; - using CandidateD0MC = soa::Join; - using JetParticles2Prong = soa::Join; - using JetParticles3Prong = soa::Join; - using JetParticlesBplus = soa::Join; + using JetTableDataJoined = soa::Join; + using JetTableMCDJoined = soa::Join; + using JetTableMCDWeightedJoined = soa::Join; + using JetTableMCDMatchedJoined = soa::Join; + using JetTableMCDMatchedWeightedJoined = soa::Join; + using JetTableMCPJoined = soa::Join; + using JetTableMCPWeightedJoined = soa::Join; + using JetTableMCPMatchedJoined = soa::Join; + using JetTableMCPMatchedWeightedJoined = soa::Join; template bool selectTrack(T const& track) { - if (trackSelection == "globalTracks" && !track.isGlobalTrackWoPtEta()) { - return false; - } - if (trackSelection == "globalTracks" && (track.pt() < trackPtMin || track.pt() >= trackPtMax || track.eta() < trackEtaMin || track.eta() >= trackEtaMax)) { - return false; + if (trackSelection == "globalTracks") { + if (track.pt() >= trackPtMin && track.pt() < trackPtMax && track.eta() >= trackEtaMin && track.eta() <= trackEtaMax) { + return track.isGlobalTrackWoPtEta(); + } else { + return false; + } } - if (trackSelection == "QualityTracks" && !track.isQualityTrack()) { - return false; + if (trackSelection == "QualityTracks") { + return track.isQualityTrack(); } - if (trackSelection == "hybridTracksJE" && !track.trackCutFlagFb5()) { // isQualityTrack - return false; + if (trackSelection == "hybridTracksJE") { // isQualityTrack + return track.trackCutFlagFb5(); } return true; } - template - void fillDataHistograms(T const& jet, float weight = 1.0) + template + void fillHistograms(T const& jet, float weight = 1.0) { - - registry.fill(HIST("h_jet_pt"), jet.pt(), weight); - registry.fill(HIST("h_jet_eta"), jet.eta(), weight); - registry.fill(HIST("h_jet_phi"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks"), jet.tracks().size() + jet.hfcandidates().size(), weight); - - registry.fill(HIST("h2_jet_pt_jet_eta"), jet.pt(), jet.eta(), weight); - registry.fill(HIST("h2_jet_pt_jet_phi"), jet.pt(), jet.phi(), weight); - registry.fill(HIST("h2_jet_pt_jet_ntracks"), jet.pt(), jet.tracks().size() + jet.hfcandidates().size(), weight); - - registry.fill(HIST("h2_jet_r_jet_pt"), jet.r() / 100.0, jet.pt(), weight); - registry.fill(HIST("h2_jet_r_jet_eta"), jet.r() / 100.0, jet.eta(), weight); - registry.fill(HIST("h2_jet_r_jet_phi"), jet.r() / 100.0, jet.phi(), weight); - registry.fill(HIST("h2_jet_r_jet_ntracks"), jet.r() / 100.0, jet.tracks().size() + jet.hfcandidates().size(), weight); - - registry.fill(HIST("h3_jet_radius_jet_pt_jet_eta"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); - registry.fill(HIST("h3_jet_radius_jet_pt_jet_phi"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); - registry.fill(HIST("h3_jet_radius_jet_eta_jet_phi"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); - - for (auto& constituent : jet.template tracks_as()) { - - registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), constituent.pt(), weight); - registry.fill(HIST("h2_jet_pt_track_eta"), jet.pt(), constituent.eta(), weight); - registry.fill(HIST("h2_jet_pt_track_phi"), jet.pt(), constituent.phi(), weight); - registry.fill(HIST("h_track_pt"), constituent.pt(), weight); - registry.fill(HIST("h_track_eta"), constituent.eta(), weight); - registry.fill(HIST("h_track_phi"), constituent.phi(), weight); + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h_jet_pt"), jet.pt(), weight); + registry.fill(HIST("h_jet_eta"), jet.eta(), weight); + registry.fill(HIST("h_jet_phi"), jet.phi(), weight); + registry.fill(HIST("h_jet_ntracks"), jet.tracks().size() + jet.hfcandidates().size(), weight); } - for (auto& hfcandidate : jet.template hfcandidates_as()) { + registry.fill(HIST("h3_jet_r_jet_pt_jet_eta"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_phi"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_eta_jet_phi"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_jet_ntracks"), jet.r() / 100.0, jet.pt(), jet.tracks().size() + jet.hfcandidates().size(), weight); - registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h2_jet_pt_track_eta"), jet.pt(), hfcandidate.eta(), weight); - registry.fill(HIST("h2_jet_pt_track_phi"), jet.pt(), hfcandidate.phi(), weight); - registry.fill(HIST("h_track_pt"), hfcandidate.pt(), weight); - registry.fill(HIST("h_track_eta"), hfcandidate.eta(), weight); - registry.fill(HIST("h_track_phi"), hfcandidate.phi(), weight); + for (auto& constituent : jet.template tracks_as()) { - registry.fill(HIST("h_candidate_pt"), hfcandidate.pt(), weight); - registry.fill(HIST("h_candidate_eta"), hfcandidate.eta(), weight); - registry.fill(HIST("h_candidate_phi"), hfcandidate.phi(), weight); - registry.fill(HIST("h_candidate_y"), hfcandidate.y(RecoDecay::getMassPDG(421)), weight); - registry.fill(HIST("h2_jet_pt_candidate_pt"), jet.pt(), hfcandidate.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_pt"), jet.r() / 100.0, jet.pt(), constituent.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_eta"), jet.r() / 100.0, jet.pt(), constituent.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_phi"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } - } - - template - void fillMCDHistograms(T const& jet, float weight = 1.0) - { - - registry.fill(HIST("h_jet_pt"), jet.pt(), weight); - registry.fill(HIST("h_jet_eta"), jet.eta(), weight); - registry.fill(HIST("h_jet_phi"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks"), jet.tracks().size() + jet.hfcandidates().size(), weight); - registry.fill(HIST("h2_jet_pt_jet_eta"), jet.pt(), jet.eta(), weight); - registry.fill(HIST("h2_jet_pt_jet_phi"), jet.pt(), jet.phi(), weight); - registry.fill(HIST("h2_jet_pt_jet_ntracks"), jet.pt(), jet.tracks().size() + jet.hfcandidates().size(), weight); + for (auto& hfcandidate : jet.template hfcandidates_as>()) { - registry.fill(HIST("h2_jet_r_jet_pt"), jet.r() / 100.0, jet.pt(), weight); - registry.fill(HIST("h2_jet_r_jet_eta"), jet.r() / 100.0, jet.eta(), weight); - registry.fill(HIST("h2_jet_r_jet_phi"), jet.r() / 100.0, jet.phi(), weight); - registry.fill(HIST("h2_jet_r_jet_ntracks"), jet.r() / 100.0, jet.tracks().size() + jet.hfcandidates().size(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_pt"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_eta"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_track_phi"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); - registry.fill(HIST("h3_jet_radius_jet_pt_jet_eta"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); - registry.fill(HIST("h3_jet_radius_jet_pt_jet_phi"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); - registry.fill(HIST("h3_jet_radius_jet_eta_jet_phi"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y"), jet.r() / 100.0, jet.pt(), hfcandidate.y(RecoDecay::getMassPDG(421)), weight); - for (auto& constituent : jet.template tracks_as()) { - - registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), constituent.pt(), weight); - registry.fill(HIST("h2_jet_pt_track_eta"), jet.pt(), constituent.eta(), weight); - registry.fill(HIST("h2_jet_pt_track_phi"), jet.pt(), constituent.phi(), weight); - registry.fill(HIST("h_track_pt"), constituent.pt(), weight); - registry.fill(HIST("h_track_eta"), constituent.eta(), weight); - registry.fill(HIST("h_track_phi"), constituent.phi(), weight); - } - - for (auto& hfcandidate : jet.template hfcandidates_as()) { + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + if constexpr (std::is_same_v, soa::Join> || std::is_same_v, soa::Join>) { + if (hfcandidate.isSelD0() >= selectionFlagD0) { + registry.fill(HIST("h3_candidate_invmass_jet_pt_candidate_pt"), hfHelper.invMassD0ToPiK(hfcandidate), jet.pt(), hfcandidate.pt(), weight); + } + if (hfcandidate.isSelD0bar() >= selectionFlagD0bar) { + registry.fill(HIST("h3_candidatebar_invmass_jet_pt_candidate_pt"), hfHelper.invMassD0barToKPi(hfcandidate), jet.pt(), hfcandidate.pt(), weight); + } + } - registry.fill(HIST("h2_jet_pt_track_pt"), jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h2_jet_pt_track_eta"), jet.pt(), hfcandidate.eta(), weight); - registry.fill(HIST("h2_jet_pt_track_phi"), jet.pt(), hfcandidate.phi(), weight); - registry.fill(HIST("h_track_pt"), hfcandidate.pt(), weight); - registry.fill(HIST("h_track_eta"), hfcandidate.eta(), weight); - registry.fill(HIST("h_track_phi"), hfcandidate.phi(), weight); + if constexpr (std::is_same_v, soa::Join> || std::is_same_v, soa::Join>) { + if (hfcandidate.isSelLcToPKPi() >= selectionFlagLcToPKPi) { + registry.fill(HIST("h3_candidate_invmass_jet_pt_candidate_pt"), hfHelper.invMassLcToPKPi(hfcandidate), jet.pt(), hfcandidate.pt(), weight); + } + if (hfcandidate.isSelLcToPiKP() >= selectionFlagLcToPiPK) { + registry.fill(HIST("h3_candidatebar_invmass_jet_pt_candidate_pt"), hfHelper.invMassLcToPiKP(hfcandidate), jet.pt(), hfcandidate.pt(), weight); + } + } - registry.fill(HIST("h_candidate_pt"), hfcandidate.pt(), weight); - registry.fill(HIST("h_candidate_eta"), hfcandidate.eta(), weight); - registry.fill(HIST("h_candidate_phi"), hfcandidate.phi(), weight); - registry.fill(HIST("h_candidate_y"), hfcandidate.y(RecoDecay::getMassPDG(421)), weight); - registry.fill(HIST("h2_jet_pt_candidate_pt"), jet.pt(), hfcandidate.pt(), weight); + if constexpr (std::is_same_v, soa::Join> || std::is_same_v, soa::Join>) { + if (hfcandidate.isSelBplusToD0Pi() >= selectionFlagBplus) { + registry.fill(HIST("h3_candidate_invmass_jet_pt_candidate_pt"), hfHelper.invMassBplusToD0Pi(hfcandidate), jet.pt(), hfcandidate.pt(), weight); + registry.fill(HIST("h3_candidatebar_invmass_jet_pt_candidate_pt"), hfHelper.invMassBplusToD0Pi(hfcandidate), jet.pt(), hfcandidate.pt(), weight); + } + } + } } } - template + template void fillMCPHistograms(T const& jet, float weight = 1.0) { + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h_jet_pt_part"), jet.pt(), weight); + registry.fill(HIST("h_jet_eta_part"), jet.eta(), weight); + registry.fill(HIST("h_jet_phi_part"), jet.phi(), weight); + registry.fill(HIST("h_jet_ntracks_part"), jet.tracks().size() + jet.hfcandidates().size(), weight); + } - registry.fill(HIST("h_jet_pt_part"), jet.pt(), weight); - registry.fill(HIST("h_jet_eta_part"), jet.eta(), weight); - registry.fill(HIST("h_jet_phi_part"), jet.phi(), weight); - registry.fill(HIST("h_jet_ntracks_part"), jet.tracks().size() + jet.hfcandidates().size(), weight); - - registry.fill(HIST("h2_jet_pt_part_jet_eta_part"), jet.pt(), jet.eta(), weight); - registry.fill(HIST("h2_jet_pt_part_jet_phi_part"), jet.pt(), jet.phi(), weight); - registry.fill(HIST("h2_jet_pt_part_jet_ntracks_part"), jet.pt(), jet.tracks().size() + jet.hfcandidates().size(), weight); - - registry.fill(HIST("h2_jet_r_part_jet_pt_part"), jet.r() / 100.0, jet.pt(), weight); - registry.fill(HIST("h2_jet_r_part_jet_eta_part"), jet.r() / 100.0, jet.eta(), weight); - registry.fill(HIST("h2_jet_r_part_jet_phi_part"), jet.r() / 100.0, jet.phi(), weight); - registry.fill(HIST("h2_jet_r_part_jet_ntracks_part"), jet.r() / 100.0, jet.tracks().size() + jet.hfcandidates().size(), weight); - - registry.fill(HIST("h3_jet_radius_part_jet_pt_part_jet_eta_part"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); - registry.fill(HIST("h3_jet_radius_part_jet_pt_part_jet_phi_part"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); - registry.fill(HIST("h3_jet_radius_part_jet_eta_part_jet_phi_part"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_eta_part"), jet.r() / 100.0, jet.pt(), jet.eta(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_phi_part"), jet.r() / 100.0, jet.pt(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_eta_part_jet_phi_part"), jet.r() / 100.0, jet.eta(), jet.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_jet_ntracks_part"), jet.r() / 100.0, jet.pt(), jet.tracks().size() + jet.hfcandidates().size(), weight); - for (auto& constituent : jet.template tracks_as()) { + for (auto& constituent : jet.template tracks_as>()) { - registry.fill(HIST("h2_jet_pt_part_track_pt_part"), jet.pt(), constituent.pt(), weight); - registry.fill(HIST("h2_jet_pt_part_track_eta_part"), jet.pt(), constituent.eta(), weight); - registry.fill(HIST("h2_jet_pt_part_track_phi_part"), jet.pt(), constituent.phi(), weight); - registry.fill(HIST("h_track_pt_part"), constituent.pt(), weight); - registry.fill(HIST("h_track_eta_part"), constituent.eta(), weight); - registry.fill(HIST("h_track_phi_part"), constituent.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_pt_part"), jet.r() / 100.0, jet.pt(), constituent.pt(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_eta_part"), jet.r() / 100.0, jet.pt(), constituent.eta(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_phi_part"), jet.r() / 100.0, jet.pt(), constituent.phi(), weight); } - for (auto& hfcandidate : jet.template hfcandidates_as()) { + for (auto& hfcandidate : jet.template hfcandidates_as>()) { - registry.fill(HIST("h2_jet_pt_part_track_pt_part"), jet.pt(), hfcandidate.pt(), weight); - registry.fill(HIST("h2_jet_pt_part_track_eta_part"), jet.pt(), hfcandidate.eta(), weight); - registry.fill(HIST("h2_jet_pt_part_track_phi_part"), jet.pt(), hfcandidate.phi(), weight); - registry.fill(HIST("h_track_pt_part"), hfcandidate.pt(), weight); - registry.fill(HIST("h_track_eta_part"), hfcandidate.eta(), weight); - registry.fill(HIST("h_track_phi_part"), hfcandidate.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_pt_part"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_eta_part"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_track_phi_part"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); - registry.fill(HIST("h_candidate_pt_part"), hfcandidate.pt(), weight); - registry.fill(HIST("h_candidate_eta_part"), hfcandidate.eta(), weight); - registry.fill(HIST("h_candidate_phi_part"), hfcandidate.phi(), weight); - registry.fill(HIST("h_candidate_y_part"), hfcandidate.y(), weight); - registry.fill(HIST("h2_jet_pt_part_candidate_pt_part"), jet.pt(), hfcandidate.pt(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_pt_part"), jet.r() / 100.0, jet.pt(), hfcandidate.pt(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_eta_part"), jet.r() / 100.0, jet.pt(), hfcandidate.eta(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_phi_part"), jet.r() / 100.0, jet.pt(), hfcandidate.phi(), weight); + registry.fill(HIST("h3_jet_r_part_jet_pt_part_candidate_y_part"), jet.r() / 100.0, jet.pt(), hfcandidate.y(), weight); } } - template + template void fillMCMatchedHistograms(T const& mcdjet, float weight = 1.0) { - if (mcdjet.has_matchedJetCand() && mcdjet.matchedJetCandId() >= 0) { - const auto& mcpjet = mcdjet.template matchedJetCand_as>(); - + // if (mcdjet.has_matchedJetCand() && mcdjet.matchedJetCandId() >= 0) {old version + // const auto& mcpjet = mcdjet.template matchedJetCand_as>();old version + for (auto& mcpjet : mcdjet.template matchedJetCand_as>()) { auto mcdCandPt = 0.0; auto mcdCandPhi = 0.0; auto mcdCandEta = 0.0; @@ -351,7 +317,7 @@ struct JetFinderHFQATask { auto mcpCandPhi = 0.0; auto mcpCandEta = 0.0; auto mcpCandY = 0.0; - for (auto& hfcandidate_mcd : mcdjet.template hfcandidates_as()) { + for (auto& hfcandidate_mcd : mcdjet.template hfcandidates_as>()) { mcdCandPt = hfcandidate_mcd.pt(); mcdCandPhi = hfcandidate_mcd.phi(); @@ -359,7 +325,7 @@ struct JetFinderHFQATask { mcdCandY = hfcandidate_mcd.y(RecoDecay::getMassPDG(421)); } - for (auto& hfcandidate_mcp : mcpjet.template hfcandidates_as()) { + for (auto& hfcandidate_mcp : mcpjet.template hfcandidates_as>()) { mcpCandPt = hfcandidate_mcp.pt(); mcpCandPhi = hfcandidate_mcp.phi(); @@ -367,88 +333,85 @@ struct JetFinderHFQATask { mcpCandY = hfcandidate_mcp.y(); } - registry.fill(HIST("h2_jet_pt_part_jet_pt"), mcpjet.pt(), mcdjet.pt(), weight); - registry.fill(HIST("h2_jet_eta_part_jet_eta"), mcpjet.eta(), mcdjet.eta(), weight); - registry.fill(HIST("h2_jet_phi_part_jet_phi"), mcpjet.phi(), mcdjet.phi(), weight); - registry.fill(HIST("h2_jet_ntracks_part_jet_ntracks"), mcpjet.tracks().size() + mcpjet.hfcandidates().size(), mcdjet.tracks().size() + mcdjet.hfcandidates().size(), weight); - registry.fill(HIST("h2_candidate_pt_part_candidate_pt"), mcpCandPt, mcdCandPt, weight); - registry.fill(HIST("h2_candidate_eta_part_candidate_eta"), mcpCandEta, mcdCandEta, weight); - registry.fill(HIST("h2_candidate_phi_part_candidate_phi"), mcpCandPhi, mcdCandPhi, weight); - registry.fill(HIST("h2_candidate_y_part_candidate_y"), mcpCandY, mcdCandY, weight); - registry.fill(HIST("h3_jet_pt_part_jet_eta_part_jet_eta"), mcpjet.pt(), mcpjet.eta(), mcdjet.eta(), weight); - registry.fill(HIST("h3_jet_pt_part_jet_phi_part_jet_phi"), mcpjet.pt(), mcpjet.phi(), mcdjet.phi(), weight); - registry.fill(HIST("h3_jet_pt_part_jet_ntracks_part_jet_ntracks"), mcpjet.pt(), mcpjet.tracks().size() + mcpjet.hfcandidates().size(), mcdjet.tracks().size() + mcdjet.hfcandidates().size(), weight); - registry.fill(HIST("h2_jet_pt_part_jet_pt_diff"), mcpjet.pt(), (mcpjet.pt() - mcdjet.pt()) / mcpjet.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_part_jet_pt"), mcdjet.r() / 100.0, mcpjet.pt(), mcdjet.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_eta_part_jet_eta"), mcdjet.r() / 100.0, mcpjet.eta(), mcdjet.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_phi_part_jet_phi"), mcdjet.r() / 100.0, mcpjet.phi(), mcdjet.phi(), weight); + registry.fill(HIST("h3_jet_r_jet_ntracks_part_jet_ntracks"), mcdjet.r() / 100.0, mcpjet.tracks().size() + mcpjet.hfcandidates().size(), mcdjet.tracks().size() + mcdjet.hfcandidates().size(), weight); + registry.fill(HIST("h3_jet_r_candidate_pt_part_candidate_pt"), mcdjet.r() / 100.0, mcpCandPt, mcdCandPt, weight); + registry.fill(HIST("h3_jet_r_candidate_eta_part_candidate_eta"), mcdjet.r() / 100.0, mcpCandEta, mcdCandEta, weight); + registry.fill(HIST("h3_jet_r_candidate_phi_part_candidate_phi"), mcdjet.r() / 100.0, mcpCandPhi, mcdCandPhi, weight); + registry.fill(HIST("h3_jet_r_candidate_y_part_candidate_y"), mcdjet.r() / 100.0, mcpCandY, mcdCandY, weight); + registry.fill(HIST("h3_jet_r_jet_pt_part_jet_pt_diff"), mcdjet.r() / 100.0, mcpjet.pt(), (mcpjet.pt() - mcdjet.pt()) / mcpjet.pt(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_part_jet_eta_diff"), mcdjet.r() / 100.0, mcpjet.pt(), (mcpjet.eta() - mcdjet.eta()) / mcpjet.eta(), weight); + registry.fill(HIST("h3_jet_r_jet_pt_part_jet_phi_diff"), mcdjet.r() / 100.0, mcpjet.pt(), (mcpjet.phi() - mcdjet.phi()) / mcpjet.phi(), weight); + + if (mcdjet.r() == round(selectedJetsRadius * 100.0f)) { + registry.fill(HIST("h3_jet_pt_part_jet_eta_part_jet_eta"), mcpjet.pt(), mcpjet.eta(), mcdjet.eta(), weight); + registry.fill(HIST("h3_jet_pt_part_jet_phi_part_jet_phi"), mcpjet.pt(), mcpjet.phi(), mcdjet.phi(), weight); + registry.fill(HIST("h3_jet_pt_part_jet_ntracks_part_jet_ntracks"), mcpjet.pt(), mcpjet.tracks().size() + mcpjet.hfcandidates().size(), mcdjet.tracks().size() + mcdjet.hfcandidates().size(), weight); + } } } - void processDummy(aod::Tracks const& track) {} - PROCESS_SWITCH(JetFinderHFQATask, processDummy, "Dummy process function turned on by default", true); - - void processJetsData(soa::Join::iterator const& jet, CandidateD0Data const& candidates, JetTracks const& tracks) + void processDummy(aod::Collisions const& collision) { + } + PROCESS_SWITCH(JetFinderHFQATask, processDummy, "dummy task", true); - fillDataHistograms(jet); - auto leadingTrackpT = -1.0; - for (auto const& track : tracks) { - if (!selectTrack(track)) { - continue; - } - if (track.pt() > leadingTrackpT) - leadingTrackpT = track.pt(); - } - registry.fill(HIST("h2_jet_pt_leadingtrack_pt"), jet.pt(), leadingTrackpT); + void processJetsData(typename JetTableDataJoined::iterator const& jet, CandidateTableData const& candidates, JetTracks const& tracks) + { + fillHistograms(jet); } PROCESS_SWITCH(JetFinderHFQATask, processJetsData, "jet finder HF QA data", false); - void processJetsMCD(soa::Join::iterator const& jet, CandidateD0MC const& candidates, JetTracks const& tracks) + void processJetsMCD(typename JetTableMCDJoined::iterator const& jet, CandidateTableMCD const& candidates, JetTracks const& tracks) { - fillMCDHistograms(jet); + fillHistograms(jet); } PROCESS_SWITCH(JetFinderHFQATask, processJetsMCD, "jet finder HF QA mcd", false); - void processJetsMCDWeighted(soa::Join::iterator const& jet, CandidateD0MC const& candidates, JetTracks const& tracks) + void processJetsMCDWeighted(typename JetTableMCDWeightedJoined::iterator const& jet, CandidateTableMCD const& candidates, JetTracks const& tracks) { - fillMCDHistograms(jet, jet.eventWeight()); + fillHistograms(jet, jet.eventWeight()); } PROCESS_SWITCH(JetFinderHFQATask, processJetsMCDWeighted, "jet finder HF QA mcd on weighted events", false); - void processJetsMCP(soa::Join::iterator const& jet, JetParticles2Prong const& particles) + void processJetsMCP(typename JetTableMCPJoined::iterator const& jet, ParticleTableMCP const& particles) { - fillMCPHistograms(jet); + fillMCPHistograms(jet); } PROCESS_SWITCH(JetFinderHFQATask, processJetsMCP, "jet finder HF QA mcp", false); - void processJetsMCPWeighted(soa::Join::iterator const& jet, JetParticles2Prong const& particles) + void processJetsMCPWeighted(typename JetTableMCDWeightedJoined::iterator const& jet, ParticleTableMCP const& particles) { - fillMCPHistograms(jet, jet.eventWeight()); + fillMCPHistograms(jet, jet.eventWeight()); } PROCESS_SWITCH(JetFinderHFQATask, processJetsMCPWeighted, "jet finder HF QA mcp on weighted events", false); void processJetsMCPMCDMatched(aod::Collisions::iterator const& collision, - soa::Join const& mcdjets, - soa::Join const& mcpjets, - CandidateD0MC const& candidates, - JetTracks const& tracks, JetParticles2Prong const& particles) + JetTableMCDMatchedJoined const& mcdjets, + JetTableMCPMatchedJoined const& mcpjets, + CandidateTableMCD const& candidates, + JetTracks const& tracks, ParticleTableMCP const& particles) { for (const auto& mcdjet : mcdjets) { - fillMCMatchedHistograms(mcdjet); + fillMCMatchedHistograms(mcdjet); } } PROCESS_SWITCH(JetFinderHFQATask, processJetsMCPMCDMatched, "jet finder HF QA matched mcp and mcd", false); void processJetsMCPMCDMatchedWeighted(aod::Collisions::iterator const& collision, - soa::Join const& mcdjets, - soa::Join const& mcpjets, - CandidateD0MC const& candidates, - JetTracks const& tracks, JetParticles2Prong const& particles) + JetTableMCDMatchedWeightedJoined const& mcdjets, + JetTableMCPMatchedWeightedJoined const& mcpjets, + CandidateTableMCD const& candidates, + JetTracks const& tracks, ParticleTableMCP const& particles) { for (const auto& mcdjet : mcdjets) { - fillMCMatchedHistograms(mcdjet); + fillMCMatchedHistograms(mcdjet, mcdjet.eventWeight()); } } PROCESS_SWITCH(JetFinderHFQATask, processJetsMCPMCDMatchedWeighted, "jet finder HF QA matched mcp and mcd on weighted events", false); @@ -461,8 +424,8 @@ struct JetFinderHFQATask { PROCESS_SWITCH(JetFinderHFQATask, processMCCollisionsWeighted, "collision QA for weighted events", false); void processTriggeredData(soa::Join::iterator const& collision, - soa::Join const& jets, - CandidateD0Data const& candidates, + JetTableDataJoined const& jets, + CandidateTableData const& candidates, JetTracks const& tracks) { registry.fill(HIST("h_collision_trigger_events"), 0.5); // all events @@ -475,17 +438,15 @@ struct JetFinderHFQATask { if (collision.hasJetChHighPt() >= 1) registry.fill(HIST("h_collision_trigger_events"), 3.5); // events with triggered jets - for (auto iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { - minJetPt[iJetRadius] = 0.0; + for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { + filledJetR[iJetRadius] = false; } for (auto& jet : jets) { - for (auto iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { - if (jet.r() == round(jetRadiiValues[iJetRadius] * 100.0f)) { - for (double pt = jet.pt(); pt > minJetPt[iJetRadius]; pt -= 1.0) { - registry.fill(HIST("h2_jet_radius_jet_pT_triggered"), jet.r() / 100.0, pt); - } - if (jet.pt() > minJetPt[iJetRadius]) { - minJetPt[iJetRadius] = jet.pt(); + for (std::size_t iJetRadius = 0; iJetRadius < jetRadiiValues.size(); iJetRadius++) { + if (jet.r() == round(jetRadiiValues[iJetRadius] * 100.0f) && !filledJetR[iJetRadius]) { + filledJetR[iJetRadius] = true; + for (double pt = 0.0; pt <= jet.pt(); pt += 1.0) { + registry.fill(HIST("h2_jet_r_jet_pT_triggered"), jet.r() / 100.0, pt); } break; } @@ -494,31 +455,31 @@ struct JetFinderHFQATask { if ((jet.eta() < (trackEtaMin + jet.r() / 100.0)) || (jet.eta() > (trackEtaMax - jet.r() / 100.0))) { continue; } - registry.fill(HIST("h3_jet_radius_jet_pt_collision"), jet.r() / 100.0, jet.pt(), collision.hasJetChHighPt()); - registry.fill(HIST("h3_jet_radius_jet_eta_collision"), jet.r() / 100.0, jet.eta(), collision.hasJetChHighPt()); - registry.fill(HIST("h3_jet_radius_jet_phi_collision"), jet.r() / 100.0, jet.phi(), collision.hasJetChHighPt()); + registry.fill(HIST("h3_jet_r_jet_pt_collision"), jet.r() / 100.0, jet.pt(), collision.hasJetChHighPt()); + registry.fill(HIST("h3_jet_r_jet_eta_collision"), jet.r() / 100.0, jet.eta(), collision.hasJetChHighPt()); + registry.fill(HIST("h3_jet_r_jet_phi_collision"), jet.r() / 100.0, jet.phi(), collision.hasJetChHighPt()); for (auto& constituent : jet.template tracks_as()) { - registry.fill(HIST("h3_jet_radius_jet_pt_track_pt_MB"), jet.r() / 100.0, jet.pt(), constituent.pt()); - registry.fill(HIST("h3_jet_radius_jet_pt_track_eta_MB"), jet.r() / 100.0, jet.pt(), constituent.eta()); - registry.fill(HIST("h3_jet_radius_jet_pt_track_phi_MB"), jet.r() / 100.0, jet.pt(), constituent.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_track_pt_MB"), jet.r() / 100.0, jet.pt(), constituent.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_track_eta_MB"), jet.r() / 100.0, jet.pt(), constituent.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_track_phi_MB"), jet.r() / 100.0, jet.pt(), constituent.phi()); if (collision.hasJetChHighPt() >= 1) { - registry.fill(HIST("h3_jet_radius_jet_pt_track_pt_Triggered"), jet.r() / 100.0, jet.pt(), constituent.pt()); - registry.fill(HIST("h3_jet_radius_jet_pt_track_eta_Triggered"), jet.r() / 100.0, jet.pt(), constituent.eta()); - registry.fill(HIST("h3_jet_radius_jet_pt_track_phi_Triggered"), jet.r() / 100.0, jet.pt(), constituent.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_track_pt_Triggered"), jet.r() / 100.0, jet.pt(), constituent.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_track_eta_Triggered"), jet.r() / 100.0, jet.pt(), constituent.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_track_phi_Triggered"), jet.r() / 100.0, jet.pt(), constituent.phi()); } } - for (auto& hfcandidate : jet.template hfcandidates_as()) { + for (auto& hfcandidate : jet.template hfcandidates_as()) { - registry.fill(HIST("h3_jet_radius_jet_pt_candidate_pt_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_radius_jet_pt_candidate_eta_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_radius_jet_pt_candidate_phi_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_radius_jet_pt_candidate_y_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.y(RecoDecay::getMassPDG(421))); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_MB"), jet.r() / 100.0, jet.pt(), hfcandidate.y(RecoDecay::getMassPDG(421))); if (collision.hasJetChHighPt() >= 1) { - registry.fill(HIST("h3_jet_radius_jet_pt_candidate_pt_Triggered"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); - registry.fill(HIST("h3_jet_radius_jet_pt_candidate_eta_Triggered"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); - registry.fill(HIST("h3_jet_radius_jet_pt_candidate_phi_Triggered"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); - registry.fill(HIST("h3_jet_radius_jet_pt_candidate_y_Triggered"), jet.r() / 100.0, jet.pt(), hfcandidate.y(RecoDecay::getMassPDG(421))); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_pt_Triggered"), jet.r() / 100.0, jet.pt(), hfcandidate.pt()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_eta_Triggered"), jet.r() / 100.0, jet.pt(), hfcandidate.eta()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_phi_Triggered"), jet.r() / 100.0, jet.pt(), hfcandidate.phi()); + registry.fill(HIST("h3_jet_r_jet_pt_candidate_y_Triggered"), jet.r() / 100.0, jet.pt(), hfcandidate.y(RecoDecay::getMassPDG(421))); } } } @@ -539,6 +500,47 @@ struct JetFinderHFQATask { } PROCESS_SWITCH(JetFinderHFQATask, processTriggeredData, "QA for charged jet trigger", false); + + void processTracks(soa::Join::iterator const& collision, + JetTracks const& tracks) + { + + registry.fill(HIST("h_collisions"), 0.5); + if (!collision.sel8()) { + return; + } + registry.fill(HIST("h_collisions"), 1.5); + for (auto const& track : tracks) { + if (!selectTrack(track)) { + continue; + } + registry.fill(HIST("h_track_pt"), track.pt()); + registry.fill(HIST("h_track_eta"), track.eta()); + registry.fill(HIST("h_track_phi"), track.phi()); + } + } + PROCESS_SWITCH(JetFinderHFQATask, processTracks, "QA for charged tracks", false); }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"jet-finder-hf-qa"})}; } +using JetFinderD0QATask = JetFinderHFQATask, aod::D0ChargedMCDetectorLevelJets, aod::D0ChargedMCDetectorLevelJetConstituents, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCParticleLevelJets, aod::D0ChargedMCDetectorLevelJetEventWeights, soa::Join, aod::D0ChargedMCParticleLevelJets, aod::D0ChargedMCParticleLevelJetConstituents, aod::D0ChargedMCParticleLevelJetsMatchedToD0ChargedMCDetectorLevelJets, aod::D0ChargedMCParticleLevelJetEventWeights, soa::Join>; +using JetFinderLcQATask = JetFinderHFQATask, aod::LcChargedMCDetectorLevelJets, aod::LcChargedMCDetectorLevelJetConstituents, aod::LcChargedMCDetectorLevelJetsMatchedToLcChargedMCParticleLevelJets, aod::LcChargedMCDetectorLevelJetEventWeights, soa::Join, aod::LcChargedMCParticleLevelJets, aod::LcChargedMCParticleLevelJetConstituents, aod::LcChargedMCParticleLevelJetsMatchedToLcChargedMCDetectorLevelJets, aod::LcChargedMCParticleLevelJetEventWeights, soa::Join>; +using JetFinderBplusQATask = JetFinderHFQATask, aod::BplusChargedMCDetectorLevelJets, aod::BplusChargedMCDetectorLevelJetConstituents, aod::BplusChargedMCDetectorLevelJetsMatchedToBplusChargedMCParticleLevelJets, aod::BplusChargedMCDetectorLevelJetEventWeights, soa::Join, aod::BplusChargedMCParticleLevelJets, aod::BplusChargedMCParticleLevelJetConstituents, aod::BplusChargedMCParticleLevelJetsMatchedToBplusChargedMCDetectorLevelJets, aod::BplusChargedMCParticleLevelJetEventWeights, soa::Join>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-charged-d0-qa"})); + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-charged-bplus-qa"})); + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-charged-lc-qa"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/Tasks/jetfragmentation.cxx b/PWGJE/Tasks/jetfragmentation.cxx index 3426e1a367e..b19e8e64f81 100644 --- a/PWGJE/Tasks/jetfragmentation.cxx +++ b/PWGJE/Tasks/jetfragmentation.cxx @@ -34,63 +34,143 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using McTracks = soa::Join; +using McDJets = soa::Join; +// using MatchedMcDJets = soa::Filtered>; +using McPJets = soa::Join; + struct JetFragmentation { HistogramRegistry registry{"registry"}; std::vector pdgVector = {211, 321, 2212, 111, 130, 310, 311, 3122}; std::vector hadronVector = {"#pi^{#pm}", "#it{K}^{#pm}", "#it{p}^{#pm}", "#pi^{0}", "#it{K}^{0}_{L}", "#it{K}^{0}_{S}", "#it{K}^{0}", "#Lambda^{0}"}; + Configurable matchedDetJetEtaMin{"matchedDetJetEtaMin", -0.5, "minimum matchedDetJet eta"}; + Configurable matchedDetJetEtaMax{"matchedDetJetEtaMax", 0.5, "maximum matchedDetJet eta"}; + // Binning - ConfigurableAxis binJetPt{"binJetPt", {200, 0.f, 200.f}, ""}; - ConfigurableAxis binEta{"binEta", {100, -1.f, 1.f}, ""}; + ConfigurableAxis binJetPt{"binJetPt", {40, 0.f, 200.f}, ""}; + ConfigurableAxis binEta{"binEta", {20, -1.f, 1.f}, ""}; ConfigurableAxis binPhi{"binPhi", {18 * 8, 0.f, 2. * TMath::Pi()}, ""}; - ConfigurableAxis binZ{"binZ", {100, -5e-3f, 1.f + 5e-3f}, ""}; - ConfigurableAxis binPDG{"binPDG", {static_cast(pdgVector.size()), -0.5f, static_cast(pdgVector.size()) - 0.5f}, ""}; + ConfigurableAxis binZ{"binZ", {20, -5e-3f, 1.f + 5e-3f}, ""}; ConfigurableAxis binJetR{"binJetR", {6, 0.05f, 0.65f}, ""}; ConfigurableAxis binTrackPt{"binTrackPt", {200, 0.f, 100.f}, ""}; + ConfigurableAxis binPDG{"binPDG", {static_cast(pdgVector.size()), -0.5f, static_cast(pdgVector.size()) - 0.5f}, ""}; + ConfigurableAxis binVtxZ{"binVtxZ", {200, -20, 20}, ""}; + + ConfigurableAxis binDiff{"binDiff", {51, -5.5f, 5.5f}, ""}; + ConfigurableAxis binRatio{"binRatio", {100, -0.5f, 9.5f}, ""}; // Ratio of pt, eta, phi + ConfigurableAxis binMatchDist{"binMatchDist", {10, 0.f, 0.5f}, ""}; // Distance between matched jets ConfigurableAxis binCount{"binCount", {1, .5f, 1.5f}, ""}; ConfigurableAxis jetCount{"jetCount", {50, -.5f, 49.5f}, ""}; ConfigurableAxis trackCount{"trackCount", {100, -.5f, 99.5f}, ""}; + Preslice perMcPJet = aod::jet::mcCollisionId; + // Filter matchedDetJetFilter = (aod::chargedmcdetectorleveljets::eta >= matchedDetJetEtaMin && aod::chargedmcdetectorleveljets::eta <= matchedDetJetEtaMax); + void init(InitContext& initContext) { - // Axis - AxisSpec jetPtAxis = {binJetPt, "#it{p}_{T}^{jet}"}; + // Axes + AxisSpec jetPtAxis = {binJetPt, "#it{p}_{T}^{ jet}"}; // Data AxisSpec etaAxis = {binEta, "#eta"}; AxisSpec phiAxis = {binPhi, "#phi"}; AxisSpec zAxis = {binZ, "#it{z}"}; + AxisSpec detJetPtAxis = {binJetPt, "#it{p}_{T}^{ jet, det}"}; // MC detector level + AxisSpec detEtaAxis = {binEta, "#eta^{ jet, det}"}; + AxisSpec detPhiAxis = {binPhi, "#phi^{ jet, det}"}; + AxisSpec detZAxis = {binZ, "#it{z}^{ det}"}; + AxisSpec partJetPtAxis = {binJetPt, "#it{p}_{T}^{ jet, part}"}; // MC particle level + AxisSpec partEtaAxis = {binEta, "#eta^{ jet, part}"}; + AxisSpec partPhiAxis = {binPhi, "#phi^{ jet, part}"}; + AxisSpec partZAxis = {binZ, "#it{z}^{ part}"}; + AxisSpec pdgAxis = {binPDG, ""}; - AxisSpec rAxis = {binJetR, "#it{R}"}; AxisSpec trackPtAxis = {binTrackPt, "#it{p}_{T}^{tr}"}; + AxisSpec diffAxis = {binDiff, ""}; + AxisSpec ratioAxis = {binRatio, ""}; + AxisSpec vtxZAxis = {binVtxZ, "Collision vertex z (cm)"}; + AxisSpec matchDistAxis = {binMatchDist, "#Delta"}; // Data - registry.add("tracks/trackPtEtaPhi", "trackPtEtaPhi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); + registry.add("data/collision/collisionVtxZ", "Collision vertex z (cm)", HistType::kTH1F, {binVtxZ}); + + registry.add("data/tracks/trackPtEtaPhi", "trackPtEtaPhi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); - registry.add("jets/jetPtEtaPhi", "Jet #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {jetPtAxis, etaAxis, phiAxis}); - registry.add("jets/jetPtTrackPt", "Jet #it{p}_{T}, track #it{p}_{T};#it{p}_{T}^{jet};#it{p}_{T}^{track}", HistType::kTH2F, {jetPtAxis, trackPtAxis}); - registry.add("jets/jetTrackPtEtaPhi", "Tracks in jets #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); - registry.add("jets/jetPtTrackProj", "Jet #it{p}_{T}, #it{z}; #it{p}_{T}; #it{z}", HistType::kTH2F, {jetPtAxis, zAxis}); - registry.add("jets/jetPtFrag", "Jet #it{p}_{T}, #it{p}_{T,jet}/#it{p}_{T,tr}; #it{p}_{T}; #it{p}_{T,jet}/#it{p}_{T,tr}", HistType::kTH2F, {jetPtAxis, zAxis}); + registry.add("data/jets/jetPtEtaPhi", "Jet #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {jetPtAxis, etaAxis, phiAxis}); + registry.add("data/jets/jetPtTrackPt", "Jet #it{p}_{T}, track #it{p}_{T};#it{p}_{T}^{jet};#it{p}_{T}^{track}", HistType::kTH2F, {jetPtAxis, trackPtAxis}); + registry.add("data/jets/jetTrackPtEtaPhi", "Tracks in jets #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); + registry.add("data/jets/jetPtTrackProj", "Jet #it{p}_{T}, #it{z}; #it{p}_{T}; #it{z}", HistType::kTH2F, {jetPtAxis, zAxis}); + registry.add("data/jets/jetPtFrag", "Jet #it{p}_{T}, #it{p}_{T,jet}/#it{p}_{T,tr}; #it{p}_{T}; #it{p}_{T,jet}/#it{p}_{T,tr}", HistType::kTH2F, {jetPtAxis, zAxis}); // MC particle level - registry.add("tracks/partTrackPtEtaPhi", "partTrackPtEtaPhi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); + registry.add("particle-level/collision/partCollisionVtxZ", "Collision vertex z (cm)", HistType::kTH1F, {binVtxZ}); - registry.add("jets/partJetPtEtaPhi", "Particle level jet #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {jetPtAxis, etaAxis, phiAxis}); - registry.add("jets/partJetPtTrackPt", "Particle level jet #it{p}_{T}, track #it{p}_{T};#it{p}_{T}^{jet};#it{p}_{T}^{track}", HistType::kTH2F, {jetPtAxis, trackPtAxis}); - registry.add("jets/partJetTrackPtEtaPhi", "Particle level tracks in jets #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); - registry.add("jets/partJetPtTrackProj", "Particle level jet #it{p}_{T}, #it{z}; #it{p}_{T}; #it{z}", HistType::kTH2F, {jetPtAxis, zAxis}); - registry.add("jets/partJetPtFrag", "Particle level jet #it{p}_{T}, #it{p}_{T,jet}/#it{p}_{T,tr}; #it{p}_{T}; #it{p}_{T,jet}/#it{p}_{T,tr}", HistType::kTH2F, {jetPtAxis, zAxis}); + registry.add("particle-level/tracks/partTrackPtEtaPhi", "partTrackPtEtaPhi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); + + registry.add("particle-level/jets/partJetPtEtaPhi", "Particle level jet #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {partJetPtAxis, partEtaAxis, partPhiAxis}); + registry.add("particle-level/jets/partJetPtTrackPt", "Particle level jet #it{p}_{T}, track #it{p}_{T};#it{p}_{T}^{jet};#it{p}_{T}^{track}", HistType::kTH2F, {partJetPtAxis, trackPtAxis}); + registry.add("particle-level/jets/partJetTrackPtEtaPhi", "Particle level tracks in jets #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {trackPtAxis, partEtaAxis, partPhiAxis}); + registry.add("particle-level/jets/partJetPtTrackProj", "Particle level jet #it{p}_{T}, #it{z}; #it{p}_{T}; #it{z}", HistType::kTH2F, {partJetPtAxis, partZAxis}); + registry.add("particle-level/jets/partJetPtFrag", "Particle level jet #it{p}_{T}, #it{p}_{T,jet}/#it{p}_{T,tr}; #it{p}_{T}; #it{p}_{T,jet}/#it{p}_{T,tr}", HistType::kTH2F, {partJetPtAxis, partZAxis}); // MC detector level - registry.add("tracks/detTrackPtEtaPhi", "detTrackPtEtaPhi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); + registry.add("detector-level/collision/detCollisionVtxZ", "Collision vertex z (cm)", HistType::kTH1F, {binVtxZ}); + + registry.add("detector-level/tracks/detTrackPtEtaPhi", "detTrackPtEtaPhi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); + + registry.add("detector-level/jets/detJetPtEtaPhi", "Detector level jet #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {detJetPtAxis, detEtaAxis, detPhiAxis}); + registry.add("detector-level/jets/detJetPtTrackPt", "Detector level jet #it{p}_{T}, track #it{p}_{T};#it{p}_{T}^{jet};#it{p}_{T}^{track}", HistType::kTH2F, {detJetPtAxis, trackPtAxis}); + registry.add("detector-level/jets/detJetTrackPtEtaPhi", "Detector level tracks in jets #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {trackPtAxis, detEtaAxis, detPhiAxis}); + registry.add("detector-level/jets/detJetPtTrackProj", "Detector level jet #it{p}_{T}, #it{z}; #it{p}_{T}; #it{z}", HistType::kTH2F, {detJetPtAxis, detZAxis}); + registry.add("detector-level/jets/detJetPtFrag", "Detector level jet #it{p}_{T}, #it{p}_{T,jet}/#it{p}_{T,tr}; #it{p}_{T}; #it{p}_{T,jet}/#it{p}_{T,tr}", HistType::kTH2F, {detJetPtAxis, detZAxis}); + + // MC particle-detector level matching + registry.add("matching/collision/matchCollisionVtxZ", "Collision vertex z (cm)", HistType::kTH1F, {binVtxZ}); + + registry.add("matching/tracks/matchDetTrackPtEtaPhi", "matchDetTrackPtEtaPhi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); + registry.add("matching/tracks/matchPartTrackPtEtaPhi", "matchPartTrackPtEtaPhi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); + registry.add("matching/tracks/matchDetTrackPtPartTrackPt", "matchDetTrackPtPartTrackPt", HistType::kTH2F, {trackPtAxis, trackPtAxis}); + registry.add("matching/tracks/matchDetTrackEtaPartTrackEta", "matchDetTrackEtaPartTrackEta", HistType::kTH2F, {etaAxis, etaAxis}); + registry.add("matching/tracks/matchDetTrackPhiPartTrackPhi", "matchDetTrackPhiPartTrackPhi", HistType::kTH2F, {phiAxis, phiAxis}); + registry.add("matching/tracks/trackResolutionPt", "trackResolutionPt; #Delta #it{p}_{T}^{tr}", HistType::kTH2F, {trackPtAxis, diffAxis}); + registry.add("matching/tracks/trackResolutionEta", "trackResolutionEta; #Delta #eta", HistType::kTH2F, {etaAxis, diffAxis}); + registry.add("matching/tracks/trackResolutionPhi", "trackResolutionPhi; #Delta #phi", HistType::kTH2F, {phiAxis, diffAxis}); + + // Detector level jets with a match + registry.add("matching/jets/matchDetJetPtEtaPhi", "Matched detector level jet #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {detJetPtAxis, detEtaAxis, detPhiAxis}); + registry.add("matching/jets/matchDetJetPtTrackPt", "Matched detector level jet #it{p}_{T}, track #it{p}_{T};#it{p}_{T}^{jet};#it{p}_{T}^{track}", HistType::kTH2F, {detJetPtAxis, trackPtAxis}); + registry.add("matching/jets/matchDetJetTrackPtEtaPhi", "Matched detector level tracks in jets #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {trackPtAxis, detEtaAxis, detPhiAxis}); + registry.add("matching/jets/matchDetJetPtTrackProj", "Matched detector level jet #it{p}_{T}, #it{z}; #it{p}_{T}; #it{z}", HistType::kTH2F, {detJetPtAxis, detZAxis}); + registry.add("matching/jets/matchDetJetPtFrag", "Matched detector level jet #it{p}_{T}, #it{p}_{T,jet}/#it{p}_{T,tr}; #it{p}_{T}; #it{p}_{T,jet}/#it{p}_{T,tr}", HistType::kTH2F, {detJetPtAxis, detZAxis}); + // Particle level jets with a match + registry.add("matching/jets/matchPartJetPtEtaPhi", "Matched particle level jet #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {partJetPtAxis, partEtaAxis, partPhiAxis}); + registry.add("matching/jets/matchPartJetPtTrackPt", "Matched particle level jet #it{p}_{T}, track #it{p}_{T};#it{p}_{T}^{jet};#it{p}_{T}^{track}", HistType::kTH2F, {partJetPtAxis, trackPtAxis}); + registry.add("matching/jets/matchPartJetTrackPtEtaPhi", "Matched particle level tracks in jets #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {trackPtAxis, partEtaAxis, partPhiAxis}); + registry.add("matching/jets/matchPartJetPtTrackProj", "Matched particle level jet #it{p}_{T}, #it{z}; #it{p}_{T}; #it{z}", HistType::kTH2F, {partJetPtAxis, partZAxis}); + registry.add("matching/jets/matchPartJetPtFrag", "Matched particle level jet #it{p}_{T}, #it{p}_{T,jet}/#it{p}_{T,tr}; #it{p}_{T}; #it{p}_{T,jet}/#it{p}_{T,tr}", HistType::kTH2F, {partJetPtAxis, partZAxis}); + // Combined information of matched jets + registry.add("matching/jets/matchDetJetPtPartJetPt", "matchDetJetPtPartJetPt; #it{p}_{T}^{jet, det}; #it{p}_{T}^{jet, part}", HistType::kTH2F, {detJetPtAxis, partJetPtAxis}); + registry.add("matching/jets/matchPartJetPtDetJetEtaPartJetEta", "matchPartJetPtDetJetEtaPartJetEta; #it{p}_{T}^{jet, part}; #eta^{jet, det}; #eta^{jet, part}", HistType::kTH3F, {partJetPtAxis, detEtaAxis, partEtaAxis}); + registry.add("matching/jets/matchPartJetPtDetJetPhiPartJetPhi", "matchPartJetPtDetJetPhiPartJetPhi; #it{p}_{T}^{jet, part}; #phi^{jet, det}; #phi^{jet, part}", HistType::kTH3F, {partJetPtAxis, detPhiAxis, partPhiAxis}); + registry.add("matching/jets/matchPartJetPtResolutionPt", "#Delta = (#it{p}_{T}^{jet, part} - #it{p}_{T}^{jet, det}) / #it{p}_{T}^{jet, part}; #it{p}_{T}^{jet, part}; #Delta", HistType::kTH2F, {partJetPtAxis, diffAxis}); + registry.add("matching/jets/matchPartJetPtResolutionEta", "(#eta^{jet, part} - #eta^{jet, det}); #eta^{jet, part}; #Delta", HistType::kTH3F, {partJetPtAxis, partEtaAxis, diffAxis}); + registry.add("matching/jets/matchPartJetPtResolutionPhi", "(#phi^{jet, part} - #phi^{jet, det}); #phi^{jet, part}; #Delta", HistType::kTH3F, {partJetPtAxis, partPhiAxis, diffAxis}); + registry.add("matching/jets/matchPartJetPtResolutionTrackProj", "Resolution #it{p}^{proj, part} / #it{p}^{jet, part}", HistType::kTH3F, {partJetPtAxis, partZAxis, diffAxis}); + registry.add("matching/jets/matchPartJetPtResolutionChargeFrag", "Resolution #it{p}_{T}^{tr, part} / #it{p}_{T}^{jet, part}", HistType::kTH3F, {partJetPtAxis, partZAxis, diffAxis}); + registry.add("matching/jets/matchPartJetPtMatchDist", "matchJetMatchDist; #it{p}_{T}^{part}; #Delta", HistType::kTH2F, {partJetPtAxis, matchDistAxis}); + registry.add("matching/jets/matchPartJetPtEnergyScale", "jetEnergyScale; #it{p}_{T}^{part}; #it{p}_{T}^{part}/#it{p}_{T}^{det}", HistType::kTH2F, {partJetPtAxis, ratioAxis}); + + // Response matrix, fakes, misses + registry.add("matching/jets/matchDetJetPtTrackProjPartJetPtTrackProj", "Matched; #it{p}_{T}^{jet, det}; #it{p}^{proj, det} / #it{p}^{jet, det}; #it{p}_{T}^{jet, part}; #it{p}^{proj, part} / #it{p}^{jet, part}", HistType::kTHnSparseF, {detJetPtAxis, detZAxis, partJetPtAxis, partZAxis}); + registry.add("matching/jets/fakeDetJetPtTrackProj", "Fakes; #it{p}_{T}^{jet, det}; #it{p}^{proj, det} / #it{p}^{jet, det}", HistType::kTH2F, {detJetPtAxis, detZAxis}); + registry.add("matching/jets/missPartJetPtTrackProj", "Misses; #it{p}_{T}^{jet, part}; #it{p}^{proj, part} / #it{p}^{jet, part}", HistType::kTH2F, {partJetPtAxis, partZAxis}); - registry.add("jets/detJetPtEtaPhi", "Detector level jet #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {jetPtAxis, etaAxis, phiAxis}); - registry.add("jets/detJetPtTrackPt", "Detector level jet #it{p}_{T}, track #it{p}_{T};#it{p}_{T}^{jet};#it{p}_{T}^{track}", HistType::kTH2F, {jetPtAxis, trackPtAxis}); - registry.add("jets/detJetTrackPtEtaPhi", "Detector level tracks in jets #it{p}_{T}, #eta, #phi;#it{p}_{T};#eta;#phi", HistType::kTH3F, {trackPtAxis, etaAxis, phiAxis}); - registry.add("jets/detJetPtTrackProj", "Detector level jet #it{p}_{T}, #it{z}; #it{p}_{T}; #it{z}", HistType::kTH2F, {jetPtAxis, zAxis}); - registry.add("jets/detJetPtFrag", "Detector level jet #it{p}_{T}, #it{p}_{T,jet}/#it{p}_{T,tr}; #it{p}_{T}; #it{p}_{T,jet}/#it{p}_{T,tr}", HistType::kTH2F, {jetPtAxis, zAxis}); + registry.add("matching/jets/matchDetJetPtFragPartJetPtFrag", "Matched; #it{p}_{T}^{jet, det}; #it{p}_{T}^{det} / #it{p}_{T}^{jet, det}; #it{p}_{T}^{jet, part}; #it{p}_{T}^{part} / #it{p}_{T}^{jet, part}", HistType::kTHnSparseF, {detJetPtAxis, detZAxis, partJetPtAxis, partZAxis}); + registry.add("matching/jets/fakeDetJetPtFrag", "Fakes; #it{p}_{T}^{jet, det}; #it{p}_{T}^{det} / #it{p}_{T}^{jet, det}", HistType::kTH2F, {detJetPtAxis, detZAxis}); + registry.add("matching/jets/missPartJetPtFrag", "Misses; #it{p}_{T}^{jet, part}; #it{p}_{T}^{part} / #it{p}_{T}^{jet, part}", HistType::kTH2F, {partJetPtAxis, partZAxis}); + // Bookkeeping registry.add("partCount", "partCount", HistType::kTH1I, {binCount}); registry.add("detCount", "detCount", HistType::kTH1I, {binCount}); registry.add("datCount", "datCount", HistType::kTH1I, {binCount}); @@ -112,8 +192,8 @@ struct JetFragmentation { void processDummy(aod::Tracks const& track) {} PROCESS_SWITCH(JetFragmentation, processDummy, "Dummy process function turned on by default", true); - void processMCD(soa::Join::iterator const& collision, - soa::Join const& jets, + void processMcD(soa::Join::iterator const& collision, + McDJets const& jets, aod::Tracks const& tracks) { int nJets = -1, nTracks = -1; @@ -121,52 +201,54 @@ struct JetFragmentation { registry.fill(HIST("detnJetnTrack"), nJets, nTracks); for (const auto& track : tracks) { if (track.pt() > 0.1) { - registry.fill(HIST("tracks/detTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("detector-level/tracks/detTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); } } for (const auto& jet : jets) { - registry.fill(HIST("jets/detJetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + registry.fill(HIST("detector-level/jets/detJetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); for (const auto& track : jet.tracks_as()) { double chargeFrag = -1., trackProj = -1.; trackProj = track.px() * jet.px() + track.py() * jet.py() + track.pz() * jet.pz(); trackProj /= (jet.p() * jet.p()); chargeFrag = track.pt() / jet.pt(); - registry.fill(HIST("jets/detJetPtTrackPt"), jet.pt(), track.pt()); - registry.fill(HIST("jets/detJetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); - registry.fill(HIST("jets/detJetPtFrag"), jet.pt(), chargeFrag); - registry.fill(HIST("jets/detJetPtTrackProj"), jet.pt(), trackProj); + registry.fill(HIST("detector-level/jets/detJetPtTrackPt"), jet.pt(), track.pt()); + registry.fill(HIST("detector-level/jets/detJetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("detector-level/jets/detJetPtFrag"), jet.pt(), chargeFrag); + registry.fill(HIST("detector-level/jets/detJetPtTrackProj"), jet.pt(), trackProj); } } } - PROCESS_SWITCH(JetFragmentation, processMCD, "Monte Carlo detector level", false); + PROCESS_SWITCH(JetFragmentation, processMcD, "Monte Carlo detector level", false); - void processMCP(aod::McCollision const& mcCollision, // Add some form of event selection? - soa::Join const& jets, + void processMcP(aod::McCollision const& mcCollision, // Add some form of event selection? + McPJets const& jets, aod::McParticles const& particles) { int nJets = -1, nTracks = -1; nJets = jets.size(), nTracks = particles.size(); registry.fill(HIST("partnJetnTrack"), nJets, nTracks); for (const auto& particle : particles) { - registry.fill(HIST("tracks/partTrackPtEtaPhi"), particle.pt(), particle.eta(), particle.phi()); + if (particle.pt() > 0.1) { + registry.fill(HIST("particle-level/tracks/partTrackPtEtaPhi"), particle.pt(), particle.eta(), particle.phi()); + } } for (const auto& jet : jets) { - registry.fill(HIST("jets/partJetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + registry.fill(HIST("particle-level/jets/partJetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); for (const auto& track : jet.tracks_as()) { double chargeFrag = -1., trackProj = -1.; trackProj = track.px() * jet.px() + track.py() * jet.py() + track.pz() * jet.pz(); trackProj /= (jet.p() * jet.p()); chargeFrag = track.pt() / jet.pt(); - registry.fill(HIST("jets/partJetPtTrackPt"), jet.pt(), track.pt()); - registry.fill(HIST("jets/partJetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); - registry.fill(HIST("jets/partJetPtFrag"), jet.pt(), chargeFrag); - registry.fill(HIST("jets/partJetPtTrackProj"), jet.pt(), trackProj); + registry.fill(HIST("particle-level/jets/partJetPtTrackPt"), jet.pt(), track.pt()); + registry.fill(HIST("particle-level/jets/partJetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("particle-level/jets/partJetPtFrag"), jet.pt(), chargeFrag); + registry.fill(HIST("particle-level/jets/partJetPtTrackProj"), jet.pt(), trackProj); } } } - PROCESS_SWITCH(JetFragmentation, processMCP, "Monte Carlo particle level", false); + PROCESS_SWITCH(JetFragmentation, processMcP, "Monte Carlo particle level", false); void processDataRun3(soa::Join::iterator const& collision, soa::Join const& jets, @@ -175,28 +257,113 @@ struct JetFragmentation { registry.fill(HIST("datCount"), 1); int nJets = -1, nTracks = -1; nJets = jets.size(), nTracks = tracks.size(); - registry.fill(HIST("partnJetnTrack"), nJets, nTracks); + registry.fill(HIST("nJetnTrack"), nJets, nTracks); for (const auto& track : tracks) { if (track.pt() > 0.1) { - registry.fill(HIST("tracks/trackPtEtaPhi"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("data/tracks/trackPtEtaPhi"), track.pt(), track.eta(), track.phi()); } } for (const auto& jet : jets) { - registry.fill(HIST("jets/jetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + registry.fill(HIST("data/jets/jetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); for (const auto& track : jet.tracks_as()) { double chargeFrag = -1., trackProj = -1.; trackProj = track.px() * jet.px() + track.py() * jet.py() + track.pz() * jet.pz(); trackProj /= (jet.p() * jet.p()); chargeFrag = track.pt() / jet.pt(); - registry.fill(HIST("jets/jetPtTrackPt"), jet.pt(), track.pt()); - registry.fill(HIST("jets/jetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); - registry.fill(HIST("jets/jetPtFrag"), jet.pt(), chargeFrag); - registry.fill(HIST("jets/jetPtTrackProj"), jet.pt(), trackProj); + registry.fill(HIST("data/jets/jetPtTrackPt"), jet.pt(), track.pt()); + registry.fill(HIST("data/jets/jetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("data/jets/jetPtFrag"), jet.pt(), chargeFrag); + registry.fill(HIST("data/jets/jetPtTrackProj"), jet.pt(), trackProj); } } } PROCESS_SWITCH(JetFragmentation, processDataRun3, "Run 3 Data", false); + + // Taken from jet-validation + void processMcDP(soa::Join::iterator const& collision, + // MatchedMcDJets const& mcDetJets, + soa::Join const& mcDetJets, + McTracks const& tracks, + aod::McCollisions const& mcCollisions, + McPJets const& mcPartJets, + aod::McParticles const& mcParticles) + { + for (const auto& detJet : mcDetJets) { + if (detJet.eta() < matchedDetJetEtaMin || detJet.eta() > matchedDetJetEtaMax) { + continue; // TODO: should be done in filter + } + for (auto& partJet : detJet.template matchedJetGeo_as()) { + double deltaEta = partJet.eta() - detJet.eta(); + double deltaPhi = partJet.phi() - detJet.phi(); + deltaPhi = CheckDphi(deltaPhi); + + registry.fill(HIST("matching/jets/matchDetJetPtEtaPhi"), detJet.pt(), detJet.eta(), detJet.phi()); + registry.fill(HIST("matching/jets/matchPartJetPtEtaPhi"), partJet.pt(), partJet.eta(), partJet.phi()); + + registry.fill(HIST("matching/jets/matchPartJetPtMatchDist"), partJet.pt(), TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi)); + registry.fill(HIST("matching/jets/matchPartJetPtEnergyScale"), partJet.pt(), detJet.pt() / partJet.pt()); + registry.fill(HIST("matching/jets/matchDetJetPtPartJetPt"), detJet.pt(), partJet.pt()); + registry.fill(HIST("matching/jets/matchPartJetPtDetJetEtaPartJetEta"), partJet.pt(), detJet.eta(), partJet.eta()); + registry.fill(HIST("matching/jets/matchPartJetPtDetJetPhiPartJetPhi"), partJet.pt(), detJet.phi(), partJet.phi()); + registry.fill(HIST("matching/jets/matchPartJetPtResolutionPt"), partJet.pt(), (partJet.pt() - detJet.pt())); + registry.fill(HIST("matching/jets/matchPartJetPtResolutionEta"), partJet.pt(), partJet.eta(), (partJet.eta() - detJet.eta())); + registry.fill(HIST("matching/jets/matchPartJetPtResolutionPhi"), partJet.pt(), partJet.phi(), CheckDphi(partJet.phi() - detJet.phi())); + + for (const auto& track : detJet.tracks_as()) { + bool isTrackMatched = false; + double detChargeFrag = -1., detTrackProj = -1.; + detTrackProj = track.px() * detJet.px() + track.py() * detJet.py() + track.pz() * detJet.pz(); + detTrackProj /= (detJet.p() * detJet.p()); + detChargeFrag = track.pt() / detJet.pt(); + + registry.fill(HIST("matching/jets/matchDetJetTrackPtEtaPhi"), track.pt(), track.eta(), track.phi()); + registry.fill(HIST("matching/jets/matchDetJetPtTrackPt"), detJet.pt(), track.pt()); + registry.fill(HIST("matching/jets/matchDetJetPtTrackProj"), detJet.pt(), detTrackProj); + registry.fill(HIST("matching/jets/matchDetJetPtFrag"), detJet.pt(), detChargeFrag); + + for (const auto& particle : partJet.tracks_as()) { + if (track.has_mcParticle() && particle.globalIndex() == track.template mcParticle_as().globalIndex()) { + isTrackMatched = true; + double partChargeFrag = -1., partTrackProj = -1.; + partTrackProj = particle.px() * partJet.px() + particle.py() * partJet.py() + particle.pz() * partJet.pz(); + partTrackProj /= (partJet.p() * partJet.p()); + partChargeFrag = particle.pt() / partJet.pt(); + + registry.fill(HIST("matching/jets/matchPartJetTrackPtEtaPhi"), particle.pt(), particle.eta(), particle.phi()); + registry.fill(HIST("matching/jets/matchPartJetPtTrackPt"), partJet.pt(), particle.pt()); + registry.fill(HIST("matching/jets/matchPartJetPtTrackProj"), partJet.pt(), partTrackProj); + registry.fill(HIST("matching/jets/matchPartJetPtFrag"), partJet.pt(), partChargeFrag); + + registry.fill(HIST("matching/jets/matchPartJetPtResolutionTrackProj"), partJet.pt(), partTrackProj, (partTrackProj - detTrackProj)); + registry.fill(HIST("matching/jets/matchPartJetPtResolutionChargeFrag"), partJet.pt(), partChargeFrag, (partChargeFrag - detChargeFrag)); + // Response + registry.fill(HIST("matching/jets/matchDetJetPtTrackProjPartJetPtTrackProj"), detJet.pt(), detTrackProj, partJet.pt(), partTrackProj); + registry.fill(HIST("matching/jets/matchDetJetPtFragPartJetPtFrag"), detJet.pt(), detChargeFrag, partJet.pt(), partChargeFrag); + break; // No need to inspect other particles + } // if track has mcParticle and particle is in matched jet + } // for particle in matched partJet + if (!isTrackMatched) { + registry.fill(HIST("matching/jets/fakeDetJetPtTrackProj"), detJet.pt(), detTrackProj); + registry.fill(HIST("matching/jets/fakeDetJetPtFrag"), detJet.pt(), detChargeFrag); + } // if track is not matched + } // for detJet tracks + } + if (!detJet.has_matchedJetGeo()) { + for (const auto& track : detJet.tracks_as()) { + double detChargeFrag = -1., detTrackProj = -1.; + detTrackProj = track.px() * detJet.px() + track.py() * detJet.py() + track.pz() * detJet.pz(); + detTrackProj /= (detJet.p() * detJet.p()); + detChargeFrag = track.pt() / detJet.pt(); + registry.fill(HIST("matching/jets/fakeDetJetPtTrackProj"), detJet.pt(), detTrackProj); + registry.fill(HIST("matching/jets/fakeDetJetPtFrag"), detJet.pt(), detChargeFrag); + } + } // if detJet does not have a match + } // for det jet + // TODO: how to deal with misses? + // -> ParticleToDetector table is currently bugged: size does not correspond to ParticleLevelJets (04.06.2023) + } + PROCESS_SWITCH(JetFragmentation, processMcDP, "Monte Carlo particle and detector level", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetmatchingqa.cxx b/PWGJE/Tasks/jetmatchingqa.cxx index 60ed222abd5..cf0e82a64fb 100644 --- a/PWGJE/Tasks/jetmatchingqa.cxx +++ b/PWGJE/Tasks/jetmatchingqa.cxx @@ -28,82 +28,149 @@ using namespace o2::framework::expressions; template struct JetMatchingQA { - OutputObj hJetHfPt{"h_jet_hf_pt"}; - OutputObj hJetHfDetaDphi{"h_jet_hf_deta_dphi"}; - OutputObj hJetGeoPt{"h_jet_geo_pt"}; - OutputObj hJetGeoDetaDphi{"h_jet_geo_deta_dphi"}; - OutputObj hJetPtPt{"h_jet_pt_pt"}; - OutputObj hJetPtDetaDphi{"h_jet_pt_deta_dphi"}; - - OutputObj hJetDetPt{"h_jet_det_pt"}; - OutputObj hJetGenPt{"h_jet_gen_pt"}; - OutputObj hJetDetPhi{"h_jet_det_phi"}; - OutputObj hJetGenPhi{"h_jet_gen_phi"}; - OutputObj hJetDetEta{"h_jet_det_eta"}; - OutputObj hJetGenEta{"h_jet_gen_eta"}; - OutputObj hJetDetNTracks{"h_jet_det_ntracks"}; - OutputObj hJetGenNTracks{"h_jet_gen_ntracks"}; + + HistogramRegistry registry{ + "registry", + { + {"h_jet_match_hf_pt", "hf-matched jets", {HistType::kTH2F, {{1000, 0.0f, 100.0f, "#it{p}_{T}^{gen} (GeV/#it{c})"}, {1000, 0.0f, 100.0f, "#it{p}_{T}^{det} (GeV/#it{c})"}}}}, + {"h_jet_match_hf_deta_dphi", "hf-matched jets", {HistType::kTH2F, {{100, -2. * TMath::Pi(), 2. * TMath::Pi(), "jet #Delta#phi"}, {100, -2.0f, 2.0f, "#Delta#eta"}}}}, + {"h_jet_match_geo_pt", "geo-matched jets", {HistType::kTH2F, {{1000, 0.0f, 100.0f, "#it{p}_{T}^{gen} (GeV/#it{c})"}, {1000, 0.0f, 100.0f, "#it{p}_{T}^{det} (GeV/#it{c})"}}}}, + {"h_jet_match_geo_deta_dphi", "geo-matched jets", {HistType::kTH2F, {{100, -2. * TMath::Pi(), 2. * TMath::Pi(), "jet #Delta#phi"}, {100, -2.0f, 2.0f, "#Delta#eta"}}}}, + {"h_jet_match_pt_pt", "pt-matched jets", {HistType::kTH2F, {{1000, 0.0f, 100.0f, "#it{p}_{T}^{gen} (GeV/#it{c})"}, {1000, 0.0f, 100.0f, "#it{p}_{T}^{det} (GeV/#it{c})"}}}}, + {"h_jet_match_pt_deta_dphi", "pt-matched jets", {HistType::kTH2F, {{100, -2. * TMath::Pi(), 2. * TMath::Pi(), "jet #Delta#phi"}, {100, -2.0f, 2.0f, "#Delta#eta"}}}}, + + {"h_jet_match_geo_pt_zoom", "geo-matched jets", {HistType::kTH2F, {{1000, 0.0f, 10.0f, "#it{p}_{T} (particle level, GeV/#it{c})"}, {1000, 0.0f, 10.0f, "#it{p}_{T} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_geo_dpt", "geo-matched jets", {HistType::kTH1F, {{100, -10.0f, 10.0f, "#Delta#it{p}_{T} (particle level vs detector level, GeV/#it{c})"}}}}, + {"h_jet_match_geo_PtLeadingPart", "geo-matched jets", {HistType::kTH2F, {{1000, 0.0f, 10.0f, "#it{p}_{T}^{leading} (particle level, GeV/#it{c})"}, {1000, 0.0f, 10.0f, "#it{p}_{T}^{leading} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_geo_phi", "geo-matched jets", {HistType::kTH2F, {{80, -1.0f, 7.0f, "#phi_{jet} (particle level, rad)"}, {80, -1.0f, 7.0f, "#phi_{jet} (detector level, rad)"}}}}, + {"h_jet_match_geo_eta", "geo-matched jets", {HistType::kTH2F, {{70, -0.7f, 0.7f, "#it{p}_{T}^{particle level} (GeV/#it{c})"}, {70, -0.7f, 0.7f, "#it{p}_{T} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_geo_Nconst", "geo-matched jets", {HistType::kTH2F, {{30, 0.0f, 30.0f, "n constituents (particle level)"}, {30, 0.0f, 30.0f, "n constituents (detector level)"}}}}, + + {"h_jet_match_hf_pt_zoom", "hf-matched jets", {HistType::kTH2F, {{1000, 0.0f, 10.0f, "#it{p}_{T} (particle level, GeV/#it{c})"}, {1000, 0.0f, 10.0f, "#it{p}_{T} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_hf_dpt", "hf-matched jets", {HistType::kTH1F, {{100, -10.0f, 10.0f, "#Delta#it{p}_{T} (particle level vs detector level, GeV/#it{c})"}}}}, + {"h_jet_match_hf_PtLeadingPart", "hf-matched jets", {HistType::kTH2F, {{1000, 0.0f, 10.0f, "#it{p}_{T}^{leading} (particle level, GeV/#it{c})"}, {1000, 0.0f, 10.0f, "#it{p}_{T}^{leading} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_hf_phi", "hf-matched jets", {HistType::kTH2F, {{80, -1.0f, 7.0f, "#phi_{jet} (particle level, rad)"}, {80, -1.0f, 7.0f, "#phi_{jet} (detector level, rad)"}}}}, + {"h_jet_match_hf_eta", "hf-matched jets", {HistType::kTH2F, {{70, -0.7f, 0.7f, "#it{p}_{T}^{particle level} (GeV/#it{c})"}, {70, -0.7f, 0.7f, "#it{p}_{T} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_hf_Nconst", "hf-matched jets", {HistType::kTH2F, {{30, 0.0f, 30.0f, "n constituents (particle level)"}, {30, 0.0f, 30.0f, "n constituents (detector level)"}}}}, + + {"h_jet_match_pt_pt_zoom", "pt-matched jets", {HistType::kTH2F, {{1000, 0.0f, 10.0f, "#it{p}_{T} (particle level, GeV/#it{c})"}, {1000, 0.0f, 10.0f, "#it{p}_{T} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_pt_dpt", "pt-matched jets", {HistType::kTH1F, {{100, -10.0f, 10.0f, "#Delta#it{p}_{T} (particle level vs detector level, GeV/#it{c})"}}}}, + {"h_jet_match_pt_PtLeadingPart", "pt-matched jets", {HistType::kTH2F, {{1000, 0.0f, 10.0f, "#it{p}_{T}^{leading} (particle level, GeV/#it{c})"}, {1000, 0.0f, 10.0f, "#it{p}_{T}^{leading} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_pt_phi", "pt-matched jets", {HistType::kTH2F, {{80, -1.0f, 7.0f, "#phi_{jet} (particle level, rad)"}, {80, -1.0f, 7.0f, "#phi_{jet} (detector level, rad)"}}}}, + {"h_jet_match_pt_eta", "pt-matched jets", {HistType::kTH2F, {{70, -0.7f, 0.7f, "#it{p}_{T}^{particle level} (GeV/#it{c})"}, {70, -0.7f, 0.7f, "#it{p}_{T} (detector level, GeV/#it{c})"}}}}, + {"h_jet_match_pt_Nconst", "pt-matched jets", {HistType::kTH2F, {{30, 0.0f, 30.0f, "n constituents (particle level)"}, {30, 0.0f, 30.0f, "n constituents (detector level)"}}}}, + + {"h_jet_det_pt", "detector level jets", {HistType::kTH1F, {{1000, 0.0f, 100.0f, "jet p_{T}^{det} (GeV/#it{c})"}}}}, + {"h_jet_gen_pt", "particle level jets", {HistType::kTH1F, {{1000, 0.0f, 100.0f, "jet p_{T}^{gen} (GeV/#it{c})"}}}}, + {"h_jet_det_phi", "detector level jet #phi", {HistType::kTH1F, {{140, -7.0f, 7.0f, "#phi"}}}}, + {"h_jet_gen_phi", "particle level jets #phi", {HistType::kTH1F, {{140, -7.0f, 7.0f, "#phi"}}}}, + {"h_jet_det_eta", "detector level jets #eta", {HistType::kTH1F, {{30, -1.5f, 1.5f, "#eta"}}}}, + {"h_jet_gen_eta", "particle level jets #eta", {HistType::kTH1F, {{30, -1.5f, 1.5f, "#eta"}}}}, + {"h_jet_det_ntracks", "detector level jets N tracks", {HistType::kTH1F, {{150, -0.5f, 99.5f, "N tracks"}}}}, + {"h_jet_gen_ntracks", "particle level jets N tracks", {HistType::kTH1F, {{150, -0.5f, 99.5f, "N tracks"}}}}, + }, + }; void init(InitContext const&) { - hJetGeoPt.setObject(new TH2F("h_jet_geo_pt", "geo-matched jets;jet p_{T}^{gen} (GeV/#it{c});jet p_{T}^{det} (GeV/#it{c})", - 100, 0., 100., 100, 0., 100.)); - hJetGeoDetaDphi.setObject(new TH2F("h_jet_geo_deta_dphi", "geo-matched jets;jet #Delta#phi;#Delta#eta", - 100, -2. * TMath::Pi(), 2. * TMath::Pi(), 100, -2., 2.)); - hJetHfPt.setObject(new TH2F("h_jet_pt", "HF-matched jets;jet p_{T}^{gen} (GeV/#it{c});jet p_{T}^{det} (GeV/#it{c})", - 100, 0., 100., 100, 0., 100.)); - hJetHfDetaDphi.setObject(new TH2F("h_jet_deta_dphi", "HF-matched jets;jet #Delta#phi;#Delta#eta", - 100, -2. * TMath::Pi(), 2. * TMath::Pi(), 100, -2., 2.)); - hJetPtPt.setObject(new TH2F("h_jet_pt_pt", "pt-matched jets;jet p_{T}^{gen} (GeV/#it{c});jet p_{T}^{det} (GeV/#it{c})", - 100, 0., 100., 100, 0., 100.)); - hJetPtDetaDphi.setObject(new TH2F("h_jet_pt_deta_dphi", "pt-matched jets;jet #Delta#phi;#Delta#eta", - 100, -2. * TMath::Pi(), 2. * TMath::Pi(), 100, -2., 2.)); - - hJetDetPt.setObject(new TH1F("h_jet_det_pt", "detector level jets;jet p_{T}^{det} (GeV/#it{c})", 100, 0., 100.)); - hJetGenPt.setObject(new TH1F("h_jet_gen_pt", "particle level jets;jet p_{T}^{gen} (GeV/#it{c})", 100, 0., 100.)); - hJetDetPhi.setObject(new TH1F("h_jet_det_phi", "jet #phi; #phi", 140, -7.0, 7.0)); - hJetGenPhi.setObject(new TH1F("h_jet_gen_phi", "jet #phi; #phi", 140, -7.0, 7.0)); - hJetDetEta.setObject(new TH1F("h_jet_det_eta", "jet #eta; #eta", 30, -1.5, 1.5)); - hJetGenEta.setObject(new TH1F("h_jet_gen_eta", "jet #eta; #eta", 30, -1.5, 1.5)); - hJetDetNTracks.setObject(new TH1F("h_jet_det_ntracks", "jet N tracks ; N tracks", 150, -0.5, 99.5)); - hJetGenNTracks.setObject(new TH1F("h_jet_gen_ntracks", "jet N tracks ; N tracks", 150, -0.5, 99.5)); } - void processMCD(aod::Collisions::iterator const& collision, + void processMCD(aod::Collisions::iterator const& collision, aod::McParticles const& mcParticles, soa::Join const& tracks, BaseJetCollection const& djets, TagJetCollection const& pjets) { for (const auto& djet : djets) { if (djet.has_matchedJetCand() || djet.has_matchedJetGeo()) { - hJetDetPhi->Fill(djet.phi()); - hJetDetEta->Fill(djet.eta()); - hJetDetNTracks->Fill(djet.tracksIds().size() + 1); // adding HF candidate + registry.fill(HIST("h_jet_det_pt"), djet.pt()); + registry.fill(HIST("h_jet_det_phi"), djet.phi()); + registry.fill(HIST("h_jet_det_eta"), djet.eta()); + registry.fill(HIST("h_jet_det_ntracks"), djet.tracksIds().size() + 1); // adding HF candidate } - if (djet.has_matchedJetCand() && djet.matchedJetCandId() >= 0) { - const auto& pjet = djet.template matchedJetCand_as(); + // HF matching QA + for (auto& pjet : djet.template matchedJetCand_as()) { LOGF(info, "djet %d (pt of %g GeV/c) is HF-matched to %d (pt of %g GeV/c)", - djet.globalIndex(), djet.pt(), djet.matchedJetCandId(), pjet.pt()); - hJetHfPt->Fill(pjet.pt(), djet.pt()); + djet.globalIndex(), djet.pt(), pjet.globalIndex(), pjet.pt()); + registry.fill(HIST("h_jet_match_hf_pt"), pjet.pt(), djet.pt()); const auto dphi = -TMath::Pi() + fmod(2 * TMath::Pi() + fmod(djet.phi() - pjet.phi() + TMath::Pi(), 2 * TMath::Pi()), 2 * TMath::Pi()); - hJetHfDetaDphi->Fill(dphi, djet.eta() - pjet.eta()); + registry.fill(HIST("h_jet_match_hf_deta_dphi"), dphi, djet.eta() - pjet.eta()); + + registry.fill(HIST("h_jet_match_hf_pt_zoom"), pjet.pt(), djet.pt()); + registry.fill(HIST("h_jet_match_hf_dpt"), pjet.pt() - djet.pt()); + registry.fill(HIST("h_jet_match_hf_phi"), pjet.phi(), djet.phi()); + registry.fill(HIST("h_jet_match_hf_eta"), pjet.eta(), djet.eta()); + registry.fill(HIST("h_jet_match_hf_Nconst"), pjet.tracksIds().size(), djet.tracksIds().size()); + + double pjet_pt_lead = 0.; + for (auto& mcparticle : pjet.template tracks_as()) { + if (mcparticle.pt() > pjet_pt_lead) { + pjet_pt_lead = mcparticle.pt(); + } + } + double djet_pt_lead = 0.; + for (auto& track : djet.template tracks_as>()) { + if (track.pt() > djet_pt_lead) { + djet_pt_lead = track.pt(); + } + } + registry.fill(HIST("h_jet_match_hf_PtLeadingPart"), djet_pt_lead, pjet_pt_lead); } - if (djet.has_matchedJetGeo()) { - const auto& pjet = djet.template matchedJetGeo_as(); + // geo matching QA + for (auto& pjet : djet.template matchedJetGeo_as()) { LOGF(info, "djet %d (pt of %g GeV/c) is geo-matched to %d (pt of %g GeV/c)", - djet.globalIndex(), djet.pt(), djet.matchedJetGeoId(), pjet.pt()); - hJetGeoPt->Fill(pjet.pt(), djet.pt()); + djet.globalIndex(), djet.pt(), pjet.globalIndex(), pjet.pt()); + registry.fill(HIST("h_jet_match_geo_pt"), pjet.pt(), djet.pt()); const auto dphi = -TMath::Pi() + fmod(2 * TMath::Pi() + fmod(djet.phi() - pjet.phi() + TMath::Pi(), 2 * TMath::Pi()), 2 * TMath::Pi()); - hJetGeoDetaDphi->Fill(dphi, djet.eta() - pjet.eta()); + registry.fill(HIST("h_jet_match_geo_deta_dphi"), dphi, djet.eta() - pjet.eta()); + + registry.fill(HIST("h_jet_match_geo_pt_zoom"), pjet.pt(), djet.pt()); + registry.fill(HIST("h_jet_match_geo_dpt"), pjet.pt() - djet.pt()); + registry.fill(HIST("h_jet_match_geo_phi"), pjet.phi(), djet.phi()); + registry.fill(HIST("h_jet_match_geo_eta"), pjet.eta(), djet.eta()); + registry.fill(HIST("h_jet_match_geo_Nconst"), pjet.tracksIds().size(), djet.tracksIds().size()); + + double pjet_pt_lead = 0.; + for (auto& mcparticle : pjet.template tracks_as()) { + if (mcparticle.pt() > pjet_pt_lead) { + pjet_pt_lead = mcparticle.pt(); + } + } + double djet_pt_lead = 0.; + for (auto& track : djet.template tracks_as>()) { + if (track.pt() > djet_pt_lead) { + djet_pt_lead = track.pt(); + } + } + registry.fill(HIST("h_jet_match_geo_PtLeadingPart"), djet_pt_lead, pjet_pt_lead); } - if (djet.has_matchedJetPt()) { - const auto& pjet = djet.template matchedJetPt_as(); + // pT matching QA + for (auto& pjet : djet.template matchedJetPt_as()) { LOGF(info, "djet %d (pt of %g GeV/c) is pt-matched to %d (pt of %g GeV/c)", - djet.globalIndex(), djet.pt(), djet.matchedJetGeoId(), pjet.pt()); - hJetPtPt->Fill(pjet.pt(), djet.pt()); + djet.globalIndex(), djet.pt(), pjet.globalIndex(), pjet.pt()); + registry.fill(HIST("h_jet_match_pt_pt"), pjet.pt(), djet.pt()); const auto dphi = -TMath::Pi() + fmod(2 * TMath::Pi() + fmod(djet.phi() - pjet.phi() + TMath::Pi(), 2 * TMath::Pi()), 2 * TMath::Pi()); - hJetPtDetaDphi->Fill(dphi, djet.eta() - pjet.eta()); + registry.fill(HIST("h_jet_match_pt_deta_dphi"), dphi, djet.eta() - pjet.eta()); + + registry.fill(HIST("h_jet_match_pt_pt_zoom"), pjet.pt(), djet.pt()); + registry.fill(HIST("h_jet_match_pt_dpt"), pjet.pt() - djet.pt()); + registry.fill(HIST("h_jet_match_pt_phi"), pjet.phi(), djet.phi()); + registry.fill(HIST("h_jet_match_pt_eta"), pjet.eta(), djet.eta()); + registry.fill(HIST("h_jet_match_pt_Nconst"), pjet.tracksIds().size(), djet.tracksIds().size()); + + double pjet_pt_lead = 0.; + for (auto& mcparticle : pjet.template tracks_as()) { + if (mcparticle.pt() > pjet_pt_lead) { + pjet_pt_lead = mcparticle.pt(); + } + } + double djet_pt_lead = 0.; + for (auto& track : djet.template tracks_as>()) { + if (track.pt() > djet_pt_lead) { + djet_pt_lead = track.pt(); + } + } + registry.fill(HIST("h_jet_match_pt_PtLeadingPart"), djet_pt_lead, pjet_pt_lead); } } } @@ -114,32 +181,34 @@ struct JetMatchingQA { { for (const auto& pjet : pjets) { if (pjet.has_matchedJetCand() || pjet.has_matchedJetGeo()) { - hJetGenPt->Fill(pjet.pt()); - hJetGenPhi->Fill(pjet.phi()); - hJetGenEta->Fill(pjet.eta()); - hJetGenNTracks->Fill(pjet.tracksIds().size() + 1); // adding HF candidate + registry.fill(HIST("h_jet_gen_pt"), pjet.pt()); + registry.fill(HIST("h_jet_gen_phi"), pjet.phi()); + registry.fill(HIST("h_jet_gen_eta"), pjet.eta()); + registry.fill(HIST("h_jet_gen_ntracks"), pjet.tracksIds().size() + 1); // adding HF candidate } - if (pjet.has_matchedJetCand()) { - const auto& djet = pjet.template matchedJetCand_as(); + for (auto& djet : pjet.template matchedJetCand_as()) { LOGF(info, "pjet %d (pt of %g GeV/c) is HF-matched to %d (pt of %g GeV/c)", - pjet.globalIndex(), pjet.pt(), pjet.matchedJetCandId(), djet.pt()); + pjet.globalIndex(), pjet.pt(), djet.globalIndex(), djet.pt()); } - if (pjet.has_matchedJetGeo()) { - const auto& djet = pjet.template matchedJetGeo_as(); + for (auto& djet : pjet.template matchedJetGeo_as()) { LOGF(info, "pjet %d (pt of %g GeV/c) is geo-matched to %d (pt of %g GeV/c)", - pjet.globalIndex(), pjet.pt(), pjet.matchedJetGeoId(), djet.pt()); + pjet.globalIndex(), pjet.pt(), djet.globalIndex(), djet.pt()); } - if (pjet.has_matchedJetPt()) { - const auto& djet = pjet.template matchedJetPt_as(); - LOGF(info, "pjet %d (pt of %g GeV/c) is geo-matched to %d (pt of %g GeV/c)", - pjet.globalIndex(), pjet.pt(), pjet.matchedJetGeoId(), djet.pt()); + for (auto& djet : pjet.template matchedJetPt_as()) { + LOGF(info, "pjet %d (pt of %g GeV/c) is pT-matched to %d (pt of %g GeV/c)", + pjet.globalIndex(), pjet.pt(), djet.globalIndex(), djet.pt()); } } } PROCESS_SWITCH(JetMatchingQA, processMCP, "QA on generator-level jets", true); + + void processDummy(aod::McCollisions const& mcCollisions) + { + } + PROCESS_SWITCH(JetMatchingQA, processDummy, "Dummy process", true); }; using ChargedDetectorLevelJets = soa::Join; @@ -163,9 +232,9 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) std::vector tasks; tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-matching-qa-ch"})); - tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-matching-qa-d0-ch"})); - tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-matching-qa-lc-ch"})); - tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-matching-qa-bplus-ch"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-qa-d0-ch"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-qa-lc-ch"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-qa-bplus-ch"})); return WorkflowSpec{tasks}; } diff --git a/PWGJE/Tasks/jetsubstructure.cxx b/PWGJE/Tasks/jetsubstructure.cxx index 71cd370f696..471ff9b0f8d 100644 --- a/PWGJE/Tasks/jetsubstructure.cxx +++ b/PWGJE/Tasks/jetsubstructure.cxx @@ -40,18 +40,15 @@ using namespace o2::framework::expressions; #include "Framework/runDataProcessing.h" -template +template struct JetSubstructureTask { Produces jetSubstructureTable; - OutputObj hZg{"h_jet_zg"}; - OutputObj hRg{"h_jet_rg"}; - OutputObj hNsd{"h_jet_nsd"}; + OutputObj hZg{"h_jet_zg_jet_pt"}; + OutputObj hRg{"h_jet_rg_jet_pt"}; + OutputObj hNsd{"h_jet_nsd_jet_pt"}; - Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT cut"}; Configurable zCut{"zCut", 0.1, "soft drop z cut"}; Configurable beta{"beta", 0.0, "soft drop beta"}; - Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; - Configurable doConstSub{"doConstSub", false, "do constituent subtraction"}; std::vector jetConstituents; std::vector jetReclustered; @@ -59,18 +56,17 @@ struct JetSubstructureTask { void init(InitContext const&) { - hZg.setObject(new TH1F("h_jet_zg", "zg ;zg", - 10, 0.0, 0.5)); - hRg.setObject(new TH1F("h_jet_rg", "rg ;rg", - 10, 0.0, 0.5)); - hNsd.setObject(new TH1F("h_jet_nsd", "nsd ;nsd", - 7, -0.5, 6.5)); + hZg.setObject(new TH2F("h_jet_zg_jet_pt", ";z_{g}; #it{p}_{T,jet} (GeV/#it{c})", + 10, 0.0, 0.5, 200, 0.0, 200.0)); + hRg.setObject(new TH2F("h_jet_rg_jet_pt", ";R_{g}; #it{p}_{T,jet} (GeV/#it{c})", + 10, 0.0, 0.5, 200, 0.0, 200.0)); + hNsd.setObject(new TH2F("h_jet_nsd_jet_pt", ";n_{SD}; #it{p}_{T,jet} (GeV/#it{c})", + 7, -0.5, 6.5, 200, 0.0, 200.0)); + jetReclusterer.isReclustering = true; jetReclusterer.algorithm = fastjet::JetAlgorithm::cambridge_algorithm; } - //Filter jetCuts = aod::jet::pt > f_jetPtMin; //how does this work? - template void jetReclustering(T const& jet) { @@ -90,19 +86,19 @@ struct JetSubstructureTask { } auto z = parentSubJet2.perp() / (parentSubJet1.perp() + parentSubJet2.perp()); auto theta = parentSubJet1.delta_R(parentSubJet2); - if (z >= zCut * TMath::Power(theta / jetR, beta)) { + if (z >= zCut * TMath::Power(theta / (jet.r() / 100.f), beta)) { if (!softDropped) { zg = z; rg = theta; - hZg->Fill(zg); - hRg->Fill(rg); + hZg->Fill(zg, jet.pt()); + hRg->Fill(rg, jet.pt()); softDropped = true; } nsd++; } daughterSubJet = parentSubJet1; } - hNsd->Fill(nsd); + hNsd->Fill(nsd, jet.pt()); jetSubstructureTable(zg, rg, nsd); } @@ -111,58 +107,31 @@ struct JetSubstructureTask { } PROCESS_SWITCH(JetSubstructureTask, processDummy, "Dummy process function turned on by default", true); - void processData(soa::Join::iterator const& jet, - aod::Tracks const& tracks, - aod::ChargedJetConstituentsSub const& constituentsSub) - { - jetConstituents.clear(); - - if (doConstSub) { - for (const auto& jetconstituentSub : constituentsSub) { - FastJetUtilities::fillTracks(jetconstituentSub, jetConstituents); - } - } else { - for (auto& jetConstituent : jet.tracks_as()) { - FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); - } - } - jetReclustering(jet); - } - PROCESS_SWITCH(JetSubstructureTask, processData, "jet substructure on data", false); - - void processMCD(soa::Join::iterator const& jet, - aod::Tracks const& tracks, - aod::ChargedJetConstituentsSub const& constituentsSub) + void processChargedJets(typename JetTable::iterator const& jet, + aod::Tracks const& tracks) { jetConstituents.clear(); - - if (doConstSub) { - for (const auto& jetconstituentSub : constituentsSub) { - FastJetUtilities::fillTracks(jetconstituentSub, jetConstituents); - } - } else { - for (auto& jetConstituent : jet.tracks_as()) { - FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); - } + for (auto& jetConstituent : jet.template tracks_as()) { + FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); } jetReclustering(jet); } - PROCESS_SWITCH(JetSubstructureTask, processMCD, "jet substructure on MC detector level", false); + PROCESS_SWITCH(JetSubstructureTask, processChargedJets, "charged jet substructure", false); - void processMCP(soa::Join::iterator const& jet, - aod::McParticles const& particles) + void processChargedJetsMCP(typename JetTableMCP::iterator const& jet, + aod::McParticles const& particles) { jetConstituents.clear(); - for (auto& jetConstituent : jet.tracks_as()) { + for (auto& jetConstituent : jet.template tracks_as()) { FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), RecoDecay::getMassPDG(jetConstituent.pdgCode())); } jetReclustering(jet); } - PROCESS_SWITCH(JetSubstructureTask, processMCP, "jet substructure on MC particle level", false); + PROCESS_SWITCH(JetSubstructureTask, processChargedJetsMCP, "charged jet substructure on MC particle level", false); }; -using JetSubstructureDataLevel = JetSubstructureTask; -using JetSubstructureMCDetectorLevel = JetSubstructureTask; -using JetSubstructureMCParticleLevel = JetSubstructureTask; +using JetSubstructureDataLevel = JetSubstructureTask, soa::Join, o2::aod::ChargedJetSubstructures>; +using JetSubstructureMCDetectorLevel = JetSubstructureTask, soa::Join, o2::aod::ChargedMCDetectorLevelJetSubstructures>; +using JetSubstructureMCParticleLevel = JetSubstructureTask, soa::Join, o2::aod::ChargedMCParticleLevelJetSubstructures>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGJE/Tasks/jetsubstructurehf.cxx b/PWGJE/Tasks/jetsubstructurehf.cxx index 0b6463a6c98..722450a475f 100644 --- a/PWGJE/Tasks/jetsubstructurehf.cxx +++ b/PWGJE/Tasks/jetsubstructurehf.cxx @@ -43,23 +43,18 @@ using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! #include "Framework/runDataProcessing.h" -template +template struct JetSubstructureHFTask { Produces jetSubstructurehfTable; - OutputObj hZg{"h_jet_zg"}; - OutputObj hRg{"h_jet_rg"}; - OutputObj hNsd{"h_jet_nsd"}; - - // HF candidate level configurables - Configurable candSpecie_s{"candSpecie_s", "D0", "options are D0, Lc, Bplus"}; + OutputObj hZg{"h_jet_zg_jet_pt"}; + OutputObj hRg{"h_jet_rg_jet_pt"}; + OutputObj hNsd{"h_jet_nsd_jet_pt"}; // Jet level configurables Configurable zCut{"zCut", 0.1, "soft drop z cut"}; Configurable beta{"beta", 0.0, "soft drop beta"}; - Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; - Configurable doConstSub{"doConstSub", false, "do constituent subtraction"}; - Service pdg; + Service pdg; int candPDG; std::vector jetConstituents; @@ -68,50 +63,25 @@ struct JetSubstructureHFTask { void init(InitContext const&) { - hZg.setObject(new TH1F("h_jet_zg", "zg ;zg", - 8, 0.1, 0.5)); - hRg.setObject(new TH1F("h_jet_rg", "rg ;rg", - 10, 0.0, 0.5)); - hNsd.setObject(new TH1F("h_jet_nsd", "nsd ;nsd", - 7, -0.5, 6.5)); + hZg.setObject(new TH2F("h_jet_zg_jet_pt", ";z_{g}; #it{p}_{T,jet} (GeV/#it{c})", + 10, 0.0, 0.5, 200, 0.0, 200.0)); + hRg.setObject(new TH2F("h_jet_rg_jet_pt", ";R_{g}; #it{p}_{T,jet} (GeV/#it{c})", + 10, 0.0, 0.5, 200, 0.0, 200.0)); + hNsd.setObject(new TH2F("h_jet_nsd_jet_pt", ";n_{SD}; #it{p}_{T,jet} (GeV/#it{c})", + 7, -0.5, 6.5, 200, 0.0, 200.0)); + jetReclusterer.isReclustering = true; jetReclusterer.algorithm = fastjet::JetAlgorithm::cambridge_algorithm; - auto candSpecie = static_cast(candSpecie_s); - if (candSpecie == "D0") { + if constexpr (std::is_same_v, soa::Join>) { candPDG = static_cast(pdg::Code::kD0); } - if (candSpecie == "Bplus") { + if constexpr (std::is_same_v, soa::Join>) { candPDG = static_cast(pdg::Code::kBPlus); } - if (candSpecie == "Lc") { + if constexpr (std::is_same_v, soa::Join>) { candPDG = static_cast(pdg::Code::kLambdaCPlus); } - if (candSpecie == "JPsi") { - candPDG = static_cast(pdg::Code::kJPsi); - } - } - - template - void processConstituents(T const& jet) - { - jetConstituents.clear(); - for (auto& jetConstituent : jet.template tracks_as()) { - FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); - } - } - - template - void processGenLevel(T const& jet) - { - jetConstituents.clear(); - for (auto& jetConstituent : jet.template tracks_as()) { - FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), RecoDecay::getMassPDG(jetConstituent.pdgCode())); - } - for (auto& jetHFCandidate : jet.template hfcandidates_as()) { // should only be one at the moment - FastJetUtilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(jetHFCandidate.pdgCode())); - } - jetReclustering(jet); } template @@ -133,12 +103,12 @@ struct JetSubstructureHFTask { } auto z = parentSubJet2.perp() / (parentSubJet1.perp() + parentSubJet2.perp()); auto theta = parentSubJet1.delta_R(parentSubJet2); - if (z >= zCut * TMath::Power(theta / jetR, beta)) { + if (z >= zCut * TMath::Power(theta / (jet.r() / 100.f), beta)) { if (!softDropped) { zg = z; rg = theta; - hZg->Fill(zg); - hRg->Fill(rg); + hZg->Fill(zg, jet.pt()); + hRg->Fill(rg, jet.pt()); softDropped = true; } nsd++; @@ -156,117 +126,55 @@ struct JetSubstructureHFTask { daughterSubJet = parentSubJet2; } } - hNsd->Fill(nsd); + hNsd->Fill(nsd, jet.pt()); jetSubstructurehfTable(zg, rg, nsd); } - void processDummy(aod::Tracks const& track) + void processDummy(aod::Tracks const& tracks) { } PROCESS_SWITCH(JetSubstructureHFTask, processDummy, "Dummy process function turned on by default", true); - void processD0Data(soa::Join::iterator const& jet, - soa::Join const& candidates, - aod::Tracks const& tracks) + void processChargedJetsHF(typename JetTable::iterator const& jet, + CandidateTable const& candidates, + aod::Tracks const& tracks) { - processConstituents(jet); - for (auto& jetHFCandidate : jet.hfcandidates_as>()) { // should only be one at the moment - FastJetUtilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(candPDG)); + jetConstituents.clear(); + for (auto& jetConstituent : jet.template tracks_as()) { + FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); } - jetReclustering(jet); - } - PROCESS_SWITCH(JetSubstructureHFTask, processD0Data, "D0 jet substructure on data", false); - - void processD0MCD(soa::Join::iterator const& jet, - soa::Join const& candidates, - aod::Tracks const& tracks) - { - processConstituents(jet); - for (auto& jetHFCandidate : jet.hfcandidates_as>()) { // should only be one at the moment + for (auto& jetHFCandidate : jet.template hfcandidates_as()) { // should only be one at the moment FastJetUtilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(candPDG)); } jetReclustering(jet); } - PROCESS_SWITCH(JetSubstructureHFTask, processD0MCD, "D0 jet substructure on MC detector level", false); - - void processD0MCP(soa::Join::iterator const& jet, - aod::McParticles const& particles) - { - processGenLevel(jet); - } - PROCESS_SWITCH(JetSubstructureHFTask, processD0MCP, "D0 jet substructure on MC particle level", false); + PROCESS_SWITCH(JetSubstructureHFTask, processChargedJetsHF, "HF jet substructure", false); - void processLcData(soa::Join::iterator const& jet, - soa::Join const& candidates, - aod::Tracks const& tracks) + void processChargedJetsHFMCP(typename JetTableMCP::iterator const& jet, + aod::McParticles const& particles) { - processConstituents(jet); - for (auto& jetHFCandidate : jet.hfcandidates_as>()) { // should only be one at the moment - FastJetUtilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(candPDG)); - } - jetReclustering(jet); - } - PROCESS_SWITCH(JetSubstructureHFTask, processLcData, "Lc jet substructure on data", false); - - void processLcMCD(soa::Join::iterator const& jet, - soa::Join const& candidates, - aod::Tracks const& tracks) - { - processConstituents(jet); - for (auto& jetHFCandidate : jet.hfcandidates_as>()) { // should only be one at the moment - FastJetUtilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(candPDG)); + jetConstituents.clear(); + for (auto& jetConstituent : jet.template tracks_as()) { + FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex(), static_cast(JetConstituentStatus::track), RecoDecay::getMassPDG(jetConstituent.pdgCode())); } - jetReclustering(jet); - } - PROCESS_SWITCH(JetSubstructureHFTask, processLcMCD, "Lc jet substructure on MC detector level", false); - - void processLcMCP(soa::Join::iterator const& jet, - aod::McParticles const& particles) - { - processGenLevel(jet); - } - PROCESS_SWITCH(JetSubstructureHFTask, processLcMCP, "Lc jet substructure on MC particle level", false); - - void processBplusData(soa::Join::iterator const& jet, - soa::Join const& candidates, - aod::Tracks const& tracks) - { - processConstituents(jet); - for (auto& jetHFCandidate : jet.hfcandidates_as>()) { // should only be one at the moment - FastJetUtilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(candPDG)); + for (auto& jetHFCandidate : jet.template hfcandidates_as()) { // should only be one at the moment + FastJetUtilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(jetHFCandidate.pdgCode())); } jetReclustering(jet); } - PROCESS_SWITCH(JetSubstructureHFTask, processBplusData, "Bplus jet substructure on data", false); + PROCESS_SWITCH(JetSubstructureHFTask, processChargedJetsHFMCP, "HF jet substructure on MC particle level", false); +}; +using JetSubstructureD0 = JetSubstructureHFTask, soa::Join, soa::Join, o2::aod::D0ChargedJetSubstructures>; +using MCDetectorLevelJetSubstructureD0 = JetSubstructureHFTask, soa::Join, soa::Join, o2::aod::D0ChargedMCDetectorLevelJetSubstructures>; +using MCParticleLevelJetSubstructureD0 = JetSubstructureHFTask, soa::Join, soa::Join, o2::aod::D0ChargedMCParticleLevelJetSubstructures>; - void processBplusMCD(soa::Join::iterator const& jet, - soa::Join const& candidates, - aod::Tracks const& tracks) - { - processConstituents(jet); - for (auto& jetHFCandidate : jet.hfcandidates_as>()) { // should only be one at the moment - FastJetUtilities::fillTracks(jetHFCandidate, jetConstituents, jetHFCandidate.globalIndex(), static_cast(JetConstituentStatus::candidateHF), RecoDecay::getMassPDG(candPDG)); - } - jetReclustering(jet); - } - PROCESS_SWITCH(JetSubstructureHFTask, processBplusMCD, "Bplus jet substructure on MC detector level", false); +// using JetSubstructureBplus = JetSubstructureHFTask,soa::Join,soa::Join,o2::aod::BplusChargedJetSubstructures>; +// using MCDetectorLevelJetSubstructureBplus = JetSubstructureHFTask,soa::Join,soa::Join,o2::aod::BplusChargedMCDetectorLevelJetSubstructures>; +// using MCParticleLevelJetSubstructureBplus = JetSubstructureHFTask,soa::Join,soa::Join,o2::aod::BplusChargedMCParticleLevelJetSubstructures>; - void processBplusMCP(soa::Join::iterator const& jet, - aod::McParticles const& particles) - { - processGenLevel(jet); - } - PROCESS_SWITCH(JetSubstructureHFTask, processBplusMCP, "Bplus jet substructure on MC particle level", false); -}; -using JetSubstructureD0 = JetSubstructureHFTask; -using MCDetectorLevelJetSubstructureD0 = JetSubstructureHFTask; -using MCParticleLevelJetSubstructureD0 = JetSubstructureHFTask; -using JetSubstructureLc = JetSubstructureHFTask; -using MCDetectorLevelJetSubstructureLc = JetSubstructureHFTask; -using MCParticleLevelJetSubstructureLc = JetSubstructureHFTask; -using JetSubstructureBplus = JetSubstructureHFTask; -using MCDetectorLevelJetSubstructureBplus = JetSubstructureHFTask; -using MCParticleLevelJetSubstructureBplus = JetSubstructureHFTask; +// using JetSubstructureLc = JetSubstructureHFTask, soa::Join, soa::Join, o2::aod::LcChargedJetSubstructures>; +// using MCDetectorLevelJetSubstructureLc = JetSubstructureHFTask,soa::Join,soa::Join,o2::aod::LcChargedMCDetectorLevelJetSubstructures>; +// using MCParticleLevelJetSubstructureLc = JetSubstructureHFTask,soa::Join,soa::Join,o2::aod::LcChargedMCParticleLevelJetSubstructures>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { @@ -283,30 +191,30 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-D0-mcp"})); - + /* tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-Lc-data"})); - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-Lc-mcd"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-Lc-mcp"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-substructure-Lc-mcd"})); - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-Bplus-data"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-substructure-Lc-mcp"})); - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-Bplus-mcd"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-substructure-Bplus-data"})); - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-Bplus-mcp"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-substructure-Bplus-mcd"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-substructure-Bplus-mcp"})); + */ return WorkflowSpec{tasks}; } diff --git a/PWGJE/Tasks/jetsubstructurehfoutput.cxx b/PWGJE/Tasks/jetsubstructurehfoutput.cxx index 0c05671ffdb..579ab6c0497 100644 --- a/PWGJE/Tasks/jetsubstructurehfoutput.cxx +++ b/PWGJE/Tasks/jetsubstructurehfoutput.cxx @@ -35,145 +35,125 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::analysis::hf_cuts_d0_to_pi_k; // NB: runDataProcessing.h must be included after customize! #include "Framework/runDataProcessing.h" -template +template struct JetSubstructureHFOutputTask { - Produces jetOutputTable; - Produces jetSubstructureOutputTable; + Produces jetOutputTableData; + Produces jetSubstructureOutputTableData; + Produces jetOutputTableMCD; + Produces jetSubstructureOutputTableMCD; + Produces jetOutputTableMCP; + Produces jetSubstructureOutputTableMCP; - template - void fillTables(T const& jet, U const& cands) - { - auto cand = cands[0]; - jetOutputTable(jet.globalIndex(), cand.globalIndex(), jet.pt(), jet.phi(), jet.eta(), jet.tracks().size()); - jetSubstructureOutputTable(jet.globalIndex(), jet.zg(), jet.rg(), jet.nsd()); - } - - void processDummy(aod::Tracks const& track) - { - } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processDummy, "Dummy process function turned on by default", true); + Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT cut"}; + Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; - void processD0Data(soa::Join::iterator const& jet, // add template back - soa::Join const& candidates, aod::Tracks const& tracks) - { - auto cands = jet.hfcandidates_as>(); - fillTables(jet, cands); - } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processD0Data, "D0 jet substructure output on data", false); + std::vector jetRadiiValues; - void processD0MCD(soa::Join::iterator const& jet, soa::Join const& candidates, aod::Tracks const& tracks) + void init(InitContext const&) { - auto cands = jet.hfcandidates_as>(); - fillTables(jet, cands); + jetRadiiValues = (std::vector)jetRadii; } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processD0MCD, "D0 jet substructure output on MC detector level", false); - void processD0MCP(soa::Join::iterator const& jet, aod::McParticles const& particles) - { - auto hfparticles = jet.hfcandidates_as(); - fillTables(jet, hfparticles); - } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processD0MCP, "D0 jet substructure output on MC particle level", false); - - void processLcData(soa::Join::iterator const& jet, // add template back - soa::Join const& candidates, aod::Tracks const& tracks) - { - auto cands = jet.hfcandidates_as>(); - fillTables(jet, cands); - } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processLcData, "Lc jet substructure output on data", false); + Filter jetSelection = aod::jet::pt >= jetPtMin; - void processLcMCD(soa::Join::iterator const& jet, soa::Join const& candidates, aod::Tracks const& tracks) + template + void fillTables(T const& collision, U const& jet, V const& cand, M& jetOutputTable, N& jetSubstructureOutputTable, std::vector geoMatching, std::vector ptMatching, std::vector candMatching) { - auto cands = jet.hfcandidates_as>(); - fillTables(jet, cands); + jetOutputTable(collision.globalIndex(), jet.globalIndex(), cand.globalIndex(), geoMatching, ptMatching, candMatching, jet.pt(), jet.phi(), jet.eta(), jet.r(), jet.tracks().size() + jet.hfcandidates().size()); + jetSubstructureOutputTable(jet.globalIndex(), jet.zg(), jet.rg(), jet.nsd()); } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processLcMCD, "Lc jet substructure output on MC detector level", false); - void processLcMCP(soa::Join::iterator const& jet, aod::McParticles const& particles) - { - auto hfparticles = jet.hfcandidates_as(); - fillTables(jet, hfparticles); - } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processLcMCP, "Lc jet substructure output on MC particle level", false); + void processDummy(typename CollisionTable::iterator const& collision) {} + PROCESS_SWITCH(JetSubstructureHFOutputTask, processDummy, "Dummy process function turned on by default", true); - void processBplusData(soa::Join::iterator const& jet, // add template back - soa::Join const& candidates, aod::Tracks const& tracks) + void processOutputData(typename CollisionTable::iterator const& collision, + JetTableData const& jets) { - auto cands = jet.hfcandidates_as>(); - fillTables(jet, cands); + std::vector geoMatching{-1}; + std::vector ptMatching{-1}; + std::vector candMatching{-1}; + for (const auto& jet : jets) { + for (const auto& jetRadiiValue : jetRadiiValues) { + if (jet.r() == round(jetRadiiValue * 100.0f)) { + auto cands = jet.template hfcandidates_as(); + auto cand = cands[0]; + fillTables(collision, jet, cand, jetOutputTableData, jetSubstructureOutputTableData, geoMatching, ptMatching, candMatching); + } + } + } } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processBplusData, "B+ jet substructure output on data", false); + PROCESS_SWITCH(JetSubstructureHFOutputTask, processOutputData, "hf jet substructure output Data", false); - void processBplusMCD(soa::Join::iterator const& jet, soa::Join const& candidates, aod::Tracks const& tracks) + void processOutputMCD(typename CollisionTable::iterator const& collision, + JetTableMCD const& mcdjets, + JetTableMCP const& mcpjets) { - auto cands = jet.hfcandidates_as>(); - fillTables(jet, cands); + for (const auto& mcdjet : mcdjets) { + for (const auto& jetRadiiValue : jetRadiiValues) { + if (mcdjet.r() == round(jetRadiiValue * 100.0f)) { + auto cands = mcdjet.template hfcandidates_as(); + auto cand = cands[0]; + std::vector geoMatching; + std::vector ptMatching; + std::vector candMatching; + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + geoMatching.push_back(mcpjet.globalIndex()); + } + for (auto& mcpjet : mcdjet.template matchedJetPt_as()) { + ptMatching.push_back(mcpjet.globalIndex()); + } + for (auto& mcpjet : mcdjet.template matchedJetCand_as()) { + candMatching.push_back(mcpjet.globalIndex()); + } + fillTables(collision, mcdjet, cand, jetOutputTableMCD, jetSubstructureOutputTableMCD, geoMatching, ptMatching, candMatching); + } + } + } } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processBplusMCD, "B+ jet substructure output on MC detector level", false); + PROCESS_SWITCH(JetSubstructureHFOutputTask, processOutputMCD, "hf jet substructure output MCD", false); - void processBplusMCP(soa::Join::iterator const& jet, aod::McParticles const& particles) + void processOutputMCP(typename McCollisionTable::iterator const& collision, + JetTableMCP const& mcpjets, + JetTableMCD const& mcdjets) { - auto hfparticles = jet.hfcandidates_as(); - fillTables(jet, hfparticles); + for (const auto& mcpjet : mcpjets) { + for (const auto& jetRadiiValue : jetRadiiValues) { + if (mcpjet.r() == round(jetRadiiValue * 100.0f)) { + auto cands = mcpjet.template hfcandidates_as(); + auto cand = cands[0]; + std::vector geoMatching; + std::vector ptMatching; + std::vector candMatching; + for (auto& mcdjet : mcpjet.template matchedJetGeo_as()) { + geoMatching.push_back(mcdjet.globalIndex()); + } + for (auto& mcdjet : mcpjet.template matchedJetPt_as()) { + ptMatching.push_back(mcdjet.globalIndex()); + } + for (auto& mcdjet : mcpjet.template matchedJetCand_as()) { + candMatching.push_back(mcdjet.globalIndex()); + } + fillTables(collision, mcpjet, cand, jetOutputTableMCP, jetSubstructureOutputTableMCP, geoMatching, ptMatching, candMatching); + } + } + } } - PROCESS_SWITCH(JetSubstructureHFOutputTask, processBplusMCP, "B+ jet substructure output on MC particle level", false); + PROCESS_SWITCH(JetSubstructureHFOutputTask, processOutputMCP, "hf jet substructure output MCP", false); }; -using JetSubstructureOutputDataD0 = JetSubstructureHFOutputTask; -using JetSubstructureOutputMCDetectorLevelD0 = JetSubstructureHFOutputTask; -using JetSubstructureOutputMCParticleLevelD0 = JetSubstructureHFOutputTask; -using JetSubstructureOutputDataLc = JetSubstructureHFOutputTask; -using JetSubstructureOutputMCDetectorLevelLc = JetSubstructureHFOutputTask; -using JetSubstructureOutputMCParticleLevelLc = JetSubstructureHFOutputTask; -using JetSubstructureOutputDataBplus = JetSubstructureHFOutputTask; -using JetSubstructureOutputMCDetectorLevelBplus = JetSubstructureHFOutputTask; -using JetSubstructureOutputMCParticleLevelBplus = JetSubstructureHFOutputTask; +using JetSubstructureOutputD0 = JetSubstructureHFOutputTask>, soa::Join, aod::D0ChargedJetOutput, aod::D0ChargedJetSubstructureOutput, soa::Filtered>, soa::Join, aod::D0ChargedMCDetectorLevelJetOutput, aod::D0ChargedMCDetectorLevelJetSubstructureOutput, soa::Filtered>, aod::McParticles, aod::D0ChargedMCParticleLevelJetOutput, aod::D0ChargedMCParticleLevelJetSubstructureOutput>; +// using JetSubstructureOutputLc = JetSubstructureHFOutputTask>, soa::Join, aod::LcChargedJetOutput, aod::LcChargedJetSubstructureOutput,soa::Filtered>, soa::Join, aod::LcChargedMCDetectorLevelJetOutput, aod::LcChargedMCDetectorLevelJetSubstructureOutput, soa::Filtered>, aod::McParticles, aod::LcChargedMCParticleLevelJetOutput, aod::LcChargedMCParticleLevelJetSubstructureOutput>; +// using JetSubstructureOutputBplus = JetSubstructureHFOutputTask>, soa::Join, aod::BplusChargedJetOutput, aod::BplusChargedJetSubstructureOutput,soa::Filtered>, soa::Join, aod::BplusChargedMCDetectorLevelJetOutput, aod::BplusChargedMCDetectorLevelJetSubstructureOutput, soa::Filtered>, aod::McParticles, aod::BplusChargedMCParticleLevelJetOutput, aod::BplusChargedMCParticleLevelJetSubstructureOutput>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { std::vector tasks; - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-D0-data"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-D0-mcd"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-D0-mcp"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-Lc-data"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-Lc-mcd"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-Lc-mcp"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-Bplus-data"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-Bplus-mcd"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, - SetDefaultProcesses{}, - TaskName{"jet-substructure-output-Bplus-mcp"})); - + tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructured0-output"})); + // tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructurelc-output"})); + // tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructurebplus-output"})); return WorkflowSpec{tasks}; } diff --git a/PWGJE/Tasks/jetsubstructureoutput.cxx b/PWGJE/Tasks/jetsubstructureoutput.cxx index faaf8143071..ce55a16cbce 100644 --- a/PWGJE/Tasks/jetsubstructureoutput.cxx +++ b/PWGJE/Tasks/jetsubstructureoutput.cxx @@ -36,47 +36,106 @@ using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! #include "Framework/runDataProcessing.h" -template +template struct JetSubstructureOutputTask { - Produces jetOutputTable; - Produces jetSubstructureOutputTable; + Produces jetOutputTableData; + Produces jetSubstructureOutputTableData; + Produces jetOutputTableMCD; + Produces jetSubstructureOutputTableMCD; + Produces jetOutputTableMCP; + Produces jetSubstructureOutputTableMCP; - template - void fillTables(T const& jet) + Configurable jetPtMin{"jetPtMin", 0.0, "minimum jet pT cut"}; + Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; + + std::vector jetRadiiValues; + + void init(InitContext const&) + { + jetRadiiValues = (std::vector)jetRadii; + } + + Filter jetSelection = aod::jet::pt >= jetPtMin; + + template + void fillTables(T const& collision, U const& jet, V& jetOutputTable, M& jetSubstructureOutputTable, std::vector geoMatching, std::vector ptMatching, std::vector candMatching) { - jetOutputTable(jet.globalIndex(), -1, jet.pt(), jet.phi(), jet.eta(), jet.tracks().size()); + jetOutputTable(collision.globalIndex(), jet.globalIndex(), -1, geoMatching, ptMatching, candMatching, jet.pt(), jet.phi(), jet.eta(), jet.r(), jet.tracks().size()); jetSubstructureOutputTable(jet.globalIndex(), jet.zg(), jet.rg(), jet.nsd()); } - void processDummy(aod::Tracks const& track) {} + void processDummy(typename CollisionTable::iterator const& collision) {} PROCESS_SWITCH(JetSubstructureOutputTask, processDummy, "Dummy process function turned on by default", true); - void processData(soa::Join::iterator const& jet, // add template back - aod::Tracks const& tracks) + void processOutputData(typename CollisionTable::iterator const& collision, + JetTableData const& jets) { - fillTables(jet); + std::vector geoMatching{-1}; + std::vector ptMatching{-1}; + std::vector candMatching{-1}; + for (const auto& jet : jets) { + for (const auto& jetRadiiValue : jetRadiiValues) { + if (jet.r() == round(jetRadiiValue * 100.0f)) { + fillTables(collision, jet, jetOutputTableData, jetSubstructureOutputTableData, geoMatching, ptMatching, candMatching); + } + } + } } - PROCESS_SWITCH(JetSubstructureOutputTask, processData, "jet substructure output on data", false); + PROCESS_SWITCH(JetSubstructureOutputTask, processOutputData, "jet substructure output Data", false); - void processMCD(soa::Join::iterator const& jet, aod::Tracks const& tracks) { fillTables(jet); } - PROCESS_SWITCH(JetSubstructureOutputTask, processMCD, "jet substructure output on MC detector level", false); + void processOutputMCD(typename CollisionTable::iterator const& collision, + JetTableMCD const& mcdjets, + JetTableMCP const& mcpjets) + { + std::vector candMatching{-1}; + for (const auto& mcdjet : mcdjets) { + for (const auto& jetRadiiValue : jetRadiiValues) { + if (mcdjet.r() == round(jetRadiiValue * 100.0f)) { + std::vector geoMatching; + std::vector ptMatching; + for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + geoMatching.push_back(mcpjet.globalIndex()); + } + for (auto& mcpjet : mcdjet.template matchedJetPt_as()) { + ptMatching.push_back(mcpjet.globalIndex()); + } + fillTables(collision, mcdjet, jetOutputTableMCD, jetSubstructureOutputTableMCD, geoMatching, ptMatching, candMatching); + } + } + } + } + PROCESS_SWITCH(JetSubstructureOutputTask, processOutputMCD, "jet substructure output MCD", false); - void processMCP(soa::Join::iterator const& jet, aod::McParticles const& particles) { fillTables(jet); } - PROCESS_SWITCH(JetSubstructureOutputTask, processMCP, "jet substructure output on MC particle level", false); + void processOutputMCP(typename McCollisionTable::iterator const& collision, + JetTableMCP const& mcpjets, + JetTableMCD const& mcdjets) + { + std::vector candMatching{-1}; + for (const auto& mcpjet : mcpjets) { + for (const auto& jetRadiiValue : jetRadiiValues) { + if (mcpjet.r() == round(jetRadiiValue * 100.0f)) { + std::vector geoMatching; + std::vector ptMatching; + for (auto& mcdjet : mcpjet.template matchedJetGeo_as()) { + geoMatching.push_back(mcdjet.globalIndex()); + } + for (auto& mcdjet : mcpjet.template matchedJetPt_as()) { + ptMatching.push_back(mcdjet.globalIndex()); + } + fillTables(collision, mcpjet, jetOutputTableMCP, jetSubstructureOutputTableMCP, geoMatching, ptMatching, candMatching); + } + } + } + } + PROCESS_SWITCH(JetSubstructureOutputTask, processOutputMCP, "jet substructure output MCP", false); }; -using JetSubstructureOutputData = JetSubstructureOutputTask; -using JetSubstructureOutputMCDetectorLevel = JetSubstructureOutputTask; -using JetSubstructureOutputMCParticleLevel = JetSubstructureOutputTask; +using JetSubstructureOutput = JetSubstructureOutputTask>, aod::ChargedJetOutput, aod::ChargedJetSubstructureOutput, soa::Filtered>, aod::ChargedMCDetectorLevelJetOutput, aod::ChargedMCDetectorLevelJetSubstructureOutput, soa::Filtered>, aod::ChargedMCParticleLevelJetOutput, aod::ChargedMCParticleLevelJetSubstructureOutput>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { std::vector tasks; - tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-output-data"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-output-mcd"})); - - tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-output-mcp"})); + tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-output"})); return WorkflowSpec{tasks}; } diff --git a/PWGJE/Tasks/jetvalidationqa.cxx b/PWGJE/Tasks/jetvalidationqa.cxx index 96e8d958f94..c90d116aaae 100644 --- a/PWGJE/Tasks/jetvalidationqa.cxx +++ b/PWGJE/Tasks/jetvalidationqa.cxx @@ -77,7 +77,8 @@ struct jetTrackCollisionQa { trackSelection = static_cast(trackSelections); // histograms // 1)Jetvalidation on data - mHistManager.add("collisionVtxZ", "control collsion VtxZ ", HistType::kTH1D, {vtxZAxis}); + mHistManager.add("collisionVtxZ", "selected collsion VtxZ ", HistType::kTH1D, {vtxZAxis}); + mHistManager.add("controlCollisionVtxZ", "control collsion VtxZ ", HistType::kTH1D, {vtxZAxis}); // process jet qa mHistManager.add("jetPt", "inclusive jetPt ", HistType::kTH1F, {ptAxis}); mHistManager.add("jetPhi", "inclusive jet #phi ", HistType::kTH1F, {phiAxis}); @@ -103,6 +104,19 @@ struct jetTrackCollisionQa { mHistManager.add("leadTrackPt", "leading selected track Pt", HistType::kTH1F, {ptAxis}); mHistManager.add("leadTrackPhi", "leading selected track #phi", HistType::kTH1F, {phiAxis}); mHistManager.add("leadTrackEta", "leading selected track #eta", HistType::kTH1F, {etaAxis}); + + // Some more Track QA histos to test the implemented track cuts + mHistManager.add("TPC/nClsCrossedRows", "nCls crossed rows TPC", HistType::kTH1F, {{165, -0.5, 164.5}}); + mHistManager.add("TPC/chi2PerCluster", "chi2 per cluster TPC", HistType::kTH1F, {{500, 0, 10}}); + mHistManager.add("TPC/crossedRowsOverFindableCls", "ratio of crossed rows over findable cluster TPC", HistType::kTH1F, {{120, 0.0, 1.2}}); + mHistManager.add("TPC/NClsFindable", "number of findable TPC clusters;# findable clusters TPC", HistType::kTH1F, {{165, -0.5, 164.5}}); + mHistManager.add("TPC/NClsFound", "number of found TPC clusters;# clusters TPC", HistType::kTH1F, {{165, -0.5, 164.5}}); + mHistManager.add("TPC/NClsShared", "number of shared TPC clusters;# shared clusters TPC", HistType::kTH1F, {{165, -0.5, 164.5}}); + mHistManager.add("TPC/FractionSharedCls", "fraction of shared TPC clusters;# fraction shared clusters TPC", HistType::kTH1F, {{100, 0., 1.}}); + + mHistManager.add("ITS/chi2PerCluster", "chi2 per ITS cluster", HistType::kTH1F, {{100, 0, 40}}); + mHistManager.add("ITS/itsHits", "hitmap ITS;#it{p}_{T} [GeV/c];layer ITS", HistType::kTH1F, {{7, -0.5, 6.5}}); + mHistManager.add("ITS/itsNCls", "number of found ITS clusters;# clusters ITS", HistType::kTH1F, {{8, -0.5, 7.5}}); } template @@ -111,6 +125,22 @@ struct jetTrackCollisionQa { mHistManager.fill(HIST("selectedTrackPt"), track.pt()); mHistManager.fill(HIST("selectedTrackPhi"), track.phi()); mHistManager.fill(HIST("selectedTrackEta"), track.eta()); + // START OF FILLING TRACK CUTS HISTOS + mHistManager.fill(HIST("TPC/chi2PerCluster"), track.tpcChi2NCl()); + mHistManager.fill(HIST("TPC/nClsCrossedRows"), track.tpcNClsCrossedRows()); + mHistManager.fill(HIST("TPC/crossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + mHistManager.fill(HIST("TPC/NClsFindable"), track.tpcNClsFindable()); + mHistManager.fill(HIST("TPC/NClsFound"), track.tpcNClsFound()); + mHistManager.fill(HIST("TPC/NClsShared"), track.tpcNClsShared()); + mHistManager.fill(HIST("TPC/FractionSharedCls"), track.tpcFractionSharedCls()); + + mHistManager.fill(HIST("ITS/chi2PerCluster"), track.itsChi2NCl()); + mHistManager.fill(HIST("ITS/itsNCls"), track.itsNCls()); + for (unsigned int i = 0; i < 7; i++) { + if (track.itsClusterMap() & (1 << i)) { + mHistManager.fill(HIST("ITS/itsHits"), i); + } + } } // end of fillTrackQA template void fillLeadingTrackQA(double leadingTrackPt, double leadingTrackPhi, double leadingTrackEta) @@ -156,6 +186,7 @@ struct jetTrackCollisionQa { void processESD(soa::Join::iterator const& collision, soa::Join const& jets, TracksJE const& tracks) { + mHistManager.fill(HIST("controlCollisionVtxZ"), collision.posZ()); if (evSel == true) { if (!collision.sel7() || fabs(collision.posZ()) > 10) { return; @@ -173,7 +204,7 @@ struct jetTrackCollisionQa { double leadingTrackEta = -1; // qa histograms for selected tracks in collision for (const auto& t : tracks) { - if ((t.collisionId() == collision.globalIndex()) & (selectTrack(t, trackSelection) == true)) { + if ((t.collisionId() == collision.globalIndex()) && (selectTrack(t, trackSelection) == true)) { fillTrackQA(t); if (t.pt() > leadingTrackPt) { leadingTrackPt = t.pt(); @@ -191,7 +222,7 @@ struct jetTrackCollisionQa { // jet QA hists per jet in this collision for (const auto& j : jets) { if (j.collisionId() != collision.globalIndex()) { - return; + continue; } fillJetQA(j); if (j.pt() > leadingJetPt) { @@ -237,7 +268,7 @@ struct jetTrackCollisionQa { double leadingTrackEta = -1; // qa histograms for selected tracks in collision for (const auto& t : tracks) { - if ((t.collisionId() == collision.globalIndex()) & (selectTrack(t, trackSelection) == true)) { + if ((t.collisionId() == collision.globalIndex()) && (selectTrack(t, trackSelection) == true)) { fillTrackQA(t); if (t.pt() > leadingTrackPt) { leadingTrackPt = t.pt(); @@ -255,7 +286,7 @@ struct jetTrackCollisionQa { // jet QA hists per jet in this collision for (const auto& j : jets) { if (j.collisionId() != collision.globalIndex()) { - return; + continue; } fillJetQA(j); if (j.pt() > leadingJetPt) { @@ -389,8 +420,8 @@ struct mcJetTrackCollisionQa { void fillMcTrackHistos(ValidationTracks const& mct, coll collision, bool mc) // could give collision as argument for additional association { for (const auto& track : mct) { - if ((!selectTrack(track, trackSelection)) || (track.collisionId() == collision.globalIndex())) { - return; + if ((!selectTrack(track, trackSelection)) || !(track.collisionId() == collision.globalIndex())) { + continue; } if (mc == true) { if (track.has_mcParticle()) { diff --git a/PWGJE/Tasks/nSubjettiness.cxx b/PWGJE/Tasks/nSubjettiness.cxx new file mode 100644 index 00000000000..e5f4586e292 --- /dev/null +++ b/PWGJE/Tasks/nSubjettiness.cxx @@ -0,0 +1,244 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file jetmatching.cxx +/// \brief jet nSubjettiness calculation task + +/// \author Aimeric Landou + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/runDataProcessing.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/Logger.h" +#include "Framework/HistogramRegistry.h" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/FastJetUtilities.h" +#include "fastjet/contrib/Nsubjettiness.hh" +#include "fastjet/contrib/AxesDefinition.hh" +#include "fastjet/contrib/MeasureDefinition.hh" +#include "fastjet/contrib/SoftDrop.hh" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using Collisions = soa::Join; +using Tracks = soa::Join; + +template +struct nSubJettiness { + + HistogramRegistry registry{ + "registry", + { + {"hErrorControl", "hErrorControl", {HistType::kTH1F, {{2, -999.0f, -997.0f, ""}}}}, + }, + }; + + Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; + + Configurable SD_beta{"SD_beta", 0.0, "SoftDrop beta"}; + Configurable SD_z_cut{"SD_z_cut", 0.10, "SoftDrop z cut"}; + + ConfigurableAxis ptBinning{"pt-binning", {200, 0.0f, 100.0f}, ""}; + ConfigurableAxis DeltaRBinning{"Delta-R-binning", {50, 0.0, 0.5}, ""}; + ConfigurableAxis NSubRatioBinning{"NSub-Ratio-binning", {50, 0.0f, 1.2f}, ""}; + + std::vector jetConstituents; + fastjet::ClusterSequence clusterSeq_pseudoJet; + + void init(InitContext const&) + { + AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/c)"}; + AxisSpec DeltaRAxis = {DeltaRBinning, "#Delta R"}; + AxisSpec NSubRatioAxis = {NSubRatioBinning, "#tau_{2}/#tau_{1}"}; + + registry.add("hNSubRatio21_Kt", "#tau_{2}/#tau_{1} distribution with k_{T} subjet axes", {HistType::kTH1F, {NSubRatioAxis}}); + registry.get(HIST("hNSubRatio21_Kt"))->Sumw2(); + registry.add("hNSubRatio21_CA", "#tau_{2}/#tau_{1} distribution with C/A subjet axes", {HistType::kTH1F, {NSubRatioAxis}}); + registry.get(HIST("hNSubRatio21_CA"))->Sumw2(); + registry.add("hNSubRatio21_SD", "#tau_{2}/#tau_{1} distribution with Softdrop subjet axes", {HistType::kTH1F, {NSubRatioAxis}}); + registry.get(HIST("hNSubRatio21_SD"))->Sumw2(); + + registry.add("hNSubRatio21VsPt_Kt", "#tau_{2}/#tau_{1} distribution with k_{T} subjet axes", {HistType::kTH2F, {ptAxis, NSubRatioAxis}}); + registry.get(HIST("hNSubRatio21VsPt_Kt"))->Sumw2(); + registry.add("hNSubRatio21VsPt_CA", "#tau_{2}/#tau_{1} distribution with C/A subjet axes", {HistType::kTH2F, {ptAxis, NSubRatioAxis}}); + registry.get(HIST("hNSubRatio21VsPt_CA"))->Sumw2(); + registry.add("hNSubRatio21VsPt_SD", "#tau_{2}/#tau_{1} distribution with Softdrop subjet axes", {HistType::kTH2F, {ptAxis, NSubRatioAxis}}); + registry.get(HIST("hNSubRatio21VsPt_SD"))->Sumw2(); + + registry.add("hDeltaR_Kt", "#Delta R distribution with k_{T} subjet axes", {HistType::kTH1F, {DeltaRAxis}}); + registry.get(HIST("hDeltaR_Kt"))->Sumw2(); + registry.add("hDeltaR_CA", "#Delta R distribution with C/A subjet axes", {HistType::kTH1F, {DeltaRAxis}}); + registry.get(HIST("hDeltaR_CA"))->Sumw2(); + registry.add("hDeltaR_SD", "#Delta R distribution with Softdrop subjet axes", {HistType::kTH1F, {DeltaRAxis}}); + registry.get(HIST("hDeltaR_SD"))->Sumw2(); + + registry.add("hDeltaRVsPt_Kt", "#Delta R distribution with k_{T} subjet axes", {HistType::kTH2F, {ptAxis, DeltaRAxis}}); + registry.get(HIST("hDeltaRVsPt_Kt"))->Sumw2(); + registry.add("hDeltaRVsPt_CA", "#Delta R distribution with C/A subjet axes", {HistType::kTH2F, {ptAxis, DeltaRAxis}}); + registry.get(HIST("hDeltaRVsPt_CA"))->Sumw2(); + registry.add("hDeltaRVsPt_SD", "#Delta R distribution with Softdrop subjet axes", {HistType::kTH2F, {ptAxis, DeltaRAxis}}); + registry.get(HIST("hDeltaRVsPt_SD"))->Sumw2(); + + registry.get(HIST("hErrorControl"))->GetXaxis()->SetBinLabel(1, "Single track jet"); + registry.get(HIST("hErrorControl"))->GetXaxis()->SetBinLabel(2, "Single track groomed jet"); + } + + // function that converts a jet from the O2Physics jet table into a pseudojet; the fastjet cluster sequence of the jet needs to be given as input and will be modified by the function to save the clustering information + template + void jetToPseudoJet(JetTableElement const& jet, fastjet::PseudoJet& pseudoJet, std::vector jetConstituents, fastjet::ClusterSequence& clusterSeqInput) + { + for (auto& jetConstituent : jet.template tracks_as()) { + FastJetUtilities::fillTracks(jetConstituent, jetConstituents, jetConstituent.globalIndex()); + } + + fastjet::JetDefinition jet_def(fastjet::JetAlgorithm::kt_algorithm, 2.5 * jet.r() / 100); + fastjet::ClusterSequence clusterSeq(jetConstituents, jet_def); + + clusterSeqInput.transfer_from_sequence(clusterSeq); + pseudoJet = sorted_by_pt(clusterSeqInput.inclusive_jets())[0]; // returns the jet found by the reclustering with the largest pT; should be the one corresponding to the jet table element + } + + // function that returns the N-subjettiness ratio and the distance betewwen the two axes considered for tau2, in the form of a vector + template + std::vector getNsubRatio21(fastjet::PseudoJet pseudoJet, float const& jetR, AxesTypeArg const& axesType, std::string const& axesTypeString) + { + std::vector nSub_results; + + fastjet::contrib::Nsubjettiness nSub_1(1, axesType, fastjet::contrib::NormalizedMeasure(1.0, jetR)); + fastjet::contrib::Nsubjettiness nSub_2(2, axesType, fastjet::contrib::NormalizedMeasure(1.0, jetR)); + + if (axesTypeString == "SD") { + fastjet::contrib::SoftDrop softdropAlgo(SD_beta, SD_z_cut); + pseudoJet = softdropAlgo(pseudoJet); + if (pseudoJet.constituents().size() < 2) { // this analsysis requires at least 2 subjets in the jet which in turn requires at least two constituents + nSub_results = {-998., -998.}; // error values + return nSub_results; + } + } + float tau1 = nSub_1.result(pseudoJet); + float tau2 = nSub_2.result(pseudoJet); + std::vector axes_nSub_2 = nSub_2.currentAxes(); // gets the two axes used in the 2-subjettiness calculation + + float nSubRatio_21 = tau2 / tau1; + float DeltaR = axes_nSub_2[0].delta_R(axes_nSub_2[1]); // distance between axes + + nSub_results = {nSubRatio_21, DeltaR}; + return nSub_results; + } + + Filter jetCuts = aod::jet::r == nround(jetR.node() * 100.0f); + + template + void processOneJet(T const& jet, float weight = 1) + { + if (jet.tracksIds().size() < 2) { // this analsysis requires at least 2 subjets in the jet which in turn requires at least two constituents + registry.fill(HIST("hErrorControl"), -999); + } else { + fastjet::PseudoJet pseudoJet; + jetConstituents.clear(); + jetToPseudoJet(jet, pseudoJet, jetConstituents, clusterSeq_pseudoJet); + std::vector nSub_Kt_results = getNsubRatio21(pseudoJet, jet.r() / 100., fastjet::contrib::KT_Axes(), "Kt"); + std::vector nSub_CA_results = getNsubRatio21(pseudoJet, jet.r() / 100., fastjet::contrib::CA_Axes(), "CA"); + std::vector nSub_SD_results = getNsubRatio21(pseudoJet, jet.r() / 100., fastjet::contrib::CA_Axes(), "SD"); + + registry.fill(HIST("hNSubRatio21_Kt"), nSub_Kt_results[0], weight); + registry.fill(HIST("hNSubRatio21_CA"), nSub_CA_results[0], weight); + registry.fill(HIST("hDeltaR_Kt"), nSub_Kt_results[1], weight); + registry.fill(HIST("hDeltaR_CA"), nSub_CA_results[1], weight); + + registry.fill(HIST("hNSubRatio21VsPt_Kt"), jet.pt(), nSub_Kt_results[0], weight); + registry.fill(HIST("hNSubRatio21VsPt_CA"), jet.pt(), nSub_CA_results[0], weight); + registry.fill(HIST("hDeltaRVsPt_Kt"), jet.pt(), nSub_Kt_results[1], weight); + registry.fill(HIST("hDeltaRVsPt_CA"), jet.pt(), nSub_CA_results[1], weight); + + if (nSub_SD_results[0] > -900) { // makes sure the grooming found at least one splitting that satisfied the Soft Drop condition before filling the result histograms for SD, like it is done for kT and CA + registry.fill(HIST("hNSubRatio21_SD"), nSub_SD_results[0], weight); + registry.fill(HIST("hDeltaR_SD"), nSub_SD_results[1], weight); + + registry.fill(HIST("hNSubRatio21VsPt_SD"), jet.pt(), nSub_SD_results[0], weight); + registry.fill(HIST("hDeltaRVsPt_SD"), jet.pt(), nSub_SD_results[1], weight); + } else { + registry.fill(HIST("hErrorControl"), -998); + } + } + } + + void processJets(typename CollisionTable::iterator const& collision, soa::Filtered const& jets, TrackTable const& tracks) + { + for (auto& jet : jets) { + processOneJet(jet); + } + } + PROCESS_SWITCH(nSubJettiness, processJets, "Process function, turned off by default", false); + + void processJetsWeighted(typename CollisionTable::iterator const& collision, soa::Filtered> const& jets, TrackTable const& tracks) + { + float weight; + for (auto& jet : jets) { + weight = jet.eventWeight(); + processOneJet(jet, weight); + } + } + PROCESS_SWITCH(nSubJettiness, processJetsWeighted, "Process function with weighted events, turned off by default", false); + + void processDummy(aod::Tracks const& track) + { + } + PROCESS_SWITCH(nSubJettiness, processDummy, "Dummy process function, turned on by default", true); +}; +using NSubjettinessChargedJetMCParticleLevel = nSubJettiness, aod::ChargedMCParticleLevelJetEventWeights, aod::McParticles>; +using NSubjettinessChargedJetMCDetectorLevel = nSubJettiness, aod::ChargedMCDetectorLevelJetEventWeights, aod::Tracks>; +// using NSubjettinessChargedJetMCParticleLevel = nSubJettiness, aod::McParticles>; +// using NSubjettinessChargedJetMCDetectorLevel = nSubJettiness, aod::Tracks>; +// using NSubjettinessChargedJetDataLevel = nSubJettiness, aod::Tracks>; + +// using NSubjettinessD0ChargedJetMCParticleLevel = nSubJettiness, aod::McParticles>; +// using NSubjettinessD0ChargedJetMCDetectorLevel = nSubJettiness, aod::Tracks>; +// // using NSubjettinessD0ChargedJetDataLevel = nSubJettiness, aod::Tracks>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-nsubjettiness-charged-mcp"})); + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-nsubjettiness-charged-mcd"})); + + // tasks.emplace_back(adaptAnalysisTask(cfgc, + // SetDefaultProcesses{}, + // TaskName{"jet-nsubjettiness-charged-data"})); + + // tasks.emplace_back(adaptAnalysisTask(cfgc, + // SetDefaultProcesses{}, + // TaskName{"jet-nsubjettiness-d0-mcp"})); + + // tasks.emplace_back(adaptAnalysisTask(cfgc, + // SetDefaultProcesses{}, + // TaskName{"jet-nsubjettiness-d0-mcd"})); + + // tasks.emplace_back(adaptAnalysisTask(cfgc, + // SetDefaultProcesses{}, + // TaskName{"jet-nsubjettiness-d0-data"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/Tasks/trackJetqa.cxx b/PWGJE/Tasks/trackJetqa.cxx new file mode 100644 index 00000000000..a844ce25ab2 --- /dev/null +++ b/PWGJE/Tasks/trackJetqa.cxx @@ -0,0 +1,322 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// \author +// Alice Caluisi - alice.caluisi@cern.ch +// \since July 2023 + +// +// Task producing jet tracking qa histograms +// +#include + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Framework/ASoA.h" + +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/TrackJetQa.h" +#include "PWGJE/TableProducer/jetfinder.h" + +using namespace o2; +using namespace o2::track; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct TrackJetQa { + HistogramRegistry histos{"JetQAHistograms"}; + // Configurable selectedTracks{"select", 1, "Choice of track selection. 0 = no selection, 1 = globalTracks"}; --not in use + Configurable enable{"selectTrack", true, "false = disable track selection, true = enable track selection"}; + Configurable nBins{"nBins", 200, "N bins in histos"}; + + Configurable ValVtx{"ValVtx", 10, "Value of the vertex position"}; + Configurable ValCutEta{"ValCutEta", 0.8f, "Eta range for tracks"}; + Configurable ValCutY{"ValCutY", 0.5f, "Y range for tracks"}; + + // Custom track cuts for the cut variation study + TrackSelection customTrackCuts; + Configurable itsPattern{"itsPattern", 1, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable requireITS{"requireITS", true, "Additional cut on the ITS requirement"}; + Configurable requireTPC{"requireTPC", true, "Additional cut on the TPC requirement"}; + Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 60.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.7f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 7.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Additional cut on the maximum value of the DCA xy (multiplicative factor)"}; + Configurable maxDcaZ{"maxDcaZ", 3.f, "Additional cut on the maximum value of the DCA z"}; + Configurable minTPCNClsFound{"minTPCNClsFound", 0.f, "Additional cut on the minimum value of the number of found clusters in the TPC"}; + + void init(o2::framework::InitContext&) + { + // Custom track cuts - to adjust cuts for the tree analysis via configurables + LOG(info) << "Using custom track cuts from values:"; + LOG(info) << "\trequireITS=" << requireITS.value; + LOG(info) << "\trequireTPC=" << requireTPC.value; + LOG(info) << "\trequireGoldenChi2=" << requireGoldenChi2.value; + LOG(info) << "\tmaxChi2PerClusterTPC=" << maxChi2PerClusterTPC.value; + LOG(info) << "\tminNCrossedRowsTPC=" << minNCrossedRowsTPC.value; + LOG(info) << "\tminTPCNClsFound=" << minTPCNClsFound.value; + LOG(info) << "\tmaxChi2PerClusterITS=" << maxChi2PerClusterITS.value; + LOG(info) << "\tmaxDcaZ=" << maxDcaZ.value; + + customTrackCuts = getGlobalTrackSelectionRun3ITSMatch(itsPattern.value); + LOG(info) << "Customizing track cuts:"; + customTrackCuts.SetRequireITSRefit(requireITS.value); + customTrackCuts.SetRequireTPCRefit(requireTPC.value); + customTrackCuts.SetRequireGoldenChi2(requireGoldenChi2.value); + customTrackCuts.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); + customTrackCuts.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); + customTrackCuts.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); + customTrackCuts.SetMinNClustersTPC(minTPCNClsFound.value); + customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + customTrackCuts.SetMaxDcaXYPtDep([](float pt) { return 10.f; }); // No DCAxy cut will be used, this is done via the member function of the task + customTrackCuts.SetMaxDcaZ(maxDcaZ.value); + customTrackCuts.print(); + // kinetic histograms + histos.add("Kine/pt", "#it{p}_{T};#it{p}_{T} [GeV/c];number of entries", HistType::kTH1F, {{nBins, 0, 200}}); + histos.add("Kine/pt_TRD", "#it{p}_{T} if track has a TRD match;#it{p}_{T} [GeV/c];number of entries", HistType::kTH1F, {{nBins, 0, 200}}); + histos.add("Kine/eta", "#eta;#it{p}_{T} [GeV/c];#eta", {HistType::kTH2F, {{nBins, 0, 200}, {180, -0.9, 0.9}}}); + histos.add("Kine/phi", "#phi;#it{p}_{T} [GeV/c];#phi [rad]", {HistType::kTH2F, {{nBins, 0, 200}, {180, 0., 2 * M_PI}}}); + histos.add("Kine/etaVSphi", "#eta VS phi;#eta;#phi [rad]", {HistType::kTH2F, {{180, -0.9, 0.9}, {180, 0., 2 * M_PI}}}); + histos.add("Kine/etaVSphi0", "#eta VS phi in pT range {0, 1};#eta;#phi [rad]", {HistType::kTH2F, {{180, -0.9, 0.9}, {180, 0., 2 * M_PI}}}); + histos.add("Kine/etaVSphi1", "#eta VS phi in pT range {1, 2};#eta;#phi [rad]", {HistType::kTH2F, {{180, -0.9, 0.9}, {180, 0., 2 * M_PI}}}); + histos.add("Kine/etaVSphi2", "#eta VS phi in pT range {2, 5};#eta;#phi [rad]", {HistType::kTH2F, {{180, -0.9, 0.9}, {180, 0., 2 * M_PI}}}); + histos.add("Kine/etaVSphi3", "#eta VS phi in pT range {5, 10};#eta;#phi [rad]", {HistType::kTH2F, {{180, -0.9, 0.9}, {180, 0., 2 * M_PI}}}); + histos.add("Kine/etaVSphi4", "#eta VS phi in pT range {10, 20};#eta;#phi [rad]", {HistType::kTH2F, {{180, -0.9, 0.9}, {180, 0., 2 * M_PI}}}); + histos.add("Kine/etaVSphi5", "#eta VS phi in pT range {20, 50};#eta;#phi [rad]", {HistType::kTH2F, {{180, -0.9, 0.9}, {180, 0., 2 * M_PI}}}); + histos.add("Kine/etaVSphi6", "#eta VS phi in pT range {50, 200};#eta;#phi [rad]", {HistType::kTH2F, {{180, -0.9, 0.9}, {180, 0., 2 * M_PI}}}); + + // track parameter histograms + histos.add("TrackPar/x", "track #it{x} position at dca in local coordinate system;#it{p}_{T} [GeV/c];#it{x} [cm]", {HistType::kTH2F, {{nBins, 0, 200}, {200, -0.36, 0.36}}}); + histos.add("TrackPar/y", "track #it{y} position at dca in local coordinate system;#it{p}_{T} [GeV/c];#it{y} [cm]", {HistType::kTH2F, {{nBins, 0, 200}, {200, -0.5, 0.5}}}); + histos.add("TrackPar/z", "track #it{z} position at dca in local coordinate system;#it{p}_{T} [GeV/c];#it{z} [cm]", {HistType::kTH2F, {{nBins, 0, 200}, {200, -11., 11.}}}); + histos.add("TrackPar/alpha", "rotation angle of local wrt. global coordinate system;#it{p}_{T} [GeV/c];#alpha [rad]", {HistType::kTH2F, {{nBins, 0, 200}, {36, -M_PI, M_PI}}}); + histos.add("TrackPar/signed1Pt", "track signed 1/#it{p}_{T};#it{p}_{T} [GeV/c];#it{q}/#it{p}_{T}", {HistType::kTH2F, {{nBins, 0, 200}, {200, -8, 8}}}); + histos.add("TrackPar/snp", "sinus of track momentum azimuthal angle;#it{p}_{T} [GeV/c];snp", {HistType::kTH2F, {{nBins, 0, 200}, {11, -0.1, 0.1}}}); + histos.add("TrackPar/tgl", "tangent of the track momentum dip angle;#it{p}_{T} [GeV/c];tgl;", {HistType::kTH2F, {{nBins, 0, 200}, {200, -1., 1.}}}); + histos.add("TrackPar/flags", "track flag;#it{p}_{T} [GeV/c];flag bit", {HistType::kTH2F, {{nBins, 0, 200}, {64, -0.5, 63.5}}}); + histos.add("TrackPar/dcaXY", "distance of closest approach in #it{xy} plane;#it{p}_{T} [GeV/c];#it{dcaXY} [cm];", {HistType::kTH2F, {{nBins, 0, 200}, {200, -0.15, 0.15}}}); + histos.add("TrackPar/dcaZ", "distance of closest approach in #it{z};#it{p}_{T} [GeV/c];#it{dcaZ} [cm];", {HistType::kTH2F, {{nBins, 0, 200}, {200, -0.15, 0.15}}}); + histos.add("TrackPar/length", "track length in cm;#it{p}_{T} [GeV/c];#it{Length} [cm];", {HistType::kTH2F, {{nBins, 0, 200}, {200, 0, 1000}}}); + histos.add("TrackPar/Sigma1Pt", "uncertainty over #it{p}_{T};#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layer1", "uncertainty over #it{p}_{T} with only 1st ITS layer active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layer2", "uncertainty over #it{p}_{T} with only 2nd ITS layer active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layers12", "uncertainty over #it{p}_{T} with only 1st and 2nd ITS layers active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layer4", "uncertainty over #it{p}_{T} with only 4th ITS layer active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layer5", "uncertainty over #it{p}_{T} with only 5th ITS layer active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layer6", "uncertainty over #it{p}_{T} with only 6th ITS layer active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layers45", "uncertainty over #it{p}_{T} with only 4th and 5th ITS layers active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layers56", "uncertainty over #it{p}_{T} with only 5th and 6th ITS layers active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layers46", "uncertainty over #it{p}_{T} with only 4th and 6th ITS layers active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + histos.add("TrackPar/Sigma1Pt_Layers456", "uncertainty over #it{p}_{T} with only 4th, 5th and 6th ITS layers active;#it{p}_{T} [GeV/c];#it{p}_{T}*#it{sigma1}{p}_{T};", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 1}}}); + + // event property histograms + histos.add("EventProp/collisionVtxZ", "Collsion Vertex Z;#it{Vtx}_{z} [cm];number of entries", HistType::kTH1F, {{nBins, -20, 20}}); + histos.add("EventProp/collisionVtxZnoSel", "Collsion Vertex Z without event selection;#it{Vtx}_{z} [cm];number of entries", HistType::kTH1F, {{nBins, -20, 20}}); + histos.add("EventProp/collisionVtxZSel8", "Collsion Vertex Z with event selection;#it{Vtx}_{z} [cm];number of entries", HistType::kTH1F, {{nBins, -20, 20}}); + + // ITS histograms + histos.add("ITS/itsNCls", "number of found ITS clusters;#it{p}_{T} [GeV/c];# clusters ITS", {HistType::kTH2F, {{nBins, 0, 200}, {8, -0.5, 7.5}}}); + histos.add("ITS/itsChi2NCl", "chi2 per ITS cluster;#it{p}_{T} [GeV/c];chi2 / cluster ITS", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 40}}}); + histos.add("ITS/itsHits", "hitmap ITS;#it{p}_{T} [GeV/c];layer ITS", {HistType::kTH2F, {{nBins, 0, 200}, {7, -0.5, 6.5}}}); + + // TPC histograms + histos.add("TPC/tpcNClsFindable", "number of findable TPC clusters;#it{p}_{T} [GeV/c];# findable clusters TPC", {HistType::kTH2F, {{nBins, 0, 200}, {165, -0.5, 164.5}}}); + histos.add("TPC/tpcNClsFound", "number of found TPC clusters;#it{p}_{T} [GeV/c];# clusters TPC", {HistType::kTH2F, {{nBins, 0, 200}, {165, -0.5, 164.5}}}); + histos.add("TPC/tpcNClsShared", "number of shared TPC clusters;#it{p}_{T} [GeV/c];# shared clusters TPC", {HistType::kTH2F, {{nBins, 0, 200}, {165, -0.5, 164.5}}}); + histos.add("TPC/tpcNClsCrossedRows", "number of crossed TPC rows;#it{p}_{T} [GeV/c];# crossed rows TPC", {HistType::kTH2F, {{nBins, 0, 200}, {165, -0.5, 164.5}}}); + histos.add("TPC/tpcFractionSharedCls", "fraction of shared TPC clusters;#it{p}_{T} [GeV/c];fraction shared clusters TPC", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0., 1.}}}); + histos.add("TPC/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;#it{p}_{T} [GeV/c];crossed rows / findable clusters TPC", {HistType::kTH2F, {{nBins, 0, 200}, {120, 0.0, 1.2}}}); + histos.add("TPC/tpcChi2NCl", "chi2 per cluster in TPC;#it{p}_{T} [GeV/c];chi2 / cluster TPC", {HistType::kTH2F, {{nBins, 0, 200}, {100, 0, 10}}}); + + histos.print(); + } + + // @Alice, please make these blocks where you fill histograms templates that we can call in both process functions. Thank you ! + void processFull(soa::Join const& collisions, + soa::Join const& tracks) + { + + for (auto& collision : collisions) { + + // fill event property variables + histos.fill(HIST("EventProp/collisionVtxZnoSel"), collision.posZ()); + + if (!collision.sel8()) { + return; + } + histos.fill(HIST("EventProp/collisionVtxZSel8"), collision.posZ()); + + if (fabs(collision.posZ()) > ValVtx) { + return; + } + histos.fill(HIST("EventProp/collisionVtxZ"), collision.posZ()); + + Partition> groupedTracks = aod::track::collisionId == collision.globalIndex(); + groupedTracks.bindTable(tracks); + for (auto& track : groupedTracks) { + // Track selection + if (enable && !track.isGlobalTrackWoPtEta()) { + continue; + } + + // fill kinematic variables + histos.fill(HIST("Kine/pt"), track.pt()); + histos.fill(HIST("Kine/eta"), track.pt(), track.eta()); + histos.fill(HIST("Kine/phi"), track.pt(), track.phi()); + histos.fill(HIST("Kine/etaVSphi"), track.eta(), track.phi()); + if (track.hasTRD()) { + histos.fill(HIST("Kine/pt_TRD"), track.pt()); + } + + //// eta VS phi for different pT ranges + double pt = track.pt(); + if (pt >= 0.0 && pt < 1.0) { + histos.fill(HIST("Kine/etaVSphi0"), track.eta(), track.phi()); + } else if (pt >= 1.0 && pt < 2.0) { + histos.fill(HIST("Kine/etaVSphi1"), track.eta(), track.phi()); + } else if (pt >= 2.0 && pt <= 5.0) { + histos.fill(HIST("Kine/etaVSphi2"), track.eta(), track.phi()); + } else if (pt >= 5.0 && pt < 10.0) { + histos.fill(HIST("Kine/etaVSphi3"), track.eta(), track.phi()); + } else if (pt >= 10.0 && pt <= 20.0) { + histos.fill(HIST("Kine/etaVSphi4"), track.eta(), track.phi()); + } else if (pt >= 20.0 && pt <= 50.0) { + histos.fill(HIST("Kine/etaVSphi5"), track.eta(), track.phi()); + } else if (pt >= 50.0 && pt <= 200.0) { + histos.fill(HIST("Kine/etaVSphi6"), track.eta(), track.phi()); + } + + // fill track parameter variables + histos.fill(HIST("TrackPar/alpha"), track.pt(), track.alpha()); + histos.fill(HIST("TrackPar/x"), track.pt(), track.x()); + histos.fill(HIST("TrackPar/y"), track.pt(), track.y()); + histos.fill(HIST("TrackPar/z"), track.pt(), track.z()); + histos.fill(HIST("TrackPar/signed1Pt"), track.pt(), track.signed1Pt()); + histos.fill(HIST("TrackPar/snp"), track.pt(), track.snp()); + histos.fill(HIST("TrackPar/tgl"), track.pt(), track.tgl()); + for (unsigned int i = 0; i < 64; i++) { + if (track.flags() & (1 << i)) { + histos.fill(HIST("TrackPar/flags"), track.pt(), i); + } + } + histos.fill(HIST("TrackPar/dcaXY"), track.pt(), track.dcaXY()); + histos.fill(HIST("TrackPar/dcaZ"), track.pt(), track.dcaZ()); + histos.fill(HIST("TrackPar/length"), track.pt(), track.length()); + histos.fill(HIST("TrackPar/Sigma1Pt"), track.pt(), track.sigma1Pt() * track.pt()); + + //// check the uncertainty over pT activating several ITS layers + bool firstLayerActive = track.itsClusterMap() & (1 << 0); + bool secondLayerActive = track.itsClusterMap() & (1 << 1); + bool fourthLayerActive = track.itsClusterMap() & (1 << 3); + bool fifthLayerActive = track.itsClusterMap() & (1 << 4); + bool sixthLayerActive = track.itsClusterMap() & (1 << 5); + if (firstLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layer1"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (secondLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layer2"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (firstLayerActive && secondLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layers12"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (fourthLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layer4"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (fifthLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layer5"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (sixthLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layer6"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (fourthLayerActive && fifthLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layers45"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (fifthLayerActive && sixthLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layers56"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (fourthLayerActive && sixthLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layers46"), track.pt(), track.sigma1Pt() * track.pt()); + } + if (fourthLayerActive && fifthLayerActive && sixthLayerActive) { + histos.fill(HIST("TrackPar/Sigma1Pt_Layers456"), track.pt(), track.sigma1Pt() * track.pt()); + } + + // fill ITS variables + histos.fill(HIST("ITS/itsNCls"), track.pt(), track.itsNCls()); + histos.fill(HIST("ITS/itsChi2NCl"), track.pt(), track.itsChi2NCl()); + for (unsigned int i = 0; i < 7; i++) { + if (track.itsClusterMap() & (1 << i)) { + histos.fill(HIST("ITS/itsHits"), track.pt(), i); + } + } + + // fill TPC variables + histos.fill(HIST("TPC/tpcNClsFindable"), track.pt(), track.tpcNClsFindable()); + histos.fill(HIST("TPC/tpcNClsFound"), track.pt(), track.tpcNClsFound()); + histos.fill(HIST("TPC/tpcNClsShared"), track.pt(), track.tpcNClsShared()); + histos.fill(HIST("TPC/tpcNClsCrossedRows"), track.pt(), track.tpcNClsCrossedRows()); + histos.fill(HIST("TPC/tpcCrossedRowsOverFindableCls"), track.pt(), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("TPC/tpcFractionSharedCls"), track.pt(), track.tpcFractionSharedCls()); + histos.fill(HIST("TPC/tpcChi2NCl"), track.pt(), track.tpcChi2NCl()); + } + } + } + PROCESS_SWITCH(TrackJetQa, processFull, "Standard data processor", true); + + Preslice spPerCol = aod::spectra::collisionId; + SliceCache cacheTrk; + void processDerived(aod::SpColls const& collisions, + aod::SpTracks const& tracks) + { + for (const auto& collision : collisions) { + // fill event property variables - i put here a duplicate of your code above to test. Please make templates to shorten the code ! + histos.fill(HIST("EventProp/collisionVtxZnoSel"), collision.posZ()); + + if (!collision.sel8()) { + return; + } + histos.fill(HIST("EventProp/collisionVtxZSel8"), collision.posZ()); + + if (fabs(collision.posZ()) > ValVtx) { + return; + } + histos.fill(HIST("EventProp/collisionVtxZ"), collision.posZ()); + + // Partition> groupedTracks = aod::track::collisionId == collision.globalIndex(); + // groupedTracks.bindTable(tracks); + + const auto& tracksInCollision = tracks.sliceByCached(aod::spectra::collisionId, collision.globalIndex(), cacheTrk); + for (const auto& track : tracksInCollision) { + if (enable && !track.isGlobalTrackWoPtEta()) { + continue; + } + // filling all your histos.... please put them into templates and call the templates in the process functions. + // else you really just duplicate code and we want to save line here :) + } + } + } // end of the process function + PROCESS_SWITCH(TrackJetQa, processDerived, "Derived data processor", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow; + workflow.push_back(adaptAnalysisTask(cfgc)); + return workflow; +} diff --git a/PWGJE/Tasks/triggerCorrelations.cxx b/PWGJE/Tasks/triggerCorrelations.cxx new file mode 100644 index 00000000000..09c6fd59288 --- /dev/null +++ b/PWGJE/Tasks/triggerCorrelations.cxx @@ -0,0 +1,157 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// QA correlation task for jet trigger +// +// Authors: Nima Zardoshti + +#include + +#include "EMCALBase/Geometry.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/HistogramRegistry.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/CCDB/TriggerAliases.h" + +#include "Common/Core/RecoDecay.h" + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +#include "Framework/runDataProcessing.h" + +struct TriggerCorrelationsTask { + + HistogramRegistry registry{"registry", + {{"h3_jetcharged_pt_jetfull_pt_photon_pt_triggered", ";#it{p}_{T,jet}^{charged} (GeV/#it{c}); #it{p}_{T,jet}^{full} (GeV/#it{c}); #it{p}_{T,photon} (GeV/#it{c})", {HistType::kTH3F, {{201, -1.0, 200}, {201, -1.0, 200}, {201, -1.0, 200}}}, true}, + {"h_collision_trigger_events", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}, true}}}; + + Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; + Configurable doChargedJetTrigger{"doChargedJetTrigger", true, "add the charged jeet trigger to the QA"}; + Configurable doFullJetTrigger{"doFullJetTrigger", true, "add the full et trigger to the QA"}; + Configurable doGammaTrigger{"doGammaTrigger", true, "add the gamma trigger to the QA"}; + Configurable jetsChargedR{"jetsChargedR", 0.6, "resolution parameter for triggered charged jets"}; + Configurable jetsFullR{"jetsFullR", 0.2, "resolution parameter for triggered full jets"}; + Configurable rejectExoticClusters{"rejectExoticClusters", true, "reject exotic clusters"}; + Configurable clusterTimeMin{"clusterTimeMin", -999, "minimum cluster time for gamma trigger"}; + Configurable clusterTimeMax{"clusterTimeMax", 999, "maximum cluster time for gamma trigger"}; + Configurable emcalTriggered{"emcalTriggered", -1, "-1 = min bias, 0 = L0"}; + Configurable clusterDefinition{"clusterDefinition", "kV3Default", "cluster definition to be selected, e.g. V3Default"}; + + void init(o2::framework::InitContext&) + { + } + + o2::aod::EMCALClusterDefinition clusterDef = o2::aod::emcalcluster::getClusterDefinitionFromString(clusterDefinition.value); + Filter clusterDefinitionSelection = o2::aod::emcalcluster::definition == static_cast(clusterDef); + + void processTriggeredCorrelations(soa::Join::iterator const& collision, + soa::Join const& jetsCharged, + soa::Join const& jetsFull, + soa::Filtered const& clusters, + soa::Join const& tracks) + { + + registry.fill(HIST("h_collision_trigger_events"), 0.5); // all events + if (collision.posZ() < vertexZCut) { + registry.fill(HIST("h_collision_trigger_events"), 1.5); // all events with z vertex cut + } + if (collision.sel8()) { + registry.fill(HIST("h_collision_trigger_events"), 2.5); // events with sel8() + } + if (collision.alias_bit(kTVXinEMC)) { + registry.fill(HIST("h_collision_trigger_events"), 3.5); // events with emcal bit + } + + float jetsChargedLeadingPt = -1.0; + float jetsFullLeadingPt = -1.0; + float gammaLeadingPt = -1.0; + if (collision.sel8()) { + if (doChargedJetTrigger) { + for (auto& jetCharged : jetsCharged) { + if (jetCharged.r() == round(jetsChargedR * 100.0f)) { + jetsChargedLeadingPt = jetCharged.pt(); + break; + } + } + } + } + + if ((emcalTriggered == -1 && collision.alias_bit(kTVXinEMC)) || (emcalTriggered == 0 && (collision.alias_bit(kEMC7) || collision.alias_bit(kDMC7)))) { + if (doFullJetTrigger) { + for (auto& jetFull : jetsFull) { + if (jetFull.r() == round(jetsFullR * 100.0f)) { + jetsFullLeadingPt = jetFull.pt(); + break; + } + } + } + + if (doGammaTrigger) { + for (const auto& cluster : clusters) { + if (rejectExoticClusters && cluster.isExotic()) { + continue; + } + if (cluster.time() < clusterTimeMin || cluster.time() > clusterTimeMax) { + continue; + } + double gammaPt = cluster.energy() / std::cosh(cluster.eta()); + if (TVector2::Phi_0_2pi(cluster.phi()) < 4 && gammaPt > gammaLeadingPt) { + gammaLeadingPt = gammaPt; + } + } + } + } + + float jetsChargedPtStart = 0.0; + float jetsFullPtStart = 0.0; + float gammaPtStart = 0.0; + if (jetsChargedLeadingPt < 0.0) { + jetsChargedPtStart = -1.0; + } + if (jetsFullLeadingPt < 0.0) { + jetsFullPtStart = -1.0; + } + if (gammaLeadingPt < 0.0) { + gammaPtStart = -1.0; + } + + for (float jetChargedPt = jetsChargedPtStart; jetChargedPt <= jetsChargedLeadingPt; jetChargedPt += 1.0) { + + for (float jetFullPt = jetsFullPtStart; jetFullPt <= jetsFullLeadingPt; jetFullPt += 1.0) { + + for (float gammaPt = gammaPtStart; gammaPt <= gammaLeadingPt; gammaPt += 1.0) { + + registry.fill(HIST("h3_jetcharged_pt_jetfull_pt_photon_pt_triggered"), jetChargedPt, jetFullPt, gammaPt); + } + } + } + } + PROCESS_SWITCH(TriggerCorrelationsTask, processTriggeredCorrelations, "QA for trigger correlations", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"trigger-correlations"})}; +} diff --git a/PWGLF/DataModel/LFHStrangeCorrelationTables.h b/PWGLF/DataModel/LFHStrangeCorrelationTables.h index 130ad501e67..dfe516ce2fc 100644 --- a/PWGLF/DataModel/LFHStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFHStrangeCorrelationTables.h @@ -54,6 +54,9 @@ DECLARE_SOA_INDEX_COLUMN(V0Data, v0Data); //! DECLARE_SOA_COLUMN(CompatibleK0Short, compatibleK0Short, bool); // compatible with K0Short DECLARE_SOA_COLUMN(CompatibleLambda, compatibleLambda, bool); // compatible with Lambda DECLARE_SOA_COLUMN(CompatibleAntiLambda, compatibleAntiLambda, bool); // compatible with AntiLambda +DECLARE_SOA_COLUMN(MCTrueK0Short, mcTrueK0Short, bool); // true K0Short in MC +DECLARE_SOA_COLUMN(MCTrueLambda, mcTrueLambda, bool); // true Lambda in MC +DECLARE_SOA_COLUMN(MCTrueAntiLambda, mcTrueAntiLambda, bool); // true AntiLambda in MC DECLARE_SOA_COLUMN(MassRegionK0Short, massRegionK0Short, int); // DECLARE_SOA_COLUMN(MassRegionLambda, massRegionLambda, int); // DECLARE_SOA_COLUMN(MassRegionAntiLambda, massRegionAntiLambda, int); // @@ -87,18 +90,32 @@ DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegion, invMassRegion, return rAntiLambda; return -1; }); +DECLARE_SOA_DYNAMIC_COLUMN(MCTrue, mcTrue, + [](int mcTrueK0Short, int mcTrueLambda, int mcTrueAntiLambda, int value) -> bool { + if (value == 0 && mcTrueK0Short == true) + return true; + if (value == 1 && mcTrueLambda == true) + return true; + if (value == 2 && mcTrueAntiLambda == true) + return true; + return false; + }); } // namespace assocV0s DECLARE_SOA_TABLE(AssocV0s, "AOD", "ASSOCV0S", o2::soa::Index<>, assocV0s::CollisionId, assocV0s::V0DataId, assocV0s::CompatibleK0Short, assocV0s::CompatibleLambda, assocV0s::CompatibleAntiLambda, + assocV0s::MCTrueK0Short, + assocV0s::MCTrueLambda, + assocV0s::MCTrueAntiLambda, assocV0s::MassRegionK0Short, assocV0s::MassRegionLambda, assocV0s::MassRegionAntiLambda, assocV0s::Compatible, assocV0s::InvMassRegionCheck, - assocV0s::InvMassRegion); + assocV0s::InvMassRegion, + assocV0s::MCTrue); /// _________________________________________ /// Table for storing associated casc indices namespace assocCascades @@ -109,6 +126,10 @@ DECLARE_SOA_COLUMN(CompatibleXiMinus, compatibleXiMinus, bool); // compati DECLARE_SOA_COLUMN(CompatibleXiPlus, compatibleXiPlus, bool); // compatible with XiPlus DECLARE_SOA_COLUMN(CompatibleOmegaMinus, compatibleOmegaMinus, bool); // compatible with OmegaMinus DECLARE_SOA_COLUMN(CompatibleOmegaPlus, compatibleOmegaPlus, bool); // compatible with OmegaPlus +DECLARE_SOA_COLUMN(MCTrueXiMinus, mcTrueXiMinus, bool); // true XiMinus in mc +DECLARE_SOA_COLUMN(MCTrueXiPlus, mcTrueXiPlus, bool); // true XiPlus in mc +DECLARE_SOA_COLUMN(MCTrueOmegaMinus, mcTrueOmegaMinus, bool); // true OmegaMinus in mc +DECLARE_SOA_COLUMN(MCTrueOmegaPlus, mcTrueOmegaPlus, bool); // true OmegaPlus in mc DECLARE_SOA_COLUMN(MassRegionXi, massRegionXi, int); // DECLARE_SOA_COLUMN(MassRegionOmega, massRegionOmega, int); // DECLARE_SOA_DYNAMIC_COLUMN(Compatible, compatible, //! check compatibility with a hypothesis of a certain number (0 - K0, 1 - L, 2 - Lbar) @@ -124,7 +145,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Compatible, compatible, //! check return false; }); DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegionCheck, invMassRegionCheck, - [](int rXi, int rOmega, int value, int region) -> int { + [](int rXi, int rOmega, int value, int region) -> bool { if (value == 0 && rXi == region) return true; if (value == 1 && rXi == region) @@ -133,7 +154,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegionCheck, invMassRegionCheck, return true; if (value == 3 && rOmega == region) return true; - return -1; + return false; }); DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegion, invMassRegion, [](int rXi, int rOmega, int value) -> int { @@ -143,17 +164,34 @@ DECLARE_SOA_DYNAMIC_COLUMN(InvMassRegion, invMassRegion, return rOmega; return -1; }); +DECLARE_SOA_DYNAMIC_COLUMN(MCTrue, mcTrue, + [](int mcTrueXiMinus, int mcTrueXiPlus, int mcTrueOmegaMinus, int mcTrueOmegaPlus, int value) -> bool { + if (value == 0 && mcTrueXiMinus == true) + return true; + if (value == 1 && mcTrueXiPlus == true) + return true; + if (value == 2 && mcTrueOmegaMinus == true) + return true; + if (value == 3 && mcTrueOmegaPlus == true) + return true; + return false; + }); } // namespace assocCascades DECLARE_SOA_TABLE(AssocCascades, "AOD", "ASSOCCASCADES", o2::soa::Index<>, assocCascades::CollisionId, assocCascades::CascDataId, assocCascades::CompatibleXiMinus, assocCascades::CompatibleXiPlus, assocCascades::CompatibleOmegaMinus, assocCascades::CompatibleOmegaPlus, + assocCascades::MCTrueXiMinus, + assocCascades::MCTrueXiPlus, + assocCascades::MCTrueOmegaMinus, + assocCascades::MCTrueOmegaPlus, assocCascades::MassRegionXi, assocCascades::MassRegionOmega, assocCascades::Compatible, assocCascades::InvMassRegionCheck, - assocCascades::InvMassRegion); + assocCascades::InvMassRegion, + assocCascades::MCTrue); } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFHSTRANGECORRELATIONTABLES_H_ diff --git a/PWGLF/DataModel/LFHyperhelium4Tables.h b/PWGLF/DataModel/LFHyperhelium4Tables.h index 882c272cf69..8d7d5f4d379 100644 --- a/PWGLF/DataModel/LFHyperhelium4Tables.h +++ b/PWGLF/DataModel/LFHyperhelium4Tables.h @@ -88,9 +88,9 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtPion, ptPion, //! pT of prong 0 (identified as prot DECLARE_SOA_DYNAMIC_COLUMN(DecayRadius, decayRadius, //! decay radius (2D, centered at zero) [](float x, float y) -> float { return RecoDecay::sqrtSumOfSquares(x, y); }); DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! mass under hyperhelium-4 hypo - [](float pxp0, float pyp0, float pzp0, float pxp1, float pyp1, float pzp1, float pxp2, float pyp2, float pzp2) -> float { return RecoDecay::m(array{array{pxp0, pyp0, pzp0}, array{pxp1, pyp1, pzp1}, array{pxp2, pyp2, pzp2}}, array{o2::constants::physics::MassHelium3, o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); }); + [](float pxp0, float pyp0, float pzp0, float pxp1, float pyp1, float pzp1, float pxp2, float pyp2, float pzp2) -> float { return RecoDecay::m(std::array{std::array{pxp0, pyp0, pzp0}, std::array{pxp1, pyp1, pzp1}, std::array{pxp2, pyp2, pzp2}}, std::array{o2::constants::physics::MassHelium3, o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); }); DECLARE_SOA_DYNAMIC_COLUMN(YHyHe4, yHyHe4, //! y -> FIXME add Hyperhelium4 mass to physics constants - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(array{Px, Py, Pz}, 3.929); }); + [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, 3.929); }); // Standard expression columns - note correct momentum for the He3 daughter DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! px diff --git a/PWGLF/DataModel/LFHypernucleiTables.h b/PWGLF/DataModel/LFHypernucleiTables.h index 3c44f0f790d..7530f5c313c 100644 --- a/PWGLF/DataModel/LFHypernucleiTables.h +++ b/PWGLF/DataModel/LFHypernucleiTables.h @@ -25,9 +25,15 @@ namespace o2::aod namespace hyperrec { DECLARE_SOA_COLUMN(IsMatter, isMatter, bool); // bool: true for matter -DECLARE_SOA_COLUMN(Pt, pt, float); // Momentum of the candidate (x direction) -DECLARE_SOA_COLUMN(Phi, phi, float); // Momentum of the candidate (y direction) -DECLARE_SOA_COLUMN(Eta, eta, float); // Momentum of the candidate (z direction) +DECLARE_SOA_COLUMN(PtHe3, ptHe3, float); // Pt of the He daughter +DECLARE_SOA_COLUMN(PhiHe3, phiHe3, float); // Phi of the He daughter +DECLARE_SOA_COLUMN(EtaHe3, etaHe3, float); // Eta of the He daughter +DECLARE_SOA_COLUMN(PtPi, ptPi, float); // Pt of the Pi daughter +DECLARE_SOA_COLUMN(PhiPi, phiPi, float); // Phi of the Pi daughter +DECLARE_SOA_COLUMN(EtaPi, etaPi, float); // Eta of the Pi daughter +DECLARE_SOA_COLUMN(XPrimVtx, xPrimVtx, float); // Decay vertex of the candidate (x direction) +DECLARE_SOA_COLUMN(YPrimVtx, yPrimVtx, float); // Decay vertex of the candidate (y direction) +DECLARE_SOA_COLUMN(ZPrimVtx, zPrimVtx, float); // Decay vertex of the candidate (z direction) DECLARE_SOA_COLUMN(XDecVtx, xDecVtx, float); // Decay vertex of the candidate (x direction) DECLARE_SOA_COLUMN(YDecVtx, yDecVtx, float); // Decay vertex of the candidate (y direction) DECLARE_SOA_COLUMN(ZDecVtx, zDecVtx, float); // Decay vertex of the candidate (z direction) @@ -44,9 +50,10 @@ DECLARE_SOA_COLUMN(TPCmomHe, tpcMomHe, float); // TPC momentum of the H DECLARE_SOA_COLUMN(TPCmomPi, tpcMomPi, float); // TPC momentum of the Pi daughter DECLARE_SOA_COLUMN(DcaHe, dcaHe, float); // DCA between He daughter and V0 DECLARE_SOA_COLUMN(DcaPi, dcaPi, float); // DCA between pi daughter and V0 -DECLARE_SOA_COLUMN(GenPt, genPt, float); // Momentum of the candidate (x direction) -DECLARE_SOA_COLUMN(GenPhi, genPhi, float); // Momentum of the candidate (y direction) -DECLARE_SOA_COLUMN(GenEta, genEta, float); // Momentum of the candidate (z direction) +DECLARE_SOA_COLUMN(GenPt, genPt, float); // Pt of the hypertriton +DECLARE_SOA_COLUMN(GenPhi, genPhi, float); // Phi of the hypertriton +DECLARE_SOA_COLUMN(GenEta, genEta, float); // Eta of the hypertriton +DECLARE_SOA_COLUMN(GenPtHe3, genPtHe3, float); // Pt of the He daughter (to be used for the recalibration) DECLARE_SOA_COLUMN(GenXDecVtx, genXDecVtx, float); // Decay vertex of the candidate (x direction) DECLARE_SOA_COLUMN(GenYDecVtx, genYDecVtx, float); // Decay vertex of the candidate (y direction) DECLARE_SOA_COLUMN(GenZDecVtx, genZDecVtx, float); // Decay vertex of the candidate (z direction) @@ -57,39 +64,47 @@ DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); // bool: true for signal DECLARE_SOA_TABLE(DataHypCands, "AOD", "DATAHYPCANDS", o2::soa::Index<>, hyperrec::IsMatter, - hyperrec::Pt, - hyperrec::Phi, - hyperrec::Eta, + hyperrec::PtHe3, + hyperrec::PhiHe3, + hyperrec::EtaHe3, + hyperrec::PtPi, + hyperrec::PhiPi, + hyperrec::EtaPi, + hyperrec::XPrimVtx, + hyperrec::YPrimVtx, + hyperrec::ZPrimVtx, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, - hyperrec::MassH3L, - hyperrec::MassH4L, hyperrec::DcaV0Daug, - hyperrec::CosPA, + hyperrec::DcaHe, + hyperrec::DcaPi, hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, - hyperrec::TPCsignalPi, - hyperrec::DcaHe, - hyperrec::DcaPi); + hyperrec::TPCsignalPi); DECLARE_SOA_TABLE(MCHypCands, "AOD", "MCHYPCANDS", o2::soa::Index<>, hyperrec::IsMatter, - hyperrec::Pt, - hyperrec::Phi, - hyperrec::Eta, + hyperrec::PtHe3, + hyperrec::PhiHe3, + hyperrec::EtaHe3, + hyperrec::PtPi, + hyperrec::PhiPi, + hyperrec::EtaPi, + hyperrec::XPrimVtx, + hyperrec::YPrimVtx, + hyperrec::ZPrimVtx, hyperrec::XDecVtx, hyperrec::YDecVtx, hyperrec::ZDecVtx, - hyperrec::MassH3L, - hyperrec::MassH4L, hyperrec::DcaV0Daug, - hyperrec::CosPA, + hyperrec::DcaHe, + hyperrec::DcaPi, hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, @@ -97,11 +112,10 @@ DECLARE_SOA_TABLE(MCHypCands, "AOD", "MCHYPCANDS", hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, - hyperrec::DcaHe, - hyperrec::DcaPi, hyperrec::GenPt, hyperrec::GenPhi, hyperrec::GenEta, + hyperrec::GenPtHe3, hyperrec::GenXDecVtx, hyperrec::GenYDecVtx, hyperrec::GenZDecVtx, diff --git a/PWGLF/DataModel/LFLithium4Tables.h b/PWGLF/DataModel/LFLithium4Tables.h new file mode 100644 index 00000000000..699e6f7f2c0 --- /dev/null +++ b/PWGLF/DataModel/LFLithium4Tables.h @@ -0,0 +1,111 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file LFLithium4Tables.h +/// \brief Slim tables for Lithium4 +/// + +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" + +#ifndef PWGLF_DATAMODEL_LFLITHIUM4TABLES_H_ +#define PWGLF_DATAMODEL_LFLITHIUM4TABLES_H_ + +namespace o2::aod +{ +namespace Lithium4TablesNS +{ + +DECLARE_SOA_COLUMN(IsMatter, isMatter, bool); + +DECLARE_SOA_COLUMN(PtHe3, ptHe3, float); +DECLARE_SOA_COLUMN(EtaHe3, etaHe3, float); +DECLARE_SOA_COLUMN(PhiHe3, phiHe3, float); +DECLARE_SOA_COLUMN(PtPr, ptPr, float); +DECLARE_SOA_COLUMN(EtaPr, etaPr, float); +DECLARE_SOA_COLUMN(PhiPr, phiPr, float); + +DECLARE_SOA_COLUMN(He3DCAxy, he3DcaXY, float); +DECLARE_SOA_COLUMN(He3DCAz, he3DcaZ, float); +DECLARE_SOA_COLUMN(ProtonDCAxy, protonDcaXY, float); +DECLARE_SOA_COLUMN(ProtonDCAz, protonDcaZ, float); + +DECLARE_SOA_COLUMN(He3SignalTPC, he3SignalTPC, float); +DECLARE_SOA_COLUMN(He3InnerParamTPC, he3InnerParamTPC, float); +DECLARE_SOA_COLUMN(He3NClsTPC, he3NClsTPC, uint8_t); +DECLARE_SOA_COLUMN(He3NSigmaTPC, he3NSigmaTPC, float); +DECLARE_SOA_COLUMN(PrNSigmaTPC, prNSigmaTOF, float); +DECLARE_SOA_COLUMN(He3MassTOF, he3MassTOF, float); +DECLARE_SOA_COLUMN(PrMassTOF, prMassTOF, float); +DECLARE_SOA_COLUMN(SharedClustersHe3, sharedClustersHe3, uint8_t); +DECLARE_SOA_COLUMN(SharedClustersPr, sharedClustersPr, uint8_t); + +DECLARE_SOA_COLUMN(IsBkgLS, isBkgLS, bool); +DECLARE_SOA_COLUMN(IsBkgEM, isBkgEM, bool); + +DECLARE_SOA_COLUMN(SignedPtMC, signedPtMC, float); +DECLARE_SOA_COLUMN(MassMC, massMC, float); + +} // namespace Lithium4TablesNS + +DECLARE_SOA_TABLE(Lithium4Table, "AOD", "LITHIUM4TABLE", + Lithium4TablesNS::IsMatter, + Lithium4TablesNS::PtHe3, + Lithium4TablesNS::EtaHe3, + Lithium4TablesNS::PhiHe3, + Lithium4TablesNS::PtPr, + Lithium4TablesNS::EtaPr, + Lithium4TablesNS::PhiPr, + Lithium4TablesNS::He3DCAxy, + Lithium4TablesNS::He3DCAz, + Lithium4TablesNS::ProtonDCAxy, + Lithium4TablesNS::ProtonDCAz, + Lithium4TablesNS::He3SignalTPC, + Lithium4TablesNS::He3InnerParamTPC, + Lithium4TablesNS::He3NClsTPC, + Lithium4TablesNS::He3NSigmaTPC, + Lithium4TablesNS::PrNSigmaTPC, + Lithium4TablesNS::He3MassTOF, + Lithium4TablesNS::PrMassTOF, + Lithium4TablesNS::SharedClustersHe3, + Lithium4TablesNS::SharedClustersPr, + Lithium4TablesNS::IsBkgLS, + Lithium4TablesNS::IsBkgEM) +DECLARE_SOA_TABLE(Lithium4TableMC, "AOD", "LITHIUM4TABLEMC", + Lithium4TablesNS::IsMatter, + Lithium4TablesNS::PtHe3, + Lithium4TablesNS::EtaHe3, + Lithium4TablesNS::PhiHe3, + Lithium4TablesNS::PtPr, + Lithium4TablesNS::EtaPr, + Lithium4TablesNS::PhiPr, + Lithium4TablesNS::He3DCAxy, + Lithium4TablesNS::He3DCAz, + Lithium4TablesNS::ProtonDCAxy, + Lithium4TablesNS::ProtonDCAz, + Lithium4TablesNS::He3SignalTPC, + Lithium4TablesNS::He3InnerParamTPC, + Lithium4TablesNS::He3NClsTPC, + Lithium4TablesNS::He3NSigmaTPC, + Lithium4TablesNS::PrNSigmaTPC, + Lithium4TablesNS::He3MassTOF, + Lithium4TablesNS::PrMassTOF, + Lithium4TablesNS::SharedClustersHe3, + Lithium4TablesNS::SharedClustersPr, + Lithium4TablesNS::IsBkgLS, + Lithium4TablesNS::IsBkgEM, + Lithium4TablesNS::SignedPtMC, + Lithium4TablesNS::MassMC) + +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFLITHIUM4TABLES_H_ diff --git a/PWGLF/DataModel/LFNucleiTables.h b/PWGLF/DataModel/LFNucleiTables.h index 8f47e253aab..7ff192ed213 100644 --- a/PWGLF/DataModel/LFNucleiTables.h +++ b/PWGLF/DataModel/LFNucleiTables.h @@ -26,41 +26,41 @@ using namespace o2; namespace o2::aod { namespace fullEvent -{ // Events -DECLARE_SOA_INDEX_COLUMN(BC, bc); //! Most probably BC to where this collision has occurred +{ // Events DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); DECLARE_SOA_COLUMN(RunNumber, runNumber, int); -DECLARE_SOA_COLUMN(MultFV0M, multFV0M, float); +DECLARE_SOA_COLUMN(CentFV0M, centFV0M, float); +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); } // namespace fullEvent -DECLARE_SOA_TABLE(LfCandNucleusFullEvents, "AOD", "LFNUCLEvent", +DECLARE_SOA_TABLE(LfNuclEvents, "AOD", "LFNUCLEvent", o2::soa::Index<>, - fullEvent::BCId, collision::NumContrib, collision::PosX, collision::PosY, collision::PosZ, - fullEvent::MultFV0M, + fullEvent::CentFV0M, + fullEvent::CentFT0M, fullEvent::IsEventReject, fullEvent::RunNumber); -using LfCandNucleusFullEvent = LfCandNucleusFullEvents::iterator; +using LfNuclEvent = LfNuclEvents::iterator; namespace full { -DECLARE_SOA_INDEX_COLUMN(LfCandNucleusFullEvent, lfCandNucleusFullEvent); -DECLARE_SOA_COLUMN(Px, px, float); -DECLARE_SOA_COLUMN(Py, py, float); -DECLARE_SOA_COLUMN(Pz, pz, float); +DECLARE_SOA_INDEX_COLUMN(LfNuclEvent, lfNuclEvent); DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_COLUMN(P, p, float); -DECLARE_SOA_COLUMN(Sign, sign, float); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * cosh(eta); }); DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Sign, sign, short); DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(IsPVContributor, isPVContributor, bool); DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, - [](float p, float pz, float mass) -> float { + [](float pt, float eta, float mass) -> float { + const auto p = pt * cosh(eta); + const auto pz = pt * sinh(eta); const auto energy = sqrt(p * p + mass * mass); return 0.5f * log((energy + pz) / (energy - pz)); }); +// TPC DECLARE_SOA_COLUMN(TPCNSigmaPi, tpcNSigmaPi, float); DECLARE_SOA_COLUMN(TPCNSigmaKa, tpcNSigmaKa, float); DECLARE_SOA_COLUMN(TPCNSigmaPr, tpcNSigmaPr, float); @@ -68,6 +68,7 @@ DECLARE_SOA_COLUMN(TPCNSigmaDe, tpcNSigmaDe, float); DECLARE_SOA_COLUMN(TPCNSigmaTr, tpcNSigmaTr, float); DECLARE_SOA_COLUMN(TPCNSigmaHe, tpcNSigmaHe, float); DECLARE_SOA_COLUMN(TPCNSigmaAl, tpcNSigmaAl, float); +// TOF DECLARE_SOA_COLUMN(TOFNSigmaPi, tofNSigmaPi, float); DECLARE_SOA_COLUMN(TOFNSigmaKa, tofNSigmaKa, float); DECLARE_SOA_COLUMN(TOFNSigmaPr, tofNSigmaPr, float); @@ -93,65 +94,147 @@ DECLARE_SOA_COLUMN(TPCSignal, tpcSignal, float); DECLARE_SOA_COLUMN(Beta, beta, float); // TPC and ITS QA DECLARE_SOA_COLUMN(ITSNCls, itsNCls, int16_t); -DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, int16_t); -DECLARE_SOA_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, float); -DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, int16_t); DECLARE_SOA_COLUMN(TPCChi2Ncl, tpcChi2NCl, float); DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, float); -DECLARE_SOA_COLUMN(ITSClusterMap, itsClusterMap, uint8_t); // For MC DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); DECLARE_SOA_COLUMN(ProducedByGenerator, producedByGenerator, bool); + } // namespace full +namespace dummy +{ +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPi, tpcNSigmaPi, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaKa, tpcNSigmaKa, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPr, tpcNSigmaPr, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaTr, tpcNSigmaTr, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaAl, tpcNSigmaAl, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPi, tofNSigmaPi, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaKa, tofNSigmaKa, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPr, tofNSigmaPr, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaTr, tofNSigmaTr, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaAl, tofNSigmaAl, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffPr, tpcExpSignalDiffPr, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffDe, tpcExpSignalDiffDe, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCExpSignalDiffHe, tpcExpSignalDiffHe, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffPr, tofExpSignalDiffPr, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffDe, tofExpSignalDiffDe, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpSignalDiffHe, tofExpSignalDiffHe, + [](bool b) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFExpMom, tofExpMom, + [](bool b) -> float { return 0.f; }); +} // namespace dummy /* namespace fullMC { -DECLARE_SOA_INDEX_COLUMN(LfCandNucleusFullEvent, lfCandNucleusFullEvent); +DECLARE_SOA_INDEX_COLUMN(LfNuclEvent, lfCandNucleusFullEvent); DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); } */ -DECLARE_SOA_TABLE(LfCandNucleusFull, "AOD", "LFNUCL", +DECLARE_SOA_TABLE(LfCandNucleus, "AOD", "LFNUCL", o2::soa::Index<>, - full::LfCandNucleusFullEventId, - full::DcaXY, - full::DcaZ, - full::TPCNSigmaPi, full::TPCNSigmaKa, full::TPCNSigmaPr, - full::TPCNSigmaDe, full::TPCNSigmaTr, full::TPCNSigmaHe, full::TPCNSigmaAl, - full::TOFNSigmaPi, full::TOFNSigmaKa, full::TOFNSigmaPr, - full::TOFNSigmaDe, full::TOFNSigmaTr, full::TOFNSigmaHe, full::TOFNSigmaAl, - full::TPCExpSignalDiffPr, full::TPCExpSignalDiffDe, full::TPCExpSignalDiffHe, - full::TOFExpSignalDiffPr, full::TOFExpSignalDiffDe, full::TOFExpSignalDiffHe, + full::LfNuclEventId, + full::DcaXY, full::DcaZ, + full::TPCNSigmaDe, full::TPCNSigmaHe, + full::TOFNSigmaDe, full::TOFNSigmaHe, full::IsEvTimeTOF, full::IsEvTimeT0AC, full::HasTOF, full::HasTRD, full::TPCInnerParam, - full::TOFExpMom, - full::TPCSignal, full::Beta, - full::Px, - full::Py, - full::Pz, + full::TPCSignal, full::Pt, - full::P, full::Eta, full::Phi, full::Sign, full::ITSNCls, - full::TPCNClsCrossedRows, - full::TPCCrossedRowsOverFindableCls, - full::TPCNClsFound, + track::TPCNClsFindable, + track::TPCNClsFindableMinusFound, + track::TPCNClsFindableMinusCrossedRows, full::TPCChi2Ncl, full::ITSChi2NCl, - full::ITSClusterMap, + track::ITSClusterMap, full::IsPVContributor, - full::Rapidity); + full::P, + full::Rapidity, + track::TPCNClsFound, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls); +DECLARE_SOA_TABLE_FULL(LfCandNucleusDummy, "LfCandNucleus", "AOD", "LFNUCL", + o2::soa::Index<>, + full::LfNuclEventId, + full::DcaXY, full::DcaZ, + full::TPCNSigmaDe, full::TPCNSigmaHe, + full::TOFNSigmaDe, full::TOFNSigmaHe, + full::IsEvTimeTOF, + full::IsEvTimeT0AC, + full::HasTOF, + full::HasTRD, + full::TPCInnerParam, + full::Beta, + full::TPCSignal, + full::Pt, + full::Eta, + full::Phi, + full::Sign, + full::ITSNCls, + track::TPCNClsFindable, + track::TPCNClsFindableMinusFound, + track::TPCNClsFindableMinusCrossedRows, + full::TPCChi2Ncl, + full::ITSChi2NCl, + track::ITSClusterMap, + full::IsPVContributor, + full::P, + dummy::TPCNSigmaPi, dummy::TPCNSigmaKa, dummy::TPCNSigmaPr, + dummy::TPCNSigmaTr, dummy::TPCNSigmaAl, + dummy::TOFNSigmaPi, dummy::TOFNSigmaKa, dummy::TOFNSigmaPr, + dummy::TOFNSigmaTr, dummy::TOFNSigmaAl, + dummy::TPCExpSignalDiffPr, dummy::TPCExpSignalDiffDe, dummy::TPCExpSignalDiffHe, + dummy::TOFExpSignalDiffPr, dummy::TOFExpSignalDiffDe, dummy::TOFExpSignalDiffHe, + dummy::TOFExpMom, + full::Rapidity, + track::TPCNClsFound, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls); + +DECLARE_SOA_TABLE(LfCandNucleusExtra, "AOD", "LFNUCLEXTRA", + full::TPCNSigmaPi, full::TPCNSigmaKa, full::TPCNSigmaPr, + full::TPCNSigmaTr, full::TPCNSigmaAl, + full::TOFNSigmaPi, full::TOFNSigmaKa, full::TOFNSigmaPr, + full::TOFNSigmaTr, full::TOFNSigmaAl, + full::TPCExpSignalDiffPr, full::TPCExpSignalDiffDe, full::TPCExpSignalDiffHe, + full::TOFExpSignalDiffPr, full::TOFExpSignalDiffDe, full::TOFExpSignalDiffHe, + full::TOFExpMom); + DECLARE_SOA_TABLE(LfCandNucleusMC, "AOD", "LFNUCLMC", mcparticle::PdgCode, full::IsPhysicalPrimary, - full::ProducedByGenerator); + full::ProducedByGenerator, + mcparticle::Px, + mcparticle::Py, + mcparticle::Pz); + +using LfCandNucleusFull = soa::Join; } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFNUCLEITABLES_H_ diff --git a/PWGLF/DataModel/LFResonanceTables.h b/PWGLF/DataModel/LFResonanceTables.h index 0f13f1e7d93..cf044640ac7 100644 --- a/PWGLF/DataModel/LFResonanceTables.h +++ b/PWGLF/DataModel/LFResonanceTables.h @@ -31,9 +31,9 @@ namespace o2::aod /// Resonance Collisions namespace resocollision { -DECLARE_SOA_COLUMN(MultV0M, multV0M, float); //! V0M multiplicity -DECLARE_SOA_COLUMN(MultTPCtemp, multTPCtemp, float); //! TPC multiplicity (temporal) -DECLARE_SOA_COLUMN(Sphericity, sphericity, float); //! Sphericity of the event +DECLARE_SOA_COLUMN(MultV0M, multV0M, float); //! V0M multiplicity percentile (run2: V0M, run3: FT0A/C/M) +DECLARE_SOA_COLUMN(MultFT0, multFT0, int); //! FT0 multiplicity +DECLARE_SOA_COLUMN(Spherocity, spherocity, float); //! Spherocity of the event DECLARE_SOA_COLUMN(BMagField, bMagField, float); //! Magnetic field } // namespace resocollision DECLARE_SOA_TABLE(ResoCollisions, "AOD", "RESOCOL", @@ -42,8 +42,8 @@ DECLARE_SOA_TABLE(ResoCollisions, "AOD", "RESOCOL", collision::PosY, collision::PosZ, resocollision::MultV0M, - resocollision::MultTPCtemp, - resocollision::Sphericity, + resocollision::MultFT0, + resocollision::Spherocity, resocollision::BMagField, timestamp::Timestamp); using ResoCollision = ResoCollisions::iterator; @@ -52,21 +52,6 @@ using ResoCollision = ResoCollisions::iterator; // inspired from PWGCF/DataModel/FemtoDerived.h namespace resodaughter { -enum PDGtype { - kPion = BIT(0), - kKaon = BIT(1), - kProton = BIT(2), - kHasTOF = BIT(6) // Save hasTOF info for TOF selection -}; - -#define requireTPCPIDCutInFilter(mask) ((aod::resodaughter::tpcPIDselectionFlag & (uint8_t)aod::resodaughter::mask) == (uint8_t)aod::resodaughter::mask) -#define requireTOFPIDCutInFilter(mask) (((aod::resodaughter::tofPIDselectionFlag & (uint8_t)aod::resodaughter::kHasTOF) != (uint8_t)aod::resodaughter::kHasTOF) || (((aod::resodaughter::tofPIDselectionFlag & (uint8_t)aod::resodaughter::mask) == (uint8_t)aod::resodaughter::mask) && ((aod::resodaughter::tofPIDselectionFlag & (uint8_t)aod::resodaughter::kHasTOF) == (uint8_t)aod::resodaughter::kHasTOF))) -#define requireTPCPIDPionCutInFilter() requireTPCPIDCutInFilter(PDGtype::kPion) -#define requireTPCPIDKaonCutInFilter() requireTPCPIDCutInFilter(PDGtype::kKaon) -#define requireTPCPIDProtonCutInFilter() requireTPCPIDCutInFilter(PDGtype::kProton) -#define requireTOFPIDPionCutInFilter() requireTOFPIDCutInFilter(PDGtype::kPion) -#define requireTOFPIDKaonCutInFilter() requireTOFPIDCutInFilter(PDGtype::kKaon) -#define requireTOFPIDProtonCutInFilter() requireTOFPIDCutInFilter(PDGtype::kProton) DECLARE_SOA_INDEX_COLUMN(ResoCollision, resoCollision); DECLARE_SOA_COLUMN(Pt, pt, float); //! p_T (GeV/c) @@ -80,20 +65,23 @@ DECLARE_SOA_COLUMN(TempFitVar, tempFitVar, float); //! Obser DECLARE_SOA_COLUMN(Indices, indices, int[2]); //! Field for the track indices to remove auto-correlations DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign of the track charge DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, uint8_t); //! Number of TPC crossed rows -DECLARE_SOA_COLUMN(TPCPIDselectionFlag, tpcPIDselectionFlag, uint8_t); //! TPC PID selection -DECLARE_SOA_COLUMN(TOFPIDselectionFlag, tofPIDselectionFlag, uint8_t); //! TOF PID selection -DECLARE_SOA_COLUMN(DaughDCA, daughDCA, float); //! DCA between daughters -DECLARE_SOA_COLUMN(CascDaughDCA, cascdaughDCA, float); //! DCA between daughters from cascade -DECLARE_SOA_COLUMN(V0CosPA, v0CosPA, float); //! V0 Cosine of Pointing Angle -DECLARE_SOA_COLUMN(CascCosPA, cascCosPA, float); //! Cascade Cosine of Pointing Angle -DECLARE_SOA_COLUMN(MLambda, mLambda, float); //! The invariant mass of V0 candidate, assuming lambda -DECLARE_SOA_COLUMN(MAntiLambda, mAntiLambda, float); //! The invariant mass of V0 candidate, assuming antilambda -DECLARE_SOA_COLUMN(MXi, mXi, float); //! The invariant mass of Xi candidate -DECLARE_SOA_COLUMN(TransRadius, transRadius, float); //! Transverse radius of the decay vertex -DECLARE_SOA_COLUMN(CascTransRadius, casctransRadius, float); //! Transverse radius of the decay vertex from cascade -DECLARE_SOA_COLUMN(DecayVtxX, decayVtxX, float); //! X position of the decay vertex -DECLARE_SOA_COLUMN(DecayVtxY, decayVtxY, float); //! Y position of the decay vertex -DECLARE_SOA_COLUMN(DecayVtxZ, decayVtxZ, float); //! Z position of the decay vertex +DECLARE_SOA_COLUMN(IsGlobalTrackWoDCA, isGlobalTrackWoDCA, bool); //! Is global track without DCA +DECLARE_SOA_COLUMN(IsPrimaryTrack, isPrimaryTrack, bool); //! Is primary track +DECLARE_SOA_COLUMN(IsPVContributor, isPVContributor, bool); //! Is primary vertex contributor +DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); //! Has TOF +DECLARE_SOA_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, float); +DECLARE_SOA_COLUMN(DaughDCA, daughDCA, float); //! DCA between daughters +DECLARE_SOA_COLUMN(CascDaughDCA, cascdaughDCA, float); //! DCA between daughters from cascade +DECLARE_SOA_COLUMN(V0CosPA, v0CosPA, float); //! V0 Cosine of Pointing Angle +DECLARE_SOA_COLUMN(CascCosPA, cascCosPA, float); //! Cascade Cosine of Pointing Angle +DECLARE_SOA_COLUMN(MLambda, mLambda, float); //! The invariant mass of V0 candidate, assuming lambda +DECLARE_SOA_COLUMN(MAntiLambda, mAntiLambda, float); //! The invariant mass of V0 candidate, assuming antilambda +DECLARE_SOA_COLUMN(MXi, mXi, float); //! The invariant mass of Xi candidate +DECLARE_SOA_COLUMN(TransRadius, transRadius, float); //! Transverse radius of the decay vertex +DECLARE_SOA_COLUMN(CascTransRadius, casctransRadius, float); //! Transverse radius of the decay vertex from cascade +DECLARE_SOA_COLUMN(DecayVtxX, decayVtxX, float); //! X position of the decay vertex +DECLARE_SOA_COLUMN(DecayVtxY, decayVtxY, float); //! Y position of the decay vertex +DECLARE_SOA_COLUMN(DecayVtxZ, decayVtxZ, float); //! Z position of the decay vertex // For MC DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! Index of the corresponding MC particle DECLARE_SOA_COLUMN(IsPhysicalPrimary, isPhysicalPrimary, bool); @@ -104,6 +92,7 @@ DECLARE_SOA_COLUMN(DaughterPDG1, daughterPDG1, int); //! PDG code of the first D DECLARE_SOA_COLUMN(DaughterPDG2, daughterPDG2, int); //! PDG code of the second Daughter particle DECLARE_SOA_COLUMN(DaughterID1, daughterId1, int); //! Id of the first Daughter particle DECLARE_SOA_COLUMN(DaughterID2, daughterId2, int); //! Id of the second Daughter particle +DECLARE_SOA_COLUMN(SiblingIds, siblingIds, int[2]); //! Index of the particles with the same mother DECLARE_SOA_COLUMN(BachTrkID, bachtrkID, int); //! Id of the bach track from cascade DECLARE_SOA_COLUMN(V0ID, v0ID, int); //! Id of the V0 from cascade } // namespace resodaughter @@ -122,14 +111,22 @@ DECLARE_SOA_TABLE(ResoTracks, "AOD", "RESOTRACKS", o2::aod::track::DcaZ, o2::aod::track::X, o2::aod::track::Alpha, - resodaughter::TPCPIDselectionFlag, - resodaughter::TOFPIDselectionFlag, + resodaughter::HasTOF, o2::aod::pidtpc::TPCNSigmaPi, o2::aod::pidtpc::TPCNSigmaKa, o2::aod::pidtpc::TPCNSigmaPr, o2::aod::pidtof::TOFNSigmaPi, o2::aod::pidtof::TOFNSigmaKa, - o2::aod::pidtof::TOFNSigmaPr); + o2::aod::pidtof::TOFNSigmaPr, + o2::aod::track::TPCSignal, + o2::aod::track::PassedITSRefit, + o2::aod::track::PassedTPCRefit, + resodaughter::IsGlobalTrackWoDCA, + resodaughter::IsPrimaryTrack, + resodaughter::IsPVContributor, + resodaughter::TPCCrossedRowsOverFindableCls, + o2::aod::track::ITSChi2NCl, + o2::aod::track::TPCChi2NCl); using ResoTrack = ResoTracks::iterator; DECLARE_SOA_TABLE(ResoV0s, "AOD", "RESOV0S", @@ -178,6 +175,7 @@ DECLARE_SOA_TABLE(ResoMCTracks, "AOD", "RESOMCTRACKS", mcparticle::PdgCode, resodaughter::MothersId, resodaughter::MotherPDG, + resodaughter::SiblingIds, resodaughter::IsPhysicalPrimary, resodaughter::ProducedByGenerator); using ResoMCTrack = ResoMCTracks::iterator; @@ -227,7 +225,7 @@ using ResoMCParent = ResoMCParents::iterator; using Reso2TracksExt = soa::Join; // without Extra using Reso2TracksMC = soa::Join; using Reso2TracksPID = soa::Join; -using Reso2TracksPIDExt = soa::Join; // Without Extra +using Reso2TracksPIDExt = soa::Join; // Without Extra } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFRESONANCETABLES_H_ diff --git a/PWGLF/DataModel/LFSlimNucleiTables.h b/PWGLF/DataModel/LFSlimNucleiTables.h index 88a89bb903d..02e8b90d303 100644 --- a/PWGLF/DataModel/LFSlimNucleiTables.h +++ b/PWGLF/DataModel/LFSlimNucleiTables.h @@ -27,14 +27,19 @@ namespace NucleiTableNS DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); -DECLARE_SOA_COLUMN(Zvertex, zVertex, uint8_t); +DECLARE_SOA_COLUMN(TPCInnerParam, tpcInnerParam, float); +DECLARE_SOA_COLUMN(Beta, beta, float); +DECLARE_SOA_COLUMN(Zvertex, zVertex, float); +DECLARE_SOA_COLUMN(DCAxy, dcaxy, float); +DECLARE_SOA_COLUMN(DCAz, dcaz, float); +DECLARE_SOA_COLUMN(TPCsignal, tpcSignal, float); +DECLARE_SOA_COLUMN(ITSchi2, itsChi2, float); +DECLARE_SOA_COLUMN(TPCchi2, tpcChi2, float); +DECLARE_SOA_COLUMN(Flags, flags, uint16_t); +DECLARE_SOA_COLUMN(TPCfindableCls, tpcFindableCls, uint8_t); +DECLARE_SOA_COLUMN(TPCcrossedRows, tpcCrossedRows, uint8_t); DECLARE_SOA_COLUMN(ITSclsMap, itsClsMap, uint8_t); DECLARE_SOA_COLUMN(TPCnCls, tpcNCls, uint8_t); -DECLARE_SOA_COLUMN(DCAxy, dcaxy, uint8_t); -DECLARE_SOA_COLUMN(DCAz, dcaz, uint8_t); -DECLARE_SOA_COLUMN(Flags, flags, uint16_t); -DECLARE_SOA_COLUMN(TPCnsigma, tpcnsigma, uint8_t); -DECLARE_SOA_COLUMN(TOFmass, tofmass, uint8_t); DECLARE_SOA_COLUMN(gPt, genPt, float); DECLARE_SOA_COLUMN(gEta, genEta, float); DECLARE_SOA_COLUMN(gPhi, genPhi, float); @@ -45,27 +50,37 @@ DECLARE_SOA_TABLE(NucleiTable, "AOD", "NUCLEITABLE", NucleiTableNS::Pt, NucleiTableNS::Eta, NucleiTableNS::Phi, + NucleiTableNS::TPCInnerParam, + NucleiTableNS::Beta, NucleiTableNS::Zvertex, - NucleiTableNS::ITSclsMap, - NucleiTableNS::TPCnCls, NucleiTableNS::DCAxy, NucleiTableNS::DCAz, + NucleiTableNS::TPCsignal, + NucleiTableNS::ITSchi2, + NucleiTableNS::TPCchi2, NucleiTableNS::Flags, - NucleiTableNS::TPCnsigma, - NucleiTableNS::TOFmass) + NucleiTableNS::TPCfindableCls, + NucleiTableNS::TPCcrossedRows, + NucleiTableNS::ITSclsMap, + NucleiTableNS::TPCnCls) DECLARE_SOA_TABLE(NucleiTableMC, "AOD", "NUCLEITABLEMC", NucleiTableNS::Pt, NucleiTableNS::Eta, NucleiTableNS::Phi, + NucleiTableNS::TPCInnerParam, + NucleiTableNS::Beta, NucleiTableNS::Zvertex, - NucleiTableNS::ITSclsMap, - NucleiTableNS::TPCnCls, NucleiTableNS::DCAxy, NucleiTableNS::DCAz, + NucleiTableNS::TPCsignal, + NucleiTableNS::ITSchi2, + NucleiTableNS::TPCchi2, NucleiTableNS::Flags, - NucleiTableNS::TPCnsigma, - NucleiTableNS::TOFmass, + NucleiTableNS::TPCfindableCls, + NucleiTableNS::TPCcrossedRows, + NucleiTableNS::ITSclsMap, + NucleiTableNS::TPCnCls, NucleiTableNS::gPt, NucleiTableNS::gEta, NucleiTableNS::gPhi, diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index 78dbc4bdf90..3f2d3c5e436 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -48,6 +48,9 @@ DECLARE_SOA_COLUMN(DCANegToPV, dcanegtopv, float); //! DCA negative pron DECLARE_SOA_COLUMN(PositionCovMat, positionCovMat, float[6]); //! covariance matrix elements DECLARE_SOA_COLUMN(MomentumCovMat, momentumCovMat, float[6]); //! covariance matrix elements +// Saved from KF particle fit for specic table +DECLARE_SOA_COLUMN(KFV0Chi2, kfV0Chi2, float); //! + // Derived expressions // Momenta DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! V0 pT @@ -73,7 +76,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to V0decay dis // CosPA DECLARE_SOA_DYNAMIC_COLUMN(V0CosPA, v0cosPA, //! V0 CosPA - [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(array{pvX, pvY, pvZ}, array{X, Y, Z}, array{Px, Py, Pz}); }); + [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(DCAV0ToPV, dcav0topv, //! DCA of V0 to PV [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); @@ -81,15 +84,15 @@ DECLARE_SOA_DYNAMIC_COLUMN(DCAV0ToPV, dcav0topv, //! DCA of V0 to PV DECLARE_SOA_DYNAMIC_COLUMN(Alpha, alpha, //! Armenteros Alpha [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { float momTot = RecoDecay::p(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); - float lQlNeg = RecoDecay::dotProd(array{pxneg, pyneg, pzneg}, array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}) / momTot; - float lQlPos = RecoDecay::dotProd(array{pxpos, pypos, pzpos}, array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}) / momTot; + float lQlNeg = RecoDecay::dotProd(std::array{pxneg, pyneg, pzneg}, std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}) / momTot; + float lQlPos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}) / momTot; return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); // alphav0 }); DECLARE_SOA_DYNAMIC_COLUMN(QtArm, qtarm, //! Armenteros Qt [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { float momTot = RecoDecay::p2(pxpos + pxneg, pypos + pyneg, pzpos + pzneg); - float dp = RecoDecay::dotProd(array{pxneg, pyneg, pzneg}, array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}); + float dp = RecoDecay::dotProd(std::array{pxneg, pyneg, pzneg}, std::array{pxpos + pxneg, pypos + pyneg, pzpos + pzneg}); return std::sqrt(RecoDecay::p2(pxneg, pyneg, pzneg) - dp * dp / momTot); // qtarm }); @@ -98,7 +101,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(PsiPair, psipair, //! psi pair angle [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) { auto clipToPM1 = [](float x) { return x < -1.f ? -1.f : (x > 1.f ? 1.f : x); }; float ptot2 = RecoDecay::p2(pxpos, pypos, pzpos) * RecoDecay::p2(pxneg, pyneg, pzneg); - float argcos = RecoDecay::dotProd(array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}) / std::sqrt(ptot2); + float argcos = RecoDecay::dotProd(std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}) / std::sqrt(ptot2); float thetaPos = std::atan2(RecoDecay::sqrtSumOfSquares(pxpos, pypos), pzpos); float thetaNeg = std::atan2(RecoDecay::sqrtSumOfSquares(pxneg, pyneg), pzneg); float argsin = (thetaNeg - thetaPos) / std::acos(clipToPM1(argcos)); @@ -122,45 +125,53 @@ DECLARE_SOA_DYNAMIC_COLUMN(PFracNeg, pfracneg, // Calculated on the fly with mass assumption + dynamic tables DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, //! mass under lambda hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); }); DECLARE_SOA_DYNAMIC_COLUMN(MAntiLambda, mAntiLambda, //! mass under antilambda hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); }); DECLARE_SOA_DYNAMIC_COLUMN(MK0Short, mK0Short, //! mass under K0short hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); }); DECLARE_SOA_DYNAMIC_COLUMN(MGamma, mGamma, //! mass under gamma hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); }); // Account for rigidity in case of hypertriton DECLARE_SOA_DYNAMIC_COLUMN(MHypertriton, mHypertriton, //! mass under hypertriton hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(array{array{2.0f * pxpos, 2.0f * pypos, 2.0f * pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassHelium3, o2::constants::physics::MassPionCharged}); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{2.0f * pxpos, 2.0f * pypos, 2.0f * pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassHelium3, o2::constants::physics::MassPionCharged}); }); DECLARE_SOA_DYNAMIC_COLUMN(MAntiHypertriton, mAntiHypertriton, //! mass under antihypertriton hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{2.0f * pxneg, 2.0f * pyneg, 2.0f * pzneg}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassHelium3}); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{2.0f * pxneg, 2.0f * pyneg, 2.0f * pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassHelium3}); }); DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! mass under a certain hypothesis (0:K0, 1:L, 2:Lbar, 3:gamma, 4:hyp, 5:ahyp) [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg, int value) -> float { if (value == 0) - return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); if (value == 1) - return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); if (value == 2) - return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); if (value == 3) - return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); if (value == 4) - return RecoDecay::m(array{array{2.0f * pxpos, 2.0f * pypos, 2.0f * pzpos}, array{pxneg, pyneg, pzneg}}, array{o2::constants::physics::MassHelium3, o2::constants::physics::MassPionCharged}); + return RecoDecay::m(std::array{std::array{2.0f * pxpos, 2.0f * pypos, 2.0f * pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassHelium3, o2::constants::physics::MassPionCharged}); if (value == 5) - return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{2.0f * pxneg, 2.0f * pyneg, 2.0f * pzneg}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassHelium3}); + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{2.0f * pxneg, 2.0f * pyneg, 2.0f * pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassHelium3}); return 0.0f; }); DECLARE_SOA_DYNAMIC_COLUMN(YK0Short, yK0Short, //! V0 y with K0short hypothesis - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(array{Px, Py, Pz}, o2::constants::physics::MassKaonNeutral); }); + [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassKaonNeutral); }); DECLARE_SOA_DYNAMIC_COLUMN(YLambda, yLambda, //! V0 y with lambda or antilambda hypothesis - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(array{Px, Py, Pz}, o2::constants::physics::MassLambda); }); + [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassLambda); }); DECLARE_SOA_DYNAMIC_COLUMN(YHypertriton, yHypertriton, //! V0 y with hypertriton hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::y(array{2.0f * pxpos + pxneg, 2.0f * pypos + pyneg, 2.0f * pzpos + pzneg}, o2::constants::physics::MassHyperTriton); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::y(std::array{2.0f * pxpos + pxneg, 2.0f * pypos + pyneg, 2.0f * pzpos + pzneg}, o2::constants::physics::MassHyperTriton); }); DECLARE_SOA_DYNAMIC_COLUMN(YAntiHypertriton, yAntiHypertriton, //! V0 y with antihypertriton hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::y(array{pxpos + 2.0f * pxneg, pypos + 2.0f * pyneg, pzpos + 2.0f * pzneg}, o2::constants::physics::MassHyperTriton); }); + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::y(std::array{pxpos + 2.0f * pxneg, pypos + 2.0f * pyneg, pzpos + 2.0f * pzneg}, o2::constants::physics::MassHyperTriton); }); +DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, //! rapidity (0:K0, 1:L, 2:Lbar) + [](float Px, float Py, float Pz, int value) -> float { + if (value == 0) + return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassKaonNeutral); + if (value == 1 || value == 2) + return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassLambda); + return 0.0f; + }); DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! V0 eta - [](float Px, float Py, float Pz) -> float { return RecoDecay::eta(array{Px, Py, Pz}); }); + [](float Px, float Py, float Pz) -> float { return RecoDecay::eta(std::array{Px, Py, Pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! V0 phi [](float Px, float Py) -> float { return RecoDecay::phi(Px, Py); }); @@ -169,11 +180,11 @@ DECLARE_SOA_DYNAMIC_COLUMN(NegativePt, negativept, //! negative daughter pT DECLARE_SOA_DYNAMIC_COLUMN(PositivePt, positivept, //! positive daughter pT [](float pxpos, float pypos) -> float { return RecoDecay::sqrtSumOfSquares(pxpos, pypos); }); DECLARE_SOA_DYNAMIC_COLUMN(NegativeEta, negativeeta, //! negative daughter eta - [](float PxNeg, float PyNeg, float PzNeg) -> float { return RecoDecay::eta(array{PxNeg, PyNeg, PzNeg}); }); + [](float PxNeg, float PyNeg, float PzNeg) -> float { return RecoDecay::eta(std::array{PxNeg, PyNeg, PzNeg}); }); DECLARE_SOA_DYNAMIC_COLUMN(NegativePhi, negativephi, //! negative daughter phi [](float PxNeg, float PyNeg) -> float { return RecoDecay::phi(PxNeg, PyNeg); }); DECLARE_SOA_DYNAMIC_COLUMN(PositiveEta, positiveeta, //! positive daughter eta - [](float PxPos, float PyPos, float PzPos) -> float { return RecoDecay::eta(array{PxPos, PyPos, PzPos}); }); + [](float PxPos, float PyPos, float PzPos) -> float { return RecoDecay::eta(std::array{PxPos, PyPos, PzPos}); }); DECLARE_SOA_DYNAMIC_COLUMN(PositivePhi, positivephi, //! positive daughter phi [](float PxPos, float PyPos) -> float { return RecoDecay::phi(PxPos, PyPos); }); @@ -222,6 +233,7 @@ DECLARE_SOA_TABLE_FULL(StoredV0Datas, "V0Datas", "AOD", "V0DATA", //! v0data::YLambda, v0data::YHypertriton, v0data::YAntiHypertriton, + v0data::Rapidity, v0data::Eta, v0data::Phi, v0data::NegativePt, @@ -293,6 +305,12 @@ DECLARE_SOA_TABLE(V0Tags, "AOD", "V0TAGS", v0tag::IsFromCascade, v0tag::IsFromTrackedCascade); +namespace kfcascdata +{ +// declare in different namespace to 'overload' operator +DECLARE_SOA_COLUMN(MLambda, mLambda, float); //! +} // namespace kfcascdata + namespace cascdata { // Necessary for full filtering functionality @@ -336,12 +354,20 @@ DECLARE_SOA_COLUMN(DCAZCascToPV, dcaZCascToPV, float); //! // Saved from finding: covariance matrix of parent track (on request) DECLARE_SOA_COLUMN(PositionCovMat, positionCovMat, float[6]); //! covariance matrix elements DECLARE_SOA_COLUMN(MomentumCovMat, momentumCovMat, float[6]); //! covariance matrix elements +DECLARE_SOA_COLUMN(KFTrackMat, kfTrackCovMat, float[15]); //! covariance matrix elements for KF method // Selection to avoid spurious invariant mass correlation // bachelor-baryon cosine of pointing angle / DCA to PV DECLARE_SOA_COLUMN(BachBaryonCosPA, bachBaryonCosPA, float); //! avoid bach-baryon correlated inv mass structure in analysis DECLARE_SOA_COLUMN(BachBaryonDCAxyToPV, bachBaryonDCAxyToPV, float); //! avoid bach-baryon correlated inv mass structure in analysis +// Saved from KF particle fit for specic table +// note: separate chi2 is a consequence of fit -> conversion -> propagation -> fit logic +// which, in turn, is necessary to do material corrections at the moment +// this could be improved in the future! +DECLARE_SOA_COLUMN(KFV0Chi2, kfV0Chi2, float); //! +DECLARE_SOA_COLUMN(KFCascadeChi2, kfCascadeChi2, float); //! + // Saved from strangeness tracking DECLARE_SOA_COLUMN(MatchingChi2, matchingChi2, float); //! DECLARE_SOA_COLUMN(TopologyChi2, topologyChi2, float); //! @@ -360,15 +386,15 @@ DECLARE_SOA_DYNAMIC_COLUMN(CascRadius, cascradius, //! // CosPAs DECLARE_SOA_DYNAMIC_COLUMN(V0CosPA, v0cosPA, //! - [](float Xlambda, float Ylambda, float Zlambda, float PxLambda, float PyLambda, float PzLambda, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(array{pvX, pvY, pvZ}, array{Xlambda, Ylambda, Zlambda}, array{PxLambda, PyLambda, PzLambda}); }); + [](float Xlambda, float Ylambda, float Zlambda, float PxLambda, float PyLambda, float PzLambda, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{Xlambda, Ylambda, Zlambda}, std::array{PxLambda, PyLambda, PzLambda}); }); DECLARE_SOA_DYNAMIC_COLUMN(CascCosPA, casccosPA, //! - [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(array{pvX, pvY, pvZ}, array{X, Y, Z}, array{Px, Py, Pz}); }); + [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(DCAV0ToPV, dcav0topv, //! [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); // Calculated on the fly with mass assumption + dynamic tables DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, //! - [](int charge, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(array{array{pxpos, pypos, pzpos}, array{pxneg, pyneg, pzneg}}, charge < 0 ? array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged} : array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); }); + [](int charge, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, charge < 0 ? std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged} : std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); }); DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! mass under a certain hypothesis (0:K0, 1:L, 2:Lbar, 3:gamma, 4:hyp, 5:ahyp) [](float mXi, float mOmega, int value) -> float { if (value == 0 || value == 1) @@ -379,11 +405,19 @@ DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! mass under a certain hypothesis (0:K0, 1:L, }); DECLARE_SOA_DYNAMIC_COLUMN(YXi, yXi, //! - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(array{Px, Py, Pz}, o2::constants::physics::MassXiMinus); }); + [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassXiMinus); }); DECLARE_SOA_DYNAMIC_COLUMN(YOmega, yOmega, //! - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(array{Px, Py, Pz}, o2::constants::physics::MassOmegaMinus); }); + [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassOmegaMinus); }); +DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, //! rapidity (0, 1: Xi; 2, 3: Omega) + [](float Px, float Py, float Pz, int value) -> float { + if (value == 0 || value == 1) + return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassXiMinus); + if (value == 2 || value == 3) + return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassOmegaMinus); + return 0.0f; + }); DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! - [](float Px, float Py, float Pz) -> float { return RecoDecay::eta(array{Px, Py, Pz}); }); + [](float Px, float Py, float Pz) -> float { return RecoDecay::eta(std::array{Px, Py, Pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! cascade phi [](float Px, float Py) -> float { return RecoDecay::phi(Px, Py); }); } // namespace cascdata @@ -423,6 +457,40 @@ DECLARE_SOA_TABLE(StoredCascDatas, "AOD", "CASCDATA", //! cascdata::MLambda, cascdata::M, + // Longitudinal + cascdata::YXi, + cascdata::YOmega, + cascdata::Rapidity, + cascdata::Eta, + cascdata::Phi); + +DECLARE_SOA_TABLE(StoredKFCascDatas, "AOD", "KFCASCDATA", //! + o2::soa::Index<>, cascdata::V0Id, cascdata::CascadeId, cascdata::BachelorId, cascdata::CollisionId, + cascdata::Sign, cascdata::MXi, cascdata::MOmega, + cascdata::X, cascdata::Y, cascdata::Z, + cascdata::Xlambda, cascdata::Ylambda, cascdata::Zlambda, + cascdata::PxPos, cascdata::PyPos, cascdata::PzPos, + cascdata::PxNeg, cascdata::PyNeg, cascdata::PzNeg, + cascdata::PxBach, cascdata::PyBach, cascdata::PzBach, + cascdata::Px, cascdata::Py, cascdata::Pz, + cascdata::DCAV0Daughters, cascdata::DCACascDaughters, + cascdata::DCAPosToPV, cascdata::DCANegToPV, cascdata::DCABachToPV, cascdata::DCAXYCascToPV, cascdata::DCAZCascToPV, + cascdata::BachBaryonCosPA, cascdata::BachBaryonDCAxyToPV, + + // KF particle fit specific + kfcascdata::MLambda, cascdata::KFV0Chi2, cascdata::KFCascadeChi2, + + // Dynamic columns + cascdata::Pt, + cascdata::V0Radius, + cascdata::CascRadius, + cascdata::V0CosPA, + cascdata::CascCosPA, + cascdata::DCAV0ToPV, + + // Invariant masses + cascdata::M, + // Longitudinal cascdata::YXi, cascdata::YOmega, @@ -441,6 +509,8 @@ DECLARE_SOA_TABLE(StoredTraCascDatas, "AOD", "TRACASCDATA", //! cascdata::DCAV0Daughters, cascdata::DCACascDaughters, cascdata::DCAPosToPV, cascdata::DCANegToPV, cascdata::DCABachToPV, cascdata::DCAXYCascToPV, cascdata::DCAZCascToPV, cascdata::BachBaryonCosPA, cascdata::BachBaryonDCAxyToPV, + + // Strangeness tracking specific cascdata::MatchingChi2, cascdata::TopologyChi2, cascdata::ItsClsSize, // Dynamic columns @@ -463,14 +533,23 @@ DECLARE_SOA_TABLE(StoredTraCascDatas, "AOD", "TRACASCDATA", //! DECLARE_SOA_TABLE_FULL(CascCovs, "CascCovs", "AOD", "CASCCOVS", //! cascdata::PositionCovMat, cascdata::MomentumCovMat); +DECLARE_SOA_TABLE_FULL(KFCascCovs, "KFCascCovs", "AOD", "KFCASCCOVS", //! + cascdata::KFTrackMat); + // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(CascDatas, StoredCascDatas, "CascDATAEXT", //! cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(KFCascDatas, StoredKFCascDatas, "KFCascDATAEXT", //! + cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda); + // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(TraCascDatas, StoredTraCascDatas, "TraCascDATAEXT", //! cascdataext::PxLambda, cascdataext::PyLambda, cascdataext::PzLambda); using CascData = CascDatas::iterator; +using KFCascData = KFCascDatas::iterator; using TraCascData = TraCascDatas::iterator; // For compatibility with previous table declarations @@ -480,13 +559,18 @@ using CascDataExt = CascDatas; namespace cascdata { DECLARE_SOA_INDEX_COLUMN(CascData, cascData); //! Index to CascData entry +DECLARE_SOA_INDEX_COLUMN(KFCascData, kfCascData); //! Index to CascData entry } DECLARE_SOA_TABLE(CascDataLink, "AOD", "CASCDATALINK", //! Joinable table with Cascades which links to CascData which is not produced for all entries cascdata::CascDataId); +DECLARE_SOA_TABLE(KFCascDataLink, "AOD", "KFCASCDATALINK", //! Joinable table with Cascades which links to CascData which is not produced for all entries + cascdata::KFCascDataId); using CascadesLinked = soa::Join; using CascadeLinked = CascadesLinked::iterator; +using KFCascadesLinked = soa::Join; +using KFCascadeLinked = KFCascadesLinked::iterator; namespace casctag { diff --git a/PWGLF/DataModel/ReducedF1ProtonTables.h b/PWGLF/DataModel/ReducedF1ProtonTables.h new file mode 100644 index 00000000000..15a8cfbbae1 --- /dev/null +++ b/PWGLF/DataModel/ReducedF1ProtonTables.h @@ -0,0 +1,95 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file LFF1Tables.h +/// +/// \author Sourav Kundu + +#ifndef PWGLF_DATAMODEL_REDUCEDF1PROTONTABLES_H_ +#define PWGLF_DATAMODEL_REDUCEDF1PROTONTABLES_H_ + +#include + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" + +namespace o2::aod +{ +namespace reducedf1protonevent +{ +DECLARE_SOA_COLUMN(Spherocity, spherocity, float); //! Spherocity of the event +} // namespace reducedf1protonevent +DECLARE_SOA_TABLE(ReducedF1ProtonEvents, "AOD", "REDUCEDF1PEVENT", + o2::soa::Index<>, + bc::GlobalBC, + bc::RunNumber, + timestamp::Timestamp, + collision::PosZ, + collision::NumContrib, + reducedf1protonevent::Spherocity); +using ReducedF1ProtonEvent = ReducedF1ProtonEvents::iterator; + +namespace f1protondaughter +{ +DECLARE_SOA_INDEX_COLUMN(ReducedF1ProtonEvent, reducedF1ProtonEvent); +DECLARE_SOA_COLUMN(F1SignalStat, f1SignalStat, int); //! F1 Px +DECLARE_SOA_COLUMN(F1Px, f1Px, float); //! F1 Px +DECLARE_SOA_COLUMN(F1Py, f1Py, float); //! F1 Py +DECLARE_SOA_COLUMN(F1Pz, f1Pz, float); //! F1 Pz +DECLARE_SOA_COLUMN(F1Mass, f1Mass, float); //! F1 mass +DECLARE_SOA_COLUMN(F1MassKaonKshort, f1MassKaonKshort, float); //! F1 mass kaon kshort +DECLARE_SOA_COLUMN(F1PionIndex, f1PionIndex, int64_t); //! F1 pion index +DECLARE_SOA_COLUMN(F1KaonIndex, f1KaonIndex, int64_t); //! F1 kaon index +DECLARE_SOA_COLUMN(F1KshortPositiveIndex, f1KshortPositiveIndex, int64_t); //! F1 kshort pion positive index +DECLARE_SOA_COLUMN(F1KshortNegativeIndex, f1KshortNegativeIndex, int64_t); //! F1 kshort pion negative index +DECLARE_SOA_COLUMN(ProtonCharge, protonCharge, float); //! Proton charge +DECLARE_SOA_COLUMN(ProtonPx, protonPx, float); //! Proton Px +DECLARE_SOA_COLUMN(ProtonPy, protonPy, float); //! Proton Py +DECLARE_SOA_COLUMN(ProtonPz, protonPz, float); //! Proton Pz +DECLARE_SOA_COLUMN(ProtonNsigmaTPC, protonNsigmaTPC, float); //! Proton TPC nsigma +DECLARE_SOA_COLUMN(ProtonTOFHit, protonTOFHit, int); //! Proton TOF Hit +DECLARE_SOA_COLUMN(ProtonNsigmaTOF, protonNsigmaTOF, float); //! Proton TOF nsigma +DECLARE_SOA_COLUMN(F1ProtonIndex, f1ProtonIndex, int64_t); //! F1 proton index +} // namespace f1protondaughter +DECLARE_SOA_TABLE(F1Tracks, "AOD", "F1TRACK", + o2::soa::Index<>, + f1protondaughter::ReducedF1ProtonEventId, + f1protondaughter::F1SignalStat, + f1protondaughter::F1Px, + f1protondaughter::F1Py, + f1protondaughter::F1Pz, + f1protondaughter::F1Mass, + f1protondaughter::F1MassKaonKshort, + f1protondaughter::F1PionIndex, + f1protondaughter::F1KaonIndex, + f1protondaughter::F1KshortPositiveIndex, + f1protondaughter::F1KshortNegativeIndex); +using F1Track = F1Tracks::iterator; + +DECLARE_SOA_TABLE(ProtonTracks, "AOD", "PROTONTRACK", + o2::soa::Index<>, + f1protondaughter::ReducedF1ProtonEventId, + f1protondaughter::ProtonCharge, + f1protondaughter::ProtonPx, + f1protondaughter::ProtonPy, + f1protondaughter::ProtonPz, + f1protondaughter::ProtonNsigmaTPC, + f1protondaughter::ProtonTOFHit, + f1protondaughter::ProtonNsigmaTOF, + f1protondaughter::F1ProtonIndex); +using ProtonTrack = ProtonTracks::iterator; +} // namespace o2::aod +#endif // PWGLF_DATAMODEL_REDUCEDF1PROTONTABLES_H_ diff --git a/PWGLF/DataModel/Vtx3BodyTables.h b/PWGLF/DataModel/Vtx3BodyTables.h new file mode 100644 index 00000000000..8281f380e3f --- /dev/null +++ b/PWGLF/DataModel/Vtx3BodyTables.h @@ -0,0 +1,183 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef PWGLF_DATAMODEL_VTX3BODYTABLES_H_ +#define PWGLF_DATAMODEL_VTX3BODYTABLES_H_ + +#include +#include "Framework/AnalysisDataModel.h" +#include "Common/Core/RecoDecay.h" +#include "CommonConstants/PhysicsConstants.h" + +namespace o2::aod +{ +namespace vtx3body +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Track0, track0, int, Tracks, "_0"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(Track1, track1, int, Tracks, "_1"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(Track2, track2, int, Tracks, "_2"); //! +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! +DECLARE_SOA_INDEX_COLUMN(Decay3Body, decay3body); //! + +// General 3 body Vtx properties: position, momentum +DECLARE_SOA_COLUMN(PxTrack0, pxtrack0, float); //! track0 px at min +DECLARE_SOA_COLUMN(PyTrack0, pytrack0, float); //! track0 py at min +DECLARE_SOA_COLUMN(PzTrack0, pztrack0, float); //! track0 pz at min +DECLARE_SOA_COLUMN(PxTrack1, pxtrack1, float); //! track1 px at min +DECLARE_SOA_COLUMN(PyTrack1, pytrack1, float); //! track1 py at min +DECLARE_SOA_COLUMN(PzTrack1, pztrack1, float); //! track1 pz at min +DECLARE_SOA_COLUMN(PxTrack2, pxtrack2, float); //! track2 px at min +DECLARE_SOA_COLUMN(PyTrack2, pytrack2, float); //! track2 py at min +DECLARE_SOA_COLUMN(PzTrack2, pztrack2, float); //! track2 pz at min +DECLARE_SOA_COLUMN(X, x, float); //! decay position X +DECLARE_SOA_COLUMN(Y, y, float); //! decay position Y +DECLARE_SOA_COLUMN(Z, z, float); //! decay position Z + +// Saved from finding: DCAs +DECLARE_SOA_COLUMN(DCAVtxDaughters, dcaVtxdaughters, float); //! DCA between daughters +DECLARE_SOA_COLUMN(DCATrack0ToPV, dcatrack0topv, float); //! DCA prong0 to PV +DECLARE_SOA_COLUMN(DCATrack1ToPV, dcatrack1topv, float); //! DCA prong1 to PV +DECLARE_SOA_COLUMN(DCATrack2ToPV, dcatrack2topv, float); //! DCA prong2 to PV + +// Derived expressions +// Momenta +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! 3 body pT + [](float pxtrack0, float pytrack0, float pxtrack1, float pytrack1, float pxtrack2, float pytrack2) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack0 + pxtrack1 + pxtrack2, pytrack0 + pytrack1 + pytrack2); }); + +// Length quantities +DECLARE_SOA_DYNAMIC_COLUMN(VtxRadius, vtxradius, //! 3 body decay radius (2D, centered at zero) + [](float x, float y) -> float { return RecoDecay::sqrtSumOfSquares(x, y); }); + +// Distance Over To Mom +DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to 3 body decay distance over total momentum + [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) { + float P = RecoDecay::sqrtSumOfSquares(Px, Py, Pz); + return std::sqrt(std::pow(X - pvX, 2) + std::pow(Y - pvY, 2) + std::pow(Z - pvZ, 2)) / (P + 1E-10); + }); + +// CosPA +DECLARE_SOA_DYNAMIC_COLUMN(VtxCosPA, vtxcosPA, //! 3 body vtx CosPA + [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(DCAVtxToPV, dcavtxtopv, //! DCA of 3 body vtx to PV + [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); + +// Calculated on the fly with mass assumption + dynamic tables +DECLARE_SOA_DYNAMIC_COLUMN(MHypertriton, mHypertriton, //! mass under Hypertriton hypothesis + [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); }); +DECLARE_SOA_DYNAMIC_COLUMN(MAntiHypertriton, mAntiHypertriton, //! mass under antiHypertriton hypothesis + [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); }); + +DECLARE_SOA_DYNAMIC_COLUMN(YHypertriton, yHypertriton, //! 3 body vtx y with hypertriton or antihypertriton hypothesis + [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassHyperTriton); }); // here MassHyperTriton = 2.992 +DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! 3 body vtx eta + [](float Px, float Py, float Pz) -> float { return RecoDecay::eta(std::array{Px, Py, Pz}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! 3 body vtx phi + [](float Px, float Py) -> float { return RecoDecay::phi(Px, Py); }); + +DECLARE_SOA_DYNAMIC_COLUMN(Track0Pt, track0pt, //! daughter0 pT + [](float pxtrack0, float pytrack0) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack0, pytrack0); }); +DECLARE_SOA_DYNAMIC_COLUMN(Track1Pt, track1pt, //! daughter1 pT + [](float pxtrack1, float pytrack1) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack1, pytrack1); }); +DECLARE_SOA_DYNAMIC_COLUMN(Track2Pt, track2pt, //! daughter2 pT + [](float pxtrack2, float pytrack2) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack2, pytrack2); }); +DECLARE_SOA_DYNAMIC_COLUMN(Track0Eta, track0eta, //! daughter0 eta + [](float pxtrack0, float pytrack0, float pztrack0) -> float { return RecoDecay::eta(std::array{pxtrack0, pytrack0, pztrack0}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Track0Phi, track0phi, //! daughter0 phi + [](float pxtrack0, float pytrack0) -> float { return RecoDecay::phi(pxtrack0, pytrack0); }); +DECLARE_SOA_DYNAMIC_COLUMN(Track1Eta, track1eta, //! daughter1 eta + [](float pxtrack1, float pytrack1, float pztrack1) -> float { return RecoDecay::eta(std::array{pxtrack1, pytrack1, pztrack1}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Track1Phi, track1phi, //! daughter1 phi + [](float pxtrack1, float pytrack1) -> float { return RecoDecay::phi(pxtrack1, pytrack1); }); +DECLARE_SOA_DYNAMIC_COLUMN(Track2Eta, track2eta, //! daughter2 eta + [](float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::eta(std::array{pxtrack2, pytrack2, pztrack2}); }); +DECLARE_SOA_DYNAMIC_COLUMN(Track2Phi, track2phi, //! daughter2 phi + [](float pxtrack2, float pytrack2) -> float { return RecoDecay::phi(pxtrack2, pytrack2); }); + +DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! 3 body vtx px + float, 1.f * aod::vtx3body::pxtrack0 + 1.f * aod::vtx3body::pxtrack1 + 1.f * aod::vtx3body::pxtrack2); +DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! 3 body vtx py + float, 1.f * aod::vtx3body::pytrack0 + 1.f * aod::vtx3body::pytrack1 + 1.f * aod::vtx3body::pytrack2); +DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! 3 body vtx pz + float, 1.f * aod::vtx3body::pztrack0 + 1.f * aod::vtx3body::pztrack1 + 1.f * aod::vtx3body::pztrack2); +} // namespace vtx3body + +DECLARE_SOA_TABLE_FULL(StoredVtx3BodyDatas, "Vtx3BodyDatas", "AOD", "Vtx3BodyDATA", //! + o2::soa::Index<>, vtx3body::Track0Id, vtx3body::Track1Id, vtx3body::Track2Id, vtx3body::CollisionId, vtx3body::Decay3BodyId, + vtx3body::X, vtx3body::Y, vtx3body::Z, + vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, + vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, + vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, + vtx3body::DCAVtxDaughters, + vtx3body::DCATrack0ToPV, vtx3body::DCATrack1ToPV, vtx3body::DCATrack2ToPV, + + // Dynamic columns + vtx3body::Pt, + vtx3body::VtxRadius, + vtx3body::DistOverTotMom, + vtx3body::VtxCosPA, + vtx3body::DCAVtxToPV, + + // Invariant masses + vtx3body::MHypertriton, + vtx3body::MAntiHypertriton, + + // Longitudinal + vtx3body::YHypertriton, + vtx3body::Eta, + vtx3body::Phi, + vtx3body::Track0Pt, + vtx3body::Track0Eta, + vtx3body::Track0Phi, + vtx3body::Track1Pt, + vtx3body::Track1Eta, + vtx3body::Track1Phi, + vtx3body::Track2Pt, + vtx3body::Track2Eta, + vtx3body::Track2Phi); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(Vtx3BodyDatas, StoredVtx3BodyDatas, "Vtx3BodyDATAEXT", //! + vtx3body::Px, vtx3body::Py, vtx3body::Pz); + +using Vtx3BodyData = Vtx3BodyDatas::iterator; +namespace vtx3body +{ +DECLARE_SOA_INDEX_COLUMN(Vtx3BodyData, vtx3BodyData); //! Index to Vtx3BodyData entry +} + +DECLARE_SOA_TABLE(Decay3BodyDataLink, "AOD", "DECAY3BODYLINK", //! Joinable table with Decay3bodys which links to Vtx3BodyData which is not produced for all entries + vtx3body::Vtx3BodyDataId); + +using Decay3BodysLinked = soa::Join; +using Decay3BodyLinked = Decay3BodysLinked::iterator; + +// Definition of labels for Vtx3BodyDatas +namespace mcvtx3bodylabel +{ +DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Vtx3BodyDatas +} // namespace mcvtx3bodylabel + +DECLARE_SOA_TABLE(McVtx3BodyLabels, "AOD", "MCVTXLABEL", //! Table joinable with Vtx3BodyData containing the MC labels + mcvtx3bodylabel::McParticleId); +using McVtx3BodyLabel = McVtx3BodyLabels::iterator; + +// Definition of labels for Decay3Bodys // Full table, joinable with Decay3Bodys (CAUTION: NOT WITH Vtx3BodyDATA) +namespace mcfullvtx3bodylabel +{ +DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Decay3Bodys +} // namespace mcfullvtx3bodylabel + +DECLARE_SOA_TABLE(McFullVtx3BodyLabels, "AOD", "MCFULLVTXLABEL", //! Table joinable with Decay3Bodys + mcfullvtx3bodylabel::McParticleId); +using McFullVtx3BodyLabel = McFullVtx3BodyLabels::iterator; + +} // namespace o2::aod +#endif // PWGLF_DATAMODEL_VTX3BODYTABLES_H_ diff --git a/PWGLF/DataModel/cascqaanalysis.h b/PWGLF/DataModel/cascqaanalysis.h index 4eb7029bf44..c5377b201fa 100644 --- a/PWGLF/DataModel/cascqaanalysis.h +++ b/PWGLF/DataModel/cascqaanalysis.h @@ -25,26 +25,23 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" #include "TRandom.h" -#include -#include -#include -#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -// using DauTracks = soa::Join; -using DauTracks = soa::Join; -using LabeledCascades = soa::Join; - namespace o2::aod { namespace mycascades { -DECLARE_SOA_INDEX_COLUMN(Collision, collision); +enum EvFlags : uint8_t { + EvINEL = 0x1, // INEL Event + EvINELgt0 = 0x2, // Event with at least 1 PV contributors from the |eta| < 1 + EvINELgt1 = 0x4 // Event with at least 2 PV contributors from the |eta| < 1 +}; + DECLARE_SOA_COLUMN(CollisionZ, zcoll, float); DECLARE_SOA_COLUMN(MultFT0M, multFT0M, float); DECLARE_SOA_COLUMN(MultFV0A, multFV0A, float); @@ -89,6 +86,9 @@ DECLARE_SOA_COLUMN(NTOFSigmaBachKa, ntofsigmabachka, float); DECLARE_SOA_COLUMN(PosNTPCClusters, posntpcscls, float); DECLARE_SOA_COLUMN(NegNTPCClusters, negntpcscls, float); DECLARE_SOA_COLUMN(BachNTPCClusters, bachntpcscls, float); +DECLARE_SOA_COLUMN(PosNTPCCrossedRows, posntpccrrows, float); +DECLARE_SOA_COLUMN(NegNTPCCrossedRows, negntpccrrows, float); +DECLARE_SOA_COLUMN(BachNTPCCrossedRows, bachntpccrrows, float); DECLARE_SOA_COLUMN(PosHasTOF, poshastof, float); DECLARE_SOA_COLUMN(NegHasTOF, neghastof, float); DECLARE_SOA_COLUMN(BachHasTOF, bachhastof, float); @@ -99,11 +99,18 @@ DECLARE_SOA_COLUMN(McPdgCode, mcPdgCode, float); //! -1 unkn DECLARE_SOA_COLUMN(IsPrimary, isPrimary, float); //! -1 unknown, 0 not primary, 1 primary DECLARE_SOA_COLUMN(BachBaryonCosPA, bachBaryonCosPA, float); //! avoid bach-baryon correlated inv mass structure in analysis DECLARE_SOA_COLUMN(BachBaryonDCAxyToPV, bachBaryonDCAxyToPV, float); //! avoid bach-baryon correlated inv mass structure in analysis +DECLARE_SOA_COLUMN(EventSelFilterBitMask, eventSelFilterBitMask, uint8_t); +DECLARE_SOA_DYNAMIC_COLUMN(IsINEL, isINEL, //! True if the Event belongs to the INEL event class + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINEL) == EvFlags::EvINEL; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsINELgt0, isINELgt0, //! True if the Event belongs to the INELgt0 event class + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINELgt0) == EvFlags::EvINELgt0; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsINELgt1, isINELgt1, //! True if the Event belongs to the INELgt1 event class + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINELgt1) == EvFlags::EvINELgt1; }); } // namespace mycascades DECLARE_SOA_TABLE(MyCascades, "AOD", "MYCASCADES", o2::soa::Index<>, - mycascades::CollisionId, mycascades::CollisionZ, mycascades::MultFT0M, mycascades::MultFV0A, mycascades::Sign, mycascades::Pt, mycascades::RapXi, mycascades::RapOmega, mycascades::Eta, mycascades::MassXi, mycascades::MassOmega, mycascades::MassLambdaDau, mycascades::CascRadius, mycascades::V0Radius, + mycascades::CollisionZ, mycascades::MultFT0M, mycascades::MultFV0A, mycascades::Sign, mycascades::Pt, mycascades::RapXi, mycascades::RapOmega, mycascades::Eta, mycascades::MassXi, mycascades::MassOmega, mycascades::MassLambdaDau, mycascades::CascRadius, mycascades::V0Radius, mycascades::CascCosPA, mycascades::V0CosPA, mycascades::DCAPosToPV, mycascades::DCANegToPV, mycascades::DCABachToPV, mycascades::DCACascDaughters, mycascades::DCAV0Daughters, mycascades::DCAV0ToPV, mycascades::PosEta, mycascades::NegEta, mycascades::BachEta, mycascades::PosITSHits, mycascades::NegITSHits, mycascades::BachITSHits, @@ -112,10 +119,65 @@ DECLARE_SOA_TABLE(MyCascades, "AOD", "MYCASCADES", o2::soa::Index<>, mycascades::NTOFSigmaNegPr, mycascades::NTOFSigmaPosPr, mycascades::NTOFSigmaNegPi, mycascades::NTOFSigmaPosPi, mycascades::NTOFSigmaBachPi, mycascades::NTOFSigmaBachKa, mycascades::PosNTPCClusters, mycascades::NegNTPCClusters, mycascades::BachNTPCClusters, + mycascades::PosNTPCCrossedRows, mycascades::NegNTPCCrossedRows, mycascades::BachNTPCCrossedRows, mycascades::PosHasTOF, mycascades::NegHasTOF, mycascades::BachHasTOF, mycascades::PosPt, mycascades::NegPt, mycascades::BachPt, mycascades::McPdgCode, mycascades::IsPrimary, - cascdata::BachBaryonCosPA, cascdata::BachBaryonDCAxyToPV); + mycascades::BachBaryonCosPA, mycascades::BachBaryonDCAxyToPV, + mycascades::EventSelFilterBitMask, + mycascades::IsINEL, + mycascades::IsINELgt0, + mycascades::IsINELgt1); + +namespace myMCcascades +{ + +enum EvFlags : uint8_t { + EvINEL = 0x1, // INEL Event + EvINELgt0 = 0x2, // Event with at least 1 PV contributors from the |eta| < 1 + EvINELgt1 = 0x4 // Event with at least 2 PV contributors from the |eta| < 1 +}; + +DECLARE_SOA_COLUMN(CollisionZ, zcoll, float); +DECLARE_SOA_COLUMN(Sign, sign, float); +DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(IsPrimary, isPrimary, bool); +DECLARE_SOA_COLUMN(NAssocColl, nAssocColl, int); // Number of reconstructed collisions assoceated to the generated one of this cascade +DECLARE_SOA_COLUMN(NChInFT0M, nChInFT0M, float); // Number of charged particles in FT0M acceptance +DECLARE_SOA_COLUMN(AssCollisionTypeFilterBitMask, assCollisionTypeFilterBitMask, uint8_t); +DECLARE_SOA_COLUMN(McCollisionTypeFilterBitMask, mcCollisionTypeFilterBitMask, uint8_t); + +DECLARE_SOA_DYNAMIC_COLUMN(IsINELassoc, isINELassoc, //! True if there's at least 1 reconstructed INEL event for the generated one of this cascade + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINEL) == EvFlags::EvINEL; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsINELgt0assoc, isINELgt0assoc, //! True if there's at least 1 reconstructed INEL>0 event for the generated one of this cascade + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINELgt0) == EvFlags::EvINELgt0; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsINELgt1assoc, isINELgt1assoc, //! True if there's at least 1 reconstructed INEL>1 event for the generated one of this cascade + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINELgt1) == EvFlags::EvINELgt1; }); + +DECLARE_SOA_DYNAMIC_COLUMN(IsINEL, isINEL, //! True if the Event belongs to the INEL event class + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINEL) == EvFlags::EvINEL; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsINELgt0, isINELgt0, //! True if the Event belongs to the INELgt0 event class + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINELgt0) == EvFlags::EvINELgt0; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsINELgt1, isINELgt1, //! True if the Event belongs to the INELgt1 event class + [](uint8_t flags) -> bool { return (flags & EvFlags::EvINELgt1) == EvFlags::EvINELgt1; }); +} // namespace myMCcascades + +DECLARE_SOA_TABLE(MyMCCascades, "AOD", "MYMCCASCADES", o2::soa::Index<>, + myMCcascades::CollisionZ, myMCcascades::Sign, myMCcascades::PdgCode, + myMCcascades::Y, myMCcascades::Eta, myMCcascades::Phi, myMCcascades::Pt, + myMCcascades::IsPrimary, myMCcascades::NAssocColl, myMCcascades::NChInFT0M, + myMCcascades::AssCollisionTypeFilterBitMask, + myMCcascades::McCollisionTypeFilterBitMask, + myMCcascades::IsINELassoc, + myMCcascades::IsINELgt0assoc, + myMCcascades::IsINELgt1assoc, + myMCcascades::IsINEL, + myMCcascades::IsINELgt0, + myMCcascades::IsINELgt1); } // namespace o2::aod diff --git a/PWGLF/Tasks/spectraTOF.h b/PWGLF/DataModel/spectraTOF.h similarity index 63% rename from PWGLF/Tasks/spectraTOF.h rename to PWGLF/DataModel/spectraTOF.h index 680882efc52..12d66f07655 100644 --- a/PWGLF/Tasks/spectraTOF.h +++ b/PWGLF/DataModel/spectraTOF.h @@ -16,21 +16,23 @@ /// \brief Header for the spectraTOF task for the analysis of the spectra with the TOF and TPC detectors. /// -#ifndef PWGLF_TASKS_SPECTRATOF_H_ -#define PWGLF_TASKS_SPECTRATOF_H_ +#ifndef PWGLF_DATAMODEL_SPECTRATOF_H_ +#define PWGLF_DATAMODEL_SPECTRATOF_H_ // O2 includes #include "ReconstructionDataFormats/Track.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/StaticFor.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" #include "Common/Core/TrackSelection.h" -#include "Framework/StaticFor.h" +#include "Common/DataModel/FT0Corrected.h" #include "Common/Core/TrackSelectionDefaults.h" #include "PWGLF/DataModel/LFParticleIdentification.h" @@ -233,4 +235,250 @@ static constexpr std::string_view hdcazmat[NpCharge] = {"dcazmat/pos/el", "dcazm "dcazmat/neg/ka", "dcazmat/neg/pr", "dcazmat/neg/de", "dcazmat/neg/tr", "dcazmat/neg/he", "dcazmat/neg/al"}; -#endif // PWGLF_TASKS_SPECTRATOF_H_ +// Derived data model for cut variation +namespace o2::aod +{ +namespace spectra +{ + +template +typename binningType::binned_t packInTable(const float& valueToBin) +{ + if (valueToBin <= binningType::binned_min) { + return (binningType::underflowBin); + } else if (valueToBin >= binningType::binned_max) { + return (binningType::overflowBin); + } else if (valueToBin >= 0) { + return (static_cast((valueToBin / binningType::bin_width) + 0.5f)); + } else { + return (static_cast((valueToBin / binningType::bin_width) - 0.5f)); + } +} +// Function to unpack a binned value into a float +template +float unPack(const typename binningType::binned_t& valueToUnpack) +{ + return binningType::bin_width * static_cast(valueToUnpack); +} + +struct binningDCA { + public: + typedef int16_t binned_t; + static constexpr int nbins = (1 << 8 * sizeof(binned_t)) - 2; + static constexpr binned_t overflowBin = nbins >> 1; + static constexpr binned_t underflowBin = -(nbins >> 1); + static constexpr float binned_max = 6.0; + static constexpr float binned_min = -6.0; + static constexpr float bin_width = (binned_max - binned_min) / nbins; +}; + +struct binningNSigma { + public: + typedef int16_t binned_t; + static constexpr int nbins = (1 << 8 * sizeof(binned_t)) - 2; + static constexpr binned_t overflowBin = nbins >> 1; + static constexpr binned_t underflowBin = -(nbins >> 1); + static constexpr float binned_max = 10.0; + static constexpr float binned_min = -10.0; + static constexpr float bin_width = (binned_max - binned_min) / nbins; +}; + +// Collision info +DECLARE_SOA_INDEX_COLUMN(BC, bc); //! Most probably BC to where this collision has occurred +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); +DECLARE_SOA_COLUMN(Sel8, sel8, bool); +DECLARE_SOA_COLUMN(MultNTracksPVeta1, multNTracksPVeta1, int); +DECLARE_SOA_DYNAMIC_COLUMN(CentFV0A, centFV0A, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(CentFT0A, centFT0A, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(CentFT0C, centFT0C, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultZeqFV0A, multZeqFV0A, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultZeqFT0A, multZeqFT0A, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultZeqFT0C, multZeqFT0C, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultZeqFDDA, multZeqFDDA, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultZeqFDDC, multZeqFDDC, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultZeqNTracksPV, multZeqNTracksPV, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultTracklets, multTracklets, //! Dummy + [](bool v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(MultTPC, multTPC, //! Dummy + [](bool v) -> float { return 0.f; }); + +// Track info +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! Index to the collision +DECLARE_SOA_COLUMN(PtSigned, ptSigned, float); //! Pt (signed) of the track +DECLARE_SOA_COLUMN(Eta, eta, float); //! Eta of the track +DECLARE_SOA_COLUMN(Phi, phi, float); //! Phi of the track +DECLARE_SOA_COLUMN(EvTimeT0AC, evTimeT0AC, float); //! Event time of the track computed with the T0AC +DECLARE_SOA_COLUMN(EvTimeT0ACErr, evTimeT0ACErr, float); //! Resolution of the event time of the track computed with the T0AC +DECLARE_SOA_COLUMN(IsPVContributor, isPVContributor, bool); //! IsPVContributor +DECLARE_SOA_COLUMN(DetectorMap, detectorMap, uint8_t); //! Detector map: see enum DetectorMapEnum +DECLARE_SOA_COLUMN(LastTRDCluster, lastTRDCluster, int8_t); //! Index of the last cluster in the TRD, -1 if no TRD information +DECLARE_SOA_COLUMN(HasTRD, hasTRD, bool); //! Has or not the TRD match +DECLARE_SOA_COLUMN(TPCNSigmaStorePi, tpcNSigmaStorePi, binningNSigma::binned_t); //! Stored binned nsigma with the TPC detector for pion +DECLARE_SOA_COLUMN(TPCNSigmaStoreKa, tpcNSigmaStoreKa, binningNSigma::binned_t); //! Stored binned nsigma with the TPC detector for kaon +DECLARE_SOA_COLUMN(TPCNSigmaStorePr, tpcNSigmaStorePr, binningNSigma::binned_t); //! Stored binned nsigma with the TPC detector for proton +DECLARE_SOA_COLUMN(TOFNSigmaStorePi, tofNSigmaStorePi, binningNSigma::binned_t); //! Stored binned nsigma with the TOF detector for pion +DECLARE_SOA_COLUMN(TOFNSigmaStoreKa, tofNSigmaStoreKa, binningNSigma::binned_t); //! Stored binned nsigma with the TOF detector for kaon +DECLARE_SOA_COLUMN(TOFNSigmaStorePr, tofNSigmaStorePr, binningNSigma::binned_t); //! Stored binned nsigma with the TOF detector for proton +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPi, tpcNSigmaPi, //! Unpacked NSigma TPC Pi + [](binningNSigma::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaKa, tpcNSigmaKa, //! Unpacked NSigma TPC Ka + [](binningNSigma::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TPCNSigmaPr, tpcNSigmaPr, //! Unpacked NSigma TPC Pr + [](binningNSigma::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPi, tofNSigmaPi, //! Unpacked NSigma TOF Pi + [](binningNSigma::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaKa, tofNSigmaKa, //! Unpacked NSigma TOF Ka + [](binningNSigma::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(TOFNSigmaPr, tofNSigmaPr, //! Unpacked NSigma TOF Pr + [](binningNSigma::binned_t binned) -> float { return unPack(binned); }); + +DECLARE_SOA_COLUMN(DCAxyStore, dcaxyStore, binningDCA::binned_t); //! Stored binned dcaxy +DECLARE_SOA_COLUMN(DCAzStore, dcazStore, binningDCA::binned_t); //! Stored binned dcaz +DECLARE_SOA_DYNAMIC_COLUMN(DCAxy, dcaXY, //! Unpacked dcaxy + [](binningDCA::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(DCAz, dcaZ, //! Unpacked dcaz + [](binningDCA::binned_t binned) -> float { return unPack(binned); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! Absolute value of signed pT + [](float signedPt) -> float { return std::abs(signedPt); }); +DECLARE_SOA_DYNAMIC_COLUMN(HasITS, hasITS, //! Dummy + [](float v) -> bool { return true; }); +DECLARE_SOA_DYNAMIC_COLUMN(HasTPC, hasTPC, //! Dummy + [](float v) -> bool { return true; }); +DECLARE_SOA_DYNAMIC_COLUMN(HasTOF, hasTOF, //! Flag to check if track has a TOF measurement + [](float tofSignal) -> bool { return tofSignal > 0; }); +DECLARE_SOA_DYNAMIC_COLUMN(TRDSignal, trdSignal, //! Dummy + [](float v) -> float { return 0.f; }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float signedpt, float eta) -> float { return std::abs(signedpt) * cosh(eta); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackType, trackType, [](float v) -> uint8_t { return o2::aod::track::TrackTypeEnum::Track; }); +DECLARE_SOA_COLUMN(IsGlobalTrack, isGlobalTrack, bool); // if a track passed the isGlobalTrack requirement +DECLARE_SOA_COLUMN(IsGlobalTrackWoDCA, isGlobalTrackWoDCA, bool); // if a track passed the isGlobalTrackWoDCA requirement +DECLARE_SOA_DYNAMIC_COLUMN(Flags, flags, [](float v) -> uint32_t { return 0; }); // Dummy +DECLARE_SOA_DYNAMIC_COLUMN(TRDPattern, trdPattern, [](float v) -> uint8_t { return 0; }); // Dummy +DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, //! Track rapidity, computed under the mass assumption given as input + [](float signedPt, float eta, float mass) -> float { + const auto pt = std::abs(signedPt); + const auto p = std::abs(signedPt) * cosh(eta); + const auto pz = std::sqrt(p * p - pt * pt); + const auto energy = sqrt(p * p + mass * mass); + return 0.5f * log((energy + pz) / (energy - pz)); + }); +DECLARE_SOA_DYNAMIC_COLUMN(IsInAcceptanceTrack, isInAcceptanceTrack, [](float v) -> bool { return false; }); // Dummy +DECLARE_SOA_DYNAMIC_COLUMN(IsQualityTrackITS, isQualityTrackITS, [](float v) -> bool { return false; }); // Dummy +DECLARE_SOA_DYNAMIC_COLUMN(IsQualityTrackTPC, isQualityTrackTPC, [](float v) -> bool { return false; }); // Dummy + +} // namespace spectra + +DECLARE_SOA_TABLE(SpColls, "AOD", "SPCOLLS", + o2::soa::Index<>, + collision::NumContrib, + collision::PosX, + collision::PosY, + collision::PosZ, + spectra::CentFT0M, + spectra::Sel8, + spectra::MultNTracksPVeta1, + spectra::RunNumber, + spectra::CentFV0A, + spectra::CentFT0A, + spectra::CentFT0C, + spectra::MultZeqFV0A, + spectra::MultZeqFT0A, + spectra::MultZeqFT0C, + spectra::MultZeqFDDA, + spectra::MultZeqFDDC, + spectra::MultZeqNTracksPV, + spectra::MultTracklets, + spectra::MultTPC + +); +using SpColl = SpColls::iterator; + +DECLARE_SOA_TABLE(SpTracks, "AOD", "SPTRACKS", + o2::soa::Index<>, + spectra::CollisionId, + spectra::TPCNSigmaStorePi, spectra::TPCNSigmaStoreKa, spectra::TPCNSigmaStorePr, + spectra::TOFNSigmaStorePi, spectra::TOFNSigmaStoreKa, spectra::TOFNSigmaStorePr, + spectra::PtSigned, spectra::Eta, spectra::Phi, + track::Length, + track::TPCSignal, + track::TPCChi2NCl, track::ITSChi2NCl, track::TOFChi2, + track::TPCNClsShared, + track::TPCNClsFindable, + track::TPCNClsFindableMinusFound, + track::TPCNClsFindableMinusCrossedRows, + spectra::IsPVContributor, + track::ITSClusterMap, + spectra::HasTRD, + // pidtofevtime::EvTimeTOF, + // pidtofevtime::EvTimeTOFErr, + // pidtofevtime::EvTimeTOFMult, + // spectra::EvTimeT0AC, + // spectra::EvTimeT0ACErr, + // collision::CollisionTime, + // collision::CollisionTimeRes, + pidflags::TOFFlags, + spectra::DCAxyStore, + spectra::DCAzStore, + spectra::IsGlobalTrack, + spectra::IsGlobalTrackWoDCA, + spectra::DCAxy, + spectra::DCAz, + spectra::Pt, + track::Sign, + spectra::P, + spectra::Rapidity, + spectra::HasITS, + spectra::HasTPC, + spectra::HasTOF, + spectra::TRDSignal, + spectra::Flags, + spectra::TrackType, + spectra::TRDPattern, + spectra::IsInAcceptanceTrack, // Dummy + spectra::IsQualityTrackITS, // Dummy + spectra::IsQualityTrackTPC, // Dummy + track::ITSNCls, track::ITSNClsInnerBarrel, + track::TPCFractionSharedCls, + track::TPCNClsFound, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls, + pidflags::IsEvTimeDefined, + pidflags::IsEvTimeTOF, + pidflags::IsEvTimeT0AC, + pidflags::IsEvTimeTOFT0AC, + spectra::TOFNSigmaPi, + spectra::TOFNSigmaKa, + spectra::TOFNSigmaPr, + spectra::TPCNSigmaPi, + spectra::TPCNSigmaKa, + spectra::TPCNSigmaPr); +} // namespace o2::aod + +struct MultCodes { + static constexpr int kNoMultiplicity = 0; + static constexpr int kMultFV0M = 1; + static constexpr int kMultFT0M = 2; + static constexpr int kMultFDDM = 3; + static constexpr int kMultTracklets = 4; + static constexpr int kMultTPC = 5; + static constexpr int kMultNTracksPV = 6; + static constexpr int kMultNTracksPVeta1 = 7; + static constexpr int kCentralityFT0C = 8; + static constexpr int kCentralityFT0M = 9; + static constexpr int kCentralityFV0A = 10; + static constexpr int kNMults = 10; +}; + +#endif // PWGLF_DATAMODEL_SPECTRATOF_H_ \ No newline at end of file diff --git a/PWGLF/TableProducer/CMakeLists.txt b/PWGLF/TableProducer/CMakeLists.txt index 1dfa7f02f38..c4aa9b30cb6 100644 --- a/PWGLF/TableProducer/CMakeLists.txt +++ b/PWGLF/TableProducer/CMakeLists.txt @@ -43,7 +43,7 @@ o2physics_add_dpl_workflow(lambdakzerotofpid o2physics_add_dpl_workflow(cascadebuilder SOURCES cascadebuilder.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(cascadelabelbuilder @@ -82,6 +82,11 @@ o2physics_add_dpl_workflow(nuclei-spectra PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lithium4analysis + SOURCES lithium4analysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + # Hypernuclei o2physics_add_dpl_workflow(hypertriton-reco-task SOURCES hyperRecoTask.cxx @@ -98,6 +103,16 @@ o2physics_add_dpl_workflow(threebodymcfinder PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(hypertriton3bodybuilder + SOURCES hypertriton3bodybuilder.cxx + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(hypertriton3bodyfinder + SOURCES hypertriton3bodyfinder.cxx + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + # Resonances o2physics_add_dpl_workflow(reso2initializer SOURCES LFResonanceInitializer.cxx @@ -114,6 +129,11 @@ o2physics_add_dpl_workflow(filterf1proton PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(f1protonreducedtable + SOURCES f1protonreducedtable.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(v0qaanalysis SOURCES v0qaanalysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -123,3 +143,9 @@ o2physics_add_dpl_workflow(cascqaanalysis SOURCES cascqaanalysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +# Spectra +o2physics_add_dpl_workflow(spectra-derived + SOURCES spectraDerivedMaker.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/LFResonanceInitializer.cxx b/PWGLF/TableProducer/LFResonanceInitializer.cxx index 4dc6c28a312..8a9ef420335 100644 --- a/PWGLF/TableProducer/LFResonanceInitializer.cxx +++ b/PWGLF/TableProducer/LFResonanceInitializer.cxx @@ -28,6 +28,7 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "Framework/O2DatabasePDGPlugin.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/LFResonanceTables.h" #include "PWGLF/Utils/collisionCuts.h" @@ -43,10 +44,24 @@ using namespace o2::soa; /// Initializer for the resonance candidate producers struct reso2initializer { - float cXiMass = RecoDecay::getMassPDG(3312); + enum { + kECbegin = 0, + kINEL = 1, + kINEL10, + kINELg0, + kINELg010, + kTrig, + kINELg0Trig, + kINELg010Trig, + kECend, + }; + SliceCache cache; + float cXiMass; int mRunNumber; + int multEstimator; float d_bz; Service ccdb; + Service pdg; Produces resoCollisions; Produces reso2trks; @@ -64,18 +79,29 @@ struct reso2initializer { Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - Configurable cfgFatalWhenNull{"cfgFatalWhenNull", true, "Fatal when null"}; + Configurable cfgFatalWhenNull{"cfgFatalWhenNull", true, "Fatal when null on ccdb access"}; // Configurables - Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Pilot beam"}; // Choose if running on converted data or pilot beam + Configurable ConfIsRun3{"ConfIsRun3", true, "Running on Pilot beam"}; // Choose if running on converted data or pilot beam Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; + Configurable ConfFillQA{"ConfFillQA", false, "Fill QA histograms"}; + Configurable ConfBypassCCDB{"ConfBypassCCDB", false, "Bypass loading CCDB part to save CPU time and memory"}; // will be affected to b_z value. + + // Track filter from tpcSkimsTableCreator + Configurable trackSelection{"trackSelection", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; + Configurable trackSphDef{"trackSphDef", 0, "Spherocity Definition: |pT| = 1 -> 0, otherwise -> 1"}; + Configurable trackSphMin{"trackSphMin", 10, "Number of tracks for Spherocity Calculation"}; + + // EventCorrection for MC + ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 0.01, 0.1, 1.0, 5.0, 10., 15., 20., 30., 40., 50., 70., 100.0, 105.}, "Binning of the centrality axis"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -20, -15, -10, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 10, 15, 20}, "Mixing bins - z-vertex"}; /// Event cuts o2::analysis::CollisonCuts colCuts; 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 ConfEvtTriggerCheck{"ConfEvtTriggerCheck", false, "Evt sel: check for trigger"}; + Configurable ConfEvtTriggerSel{"ConfEvtTriggerSel", 8, "Evt sel: trigger"}; + Configurable ConfEvtOfflineCheck{"ConfEvtOfflineCheck", true, "Evt sel: check for offline selection"}; Configurable cfgMultName{"cfgMultName", "FT0M", "The name of multiplicity estimator"}; @@ -86,14 +112,14 @@ struct reso2initializer { /// DCA Selections for V0 // DCAr to PV - Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.05, "Track DCAr cut to PV Maximum"}; + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 2.0, "Track DCAr cut to PV Maximum"}; Configurable cMinV0PosDCArToPVcut{"cMinV0PosDCArToPVcut", 0.05f, "V0 Positive Track DCAr cut to PV Minimum"}; // Pre-selection Configurable cMinV0NegDCArToPVcut{"cMinV0NegDCArToPVcut", 0.05f, "V0 Negative Track DCAr cut to PV Minimum"}; // Pre-selection // DCAz to PV Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; - Configurable cMinV0Radius{"cMinV0Radius", 5.0, "Minimum V0 radius from PV"}; + Configurable cMinV0Radius{"cMinV0Radius", 0.0, "Minimum V0 radius from PV"}; Configurable cMaxV0Radius{"cMaxV0Radius", 200.0, "Maximum V0 radius from PV"}; Configurable cMinV0CosPA{"cMinV0CosPA", 0.995, "Minimum V0 CosPA to PV"}; @@ -111,21 +137,18 @@ struct reso2initializer { Configurable cMinCascRadius{"cMinCascRadius", 0.0, "Minimum Cascade radius from PV"}; Configurable cCascMassResol{"cCascMassResol", 999, "Cascade mass resolution"}; - HistogramRegistry qaRegistry{"QAHistos", { - {"hGoodTrackIndices", "hGoodTrackIndices", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, - {"hGoodMCTrackIndices", "hGoodMCTrackIndices", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, - {"hGoodV0Indices", "hGoodV0Indices", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - {"hGoodMCV0Indices", "hGoodMCV0Indices", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - {"hGoodCascIndices", "hGoodCascIndices", {HistType::kTH1F, {{8, 0.0f, 8.0f}}}}, - {"hGoodMCCascIndices", "hGoodMCCascIndices", {HistType::kTH1F, {{8, 0.0f, 8.0f}}}}, - }, - OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Pre-filters for efficient process // Filter tofPIDFilter = aod::track::tofExpMom < 0.f || ((aod::track::tofExpMom > 0.f) && ((nabs(aod::pidtof::tofNSigmaPi) < pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaKa) < pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaPr) < pidnSigmaPreSelectionCut))); // TOF + Filter trackFilter = (trackSelection.node() == 0) || // from tpcSkimsTableCreator + ((trackSelection.node() == 1) && requireGlobalTrackInFilter()) || + ((trackSelection.node() == 2) && requireGlobalTrackWoPtEtaInFilter()) || + ((trackSelection.node() == 3) && requireGlobalTrackWoDCAInFilter()) || + ((trackSelection.node() == 4) && requireQualityTracksInFilter()) || + ((trackSelection.node() == 5) && requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks)); Filter tpcPIDFilter = nabs(aod::pidtpc::tpcNSigmaPi) < pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaKa) < pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaPr) < pidnSigmaPreSelectionCut; // TPC - Filter trackFilter = nabs(aod::track::eta) < cfgCutEta; // Eta cut - Filter trackCutFilter = requireGlobalTrackInFilter(); // Global track cuts + Filter trackEtaFilter = nabs(aod::track::eta) < cfgCutEta; // Eta cut Filter collisionFilter = nabs(aod::collision::posZ) < ConfEvtZvtx; // MC Resonance parent filter @@ -139,12 +162,13 @@ struct reso2initializer { || (nabs(aod::mcparticle::pdgCode) == 113) // rho(770) || (nabs(aod::mcparticle::pdgCode) == 213) // rho(770)pm || (nabs(aod::mcparticle::pdgCode) == 3224) // Sigma(1385)+ - || (nabs(aod::mcparticle::pdgCode) == 3124) // Sigma(1385)- + || (nabs(aod::mcparticle::pdgCode) == 3124) // Lambda(1520) || (nabs(aod::mcparticle::pdgCode) == 3324) // Xi(1530)0 + || (nabs(aod::mcparticle::pdgCode) == 10323) // K1(1270)+ || (nabs(aod::mcparticle::pdgCode) == 123314) // Xi(1820)0 || (nabs(aod::mcparticle::pdgCode) == 123324); // Xi(1820)-0 - using ResoEvents = soa::Join; + using ResoEvents = soa::Join; using ResoEventsMC = soa::Join; using ResoTracks = aod::Reso2TracksPIDExt; using ResoTracksMC = soa::Join; @@ -157,13 +181,27 @@ struct reso2initializer { bool IsTrackSelected(CollisionType const& collision, TrackType const& track) { // Track selection - qaRegistry.fill(HIST("hGoodTrackIndices"), 0.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodTrackIndices"), 0.5); // MC case can be handled here if constexpr (isMC) { // MC check - qaRegistry.fill(HIST("hGoodMCTrackIndices"), 0.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodMCTrackIndices"), 0.5); } - qaRegistry.fill(HIST("hGoodTrackIndices"), 1.5); + // DCAxy cut + if (fabs(track.dcaXY()) > cMaxDCArToPVcut) + return false; + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodTrackIndices"), 1.5); + // DCAz cut + if (fabs(track.dcaZ()) > cMaxDCAzToPVcut || fabs(track.dcaZ()) < cMinDCAzToPVcut) + return false; + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodTrackIndices"), 2.5); + + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodTrackIndices"), 7.5); return true; } @@ -171,7 +209,8 @@ struct reso2initializer { bool IsV0Selected(CollisionType const& collision, V0Type const& v0, TrackType const& track) { // V0 selection - qaRegistry.fill(HIST("hGoodV0Indices"), 0.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodV0Indices"), 0.5); auto postrack = v0.template posTrack_as(); auto negtrack = v0.template negTrack_as(); @@ -180,25 +219,30 @@ struct reso2initializer { return false; if (negtrack.tpcNClsCrossedRows() < mincrossedrows) return false; - qaRegistry.fill(HIST("hGoodV0Indices"), 1.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodV0Indices"), 1.5); if (fabs(postrack.dcaXY()) < cMinV0PosDCArToPVcut) return false; if (fabs(negtrack.dcaXY()) < cMinV0NegDCArToPVcut) return false; - qaRegistry.fill(HIST("hGoodV0Indices"), 2.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodV0Indices"), 2.5); if ((v0.v0radius() > cMaxV0Radius) || (v0.v0radius() < cMinV0Radius)) return false; - qaRegistry.fill(HIST("hGoodV0Indices"), 3.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodV0Indices"), 3.5); if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cMinV0CosPA) return false; - qaRegistry.fill(HIST("hGoodV0Indices"), 4.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodV0Indices"), 4.5); // MC case can be handled here if constexpr (isMC) { // MC check - qaRegistry.fill(HIST("hGoodMCV0Indices"), 0.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodMCV0Indices"), 0.5); } return true; } @@ -207,7 +251,8 @@ struct reso2initializer { bool IsCascSelected(CollisionType const& collision, CascType const& casc, TrackType const& track) { // V0 selection - qaRegistry.fill(HIST("hGoodCascIndices"), 0.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodCascIndices"), 0.5); auto trackBach = casc.template bachelor_as(); // auto trackPos = casc.template posTrack_as(); @@ -216,69 +261,153 @@ struct reso2initializer { // track cuts if (trackBach.tpcNClsCrossedRows() < mincrossedrows_cascbach) return false; - qaRegistry.fill(HIST("hGoodCascIndices"), 1.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodCascIndices"), 1.5); if (fabs(trackBach.dcaXY()) < cMinCascBachDCArToPVcut) return false; if (fabs(trackBach.dcaXY()) > cMaxCascBachDCArToPVcut) return false; - qaRegistry.fill(HIST("hGoodCascIndices"), 2.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodCascIndices"), 2.5); // DCA daugthers if (casc.dcaV0daughters() > cMaxCascDCAV0Daughters) return false; if (casc.dcacascdaughters() > cMaxCascDCACascDaughters) return false; - qaRegistry.fill(HIST("hGoodCascIndices"), 3.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodCascIndices"), 3.5); // CPA cuts if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cMinCascCosPA) return false; if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cMinCascV0CosPA) return false; - qaRegistry.fill(HIST("hGoodCascIndices"), 4.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodCascIndices"), 4.5); // V0 radius auto v0radius = casc.v0radius(); if ((v0radius > cMaxCascV0Radius) || (v0radius < cMinCascV0Radius)) return false; - qaRegistry.fill(HIST("hGoodCascIndices"), 5.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodCascIndices"), 5.5); // Casc radius auto cascradius = casc.cascradius(); if ((cascradius > cMaxCascRadius) || (cascradius < cMinCascRadius)) return false; - qaRegistry.fill(HIST("hGoodCascIndices"), 6.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodCascIndices"), 6.5); // Casc mass auto cascMass = casc.mXi(); if (abs(cascMass - cXiMass) > cCascMassResol) return false; - qaRegistry.fill(HIST("hGoodCascIndices"), 7.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodCascIndices"), 7.5); // MC case can be handled here if constexpr (isMC) { // MC check - qaRegistry.fill(HIST("hGoodMCCascIndices"), 0.5); + if (ConfFillQA) + qaRegistry.fill(HIST("hGoodMCCascIndices"), 0.5); } return true; } + // Centralicity estimator selection + template + float CentEst(ResoColl ResoEvents) + { + float returnValue = -999.0; + switch (multEstimator) { + case 0: + returnValue = ResoEvents.centFT0M(); + case 1: + returnValue = ResoEvents.centFT0C(); + case 2: + returnValue = ResoEvents.centFT0A(); + case 99: + returnValue = ResoEvents.centFV0A(); + default: + returnValue = ResoEvents.centFT0M(); + } + return returnValue; + } + // Multiplicity estimator selection template float MultEst(ResoColl ResoEvents) { - if (cfgMultName.value == "FT0M") { - return ResoEvents.centFT0M(); - } else if (cfgMultName.value == "FT0C") { - return ResoEvents.centFT0C(); - } else if (cfgMultName.value == "FT0A") { - return ResoEvents.centFT0A(); - } else if (cfgMultName.value == "FV0M") { - return ResoEvents.multFV0M(); - } else { - return ResoEvents.centFT0M(); + float returnValue = -999.0; + switch (multEstimator) { + case 0: + returnValue = ResoEvents.multFT0M(); + case 1: + returnValue = ResoEvents.multFT0C(); + case 2: + returnValue = ResoEvents.multFT0A(); + case 99: + returnValue = ResoEvents.multFV0A(); + default: + returnValue = ResoEvents.multFT0M(); } + return returnValue; + } + + /// Compute the spherocity of an event + /// Important here is that the filter on tracks does not interfere here! + /// In Run 2 we used here global tracks within |eta| < 0.8 + /// \tparam T type of the tracks + /// \param tracks All tracks + /// \return value of the spherocity of the event + template + float ComputeSpherocity(T const& tracks, int nTracksMin, int spdef) + { + // if number of tracks is not enough for spherocity estimation. + int ntrks = tracks.size(); + if (ntrks < nTracksMin) + return -99.; + + // start computing spherocity + + float ptSum = 0.; + for (auto const& track : tracks) { + if (ConfFillQA) { + qaRegistry.fill(HIST("Phi"), track.phi()); + } + if (spdef == 0) { + ptSum += 1.; + } else { + ptSum += track.pt(); + } + } + + float tempSph = 1.; + for (int i = 0; i < 360 / 0.1; ++i) { + float sum = 0., pt = 0.; + float phiparm = (TMath::Pi() * i * 0.1) / 180.; + float nx = TMath::Cos(phiparm); + float ny = TMath::Sin(phiparm); + for (auto const& trk : tracks) { + pt = trk.pt(); + if (spdef == 0) { + pt = 1.; + } + float phi = trk.phi(); + float px = pt * TMath::Cos(phi); + float py = pt * TMath::Sin(phi); + // sum += pt * abs(sin(phiparm - phi)); + sum += TMath::Abs(px * ny - py * nx); + } + float sph = TMath::Power((sum / ptSum), 2); + if (sph < tempSph) + tempSph = sph; + } + + return TMath::Power(TMath::Pi() / 2., 2) * tempSph; } // Filter for all tracks @@ -289,26 +418,6 @@ struct reso2initializer { for (auto& track : tracks) { if (!IsTrackSelected(collision, track)) continue; - // Add PID selection criteria here - uint8_t tpcPIDselections = 0; - uint8_t tofPIDselections = 0; - // TPC PID - if (std::abs(track.tpcNSigmaPi()) < pidnSigmaPreSelectionCut) - tpcPIDselections |= aod::resodaughter::PDGtype::kPion; - if (std::abs(track.tpcNSigmaKa()) < pidnSigmaPreSelectionCut) - tpcPIDselections |= aod::resodaughter::PDGtype::kKaon; - if (std::abs(track.tpcNSigmaPr()) < pidnSigmaPreSelectionCut) - tpcPIDselections |= aod::resodaughter::PDGtype::kProton; - // TOF PID - if (track.hasTOF()) { - tofPIDselections |= aod::resodaughter::PDGtype::kHasTOF; - if (std::abs(track.tofNSigmaPi()) < pidnSigmaPreSelectionCut) - tofPIDselections |= aod::resodaughter::PDGtype::kPion; - if (std::abs(track.tofNSigmaKa()) < pidnSigmaPreSelectionCut) - tofPIDselections |= aod::resodaughter::PDGtype::kKaon; - if (std::abs(track.tofNSigmaPr()) < pidnSigmaPreSelectionCut) - tofPIDselections |= aod::resodaughter::PDGtype::kProton; - } reso2trks(resoCollisions.lastIndex(), track.pt(), track.px(), @@ -322,14 +431,22 @@ struct reso2initializer { track.dcaZ(), track.x(), track.alpha(), - tpcPIDselections, - tofPIDselections, + track.hasTOF(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tofNSigmaPi(), track.tofNSigmaKa(), - track.tofNSigmaPr()); + track.tofNSigmaPr(), + track.tpcSignal(), + track.passedITSRefit(), + track.passedTPCRefit(), + track.isGlobalTrackWoDCA(), + track.isPrimaryTrack(), + track.isPVContributor(), + track.tpcCrossedRowsOverFindableCls(), + track.itsChi2NCl(), + track.tpcChi2NCl()); if constexpr (isMC) { fillMCTrack(track); } @@ -411,9 +528,24 @@ struct reso2initializer { } return lMothersPDGs; }; + auto getSiblingsIndeces = [&](auto const& theMcParticle) { + std::vector lSiblingsIndeces{}; + for (auto& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother index lMother: %d", lMother.globalIndex()); + for (auto& lDaughter : lMother.template daughters_as()) { + LOGF(debug, " daughter index lDaughter: %d", lDaughter.globalIndex()); + if (lDaughter.globalIndex() != 0 && lDaughter.globalIndex() != theMcParticle.globalIndex()) { + lSiblingsIndeces.push_back(lDaughter.globalIndex()); + } + } + } + return lSiblingsIndeces; + }; // ------ std::vector mothers = {-1, -1}; std::vector motherPDGs = {-1, -1}; + int siblings[2] = {0, 0}; + std::vector siblings_temp = {-1, -1}; if (track.has_mcParticle()) { // // Get the MC particle @@ -421,14 +553,20 @@ struct reso2initializer { if (particle.has_mothers()) { mothers = getMothersIndeces(particle); motherPDGs = getMothersPDGCodes(particle); + siblings_temp = getSiblingsIndeces(particle); } while (mothers.size() > 2) { mothers.pop_back(); motherPDGs.pop_back(); } + if (siblings_temp.size() > 0) + siblings[0] = siblings_temp[0]; + if (siblings_temp.size() > 1) + siblings[1] = siblings_temp[1]; reso2mctracks(particle.pdgCode(), mothers[0], motherPDGs[0], + siblings, particle.isPhysicalPrimary(), particle.producedByGenerator()); } else { @@ -436,6 +574,7 @@ struct reso2initializer { reso2mctracks(0, mothers[0], motherPDGs[0], + siblings, 0, 0); } @@ -644,21 +783,58 @@ struct reso2initializer { void init(InitContext&) { + cXiMass = pdg->GetParticle(3312)->Mass(); mRunNumber = 0; d_bz = 0; + // Multiplicity estimator selection (0: FT0M, 1: FT0C, 2: FT0A, 99: FV0A) + if (cfgMultName.value == "FT0M") { + multEstimator = 0; + } else if (cfgMultName.value == "FT0C") { + multEstimator = 1; + } else if (cfgMultName.value == "FT0A") { + multEstimator = 2; + } else if (cfgMultName.value == "FV0A") { + multEstimator = 99; + } else { + multEstimator = 0; + } + colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3); colCuts.init(&qaRegistry); + if (!ConfBypassCCDB) { + ccdb->setURL(ccdburl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(cfgFatalWhenNull); + uint64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); // TODO must become global parameter from the train creation time + } - ccdb->setURL(ccdburl.value); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(cfgFatalWhenNull); - uint64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - ccdb->setCreatedNotAfter(now); // TODO must become global parameter from the train creation time + // QA histograms + AxisSpec idxAxis = {8, 0, 8, "Index"}; + if (ConfFillQA) { + qaRegistry.add("hGoodTrackIndices", "hGoodTrackIndices", kTH1F, {idxAxis}); + qaRegistry.add("hGoodMCTrackIndices", "hGoodMCTrackIndices", kTH1F, {idxAxis}); + qaRegistry.add("hGoodV0Indices", "hGoodV0Indices", kTH1F, {idxAxis}); + qaRegistry.add("hGoodMCV0Indices", "hGoodMCV0Indices", kTH1F, {idxAxis}); + qaRegistry.add("hGoodCascIndices", "hGoodCascIndices", kTH1F, {idxAxis}); + qaRegistry.add("hGoodMCCascIndices", "hGoodMCCascIndices", kTH1F, {idxAxis}); + qaRegistry.add("Phi", "#phi distribution", kTH1F, {{65, -0.1, 6.4}}); + } + // MC histograms + if (doprocessMCGenCount) { + AxisSpec EvtClassAxis = {kECend - 1, kECbegin + 0.5, kECend - 0.5, "", "event class"}; + AxisSpec ZAxis = {CfgVtxBins, "zaxis"}; + AxisSpec CentAxis = {binsCent, "centrality"}; + qaRegistry.add("Event/totalEventGenMC", "totalEventGenMC", {HistType::kTHnSparseF, {EvtClassAxis}}); + qaRegistry.add("Event/hgenzvtx", "evntclass; zvtex", {HistType::kTHnSparseF, {EvtClassAxis, ZAxis, CentAxis}}); + } } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) // Simple copy from LambdaKzeroFinder.cxx { + if (ConfBypassCCDB) + return; if (mRunNumber == bc.runNumber()) { return; } @@ -711,15 +887,70 @@ struct reso2initializer { colCuts.fillQA(collision); if (ConfIsRun3) { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), MultEst(collision), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), CentEst(collision), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } else { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } fillTracks(collision, tracks); } PROCESS_SWITCH(reso2initializer, processTrackData, "Process for data", true); + PresliceUnsorted perMcCol = aod::mccollisionlabel::mcCollisionId; + void processMCGenCount(aod::McCollisions const& mccollisions, aod::McParticles const& mcParticles, ResoEventsMC const& mcCols) + { + // Mainly referenced from dndeta_hi task in PWG-MM PAG-Multiplicity (Beomkyu Kim) + for (auto& mcCollision : mccollisions) { // Gen MC Event loop + auto particles = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + std::vector bevtc(kECend, false); + bevtc[kINEL] = true; + auto posZ = mcCollision.posZ(); + if (std::abs(posZ) < 10) + bevtc[kINEL10] = true; + for (auto& particle : particles) { + if (!particle.isPhysicalPrimary()) + continue; + auto kp = pdg->GetParticle(particle.pdgCode()); + if (kp != nullptr) { + if (std::abs(kp->Charge()) >= 3) { // 3 quarks + if (std::abs(particle.eta()) < 1) { // INEL>0 definition + bevtc[kINELg0] = true; + break; + } + } + } + } + if (bevtc[kINELg0] && bevtc[kINEL10]) + bevtc[kINELg010] = true; + + for (auto ievtc = 1u; ievtc < kECend; ievtc++) { + if (bevtc[ievtc]) + qaRegistry.fill(HIST("Event/totalEventGenMC"), Double_t(ievtc)); + } + + auto collisionsample = mcCols.sliceBy(perMcCol, mcCollision.globalIndex()); + float cent = -1.0; + if (collisionsample.size() != 1) { // Prevent no reconstructed collision case + cent = -1; + } else { + for (auto& collision : collisionsample) { + cent = CentEst(collision); + if (collision.sel8()) + bevtc[kTrig] = true; + } + } + if (bevtc[kTrig] && bevtc[kINELg0]) + bevtc[kINELg0Trig] = true; + if (bevtc[kINELg0Trig] && bevtc[kINEL10]) + bevtc[kINELg010Trig] = true; + for (auto ievtc = 1u; ievtc < kECend; ievtc++) { + if (bevtc[ievtc]) + qaRegistry.fill(HIST("Event/hgenzvtx"), Double_t(ievtc), posZ, cent); + } + } + } + PROCESS_SWITCH(reso2initializer, processMCGenCount, "Process for MC", false); + void processTrackV0Data(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, ResoV0s const& V0s, @@ -733,9 +964,9 @@ struct reso2initializer { colCuts.fillQA(collision); if (ConfIsRun3) { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), MultEst(collision), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), CentEst(collision), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } else { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } fillTracks(collision, tracks); @@ -757,9 +988,9 @@ struct reso2initializer { colCuts.fillQA(collision); if (ConfIsRun3) { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), MultEst(collision), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), CentEst(collision), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } else { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } fillTracks(collision, tracks); @@ -780,9 +1011,9 @@ struct reso2initializer { colCuts.fillQA(collision); if (ConfIsRun3) { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), MultEst(collision), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), CentEst(collision), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } else { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } // Loop over tracks @@ -806,9 +1037,9 @@ struct reso2initializer { colCuts.fillQA(collision); if (ConfIsRun3) { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), MultEst(collision), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), CentEst(collision), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } else { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } // Loop over tracks @@ -834,9 +1065,9 @@ struct reso2initializer { colCuts.fillQA(collision); if (ConfIsRun3) { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), MultEst(collision), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), CentEst(collision), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } else { - resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), collision.multTPC(), colCuts.computeSphericity(collision, tracks), d_bz, bc.timestamp()); + resoCollisions(collision.posX(), collision.posY(), collision.posZ(), collision.multFV0M(), MultEst(collision), ComputeSpherocity(tracks, trackSphMin, trackSphDef), d_bz, bc.timestamp()); } // Loop over tracks diff --git a/PWGLF/TableProducer/LFTreeCreatorNuclei.cxx b/PWGLF/TableProducer/LFTreeCreatorNuclei.cxx index 065d085c64c..c1bfb7833d0 100644 --- a/PWGLF/TableProducer/LFTreeCreatorNuclei.cxx +++ b/PWGLF/TableProducer/LFTreeCreatorNuclei.cxx @@ -19,7 +19,7 @@ /// #include "PWGLF/DataModel/LFNucleiTables.h" - +#include "PWGLF/DataModel/LFParticleIdentification.h" #include #include #include @@ -46,15 +46,25 @@ using namespace o2::framework::expressions; /// Writes the full information in an output TTree struct LfTreeCreatorNuclei { - Produces tableEvents; - Produces tableCandidate; + Produces tableEvents; + Produces tableCandidate; + Produces tableCandidateExtra; Produces tableCandidateMC; + HistogramRegistry hEvents{"hEvents", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) { if (doprocessData == true && doprocessMC == true) { LOGF(fatal, "Cannot enable processData and processMC at the same time. Please choose one."); } + + hEvents.add("eventSelection", "eventSelection", kTH1D, {{5, -0.5, 4.5}}); + auto h = hEvents.get(HIST("eventSelection")); + h->GetXaxis()->SetBinLabel(1, "total"); + h->GetXaxis()->SetBinLabel(2, "sel8"); + h->GetXaxis()->SetBinLabel(3, "z-vertex"); + h->GetXaxis()->SetBinLabel(4, "not empty"); + h->GetXaxis()->SetBinLabel(5, "With a good track"); } // track @@ -64,96 +74,145 @@ struct LfTreeCreatorNuclei { Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; Configurable nsigmacutLow{"nsigmacutLow", -8.0, "Value of the Nsigma cut"}; Configurable nsigmacutHigh{"nsigmacutHigh", +8.0, "Value of the Nsigma cut"}; - Configurable trackSelType{"trackSelType", 0, "Option for the track cut: 0 isGlobalTrackWoDCA, 1 isGlobalTrack"}; + Configurable ptcutLow{"ptcutLow", 0.f, "Value of the lower pt cut for the filtering (option 3)"}; + Configurable ptcutHigh{"ptcutHigh", 10.f, "Value of the upper pt cut for the filtering (option 3)"}; + Configurable filterDeTPC{"filterDeTPC", 15.0, "Value of the Nsigma cut for deuterons for the filtering (option 3)"}; + Configurable filterHeTPC{"filterHeTPC", 15.0, "Value of the Nsigma cut for helium3 for the filtering (option 3)"}; + Configurable trackSelType{"trackSelType", 0, "Option for the track cut: 0 isGlobalTrackWoDCA, 1 isGlobalTrack, 3 is for filtered mode"}; Configurable nITSInnerBarrelHits{"nITSInnerBarrelHits", 0, "Option for ITS inner barrel hits maximum: 3"}; // events Configurable cfgHighCutVertex{"cfgHighCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgLowCutVertex{"cfgLowCutVertex", -10.0f, "Accepted z-vertex range"}; Configurable useEvsel{"useEvsel", true, "Use sel8 for run3 Event Selection"}; + Configurable doSkim{"doSkim", false, "Save events that contains only selected tracks (for filtered mode)"}; Filter collisionFilter = (aod::collision::posZ < cfgHighCutVertex && aod::collision::posZ > cfgLowCutVertex); // Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (requireGlobalTrackInFilter()); Filter etaFilter = (nabs(aod::track::eta) < cfgCutEta); - Filter trackFilter = (trackSelType.value == 0 && requireGlobalTrackWoDCAInFilter()) || (trackSelType.value == 1 && requireGlobalTrackInFilter()); + Filter trackFilter = (trackSelType.value == 0 && requireGlobalTrackWoDCAInFilter()) || + (trackSelType.value == 1 && requireGlobalTrackInFilter()) || + (trackSelType.value == 3); Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); - using EventCandidates = soa::Join; + using EventCandidates = soa::Join; using TrackCandidates = soa::Join; + aod::pidTPCLfFullPi, aod::pidTOFFullPi, + aod::pidTPCLfFullKa, aod::pidTOFFullKa, + aod::pidTPCLfFullPr, aod::pidTOFFullPr, + aod::pidTPCLfFullDe, aod::pidTOFFullDe, + aod::pidTPCLfFullTr, aod::pidTOFFullTr, + aod::pidTPCLfFullHe, aod::pidTOFFullHe, + aod::pidTPCLfFullAl, aod::pidTOFFullAl>; + + template + bool checkQuality(CollisionType const& collision, TrackType const& tracks) + { + bool out = kFALSE; + for (auto& track : tracks) { + + if (track.itsNClsInnerBarrel() < nITSInnerBarrelHits) { + continue; + } + if (!track.hasTPC()) { + continue; + } + if (track.tpcNClsCrossedRows() < 90) { + continue; + } + if ((track.pt() < ptcutLow.value) || (track.pt() > ptcutHigh.value)) { + continue; + } + if ((TMath::Abs(track.tpcNSigmaDe()) > filterDeTPC.value) && (TMath::Abs(track.tpcNSigmaHe()) > filterHeTPC.value)) { + continue; + } + out = kTRUE; + } + return out; + } template void fillForOneEvent(CollisionType const& collision, TrackType const& tracks) { // Filling event properties - tableEvents(collision.bcId(), - collision.numContrib(), + tableEvents(collision.numContrib(), // collision.bcId(), collision.posX(), collision.posY(), collision.posZ(), - collision.multFV0M(), + collision.centFV0A(), + collision.centFT0M(), collision.sel8(), collision.bc().runNumber()); // Filling candidate properties tableCandidate.reserve(tracks.size()); + tableCandidateExtra.reserve(tracks.size()); if constexpr (isMC) { tableCandidateMC.reserve(tracks.size()); } for (auto& track : tracks) { - if (track.itsNClsInnerBarrel() < nITSInnerBarrelHits) + if (track.itsNClsInnerBarrel() < nITSInnerBarrelHits) { continue; - // auto const& mcParticle = track.mcParticle(); + } + if (trackSelType.value == 3) { // Filtering mode + if (!track.hasTPC()) { + continue; + } + if (track.tpcNClsCrossedRows() < 90) { + continue; + } + if ((track.pt() < ptcutLow.value) || (track.pt() > ptcutHigh.value)) { + continue; + } + if ((TMath::Abs(track.tpcNSigmaDe()) > filterDeTPC.value) && (TMath::Abs(track.tpcNSigmaHe()) > filterHeTPC.value)) { + continue; + } + } + tableCandidate( tableEvents.lastIndex(), - track.dcaXY(), - track.dcaZ(), - track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.tpcNSigmaDe(), track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl(), - track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.tofNSigmaDe(), track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl(), - track.tpcExpSignalDiffPr(), track.tpcExpSignalDiffDe(), track.tpcExpSignalDiffHe(), - track.tofExpSignalDiffPr(), track.tofExpSignalDiffDe(), track.tofExpSignalDiffHe(), + track.dcaXY(), track.dcaZ(), + track.tpcNSigmaDe(), track.tpcNSigmaHe(), + track.tofNSigmaDe(), track.tofNSigmaHe(), track.isEvTimeTOF(), track.isEvTimeT0AC(), track.hasTOF(), track.hasTRD(), track.tpcInnerParam(), - track.tofExpMom(), - track.tpcSignal(), track.beta(), - track.px(), - track.py(), - track.pz(), - track.pt(), - track.p(), - track.eta(), - track.phi(), + track.tpcSignal(), + track.pt(), track.eta(), track.phi(), track.sign(), track.itsNCls(), - track.tpcNClsCrossedRows(), - track.tpcCrossedRowsOverFindableCls(), - track.tpcNClsFound(), + track.tpcNClsFindable(), + track.tpcNClsFindableMinusFound(), + track.tpcNClsFindableMinusCrossedRows(), track.tpcChi2NCl(), track.itsChi2NCl(), track.itsClusterMap(), track.isPVContributor()); + tableCandidateExtra( + track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.tpcNSigmaTr(), track.tpcNSigmaAl(), + track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.tofNSigmaTr(), track.tofNSigmaAl(), + track.tpcExpSignalDiffPr(), track.tpcExpSignalDiffDe(), track.tpcExpSignalDiffHe(), + track.tofExpSignalDiffPr(), track.tofExpSignalDiffDe(), track.tofExpSignalDiffHe(), + track.tofExpMom()); + if constexpr (isMC) { // Filling MC reco information if (track.has_mcParticle()) { const auto& particle = track.mcParticle(); tableCandidateMC(particle.pdgCode(), particle.isPhysicalPrimary(), - particle.producedByGenerator()); + particle.producedByGenerator(), + particle.px(), + particle.py(), + particle.pz()); continue; } - tableCandidateMC(0, -1, -1); + tableCandidateMC(0, -1, -1, 0, 0, 0); } } } @@ -161,14 +220,26 @@ struct LfTreeCreatorNuclei { Preslice> perCollision = aod::track::collisionId; void processData(soa::Filtered const& collisions, - soa::Filtered const& tracks, aod::BCs const&) + soa::Filtered const& tracks, + aod::BCs const&) { for (const auto& collision : collisions) { + hEvents.fill(HIST("eventSelection"), 0); if (useEvsel && !collision.sel8()) { continue; } + hEvents.fill(HIST("eventSelection"), 1); + if (collision.posZ() >= cfgHighCutVertex && collision.posZ() <= cfgLowCutVertex) + continue; + hEvents.fill(HIST("eventSelection"), 2); const auto& tracksInCollision = tracks.sliceBy(perCollision, collision.globalIndex()); + if (tracksInCollision.size() == 0) + continue; + hEvents.fill(HIST("eventSelection"), 3); + if (doSkim && (trackSelType.value == 3) && !checkQuality(collision, tracksInCollision)) + continue; fillForOneEvent(collision, tracksInCollision); + hEvents.fill(HIST("eventSelection"), 4); } } diff --git a/PWGLF/TableProducer/cascadebuilder.cxx b/PWGLF/TableProducer/cascadebuilder.cxx index efb7394133a..4862adacc0b 100644 --- a/PWGLF/TableProducer/cascadebuilder.cxx +++ b/PWGLF/TableProducer/cascadebuilder.cxx @@ -62,6 +62,17 @@ #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#ifndef HomogeneousField +#define HomogeneousField +#endif + +/// includes KFParticle +#include "KFParticle.h" +#include "KFPTrack.h" +#include "KFPVertex.h" +#include "KFParticleBase.h" +#include "KFVertex.h" + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -93,8 +104,10 @@ using LabeledTracksExtra = soa::Join; // Builder task: rebuilds multi-strange candidates struct cascadeBuilder { Produces cascdata; + Produces kfcascdata; Produces trackedcascdata; Produces casccovs; // if requested by someone + Produces kfcasccovs; // if requested by someone Service ccdb; Configurable d_UseAutodetectMode{"d_UseAutodetectMode", false, "Autodetect requested topo sels"}; @@ -111,6 +124,8 @@ struct cascadeBuilder { Configurable lambdaMassWindow{"lambdaMassWindow", .01, "Distance from Lambda mass"}; Configurable dcaXYCascToPV{"dcaXYCascToPV", 1e+6, "dcaXYCascToPV"}; Configurable dcaZCascToPV{"dcaZCascToPV", 1e+6, "dcaZCascToPV"}; + Configurable d_doPtDep_CosPaCut{"d_doPtDep_CosPaCut", false, "Enable pt dependent cos PA cut"}; + Configurable cas_cospaParameter{"cas_cospaParameter", 0.341715, "Parameter for pt dependent cos PA cut"}; // Operation and minimisation criteria Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; @@ -132,6 +147,7 @@ struct cascadeBuilder { Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; // generate and fill extra QA histograms if requested Configurable d_doQA{"d_doQA", false, "Do basic QA"}; @@ -148,6 +164,23 @@ struct cascadeBuilder { Configurable dQAXiMassWindow{"dQAXiMassWindow", 0.005, "Xi mass window for ITS cluster map QA"}; Configurable dQAOmegaMassWindow{"dQAOmegaMassWindow", 0.005, "Omega mass window for ITS cluster map QA"}; + // for KF particle operation + Configurable kfTuneForOmega{"kfTuneForOmega", false, "if enabled, take main cascade properties from Omega fit instead of Xi fit (= default)"}; + Configurable kfConstructMethod{"kfConstructMethod", 2, "KF Construct Method"}; + Configurable kfUseV0MassConstraint{"kfUseV0MassConstraint", true, "KF: use Lambda mass constraint"}; + Configurable kfUseCascadeMassConstraint{"kfUseCascadeMassConstraint", false, "KF: use Cascade mass constraint - WARNING: not adequate for inv mass analysis of Xi"}; + Configurable kfDoDCAFitterPreMinim{"kfDoDCAFitterPreMinim", true, "KF: do DCAFitter pre-optimization before KF fit to include material corrections"}; + + ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + + // for topo var QA + ConfigurableAxis axisTopoVarPointingAngle{"axisTopoVarPointingAngle", {50, 0.0, 1.0}, "pointing angle"}; + ConfigurableAxis axisTopoVarRAP{"axisTopoVarRAP", {50, 0.0, 1.0}, "radius x pointing angle axis"}; + ConfigurableAxis axisTopoVarV0Radius{"axisTopoVarV0Radius", {500, 0.0, 100.0}, "V0 decay radius (cm)"}; + ConfigurableAxis axisTopoVarDCAV0Dau{"axisTopoVarDCAV0Dau", {200, 0.0, 2.0}, "DCA between V0 daughters (cm)"}; + ConfigurableAxis axisTopoVarDCAToPV{"axisTopoVarDCAToPV", {200, -1, 1.0}, "single track DCA to PV (cm)"}; + ConfigurableAxis axisTopoVarDCAV0ToPV{"axisTopoVarDCAV0ToPV", {200, 0, 5.0}, "V0 DCA to PV (cm)"}; + int mRunNumber; float d_bz; float maxSnp; // max sine phi for propagation @@ -190,6 +223,7 @@ struct cascadeBuilder { std::array v0pos; std::array v0mompos; std::array v0momneg; + std::array cascademom; float v0dcadau; float v0dcapostopv; float v0dcanegtopv; @@ -199,11 +233,14 @@ struct cascadeBuilder { float yOmega; float bachBaryonCosPA; float bachBaryonDCAxyToPV; + float kfMLambda; + float kfV0Chi2; + float kfCascadeChi2; } cascadecandidate; o2::track::TrackParCov lBachelorTrack; o2::track::TrackParCov lV0Track; - o2::track::TrackPar lCascadeTrack; + o2::track::TrackParCov lCascadeTrack; // Helper struct to do bookkeeping of building parameters struct { @@ -255,6 +292,7 @@ struct cascadeBuilder { void init(InitContext& context) { resetHistos(); + registry.add("hKFParticleStatistics", "hKFParticleStatistics", kTH1F, {{10, -0.5f, 9.5f}}); // Optionally, add extra QA histograms to processing chain if (d_doQA) { @@ -264,10 +302,13 @@ struct cascadeBuilder { const AxisSpec axisOmegaMass{(int)dQANBinsMass, 1.572f, 1.772f, "Inv. Mass (GeV/c^{2})"}; const AxisSpec axisCascadeDCAtoPV{(int)dQANBinsDCAxy, -dQAMaxDCA, dQAMaxDCA, "DCA_{xy} (cm)"}; - registry.add("h2dXiMinusMass", "h2dXiMinusMass", kTH2F, {axisVsPtCoarse, axisXiMass}); - registry.add("h2dXiPlusMass", "h2dXiPlusMass", kTH2F, {axisVsPtCoarse, axisXiMass}); - registry.add("h2dOmegaMinusMass", "h2dOmegaMinusMass", kTH2F, {axisVsPtCoarse, axisOmegaMass}); - registry.add("h2dOmegaPlusMass", "h2dOmegaPlusMass", kTH2F, {axisVsPtCoarse, axisOmegaMass}); + registry.add("MassHistograms/h2dXiMinusMass", "h2dXiMinusMass", kTH2F, {axisVsPtCoarse, axisXiMass}); + registry.add("MassHistograms/h2dXiPlusMass", "h2dXiPlusMass", kTH2F, {axisVsPtCoarse, axisXiMass}); + registry.add("MassHistograms/h2dOmegaMinusMass", "h2dOmegaMinusMass", kTH2F, {axisVsPtCoarse, axisOmegaMass}); + registry.add("MassHistograms/h2dOmegaPlusMass", "h2dOmegaPlusMass", kTH2F, {axisVsPtCoarse, axisOmegaMass}); + + if (d_doPtDep_CosPaCut) + registry.addClone("MassHistograms/", "MassHistograms_BefPAcut/"); // bit packed ITS cluster map const AxisSpec axisITSCluMap{(int)128, -0.5f, +127.5f, "Packed ITS map"}; @@ -287,6 +328,11 @@ struct cascadeBuilder { registry.add("h2dITSCluMap_OmegaPlusNegative", "h2dITSCluMap_OmegaPlusNegative", kTH2D, {axisITSCluMap, axisRadius}); registry.add("h2dITSCluMap_OmegaPlusBachelor", "h2dITSCluMap_OmegaPlusBachelor", kTH2D, {axisITSCluMap, axisRadius}); + // QA plots of topological variables using axisPtQA + registry.add("h2dTopoVarCascPointingAngle", "h2dTopoVarCascPointingAngle", kTH2D, {axisPtQA, axisTopoVarPointingAngle}); + registry.add("h2dTopoVarCascRAP", "h2dTopoVarCascRAP", kTH2D, {axisPtQA, axisTopoVarRAP}); + registry.add("h2dTopoVarCascRadius", "h2dTopoVarCascRadius", kTH2D, {axisPtQA, axisTopoVarV0Radius}); + // if basic strangeness tracking QA is desired, do it here // convenience: equivalence between regular cascade and tracked cascade is easy to check here // -> completely automatic, easy comparison of 'trackable' candidates (<< all) @@ -378,7 +424,7 @@ struct cascadeBuilder { lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); } - if (doprocessRun2 == false && doprocessRun3 == false && doprocessRun3withStrangenessTracking == false) { + if (doprocessRun2 == false && doprocessRun3 == false && doprocessRun3withStrangenessTracking == false && doprocessRun3withKFParticle == false) { LOGF(fatal, "Neither processRun2 nor processRun3 nor processRun3withstrangenesstracking enabled. Please choose one!"); } if (doprocessRun2 == true && doprocessRun3 == true) { @@ -547,8 +593,10 @@ struct cascadeBuilder { } auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + o2::parameters::GRPObject* grpo = 0x0; o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); if (grpo) { o2::base::Propagator::initFieldFromGRP(grpo); // Fetch magnetic field from ccdb for current collision @@ -567,6 +615,9 @@ struct cascadeBuilder { mRunNumber = bc.runNumber(); // Set magnetic field value once known fitter.setBz(d_bz); + float magneticField = o2::base::Propagator::Instance()->getNominalBz(); + /// Set magnetic field for KF vertexing + KFParticle::SetField(magneticField); if (useMatCorrType == 2) { // setMatLUT only after magfield has been initalized @@ -574,6 +625,69 @@ struct cascadeBuilder { o2::base::Propagator::Instance()->setMatLUT(lut); } } + // TrackParCov to KF converter + // FIXME: could be an utility somewhere else + // from Carolina Reetz (thank you!) + template + KFParticle createKFParticleFromTrackParCov(const o2::track::TrackParametrizationWithError& trackparCov, int charge, float mass) + { + std::array xyz, pxpypz; + float xyzpxpypz[6]; + trackparCov.getPxPyPzGlo(pxpypz); + trackparCov.getXYZGlo(xyz); + for (int i{0}; i < 3; ++i) { + xyzpxpypz[i] = xyz[i]; + xyzpxpypz[i + 3] = pxpypz[i]; + } + + std::array cv; + try { + trackparCov.getCovXYZPxPyPzGlo(cv); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to get cov matrix from TrackParCov" << e.what(); + } + + KFParticle kfPart; + float Mini, SigmaMini, M, SigmaM; + kfPart.GetMass(Mini, SigmaMini); + LOG(debug) << "Daughter KFParticle mass before creation: " << Mini << " +- " << SigmaMini; + + try { + kfPart.Create(xyzpxpypz, cv.data(), charge, mass); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to create KFParticle from daughter TrackParCov" << e.what(); + } + + kfPart.GetMass(M, SigmaM); + LOG(debug) << "Daughter KFParticle mass after creation: " << M << " +- " << SigmaM; + return kfPart; + } + + // KF to TrackParCov converter + // FIXME: could be an utility somewhere else + // from Carolina Reetz (thank you!) + o2::track::TrackParCov getTrackParCovFromKFP(const KFParticle& kfParticle, const o2::track::PID pid, const int sign) + { + o2::gpu::gpustd::array xyz, pxpypz; + o2::gpu::gpustd::array cv; + + // get parameters from kfParticle + xyz[0] = kfParticle.GetX(); + xyz[1] = kfParticle.GetY(); + xyz[2] = kfParticle.GetZ(); + pxpypz[0] = kfParticle.GetPx(); + pxpypz[1] = kfParticle.GetPy(); + pxpypz[2] = kfParticle.GetPz(); + + // set covariance matrix elements (lower triangle) + for (int i = 0; i < 21; i++) { + cv[i] = kfParticle.GetCovariance(i); + } + + // create TrackParCov track + o2::track::TrackParCov track = o2::track::TrackParCov(xyz, pxpypz, cv, sign, true, pid); + return track; + } template void processBachBaryonVariables(TCollision const& collision, TTrack const& track1, TTrack const& track2) @@ -731,11 +845,38 @@ struct cascadeBuilder { cascadecandidate.pos[i] = vtx[i]; } + if (d_doQA && d_doPtDep_CosPaCut) { + bool mcUnchecked = !d_QA_checkMC; + bool dEdxUnchecked = !d_QA_checkdEdx; + + // Calculate masses + auto lPt = RecoDecay::sqrtSumOfSquares(v0.pxpos() + v0.pxneg() + cascadecandidate.bachP[0], v0.pypos() + v0.pyneg() + cascadecandidate.bachP[1]); + + // Fill basic mass histograms + // Note: all presel bools are true if unchecked + if ((cascade.isdEdxXiMinus() || dEdxUnchecked) && (cascade.isTrueXiMinus() || mcUnchecked) && cascadecandidate.charge < 0) + registry.fill(HIST("MassHistograms_BefPAcut/h2dXiMinusMass"), lPt, RecoDecay::m(array{array{cascadecandidate.bachP[0], cascadecandidate.bachP[1], cascadecandidate.bachP[2]}, array{v0.pxpos() + v0.pxneg(), v0.pypos() + v0.pyneg(), v0.pzpos() + v0.pzneg()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda})); + if ((cascade.isdEdxXiPlus() || dEdxUnchecked) && (cascade.isTrueXiPlus() || mcUnchecked) && cascadecandidate.charge > 0) + registry.fill(HIST("MassHistograms_BefPAcut/h2dXiPlusMass"), lPt, RecoDecay::m(array{array{cascadecandidate.bachP[0], cascadecandidate.bachP[1], cascadecandidate.bachP[2]}, array{v0.pxpos() + v0.pxneg(), v0.pypos() + v0.pyneg(), v0.pzpos() + v0.pzneg()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda})); + if ((cascade.isdEdxOmegaMinus() || dEdxUnchecked) && (cascade.isTrueOmegaMinus() || mcUnchecked) && cascadecandidate.charge < 0) + registry.fill(HIST("MassHistograms_BefPAcut/h2dOmegaMinusMass"), lPt, RecoDecay::m(array{array{cascadecandidate.bachP[0], cascadecandidate.bachP[1], cascadecandidate.bachP[2]}, array{v0.pxpos() + v0.pxneg(), v0.pypos() + v0.pyneg(), v0.pzpos() + v0.pzneg()}}, array{o2::constants::physics::MassKaonCharged, o2::constants::physics::MassLambda})); + if ((cascade.isdEdxOmegaPlus() || dEdxUnchecked) && (cascade.isTrueOmegaPlus() || mcUnchecked) && cascadecandidate.charge > 0) + registry.fill(HIST("MassHistograms_BefPAcut/h2dOmegaPlusMass"), lPt, RecoDecay::m(array{array{cascadecandidate.bachP[0], cascadecandidate.bachP[1], cascadecandidate.bachP[2]}, array{v0.pxpos() + v0.pxneg(), v0.pypos() + v0.pyneg(), v0.pzpos() + v0.pzneg()}}, array{o2::constants::physics::MassKaonCharged, o2::constants::physics::MassLambda})); + } + cascadecandidate.cosPA = RecoDecay::cpa( array{collision.posX(), collision.posY(), collision.posZ()}, array{cascadecandidate.pos[0], cascadecandidate.pos[1], cascadecandidate.pos[2]}, array{v0.pxpos() + v0.pxneg() + cascadecandidate.bachP[0], v0.pypos() + v0.pyneg() + cascadecandidate.bachP[1], v0.pzpos() + v0.pzneg() + cascadecandidate.bachP[2]}); - if (cascadecandidate.cosPA < casccospa) { + if (d_doPtDep_CosPaCut) { + auto lPt = RecoDecay::sqrtSumOfSquares(v0.pxpos() + v0.pxneg() + cascadecandidate.bachP[0], v0.pypos() + v0.pyneg() + cascadecandidate.bachP[1]); + double ptdepCut = cas_cospaParameter / lPt; + if (ptdepCut > 0.3 || lPt < 0.5) + ptdepCut = 0.3; + if (cascadecandidate.cosPA < TMath::Cos(ptdepCut)) { + return false; + } + } else if (cascadecandidate.cosPA < casccospa) { return false; } statisticsRegistry.cascstats[kCascCosPA]++; @@ -747,7 +888,7 @@ struct cascadeBuilder { statisticsRegistry.cascstats[kCascRadius]++; // Calculate DCAxy of the cascade (with bending) - lCascadeTrack = fitter.createParentTrackPar(); + lCascadeTrack = fitter.createParentTrackParCov(); lCascadeTrack.setAbsCharge(cascadecandidate.charge); // to be sure lCascadeTrack.setPID(o2::track::PID::XiMinus); // FIXME: not OK for omegas dcaInfo[0] = 999; @@ -798,13 +939,13 @@ struct cascadeBuilder { // Fill basic mass histograms // Note: all presel bools are true if unchecked if ((cascade.isdEdxXiMinus() || dEdxUnchecked) && (cascade.isTrueXiMinus() || mcUnchecked) && cascadecandidate.charge < 0) - registry.fill(HIST("h2dXiMinusMass"), lPt, cascadecandidate.mXi); + registry.fill(HIST("MassHistograms/h2dXiMinusMass"), lPt, cascadecandidate.mXi); if ((cascade.isdEdxXiPlus() || dEdxUnchecked) && (cascade.isTrueXiPlus() || mcUnchecked) && cascadecandidate.charge > 0) - registry.fill(HIST("h2dXiPlusMass"), lPt, cascadecandidate.mXi); + registry.fill(HIST("MassHistograms/h2dXiPlusMass"), lPt, cascadecandidate.mXi); if ((cascade.isdEdxOmegaMinus() || dEdxUnchecked) && (cascade.isTrueOmegaMinus() || mcUnchecked) && cascadecandidate.charge < 0) - registry.fill(HIST("h2dOmegaMinusMass"), lPt, cascadecandidate.mOmega); + registry.fill(HIST("MassHistograms/h2dOmegaMinusMass"), lPt, cascadecandidate.mOmega); if ((cascade.isdEdxOmegaPlus() || dEdxUnchecked) && (cascade.isTrueOmegaPlus() || mcUnchecked) && cascadecandidate.charge > 0) - registry.fill(HIST("h2dOmegaPlusMass"), lPt, cascadecandidate.mOmega); + registry.fill(HIST("MassHistograms/h2dOmegaPlusMass"), lPt, cascadecandidate.mOmega); // Fill ITS cluster maps with specific mass cuts if (TMath::Abs(cascadecandidate.mXi - 1.322) < dQAXiMassWindow && ((cascade.isdEdxXiMinus() || dEdxUnchecked) && (cascade.isTrueXiMinus() || mcUnchecked)) && cascadecandidate.charge < 0) { @@ -827,7 +968,255 @@ struct cascadeBuilder { registry.fill(HIST("h2dITSCluMap_OmegaPlusNegative"), (float)negTrack.itsClusterMap(), v0.v0radius()); registry.fill(HIST("h2dITSCluMap_OmegaPlusBachelor"), (float)bachTrack.itsClusterMap(), cascadecandidate.cascradius); } + + // do specific topological variable QA too + registry.fill(HIST("h2dTopoVarCascPointingAngle"), lPt, TMath::ACos(cascadecandidate.cosPA)); + registry.fill(HIST("h2dTopoVarCascRAP"), lPt, TMath::ACos(cascadecandidate.cosPA) * cascadecandidate.cascradius); + registry.fill(HIST("h2dTopoVarCascRadius"), lPt, cascadecandidate.cascradius); + } + return true; + } + + template + bool buildCascadeCandidateWithKF(TCascObject const& cascade) + { + registry.fill(HIST("hKFParticleStatistics"), 0.0f); + //*>~<*>~<*>~<*>~<*>~<*>~<*>~<*>~<*>~<* + // KF particle based rebuilding + // dispenses prior V0 generation, uses constrained (re-)fit based on bachelor charge + //*>~<*>~<*>~<*>~<*>~<*>~<*>~<*>~<*>~<* + + // Track casting + auto bachTrack = cascade.template bachelor_as(); + auto v0 = cascade.v0(); + auto posTrack = v0.template posTrack_as(); + auto negTrack = v0.template negTrack_as(); + auto const& collision = cascade.collision(); + + if (calculateBachBaryonVars) { + // Calculates properties of the V0 comprised of bachelor and baryon in the cascade + // baryon: distinguished via bachelor charge + if (bachTrack.sign() < 0) { + processBachBaryonVariables(collision, bachTrack, posTrack); + } else { + processBachBaryonVariables(collision, bachTrack, negTrack); + } + } + + // value 0.5: any considered cascade + statisticsRegistry.cascstats[kCascAll]++; + + // Overall cascade charge + cascadecandidate.charge = bachTrack.signed1Pt() > 0 ? +1 : -1; + + // bachelor DCA track to PV + // Calculate DCA with respect to the collision associated to the V0, not individual tracks + gpu::gpustd::array dcaInfo; + + auto bachTrackPar = getTrackPar(bachTrack); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, bachTrackPar, 2.f, fitter.getMatCorrType(), &dcaInfo); + cascadecandidate.bachDCAxy = dcaInfo[0]; + + o2::track::TrackParCov posTrackParCovForDCA = getTrackParCov(posTrack); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, posTrackParCovForDCA, 2.f, fitter.getMatCorrType(), &dcaInfo); + cascadecandidate.v0dcapostopv = dcaInfo[0]; + o2::track::TrackParCov negTrackParCovForDCA = getTrackParCov(negTrack); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, negTrackParCovForDCA, 2.f, fitter.getMatCorrType(), &dcaInfo); + cascadecandidate.v0dcanegtopv = dcaInfo[0]; + + if (TMath::Abs(cascadecandidate.bachDCAxy) < dcabachtopv) + return false; + + lBachelorTrack = getTrackParCov(bachTrack); + o2::track::TrackParCov negTrackParCov = getTrackParCov(negTrack); + o2::track::TrackParCov posTrackParCov = getTrackParCov(posTrack); + + float massPosTrack, massNegTrack; + if (cascadecandidate.charge < 0) { + massPosTrack = o2::constants::physics::MassProton; + massNegTrack = o2::constants::physics::MassPionCharged; + } else { + massPosTrack = o2::constants::physics::MassPionCharged; + massNegTrack = o2::constants::physics::MassProton; + } + + //__________________________________________ + //*>~<* step 1 : V0 with dca fitter, uses material corrections implicitly + // This is optional - move close to minima and therefore take material + if (kfDoDCAFitterPreMinim) { + int nCand = 0; + try { + nCand = fitter.process(posTrackParCov, negTrackParCov); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + return false; + } + if (nCand == 0) { + return false; + } + // save classical DCA daughters + cascadecandidate.v0dcadau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + + // re-acquire from DCA fitter + posTrackParCov = fitter.getTrack(0); + negTrackParCov = fitter.getTrack(1); + } + + //__________________________________________ + //*>~<* step 2 : V0 with KF + // create KFParticle objects from trackParCovs + KFParticle kfpPos = createKFParticleFromTrackParCov(posTrackParCov, posTrackParCov.getCharge(), massPosTrack); + KFParticle kfpNeg = createKFParticleFromTrackParCov(negTrackParCov, negTrackParCov.getCharge(), massNegTrack); + const KFParticle* V0Daughters[2] = {&kfpPos, &kfpNeg}; + + // construct V0 + KFParticle KFV0; + KFV0.SetConstructMethod(kfConstructMethod); + try { + KFV0.Construct(V0Daughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct cascade V0 from daughter tracks: " << e.what(); + return false; + } + if (kfUseV0MassConstraint) { + KFV0.SetNonlinearMassConstraint(o2::constants::physics::MassLambda); + } + + // V0 constructed, now recovering TrackParCov for dca fitter minimization (with material correction) + KFV0.TransportToDecayVertex(); + o2::track::TrackParCov v0TrackParCov = getTrackParCovFromKFP(KFV0, o2::track::PID::Lambda, 0); + v0TrackParCov.setAbsCharge(0); // to be sure + + //__________________________________________ + //*>~<* step 3 : Cascade with dca fitter (with material corrections) + if (kfDoDCAFitterPreMinim) { + int nCandCascade = 0; + try { + nCandCascade = fitter.process(v0TrackParCov, lBachelorTrack); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + return false; + } + if (nCandCascade == 0) + return false; + + // save classical DCA daughters + cascadecandidate.dcacascdau = TMath::Sqrt(fitter.getChi2AtPCACandidate()); + + v0TrackParCov = fitter.getTrack(0); + lBachelorTrack = fitter.getTrack(1); + } + + //__________________________________________ + //*>~<* step 4 : Cascade with KF particle (potentially mass-constrained if asked) + float massBachelorPion = o2::constants::physics::MassPionCharged; + float massBachelorKaon = o2::constants::physics::MassKaonCharged; + + KFParticle kfpV0 = createKFParticleFromTrackParCov(v0TrackParCov, 0, o2::constants::physics::MassLambda); + KFParticle kfpBachPion = createKFParticleFromTrackParCov(lBachelorTrack, cascadecandidate.charge, massBachelorPion); + KFParticle kfpBachKaon = createKFParticleFromTrackParCov(lBachelorTrack, cascadecandidate.charge, massBachelorKaon); + const KFParticle* XiDaugthers[2] = {&kfpBachPion, &kfpV0}; + const KFParticle* OmegaDaugthers[2] = {&kfpBachKaon, &kfpV0}; + + // construct mother + KFParticle KFXi, KFOmega; + KFXi.SetConstructMethod(kfConstructMethod); + KFOmega.SetConstructMethod(kfConstructMethod); + try { + KFXi.Construct(XiDaugthers, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct xi from V0 and bachelor track: " << e.what(); + return false; + } + try { + KFOmega.Construct(OmegaDaugthers, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct omega from V0 and bachelor track: " << e.what(); + return false; + } + if (kfUseCascadeMassConstraint) { + // set mass constraint if requested + // WARNING: this is only adequate for decay chains, i.e. XiC -> Xi or OmegaC -> Omega + KFXi.SetNonlinearMassConstraint(o2::constants::physics::MassXiMinus); + KFOmega.SetNonlinearMassConstraint(o2::constants::physics::MassOmegaMinus); } + KFXi.TransportToDecayVertex(); + KFOmega.TransportToDecayVertex(); + + //__________________________________________ + //*>~<* step 5 : propagate cascade to primary vertex with material corrections if asked + if (!kfTuneForOmega) { + lCascadeTrack = getTrackParCovFromKFP(KFXi, o2::track::PID::XiMinus, cascadecandidate.charge); + } else { + lCascadeTrack = getTrackParCovFromKFP(KFOmega, o2::track::PID::OmegaMinus, cascadecandidate.charge); + } + dcaInfo[0] = 999; + dcaInfo[1] = 999; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, lCascadeTrack, 2.f, matCorrCascade, &dcaInfo); + cascadecandidate.cascDCAxy = dcaInfo[0]; + cascadecandidate.cascDCAz = dcaInfo[1]; + + //__________________________________________ + //*>~<* step 6 : acquire all parameters for analysis + + // basic indices + cascadecandidate.v0Id = v0.globalIndex(); + cascadecandidate.bachelorId = bachTrack.globalIndex(); + + // KF chi2 + cascadecandidate.kfV0Chi2 = KFV0.GetChi2(); + cascadecandidate.kfCascadeChi2 = KFXi.GetChi2(); + if (kfTuneForOmega) + cascadecandidate.kfCascadeChi2 = KFOmega.GetChi2(); + + // Daughter momentum not KF-updated FIXME + lBachelorTrack.getPxPyPzGlo(cascadecandidate.bachP); + posTrackParCov.getPxPyPzGlo(cascadecandidate.v0mompos); + negTrackParCov.getPxPyPzGlo(cascadecandidate.v0momneg); + + // mother position information from KF + cascadecandidate.v0pos[0] = KFV0.GetX(); + cascadecandidate.v0pos[1] = KFV0.GetY(); + cascadecandidate.v0pos[2] = KFV0.GetZ(); + + // Mother position + momentum is KF updated + if (!kfTuneForOmega) { + cascadecandidate.pos[0] = KFXi.GetX(); + cascadecandidate.pos[1] = KFXi.GetY(); + cascadecandidate.pos[2] = KFXi.GetZ(); + cascadecandidate.cascademom[0] = KFXi.GetPx(); + cascadecandidate.cascademom[1] = KFXi.GetPy(); + cascadecandidate.cascademom[2] = KFXi.GetPz(); + } else { + cascadecandidate.pos[0] = KFOmega.GetX(); + cascadecandidate.pos[1] = KFOmega.GetY(); + cascadecandidate.pos[2] = KFOmega.GetZ(); + cascadecandidate.cascademom[0] = KFOmega.GetPx(); + cascadecandidate.cascademom[1] = KFOmega.GetPy(); + cascadecandidate.cascademom[2] = KFOmega.GetPz(); + } + + // KF-aware cosPA + cascadecandidate.cosPA = RecoDecay::cpa( + array{collision.posX(), collision.posY(), collision.posZ()}, + array{cascadecandidate.pos[0], cascadecandidate.pos[1], cascadecandidate.pos[2]}, + array{cascadecandidate.cascademom[0], cascadecandidate.cascademom[1], cascadecandidate.cascademom[2]}); + if (cascadecandidate.cosPA < casccospa) { + return false; + } + + // KF-aware Cascade radius + cascadecandidate.cascradius = RecoDecay::sqrtSumOfSquares(cascadecandidate.pos[0], cascadecandidate.pos[1]); + if (cascadecandidate.cascradius < cascradius) + return false; + + // Calculate masses a priori + cascadecandidate.kfMLambda = KFV0.GetMass(); + cascadecandidate.mXi = KFXi.GetMass(); + cascadecandidate.mOmega = KFOmega.GetMass(); + cascadecandidate.yXi = KFXi.GetRapidity(); + cascadecandidate.yOmega = KFOmega.GetRapidity(); + registry.fill(HIST("hKFParticleStatistics"), 1.0f); return true; } @@ -890,6 +1279,44 @@ struct cascadeBuilder { resetHistos(); } + template + void buildKFStrangenessTables(TCascTable const& cascades) + { + for (auto& cascade : cascades) { + bool validCascadeCandidateKF = buildCascadeCandidateWithKF(cascade); + if (!validCascadeCandidateKF) + continue; // doesn't pass cascade selections + registry.fill(HIST("hKFParticleStatistics"), 2.0f); + kfcascdata(cascadecandidate.v0Id, + cascade.globalIndex(), + cascadecandidate.bachelorId, + cascade.collisionId(), + cascadecandidate.charge, cascadecandidate.mXi, cascadecandidate.mOmega, + cascadecandidate.pos[0], cascadecandidate.pos[1], cascadecandidate.pos[2], + cascadecandidate.v0pos[0], cascadecandidate.v0pos[1], cascadecandidate.v0pos[2], + cascadecandidate.v0mompos[0], cascadecandidate.v0mompos[1], cascadecandidate.v0mompos[2], + cascadecandidate.v0momneg[0], cascadecandidate.v0momneg[1], cascadecandidate.v0momneg[2], + cascadecandidate.bachP[0], cascadecandidate.bachP[1], cascadecandidate.bachP[2], + cascadecandidate.bachP[0] + cascadecandidate.v0mompos[0] + cascadecandidate.v0momneg[0], // <--- redundant but ok + cascadecandidate.bachP[1] + cascadecandidate.v0mompos[1] + cascadecandidate.v0momneg[1], // <--- redundant but ok + cascadecandidate.bachP[2] + cascadecandidate.v0mompos[2] + cascadecandidate.v0momneg[2], // <--- redundant but ok + cascadecandidate.v0dcadau, cascadecandidate.dcacascdau, + cascadecandidate.v0dcapostopv, cascadecandidate.v0dcanegtopv, + cascadecandidate.bachDCAxy, cascadecandidate.cascDCAxy, cascadecandidate.cascDCAz, + cascadecandidate.bachBaryonCosPA, cascadecandidate.bachBaryonDCAxyToPV, + cascadecandidate.kfMLambda, cascadecandidate.kfV0Chi2, cascadecandidate.kfCascadeChi2); + + if (createCascCovMats) { + gpu::gpustd::array covmatrix; + float trackCovariance[15]; + covmatrix = lCascadeTrack.getCov(); + for (int i = 0; i < 15; i++) + trackCovariance[i] = covmatrix[i]; + kfcasccovs(trackCovariance); + } + } + } + template void buildStrangenessTablesWithStrangenessTracking(TCascTable const& cascades, TStraTrack const& trackedCascades) { @@ -1113,6 +1540,20 @@ struct cascadeBuilder { } PROCESS_SWITCH(cascadeBuilder, processRun3, "Produce Run 3 cascade tables", false); + void processRun3withKFParticle(aod::Collisions const& collisions, soa::Filtered const& cascades, FullTracksExtIU const&, aod::BCsWithTimestamps const&, aod::V0s const&) + { + for (const auto& collision : collisions) { + // Fire up CCDB + auto bc = collision.bc_as(); + initCCDB(bc); + // Do analysis with collision-grouped V0s, retain full collision information + const uint64_t collIdx = collision.globalIndex(); + auto CascadeTable_thisCollision = cascades.sliceBy(perCollision, collIdx); + buildKFStrangenessTables(CascadeTable_thisCollision); + } + } + PROCESS_SWITCH(cascadeBuilder, processRun3withKFParticle, "Produce Run 3 KF cascade tables", false); + void processRun3withStrangenessTracking(aod::Collisions const& collisions, aod::V0sLinked const&, V0full const&, soa::Filtered const& cascades, FullTracksExtIU const&, aod::BCsWithTimestamps const&, aod::TrackedCascades const& trackedCascades) { for (const auto& collision : collisions) { @@ -1136,6 +1577,8 @@ struct cascadePreselector { Configurable dIfMCgenerateXiPlus{"dIfMCgenerateXiPlus", true, "if MC, generate MC true XiPlus (yes/no)"}; Configurable dIfMCgenerateOmegaMinus{"dIfMCgenerateOmegaMinus", true, "if MC, generate MC true OmegaMinus (yes/no)"}; Configurable dIfMCgenerateOmegaPlus{"dIfMCgenerateOmegaPlus", true, "if MC, generate MC true OmegaPlus (yes/no)"}; + Configurable dIfMCselectV0MotherPDG{"dIfMCselectV0MotherPDG", 0, "if MC, selects based on mother particle (zero for no selection)"}; + Configurable dIfMCselectPhysicalPrimary{"dIfMCselectPhysicalPrimary", true, "if MC, select MC physical primary (yes/no)"}; Configurable ddEdxPreSelectXiMinus{"ddEdxPreSelectXiMinus", true, "pre-select dE/dx compatibility with XiMinus (yes/no)"}; Configurable ddEdxPreSelectXiPlus{"ddEdxPreSelectXiPlus", true, "pre-select dE/dx compatibility with XiPlus (yes/no)"}; @@ -1223,6 +1666,18 @@ struct cascadePreselector { for (auto& lBachMother : lMCBachTrack.template mothers_as()) { if (lV0Mother == lBachMother) { lPDG = lV0Mother.pdgCode(); + + // additionally check PDG of the mother particle if requested + if (dIfMCselectV0MotherPDG != 0) { + lPDG = 0; // this is not the species you're looking for + if (lBachMother.has_mothers()) { + for (auto& lBachGrandMother : lBachMother.template mothers_as()) { + if (lBachGrandMother.pdgCode() == dIfMCselectV0MotherPDG && (!dIfMCselectPhysicalPrimary || lBachGrandMother.isPhysicalPrimary())) + lPDG = lV0Mother.pdgCode(); + } + } + } + // end extra PDG of mother check } } } // end conditional V0-bach pair @@ -1265,7 +1720,7 @@ struct cascadePreselector { if (TMath::Abs(lNegTrack.tpcNSigmaPr()) < ddEdxPreSelectionWindow && TMath::Abs(lPosTrack.tpcNSigmaPi()) < ddEdxPreSelectionWindow && TMath::Abs(lBachTrack.tpcNSigmaPi()) < ddEdxPreSelectionWindow) - bitset(maskElement, bitdEdxOmegaPlus); + bitset(maskElement, bitdEdxXiPlus); if (TMath::Abs(lNegTrack.tpcNSigmaPi()) < ddEdxPreSelectionWindow && TMath::Abs(lPosTrack.tpcNSigmaPr()) < ddEdxPreSelectionWindow && TMath::Abs(lBachTrack.tpcNSigmaKa()) < ddEdxPreSelectionWindow) @@ -1351,7 +1806,7 @@ struct cascadePreselector { checkAndFinalize(); } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void processBuildValiddEdxMCAssociated(aod::Collisions const& collisions, aod::Cascades const& cascades, aod::V0sLinked const&, aod::V0Datas const&, TracksExtraWithPIDandLabels const&) + void processBuildValiddEdxMCAssociated(aod::Collisions const& collisions, aod::Cascades const& cascades, aod::V0sLinked const&, aod::V0Datas const&, TracksExtraWithPIDandLabels const&, aod::McParticles const&) { initializeMasks(cascades.size()); for (auto& casc : cascades) { @@ -1387,6 +1842,7 @@ struct cascadePreselector { /// Extends the cascdata table with expression columns struct cascadeInitializer { Spawns cascdataext; + Spawns kfcascdataext; Spawns tracascdataext; void init(InitContext const&) {} }; @@ -1412,11 +1868,33 @@ struct cascadeLinkBuilder { } }; +struct kfcascadeLinkBuilder { + Produces cascdataLink; + + void init(InitContext const&) {} + + // build Cascade -> CascData link table + void process(aod::Cascades const& casctable, aod::KFCascDatas const& cascdatatable) + { + std::vector lIndices; + lIndices.reserve(casctable.size()); + for (int ii = 0; ii < casctable.size(); ii++) + lIndices[ii] = -1; + for (auto& cascdata : cascdatatable) { + lIndices[cascdata.cascadeId()] = cascdata.globalIndex(); + } + for (int ii = 0; ii < casctable.size(); ii++) { + cascdataLink(lIndices[ii]); + } + } +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/cascademcfinder.cxx b/PWGLF/TableProducer/cascademcfinder.cxx index f37a13d4a27..a565fdf3819 100644 --- a/PWGLF/TableProducer/cascademcfinder.cxx +++ b/PWGLF/TableProducer/cascademcfinder.cxx @@ -32,9 +32,9 @@ #include "ReconstructionDataFormats/Track.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/PIDResponse.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFQATables.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" @@ -259,7 +259,7 @@ struct cascademcfinder { // Step 1: sweep over all mcCollisions and find all relevant candidates for (auto const& mcCollision : mcCollisions) { - histos.fill(HIST("hNTimesCollRecoed"), mcCollision.hasRecoCollision()); + histos.fill(HIST("hNTimesCollRecoed"), mcCollision.numRecoCollision()); int bestCollisionIndex = mcCollision.bestCollisionIndex(); auto mcParticles = allMcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); diff --git a/PWGLF/TableProducer/cascqaanalysis.cxx b/PWGLF/TableProducer/cascqaanalysis.cxx index 29e0108f0dc..e85ebeff04e 100644 --- a/PWGLF/TableProducer/cascqaanalysis.cxx +++ b/PWGLF/TableProducer/cascqaanalysis.cxx @@ -9,9 +9,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// -/// \brief QA task for V0 analysis using derived data +/// \brief QA task for Cascade analysis using derived data /// +/// \author Chiara De Martin (chiara.de.martin@cern.ch) /// \author Francesca Ercolessi (francesca.ercolessi@cern.ch) +/// \modified by Roman Nepeivoda (roman.nepeivoda@cern.ch) +/// \since June 1, 2023 #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -22,79 +25,31 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" #include "PWGLF/DataModel/cascqaanalysis.h" -#include "TRandom.h" -#include -#include -#include -#include +#include "TRandom2.h" +#include "Framework/O2DatabasePDGPlugin.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -// using DauTracks = soa::Join; -using DauTracks = soa::Join; +// using DauTracks = soa::Join; +using TrkPidInfo = soa::Join; +using DauTracks = soa::Join; using LabeledCascades = soa::Join; struct cascqaanalysis { - // Produces + // Tables to produce Produces mycascades; + Produces myMCcascades; HistogramRegistry registry{"registry"}; - AxisSpec ptAxis = {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec rapidityAxis = {200, -2.0f, 2.0f, "y"}; - AxisSpec centFT0MAxis = {100, 0.0f, 100.0f, "FT0M (%)"}; - - void init(InitContext const&) - { - TString hCandidateCounterLabels[5] = {"All candidates", "v0data exists", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; - TString hNEventsMCLabels[4] = {"All", "z vrtx", "INEL>0", "Associated with rec. collision"}; - TString hNEventsLabels[4] = {"All", "sel8", "z vrtx", "INEL>0"}; - - registry.add("hNEvents", "hNEvents", {HistType::kTH1I, {{4, 0.f, 4.f}}}); - for (Int_t n = 1; n <= registry.get(HIST("hNEvents"))->GetNbinsX(); n++) { - registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(n, hNEventsLabels[n - 1]); - } - registry.add("hZCollision", "hZCollision", {HistType::kTH1F, {{200, -20.f, 20.f}}}); - registry.add("hZCollisionGen", "hZCollisionGen", {HistType::kTH1F, {{200, -20.f, 20.f}}}); - registry.add("hCentFT0M", "hCentFT0M", {HistType::kTH1F, {{1000, 0.f, 100.f}}}); - registry.add("hCentFV0A", "hCentFV0A", {HistType::kTH1F, {{1000, 0.f, 100.f}}}); - registry.add("hPtXiPlusTrue", "hPtXiPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - registry.add("hPtXiMinusTrue", "hPtXiMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - registry.add("hPtOmegaPlusTrue", "hPtOmegaPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - registry.add("hPtOmegaMinusTrue", "hPtOmegaMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - registry.add("hPtXiPlusTrueAssoiciatedWithSelColl", "hPtXiPlusTrueAssoiciatedWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - registry.add("hPtXiMinusTrueAssoiciatedWithSelColl", "hPtXiMinusTrueAssoiciatedWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - registry.add("hPtOmegaPlusTrueAssoiciatedWithSelColl", "hPtOmegaPlusTrueAssoiciatedWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - registry.add("hPtOmegaMinusTrueAssoiciatedWithSelColl", "hPtOmegaMinusTrueAssoiciatedWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - - registry.add("hNEventsMC", "hNEventsMC", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}); - for (Int_t n = 1; n <= registry.get(HIST("hNEventsMC"))->GetNbinsX(); n++) { - registry.get(HIST("hNEventsMC"))->GetXaxis()->SetBinLabel(n, hNEventsMCLabels[n - 1]); - } - - registry.add("hCandidateCounter", "hCandidateCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}); - for (Int_t n = 1; n <= registry.get(HIST("hCandidateCounter"))->GetNbinsX(); n++) { - registry.get(HIST("hCandidateCounter"))->GetXaxis()->SetBinLabel(n, hCandidateCounterLabels[n - 1]); - } - - AxisSpec allTracks = {2000, 0, 2000, "N_{all tracks}"}; - AxisSpec secondaryTracks = {2000, 0, 2000, "N_{secondary tracks}"}; - registry.add("hINELgt0PrimariesSelection", "hINELgt0PrimariesSelection", {HistType::kTH2F, {allTracks, secondaryTracks}}); - registry.add("hDCAz_BefCut", "hDCAz_BefCut", HistType::kTH2F, {{400, -0.2, 0.2, "DCAz"}, {150, 0.0, 15.0, "p_{T} (GeV/c)"}}); - registry.add("hDCAz_AfterCut", "hDCAz_AfterCut", HistType::kTH2F, {{400, -0.2, 0.2, "DCAz"}, {150, 0.0, 15.0, "p_{T} (GeV/c)"}}); - registry.add("hDCAxy_BefCut", "hDCAxy_BefCut", HistType::kTH2F, {{400, -0.2, 0.2, "DCAxy"}, {150, 0.0, 15.0, "p_{T} (GeV/c)"}}); - registry.add("hDCAxy_AfterCut", "hDCAxy_AfterCut", HistType::kTH2F, {{400, -0.2, 0.2, "DCAxy"}, {150, 0.0, 15.0, "p_{T} (GeV/c)"}}); - } - // Event selection criteria Configurable cutzvertex{"cutzvertex", 20.0f, "Accepted z-vertex range (cm)"}; Configurable sel8{"sel8", 1, "Apply sel8 event selection"}; - Configurable INELgt0{"INELgt0", 1, "Apply INEL>0 selection"}; - // Selection criteria + // Cascade selection criteria Configurable scalefactor{"scalefactor", 1.0, "Scaling factor"}; Configurable casccospa{"casccospa", 0.97, "Casc CosPA"}; Configurable v0cospa{"v0cospa", 0.97, "V0 CosPA"}; @@ -107,12 +62,95 @@ struct cascqaanalysis { Configurable cascradius{"cascradius", 0.0, "Casc Radius"}; Configurable etadau{"etadau", 0.8, "Eta Daughters"}; - Configurable maxDCANsigmaScaling{"maxDCANsigmaScaling", 1.0f, "N of 7*sigma scaling factor for DCA to select primaries"}; - Configurable DCASigma{"DCASigma", 0.004f, "7*sigma for DCA"}; - Configurable DCAPtScaling{"DCAPtScaling", 0.013f, "pt scaling for DCA"}; - Configurable maxDCAz{"maxDCAz", 0.5f, "DCA z cut to select primaries"}; + // Switch between Data/MC-dedicated histograms + Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; + + // QA histograms for the multiplicity estimation + Configurable multQA{"multQA", 0, "0 - not to do QA, 1 - do the QA"}; + + // Necessary for particle charges + Service pdgDB; + + SliceCache cache; + + // Random number generator for event scaling + TRandom2* fRand = new TRandom2(); + + // Struct to select on event type + typedef struct CollisionIndexAndType { + int64_t index; + uint8_t typeFlag; + } CollisionIndexAndType; - TRandom* fRand = new TRandom(); + // Struct for counting charged particles in |eta| region + typedef struct EtaCharge { + double eta; + int charge; + } EtaCharge; + + void init(InitContext const&) + { + AxisSpec ptAxis = {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec rapidityAxis = {200, -2.0f, 2.0f, "y"}; + ConfigurableAxis centFT0MAxis{"FT0M", + {VARIABLE_WIDTH, 0., 0.01, 0.05, 0.1, 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 105.5}, + "FT0M (%)"}; + ConfigurableAxis centFV0AAxis{"FV0A", + {VARIABLE_WIDTH, 0., 0.01, 0.05, 0.1, 0.5, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 105.5}, + "FV0A (%)"}; + AxisSpec eventTypeAxis = {3, -0.5f, 2.5f, "Event Type"}; + AxisSpec nAssocCollAxis = {5, -0.5f, 4.5f, "N_{assoc.}"}; + AxisSpec nChargedFT0MGenAxis = {500, 0, 500, "N_{FT0M, gen.}"}; + AxisSpec nChargedFV0AGenAxis = {500, 0, 500, "N_{FV0A, gen.}"}; + AxisSpec multNTracksAxis = {500, 0, 500, "N_{tracks}"}; + AxisSpec signalFT0MAxis = {10000, 0, 40000, "FT0M amplitude"}; + AxisSpec signalFV0AAxis = {10000, 0, 40000, "FV0A amplitude"}; + + TString hCandidateCounterLabels[5] = {"All candidates", "v0data exists", "passed topo cuts", "has associated MC particle", "associated with Xi(Omega)"}; + TString hNEventsMCLabels[6] = {"All", "z vrtx", "INEL", "INEL>0", "INEL>1", "Associated with rec. collision"}; + TString hNEventsLabels[6] = {"All", "sel8", "z vrtx", "INEL", "INEL>0", "INEL>1"}; + + registry.add("hNEvents", "hNEvents", {HistType::kTH1F, {{6, 0.f, 6.f}}}); + for (Int_t n = 1; n <= registry.get(HIST("hNEvents"))->GetNbinsX(); n++) { + registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(n, hNEventsLabels[n - 1]); + } + registry.add("hZCollision", "hZCollision", {HistType::kTH1F, {{200, -20.f, 20.f}}}); + + registry.add("hCandidateCounter", "hCandidateCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}); + for (Int_t n = 1; n <= registry.get(HIST("hCandidateCounter"))->GetNbinsX(); n++) { + registry.get(HIST("hCandidateCounter"))->GetXaxis()->SetBinLabel(n, hCandidateCounterLabels[n - 1]); + } + if (isMC) { + // Rec. lvl + registry.add("hNchFT0MPVContr", "hNchFT0MPVContr", {HistType::kTH3F, {nChargedFT0MGenAxis, multNTracksAxis, eventTypeAxis}}); + registry.add("hNchFV0APVContr", "hNchFV0APVContr", {HistType::kTH3F, {nChargedFV0AGenAxis, multNTracksAxis, eventTypeAxis}}); + // Gen. lvl + registry.add("hNEventsMC", "hNEventsMC", {HistType::kTH1F, {{6, 0.0f, 6.0f}}}); + for (Int_t n = 1; n <= registry.get(HIST("hNEventsMC"))->GetNbinsX(); n++) { + registry.get(HIST("hNEventsMC"))->GetXaxis()->SetBinLabel(n, hNEventsMCLabels[n - 1]); + } + registry.add("hZCollisionGen", "hZCollisionGen", {HistType::kTH1F, {{200, -20.f, 20.f}}}); + registry.add("hNchFT0MNAssocMCCollisions", "hNchFT0MNAssocMCCollisions", {HistType::kTH3F, {nChargedFT0MGenAxis, nAssocCollAxis, eventTypeAxis}}); + registry.add("hNchFT0MNAssocMCCollisionsSameType", "hNchFT0MNAssocMCCollisionsSameType", {HistType::kTH3F, {nChargedFT0MGenAxis, nAssocCollAxis, eventTypeAxis}}); + registry.add("hNContributorsCorrelation", "hNContributorsCorrelation", {HistType::kTH2F, {{250, -0.5f, 249.5f, "Secondary Contributor"}, {250, -0.5f, 249.5f, "Main Contributor"}}}); + registry.add("hNchFT0MGenEvType", "hNchFT0MGenEvType", {HistType::kTH2F, {nChargedFT0MGenAxis, eventTypeAxis}}); + registry.add("hNchFV0AGenEvType", "hNchFV0AGenEvType", {HistType::kTH2F, {nChargedFV0AGenAxis, eventTypeAxis}}); + } else { + registry.add("hFT0MpvContr", "hFT0MpvContr", {HistType::kTH3F, {centFT0MAxis, multNTracksAxis, eventTypeAxis}}); + registry.add("hFV0ApvContr", "hFV0ApvContr", {HistType::kTH3F, {centFV0AAxis, multNTracksAxis, eventTypeAxis}}); + } + + if (multQA) { + if (isMC) { + // Rec. lvl + registry.add("hNchFT0Mglobal", "hNchFT0Mglobal", {HistType::kTH3F, {nChargedFT0MGenAxis, multNTracksAxis, eventTypeAxis}}); + } else { + registry.add("hFT0Mglobal", "hFT0Mglobal", {HistType::kTH3F, {centFT0MAxis, multNTracksAxis, eventTypeAxis}}); + registry.add("hFV0AFT0M", "hFV0AFT0M", {HistType::kTH3F, {centFV0AAxis, centFT0MAxis, eventTypeAxis}}); + } + registry.add("hFT0MFV0Asignal", "hFT0MFV0Asignal", {HistType::kTH2F, {signalFT0MAxis, signalFV0AAxis}}); + } + } Filter preFilter = (nabs(aod::cascdata::dcapostopv) > dcapostopv && @@ -121,6 +159,9 @@ struct cascqaanalysis { aod::cascdata::dcaV0daughters < dcav0dau && aod::cascdata::dcacascdaughters < dcacascdau); + Partition pvContribTracksIUEta1 = (nabs(aod::track::eta) < 1.0f) && ((aod::track::flags & (uint32_t)o2::aod::track::PVContributor) == (uint32_t)o2::aod::track::PVContributor); + Partition globalTracksIUEta05 = (nabs(aod::track::eta) < 0.5f) && (requireGlobalTrackInFilter()); + template bool AcceptCascCandidate(TCascade const& cascCand, float const& pvx, float const& pvy, float const& pvz) { @@ -145,8 +186,73 @@ struct cascqaanalysis { } } - template - bool AcceptEvent(TCollision const& collision, TTracks const& tracks, bool isFillEventSelectionQA) + template + uint16_t GetGenNchInFT0Mregion(TMcParticles particles) + { + // Particle counting in FITFT0: -3.3<η<-2.1; 3.5<η<4.9 + uint16_t nchFT0 = 0; + for (auto& mcParticle : particles) { + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + const auto& pdgInfo = pdgDB->GetParticle(mcParticle.pdgCode()); + if (!pdgInfo) { + continue; + } + if (pdgInfo->Charge() == 0) { + continue; + } + if (mcParticle.eta() < -3.3 || mcParticle.eta() > 4.9 || (mcParticle.eta() > -2.1 && mcParticle.eta() < 3.5)) { + continue; // select on T0M Nch region + } + nchFT0++; // increment + } + return nchFT0; + } + + template + uint16_t GetGenNchInFV0Aregion(TMcParticles particles) + { + // Particle counting in FV0A: 2.2<η<5.1 + uint16_t nchFV0A = 0; + for (auto& mcParticle : particles) { + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + const auto& pdgInfo = pdgDB->GetParticle(mcParticle.pdgCode()); + if (!pdgInfo) { + continue; + } + if (pdgInfo->Charge() == 0) { + continue; + } + if (mcParticle.eta() < 2.2 || mcParticle.eta() > 5.1) { + continue; // select on V0A Nch region + } + nchFV0A++; // increment + } + return nchFV0A; + } + + template + int GetEventTypeFlag(TCollision const& collision) + { + // 0 - INEL, 1 - INEL > 0, 2 - INEL>1 + int evFlag = 0; + registry.fill(HIST("hNEvents"), 3.5); // INEL + if (collision.multNTracksPVeta1() > 0) { + evFlag += 1; + registry.fill(HIST("hNEvents"), 4.5); // INEL>0 + } + if (collision.multNTracksPVeta1() > 1) { + evFlag += 1; + registry.fill(HIST("hNEvents"), 5.5); // INEL>1 + } + return evFlag; + } + + template + bool AcceptEvent(TCollision const& collision, bool isFillEventSelectionQA) { if (isFillEventSelectionQA) { registry.fill(HIST("hNEvents"), 0.5); @@ -159,73 +265,22 @@ struct cascqaanalysis { registry.fill(HIST("hNEvents"), 1.5); } + // Z vertex selection if (TMath::Abs(collision.posZ()) > cutzvertex) { return false; } if (isFillEventSelectionQA) { registry.fill(HIST("hNEvents"), 2.5); - } - - if (INELgt0 && !isINELgt0(tracks, isFillEventSelectionQA)) { - return false; - } - if (isFillEventSelectionQA) { - registry.fill(HIST("hNEvents"), 3.5); - } - - if (isFillEventSelectionQA) { registry.fill(HIST("hZCollision"), collision.posZ()); - registry.fill(HIST("hCentFT0M"), collision.centFT0M()); - registry.fill(HIST("hCentFV0A"), collision.centFV0A()); } - return true; - } - template - bool isINELgt0(TTracks tracks, bool isFillEventSelectionQA) - { - // INEL > 0 (at least 1 charged track in |eta| < 1.0) - std::vector TracksEta(tracks.size()); - int nTracks = 0; - int nRejTracks = 0; - - for (const auto& track : tracks) { - registry.fill(HIST("hDCAxy_BefCut"), track.dcaXY(), track.pt()); - registry.fill(HIST("hDCAz_BefCut"), track.dcaZ(), track.pt()); - - if (TMath::Abs(track.dcaXY()) > (maxDCANsigmaScaling * (DCASigma + DCAPtScaling / track.pt())) || TMath::Abs(track.dcaZ()) > maxDCAz) { - nRejTracks++; - continue; // consider only primaries - } - TracksEta[nTracks++] = track.eta(); - - registry.fill(HIST("hDCAxy_AfterCut"), track.dcaXY(), track.pt()); - registry.fill(HIST("hDCAz_AfterCut"), track.dcaZ(), track.pt()); - } - - if (isFillEventSelectionQA) { - registry.fill(HIST("hINELgt0PrimariesSelection"), tracks.size(), nRejTracks); - } - - auto etaConditionFunc = [](float elem) { - return TMath::Abs(elem) < 1.0; - }; - - if (std::any_of(TracksEta.begin(), TracksEta.end(), etaConditionFunc)) { - return true; - } else { - return false; - } + return true; } template - bool isINELgt0mc(TMcParticles particles) + bool isINELgtNmc(TMcParticles particles, int nChToSatisfySelection) { - // INEL > 0 (at least 1 charged particle in |eta| < 1.0) - typedef struct EtaCharge { - double eta; - int charge; - } EtaCharge; + // INEL > N (at least N+1 charged particles in |eta| < 1.0) EtaCharge etaCharge; std::vector ParticlesEtaAndCharge(particles.size()); unsigned int nParticles = 0; @@ -233,7 +288,7 @@ struct cascqaanalysis { if (particle.isPhysicalPrimary() == 0) continue; // consider only primaries etaCharge = {999, 0}; // refresh init. for safety - TParticlePDG* p = TDatabasePDG::Instance()->GetParticle(particle.pdgCode()); + TParticlePDG* p = pdgDB->GetParticle(particle.pdgCode()); if (!p) { switch (std::to_string(particle.pdgCode()).length()) { case 10: // nuclei @@ -257,7 +312,7 @@ struct cascqaanalysis { return ((TMath::Abs(elem.eta) < 1.0) && (TMath::Abs(elem.charge) > 0.001)); }; - if (std::any_of(ParticlesEtaAndCharge.begin(), ParticlesEtaAndCharge.end(), etaChargeConditionFunc)) { + if (std::count_if(ParticlesEtaAndCharge.begin(), ParticlesEtaAndCharge.end(), etaChargeConditionFunc) > nChToSatisfySelection) { return true; } else { return false; @@ -268,12 +323,29 @@ struct cascqaanalysis { soa::Filtered const& Cascades, aod::V0sLinked const&, aod::V0Datas const&, - DauTracks const& Tracks) + DauTracks const&) { - if (!AcceptEvent(collision, Tracks, 1)) { + if (!AcceptEvent(collision, 1)) { return; } + int evType = GetEventTypeFlag(collision); + + auto tracksGroupedPVcontr = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + int nTracksPVcontr = tracksGroupedPVcontr.size(); + + auto tracksGroupedGlobal = globalTracksIUEta05->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + int nTracksGlobal = tracksGroupedGlobal.size(); + + registry.fill(HIST("hFT0MpvContr"), collision.centFT0M(), nTracksPVcontr, evType); + registry.fill(HIST("hFV0ApvContr"), collision.centFV0A(), nTracksPVcontr, evType); + + if (multQA) { + registry.fill(HIST("hFT0Mglobal"), collision.centFT0M(), nTracksGlobal, evType); + registry.fill(HIST("hFV0AFT0M"), collision.centFV0A(), collision.centFT0M(), evType); + registry.fill(HIST("hFT0MFV0Asignal"), collision.multFT0A() + collision.multFT0C(), collision.multFV0A()); + } + float lEventScale = scalefactor; for (const auto& casc : Cascades) { // loop over Cascades @@ -286,37 +358,45 @@ struct cascqaanalysis { } registry.fill(HIST("hCandidateCounter"), 1.5); // v0data exists - auto v0 = v0index.v0Data(); - auto posdau = v0.posTrack_as(); - auto negdau = v0.negTrack_as(); - auto bachelor = casc.bachelor_as(); - - // ITS N hits - int posITSNhits = 0, negITSNhits = 0, bachITSNhits = 0; - for (unsigned int i = 0; i < 7; i++) { - if (posdau.itsClusterMap() & (1 << i)) { - posITSNhits++; - } - if (negdau.itsClusterMap() & (1 << i)) { - negITSNhits++; - } - if (bachelor.itsClusterMap() & (1 << i)) { - bachITSNhits++; - } - } - - // c x tau - float cascpos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); - float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); - // - float ctauXi = RecoDecay::getMassPDG(3312) * cascpos / (cascptotmom + 1e-13); - float ctauOmega = RecoDecay::getMassPDG(3334) * cascpos / (cascptotmom + 1e-13); - if (AcceptCascCandidate(casc, collision.posX(), collision.posY(), collision.posZ())) { registry.fill(HIST("hCandidateCounter"), 2.5); // passed topo cuts // Fill table if (fRand->Rndm() < lEventScale) { - mycascades(casc.globalIndex(), collision.posZ(), collision.centFT0M(), collision.centFV0A(), casc.sign(), casc.pt(), casc.yXi(), casc.yOmega(), casc.eta(), + auto v0 = v0index.v0Data(); + auto posdau = v0.posTrack_as(); + auto negdau = v0.negTrack_as(); + auto bachelor = casc.bachelor_as(); + + // ITS N hits + int posITSNhits = 0, negITSNhits = 0, bachITSNhits = 0; + for (unsigned int i = 0; i < 7; i++) { + if (posdau.itsClusterMap() & (1 << i)) { + posITSNhits++; + } + if (negdau.itsClusterMap() & (1 << i)) { + negITSNhits++; + } + if (bachelor.itsClusterMap() & (1 << i)) { + bachITSNhits++; + } + } + + uint8_t evFlag = 0; + evFlag |= o2::aod::mycascades::EvFlags::EvINEL; + if (collision.multNTracksPVeta1() > 0) { + evFlag |= o2::aod::mycascades::EvFlags::EvINELgt0; + } + if (collision.multNTracksPVeta1() > 1) { + evFlag |= o2::aod::mycascades::EvFlags::EvINELgt1; + } + + // c x tau + float cascpos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); + float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); + float ctauXi = pdgDB->Mass(3312) * cascpos / (cascptotmom + 1e-13); + float ctauOmega = pdgDB->Mass(3334) * cascpos / (cascptotmom + 1e-13); + + mycascades(collision.posZ(), collision.centFT0M(), collision.centFV0A(), casc.sign(), casc.pt(), casc.yXi(), casc.yOmega(), casc.eta(), casc.mXi(), casc.mOmega(), casc.mLambda(), casc.cascradius(), casc.v0radius(), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), casc.dcapostopv(), casc.dcanegtopv(), casc.dcabachtopv(), casc.dcacascdaughters(), casc.dcaV0daughters(), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()), @@ -324,26 +404,49 @@ struct cascqaanalysis { ctauXi, ctauOmega, negdau.tpcNSigmaPr(), posdau.tpcNSigmaPr(), negdau.tpcNSigmaPi(), posdau.tpcNSigmaPi(), bachelor.tpcNSigmaPi(), bachelor.tpcNSigmaKa(), negdau.tofNSigmaPr(), posdau.tofNSigmaPr(), negdau.tofNSigmaPi(), posdau.tofNSigmaPi(), bachelor.tofNSigmaPi(), bachelor.tofNSigmaKa(), posdau.tpcNClsFound(), negdau.tpcNClsFound(), bachelor.tpcNClsFound(), + posdau.tpcNClsCrossedRows(), negdau.tpcNClsCrossedRows(), bachelor.tpcNClsCrossedRows(), posdau.hasTOF(), negdau.hasTOF(), bachelor.hasTOF(), - posdau.pt(), negdau.pt(), bachelor.pt(), -1, -1, casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV()); + posdau.pt(), negdau.pt(), bachelor.pt(), -1, -1, casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV(), evFlag); } } } } - PROCESS_SWITCH(cascqaanalysis, processData, "Process Run 3 data", true); + Preslice perMcCollision = aod::mcparticle::mcCollisionId; - void processMCrec(soa::Join::iterator const& collision, - soa::Filtered const& Cascades, - aod::V0sLinked const&, + void processMCrec(soa::Join::iterator const& collision, aod::V0Datas const&, - DauTracks const& Tracks, - aod::McParticles const&) + soa::Filtered const& Cascades, + DauTracks const&, + aod::McCollisions const&, + aod::McParticles const& mcParticles, + aod::V0sLinked const&) { - if (!AcceptEvent(collision, Tracks, 1)) { + if (!AcceptEvent(collision, 1)) { return; } + int evType = GetEventTypeFlag(collision); + + auto tracksGroupedPVcontr = pvContribTracksIUEta1->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + int nTracksPVcontr = tracksGroupedPVcontr.size(); + + auto tracksGroupedGlobal = globalTracksIUEta05->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + int nTracksGlobal = tracksGroupedGlobal.size(); + + // N charged in FT0M region in corresponding gen. MC collision + auto mcPartSlice = mcParticles.sliceBy(perMcCollision, collision.mcCollision_as().globalIndex()); + uint16_t nchFT0 = GetGenNchInFT0Mregion(mcPartSlice); + uint16_t nchFV0 = GetGenNchInFV0Aregion(mcPartSlice); + + registry.fill(HIST("hNchFT0MPVContr"), nchFT0, nTracksPVcontr, evType); + registry.fill(HIST("hNchFV0APVContr"), nchFV0, nTracksPVcontr, evType); + + if (multQA) { + registry.fill(HIST("hNchFT0Mglobal"), nchFT0, nTracksGlobal, evType); + registry.fill(HIST("hFT0MFV0Asignal"), collision.multFT0A() + collision.multFT0C(), collision.multFV0A()); + } + float lEventScale = scalefactor; for (const auto& casc : Cascades) { // loop over Cascades @@ -356,32 +459,6 @@ struct cascqaanalysis { registry.fill(HIST("hCandidateCounter"), 1.5); // v0data exists - auto v0 = v0index.v0Data(); - auto posdau = v0.posTrack_as(); - auto negdau = v0.negTrack_as(); - auto bachelor = casc.bachelor_as(); - - // ITS N hits - int posITSNhits = 0, negITSNhits = 0, bachITSNhits = 0; - for (unsigned int i = 0; i < 7; i++) { - if (posdau.itsClusterMap() & (1 << i)) { - posITSNhits++; - } - if (negdau.itsClusterMap() & (1 << i)) { - negITSNhits++; - } - if (bachelor.itsClusterMap() & (1 << i)) { - bachITSNhits++; - } - } - - // c x tau - float cascpos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); - float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); - // - float ctauXi = RecoDecay::getMassPDG(3312) * cascpos / (cascptotmom + 1e-13); - float ctauOmega = RecoDecay::getMassPDG(3334) * cascpos / (cascptotmom + 1e-13); - if (AcceptCascCandidate(casc, collision.posX(), collision.posY(), collision.posZ())) { registry.fill(HIST("hCandidateCounter"), 2.5); // passed topo cuts // Check mc association @@ -396,9 +473,44 @@ struct cascqaanalysis { isPrimary = cascmc.isPhysicalPrimary() ? 1 : 0; } } - // Fill table if (fRand->Rndm() < lEventScale) { - mycascades(casc.globalIndex(), collision.posZ(), collision.centFT0M(), collision.centFV0A(), casc.sign(), casc.pt(), casc.yXi(), casc.yOmega(), casc.eta(), + // Fill table + auto v0 = v0index.v0Data(); + auto posdau = v0.posTrack_as(); + auto negdau = v0.negTrack_as(); + auto bachelor = casc.bachelor_as(); + + // ITS N hits + int posITSNhits = 0, negITSNhits = 0, bachITSNhits = 0; + for (unsigned int i = 0; i < 7; i++) { + if (posdau.itsClusterMap() & (1 << i)) { + posITSNhits++; + } + if (negdau.itsClusterMap() & (1 << i)) { + negITSNhits++; + } + if (bachelor.itsClusterMap() & (1 << i)) { + bachITSNhits++; + } + } + + // Event type flag + uint8_t evFlag = 0; + evFlag |= o2::aod::mycascades::EvFlags::EvINEL; + if (collision.multNTracksPVeta1() > 0) { + evFlag |= o2::aod::mycascades::EvFlags::EvINELgt0; + } + if (collision.multNTracksPVeta1() > 1) { + evFlag |= o2::aod::mycascades::EvFlags::EvINELgt1; + } + + // c x tau + float cascpos = std::hypot(casc.x() - collision.posX(), casc.y() - collision.posY(), casc.z() - collision.posZ()); + float cascptotmom = std::hypot(casc.px(), casc.py(), casc.pz()); + float ctauXi = pdgDB->Mass(3312) * cascpos / (cascptotmom + 1e-13); + float ctauOmega = pdgDB->Mass(3334) * cascpos / (cascptotmom + 1e-13); + + mycascades(collision.posZ(), nchFT0, collision.multFV0A(), casc.sign(), casc.pt(), casc.yXi(), casc.yOmega(), casc.eta(), casc.mXi(), casc.mOmega(), casc.mLambda(), casc.cascradius(), casc.v0radius(), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()), casc.dcapostopv(), casc.dcanegtopv(), casc.dcabachtopv(), casc.dcacascdaughters(), casc.dcaV0daughters(), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ()), @@ -406,19 +518,18 @@ struct cascqaanalysis { ctauXi, ctauOmega, negdau.tpcNSigmaPr(), posdau.tpcNSigmaPr(), negdau.tpcNSigmaPi(), posdau.tpcNSigmaPi(), bachelor.tpcNSigmaPi(), bachelor.tpcNSigmaKa(), negdau.tofNSigmaPr(), posdau.tofNSigmaPr(), negdau.tofNSigmaPi(), posdau.tofNSigmaPi(), bachelor.tofNSigmaPi(), bachelor.tofNSigmaKa(), posdau.tpcNClsFound(), negdau.tpcNClsFound(), bachelor.tpcNClsFound(), + posdau.tpcNClsCrossedRows(), negdau.tpcNClsCrossedRows(), bachelor.tpcNClsCrossedRows(), posdau.hasTOF(), negdau.hasTOF(), bachelor.hasTOF(), - posdau.pt(), negdau.pt(), bachelor.pt(), lPDG, isPrimary, casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV()); + posdau.pt(), negdau.pt(), bachelor.pt(), lPDG, isPrimary, casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV(), evFlag); } } } } - PROCESS_SWITCH(cascqaanalysis, processMCrec, "Process Run 3 mc, reconstructed", false); - void processMCgen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups>& collisions, - DauTracks const& Tracks) + DauTracks const&) { // All generated collisions registry.fill(HIST("hNEventsMC"), 0.5); @@ -427,70 +538,125 @@ struct cascqaanalysis { if (TMath::Abs(mcCollision.posZ()) > cutzvertex) { return; } + registry.fill(HIST("hZCollisionGen"), mcCollision.posZ()); registry.fill(HIST("hNEventsMC"), 1.5); - // Generated collision is INEL>=0 - if (INELgt0 && !isINELgt0mc(mcParticles)) { - return; - } + // Define the type of generated MC collision + int evType = 0; + uint8_t flagsGen = 0; + flagsGen |= o2::aod::myMCcascades::EvFlags::EvINEL; registry.fill(HIST("hNEventsMC"), 2.5); + // Generated collision is INEL>0 + if (isINELgtNmc(mcParticles, 0)) { + flagsGen |= o2::aod::myMCcascades::EvFlags::EvINELgt0; + evType++; + registry.fill(HIST("hNEventsMC"), 3.5); + } + // Generated collision is INEL>1 + if (isINELgtNmc(mcParticles, 1)) { + flagsGen |= o2::aod::myMCcascades::EvFlags::EvINELgt1; + evType++; + registry.fill(HIST("hNEventsMC"), 4.5); + } - registry.fill(HIST("hZCollisionGen"), mcCollision.posZ()); + uint16_t nchFT0 = GetGenNchInFT0Mregion(mcParticles); + uint16_t nchFV0 = GetGenNchInFV0Aregion(mcParticles); + registry.fill(HIST("hNchFT0MGenEvType"), nchFT0, evType); + registry.fill(HIST("hNchFV0AGenEvType"), nchFV0, evType); - // Histos of generated cascades from generated events with accepted z vrtx + INEL>0 (for signal loss correction) - for (const auto& mcParticle : mcParticles) { - if (mcParticle.isPhysicalPrimary() == 0) - continue; // Consider only primaries - if (mcParticle.pdgCode() == -3312) { - registry.fill(HIST("hPtXiPlusTrue"), mcParticle.pt(), mcParticle.y(), 0); // MB will be used correction - } - if (mcParticle.pdgCode() == 3312) { - registry.fill(HIST("hPtXiMinusTrue"), mcParticle.pt(), mcParticle.y(), 0); + std::vector SelectedEvents(collisions.size()); + std::vector NumberOfContributors; + int nevts = 0; + int nAssocColl = 0; + for (const auto& collision : collisions) { + CollisionIndexAndType collWithType = {0, 0x0}; + if (!AcceptEvent(collision, 0)) { + continue; } - if (mcParticle.pdgCode() == -3334) { - registry.fill(HIST("hPtOmegaPlusTrue"), mcParticle.pt(), mcParticle.y(), 0); + collWithType.index = collision.mcCollision_as().globalIndex(); + collWithType.typeFlag |= o2::aod::myMCcascades::EvFlags::EvINEL; + + if (collision.multNTracksPVeta1() > 0) { + collWithType.typeFlag |= o2::aod::myMCcascades::EvFlags::EvINELgt0; } - if (mcParticle.pdgCode() == 3334) { - registry.fill(HIST("hPtOmegaMinusTrue"), mcParticle.pt(), mcParticle.y(), 0); + if (collision.multNTracksPVeta1() > 1) { + collWithType.typeFlag |= o2::aod::myMCcascades::EvFlags::EvINELgt1; } - } - std::vector SelectedEvents(collisions.size()); - int nevts = 0; - for (const auto& collision : collisions) { - if (!AcceptEvent(collision, Tracks, 0)) { - continue; + SelectedEvents[nevts++] = collWithType; + if (collision.mcCollision_as().globalIndex() == mcCollision.globalIndex()) { + nAssocColl++; + NumberOfContributors.push_back(collision.numContrib()); } - SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); } SelectedEvents.resize(nevts); - const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); // at least 1 selected reconstructed event has the same global index as mcCollision + registry.fill(HIST("hNchFT0MNAssocMCCollisions"), nchFT0, nAssocColl, evType); - if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed event passes the selection - return; + if (NumberOfContributors.size() == 2) { + std::sort(NumberOfContributors.begin(), NumberOfContributors.end()); + registry.fill(HIST("hNContributorsCorrelation"), NumberOfContributors[0], NumberOfContributors[1]); } - registry.fill(HIST("hNEventsMC"), 3.5); - - // Histos of generated cascades from generated events with good z vrtx + INEL>0 + associated to the accepted reconstructed event (for signal loss + efficiency x acceptance correction) - for (const auto& mcParticle : mcParticles) { - if (mcParticle.isPhysicalPrimary() == 0) - continue; // Consider only primaries - if (mcParticle.pdgCode() == -3312) { - registry.fill(HIST("hPtXiPlusTrueAssoiciatedWithSelColl"), mcParticle.pt(), mcParticle.y(), 0); // MB will be used correction + auto isAssocToINEL = [&mcCollision](CollisionIndexAndType i) { return (i.index == mcCollision.globalIndex()) && ((i.typeFlag & o2::aod::myMCcascades::EvFlags::EvINEL) == o2::aod::myMCcascades::EvFlags::EvINEL); }; + auto isAssocToINELgt0 = [&mcCollision](CollisionIndexAndType i) { return (i.index == mcCollision.globalIndex()) && ((i.typeFlag & o2::aod::myMCcascades::EvFlags::EvINELgt0) == o2::aod::myMCcascades::EvFlags::EvINELgt0); }; + auto isAssocToINELgt1 = [&mcCollision](CollisionIndexAndType i) { return (i.index == mcCollision.globalIndex()) && ((i.typeFlag & o2::aod::myMCcascades::EvFlags::EvINELgt1) == o2::aod::myMCcascades::EvFlags::EvINELgt1); }; + // number of reconstructed INEL events that have the same global index as mcCollision + const auto evtReconstructedAndINEL = std::count_if(SelectedEvents.begin(), SelectedEvents.end(), isAssocToINEL); + // number of reconstructed INEL > 0 events that have the same global index as mcCollision + const auto evtReconstructedAndINELgt0 = std::count_if(SelectedEvents.begin(), SelectedEvents.end(), isAssocToINELgt0); + // number of reconstructed INEL > 1 events that have the same global index as mcCollision + const auto evtReconstructedAndINELgt1 = std::count_if(SelectedEvents.begin(), SelectedEvents.end(), isAssocToINELgt1); + + switch (evType) { + case 0: { + registry.fill(HIST("hNchFT0MNAssocMCCollisionsSameType"), nchFT0, evtReconstructedAndINEL, evType); + break; } - if (mcParticle.pdgCode() == 3312) { - registry.fill(HIST("hPtXiMinusTrueAssoiciatedWithSelColl"), mcParticle.pt(), mcParticle.y(), 0); + case 1: { + registry.fill(HIST("hNchFT0MNAssocMCCollisionsSameType"), nchFT0, evtReconstructedAndINELgt0, evType); + break; } - if (mcParticle.pdgCode() == -3334) { - registry.fill(HIST("hPtOmegaPlusTrueAssoiciatedWithSelColl"), mcParticle.pt(), mcParticle.y(), 0); + case 2: { + registry.fill(HIST("hNchFT0MNAssocMCCollisionsSameType"), nchFT0, evtReconstructedAndINELgt1, evType); + break; } - if (mcParticle.pdgCode() == 3334) { - registry.fill(HIST("hPtOmegaMinusTrueAssoiciatedWithSelColl"), mcParticle.pt(), mcParticle.y(), 0); + default: + LOGF(fatal, "incorrect evType in cascqaanalysis task"); + break; + } + + uint8_t flagsAssoc = 0; + if (evtReconstructedAndINEL) { + flagsAssoc |= o2::aod::myMCcascades::EvFlags::EvINEL; + registry.fill(HIST("hNEventsMC"), 5.5); + } + if (evtReconstructedAndINELgt0) { + flagsAssoc |= o2::aod::myMCcascades::EvFlags::EvINELgt0; + } + if (evtReconstructedAndINELgt1) { + flagsAssoc |= o2::aod::myMCcascades::EvFlags::EvINELgt1; + } + + for (const auto& mcParticle : mcParticles) { + float sign = 0; + if (mcParticle.pdgCode() == -3312 || mcParticle.pdgCode() == -3334) { + sign = 1; + } else if (mcParticle.pdgCode() == 3312 || mcParticle.pdgCode() == 3334) { + sign = -1; + } else { + continue; } + myMCcascades(mcCollision.posZ(), sign, mcParticle.pdgCode(), + mcParticle.y(), mcParticle.eta(), mcParticle.phi(), mcParticle.pt(), + mcParticle.isPhysicalPrimary(), nAssocColl, nchFT0, + flagsAssoc, + flagsGen); } } + + PROCESS_SWITCH(cascqaanalysis, processData, "Process Run 3 data", true); + PROCESS_SWITCH(cascqaanalysis, processMCrec, "Process Run 3 mc, reconstructed", false); PROCESS_SWITCH(cascqaanalysis, processMCgen, "Process Run 3 mc, genereated", false); }; @@ -498,43 +664,48 @@ struct myCascades { HistogramRegistry registry{"registry"}; + // QA + Configurable doQA{"doQA", 0, "Fill QA histograms"}; + void init(InitContext const&) { TString PGDlabels[3] = {"Unknown", "3312", "3334"}; registry.add("hPt", "hPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}); - registry.add("hMassXi", "hMassXi", {HistType::kTH1F, {{3000, 0.0f, 3.0f}}}); - registry.add("hMassOmega", "hMassOmega", {HistType::kTH1F, {{3000, 0.0f, 3.0f}}}); - registry.add("hCascRadius", "hCascRadius", {HistType::kTH1D, {{100, 0.0f, 40.0f}}}); - registry.add("hV0Radius", "hV0Radius", {HistType::kTH1D, {{100, 0.0f, 40.0f}}}); - registry.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.9f, 1.0f}}}); - registry.add("hV0CosPA", "hV0CosPA", {HistType::kTH1F, {{100, 0.9f, 1.0f}}}); - registry.add("hDCANegToPV", "hDCANegToPV", {HistType::kTH1F, {{100, -1.0f, 1.0f}}}); - registry.add("hDCAPosToPV", "hDCAPosToPV", {HistType::kTH1F, {{100, -1.0f, 1.0f}}}); - registry.add("hDCABachToPV", "hDCABachToPV", {HistType::kTH1F, {{100, -1.0f, 1.0f}}}); - registry.add("hDCACascDaughters", "hDCACascDaughters", {HistType::kTH1F, {{55, 0.0f, 2.20f}}}); - registry.add("hDCAV0Daughters", "hDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.20f}}}); - registry.add("hCtauXi", "hCtauXi", {HistType::kTH1F, {{100, 0.0f, 40.0f}}}); - registry.add("hCtauOmega", "hCtauOmega", {HistType::kTH1F, {{100, 0.0f, 40.0f}}}); - registry.add("hTPCNSigmaPosPi", "hTPCNSigmaPosPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTPCNSigmaNegPi", "hTPCNSigmaNegPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTPCNSigmaPosPr", "hTPCNSigmaPosPr", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTPCNSigmaNegPr", "hTPCNSigmaNegPr", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTPCNSigmaBachPi", "hTPCNSigmaBachPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTOFNSigmaPosPi", "hTOFNSigmaPosPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTOFNSigmaNegPi", "hTOFNSigmaNegPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTOFNSigmaPosPr", "hTOFNSigmaPosPr", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTOFNSigmaNegPr", "hTOFNSigmaNegPr", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hTOFNSigmaBachPi", "hTOFNSigmaBachPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); - registry.add("hPosITSHits", "hPosITSHits", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}); - registry.add("hNegITSHits", "hNegITSHits", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}); - registry.add("hBachITSHits", "hBachITSHits", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}); - registry.add("hIsPrimary", "hIsPrimary", {HistType::kTH1F, {{3, -1.5f, 1.5f}}}); - registry.add("hPDGcode", "hPDGcode", {HistType::kTH1F, {{3, -1.5f, 1.5f}}}); - for (Int_t n = 1; n <= registry.get(HIST("hPDGcode"))->GetNbinsX(); n++) { - registry.get(HIST("hPDGcode"))->GetXaxis()->SetBinLabel(n, PGDlabels[n - 1]); - } - registry.add("hBachBaryonCosPA", "hBachBaryonCosPA", {HistType::kTH1F, {{100, 0.0f, 1.0f}}}); - registry.add("hBachBaryonDCAxyToPV", "hBachBaryonDCAxyToPV", {HistType::kTH1F, {{300, -3.0f, 3.0f}}}); + registry.add("hMassXi", "hMassXi", {HistType::kTH1F, {{1000, 1.0f, 2.0f}}}); + registry.add("hMassOmega", "hMassOmega", {HistType::kTH1F, {{1000, 1.0f, 2.0f}}}); + if (doQA) { + registry.add("hCascRadius", "hCascRadius", {HistType::kTH1D, {{100, 0.0f, 40.0f}}}); + registry.add("hV0Radius", "hV0Radius", {HistType::kTH1D, {{100, 0.0f, 40.0f}}}); + registry.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.9f, 1.0f}}}); + registry.add("hV0CosPA", "hV0CosPA", {HistType::kTH1F, {{100, 0.9f, 1.0f}}}); + registry.add("hDCANegToPV", "hDCANegToPV", {HistType::kTH1F, {{100, -1.0f, 1.0f}}}); + registry.add("hDCAPosToPV", "hDCAPosToPV", {HistType::kTH1F, {{100, -1.0f, 1.0f}}}); + registry.add("hDCABachToPV", "hDCABachToPV", {HistType::kTH1F, {{100, -1.0f, 1.0f}}}); + registry.add("hDCACascDaughters", "hDCACascDaughters", {HistType::kTH1F, {{55, 0.0f, 2.20f}}}); + registry.add("hDCAV0Daughters", "hDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.20f}}}); + registry.add("hCtauXi", "hCtauXi", {HistType::kTH1F, {{100, 0.0f, 40.0f}}}); + registry.add("hCtauOmega", "hCtauOmega", {HistType::kTH1F, {{100, 0.0f, 40.0f}}}); + registry.add("hTPCNSigmaPosPi", "hTPCNSigmaPosPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTPCNSigmaNegPi", "hTPCNSigmaNegPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTPCNSigmaPosPr", "hTPCNSigmaPosPr", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTPCNSigmaNegPr", "hTPCNSigmaNegPr", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTPCNSigmaBachPi", "hTPCNSigmaBachPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTOFNSigmaPosPi", "hTOFNSigmaPosPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTOFNSigmaNegPi", "hTOFNSigmaNegPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTOFNSigmaPosPr", "hTOFNSigmaPosPr", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTOFNSigmaNegPr", "hTOFNSigmaNegPr", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hTOFNSigmaBachPi", "hTOFNSigmaBachPi", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}); + registry.add("hPosITSHits", "hPosITSHits", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}); + registry.add("hNegITSHits", "hNegITSHits", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}); + registry.add("hBachITSHits", "hBachITSHits", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}); + registry.add("hIsPrimary", "hIsPrimary", {HistType::kTH1F, {{3, -1.5f, 1.5f}}}); + registry.add("hPDGcode", "hPDGcode", {HistType::kTH1F, {{3, -1.5f, 1.5f}}}); + for (Int_t n = 1; n <= registry.get(HIST("hPDGcode"))->GetNbinsX(); n++) { + registry.get(HIST("hPDGcode"))->GetXaxis()->SetBinLabel(n, PGDlabels[n - 1]); + } + registry.add("hBachBaryonCosPA", "hBachBaryonCosPA", {HistType::kTH1F, {{100, 0.0f, 1.0f}}}); + registry.add("hBachBaryonDCAxyToPV", "hBachBaryonDCAxyToPV", {HistType::kTH1F, {{300, -3.0f, 3.0f}}}); + } } void process(aod::MyCascades const& mycascades) @@ -544,38 +715,40 @@ struct myCascades { registry.fill(HIST("hMassXi"), candidate.massxi()); registry.fill(HIST("hMassOmega"), candidate.massomega()); registry.fill(HIST("hPt"), candidate.pt()); - registry.fill(HIST("hCascRadius"), candidate.cascradius()); - registry.fill(HIST("hV0Radius"), candidate.v0radius()); - registry.fill(HIST("hCascCosPA"), candidate.casccospa()); - registry.fill(HIST("hV0CosPA"), candidate.v0cospa()); - registry.fill(HIST("hDCANegToPV"), candidate.dcanegtopv()); - registry.fill(HIST("hDCAPosToPV"), candidate.dcapostopv()); - registry.fill(HIST("hDCABachToPV"), candidate.dcabachtopv()); - registry.fill(HIST("hDCACascDaughters"), candidate.dcacascdaughters()); - registry.fill(HIST("hDCAV0Daughters"), candidate.dcav0daughters()); - registry.fill(HIST("hCtauXi"), candidate.ctauxi()); - registry.fill(HIST("hCtauOmega"), candidate.ctauomega()); - registry.fill(HIST("hTPCNSigmaPosPi"), candidate.ntpcsigmapospi()); - registry.fill(HIST("hTPCNSigmaNegPi"), candidate.ntpcsigmanegpi()); - registry.fill(HIST("hTPCNSigmaPosPr"), candidate.ntpcsigmapospr()); - registry.fill(HIST("hTPCNSigmaNegPr"), candidate.ntpcsigmanegpr()); - registry.fill(HIST("hTPCNSigmaBachPi"), candidate.ntpcsigmabachpi()); - registry.fill(HIST("hTOFNSigmaPosPi"), candidate.ntofsigmapospi()); - registry.fill(HIST("hTOFNSigmaNegPi"), candidate.ntofsigmanegpi()); - registry.fill(HIST("hTOFNSigmaPosPr"), candidate.ntofsigmapospr()); - registry.fill(HIST("hTOFNSigmaNegPr"), candidate.ntofsigmanegpr()); - registry.fill(HIST("hTOFNSigmaBachPi"), candidate.ntofsigmabachpi()); - registry.fill(HIST("hPosITSHits"), candidate.positshits()); - registry.fill(HIST("hNegITSHits"), candidate.negitshits()); - registry.fill(HIST("hBachITSHits"), candidate.bachitshits()); - registry.fill(HIST("hIsPrimary"), candidate.isPrimary()); - registry.fill(HIST("hBachBaryonCosPA"), candidate.bachBaryonCosPA()); - registry.fill(HIST("hBachBaryonDCAxyToPV"), candidate.bachBaryonDCAxyToPV()); - - if (TMath::Abs(candidate.mcPdgCode()) == 3312 || TMath::Abs(candidate.mcPdgCode()) == 3334) { - registry.fill(HIST("hPDGcode"), TMath::Abs(candidate.mcPdgCode()) == 3312 ? 0 : 1); // 0 if Xi, 1 if Omega - } else { - registry.fill(HIST("hPDGcode"), -1); // -1 if unknown + if (doQA) { + registry.fill(HIST("hCascRadius"), candidate.cascradius()); + registry.fill(HIST("hV0Radius"), candidate.v0radius()); + registry.fill(HIST("hCascCosPA"), candidate.casccospa()); + registry.fill(HIST("hV0CosPA"), candidate.v0cospa()); + registry.fill(HIST("hDCANegToPV"), candidate.dcanegtopv()); + registry.fill(HIST("hDCAPosToPV"), candidate.dcapostopv()); + registry.fill(HIST("hDCABachToPV"), candidate.dcabachtopv()); + registry.fill(HIST("hDCACascDaughters"), candidate.dcacascdaughters()); + registry.fill(HIST("hDCAV0Daughters"), candidate.dcav0daughters()); + registry.fill(HIST("hCtauXi"), candidate.ctauxi()); + registry.fill(HIST("hCtauOmega"), candidate.ctauomega()); + registry.fill(HIST("hTPCNSigmaPosPi"), candidate.ntpcsigmapospi()); + registry.fill(HIST("hTPCNSigmaNegPi"), candidate.ntpcsigmanegpi()); + registry.fill(HIST("hTPCNSigmaPosPr"), candidate.ntpcsigmapospr()); + registry.fill(HIST("hTPCNSigmaNegPr"), candidate.ntpcsigmanegpr()); + registry.fill(HIST("hTPCNSigmaBachPi"), candidate.ntpcsigmabachpi()); + registry.fill(HIST("hTOFNSigmaPosPi"), candidate.ntofsigmapospi()); + registry.fill(HIST("hTOFNSigmaNegPi"), candidate.ntofsigmanegpi()); + registry.fill(HIST("hTOFNSigmaPosPr"), candidate.ntofsigmapospr()); + registry.fill(HIST("hTOFNSigmaNegPr"), candidate.ntofsigmanegpr()); + registry.fill(HIST("hTOFNSigmaBachPi"), candidate.ntofsigmabachpi()); + registry.fill(HIST("hPosITSHits"), candidate.positshits()); + registry.fill(HIST("hNegITSHits"), candidate.negitshits()); + registry.fill(HIST("hBachITSHits"), candidate.bachitshits()); + registry.fill(HIST("hIsPrimary"), candidate.isPrimary()); + registry.fill(HIST("hBachBaryonCosPA"), candidate.bachBaryonCosPA()); + registry.fill(HIST("hBachBaryonDCAxyToPV"), candidate.bachBaryonDCAxyToPV()); + + if (TMath::Abs(candidate.mcPdgCode()) == 3312 || TMath::Abs(candidate.mcPdgCode()) == 3334) { + registry.fill(HIST("hPDGcode"), TMath::Abs(candidate.mcPdgCode()) == 3312 ? 0 : 1); // 0 if Xi, 1 if Omega + } else { + registry.fill(HIST("hPDGcode"), -1); // -1 if unknown + } } } } diff --git a/PWGLF/TableProducer/f1protonInitializer.cxx b/PWGLF/TableProducer/f1protonInitializer.cxx index f50fcb64dc7..ed406895e0a 100644 --- a/PWGLF/TableProducer/f1protonInitializer.cxx +++ b/PWGLF/TableProducer/f1protonInitializer.cxx @@ -294,16 +294,16 @@ struct f1protoninitializer { if (numberPiKpair == 1) { qaRegistry.fill(HIST("hInvMassk0"), track3.mK0Short(), track3.pt()); } - pT = RecoDecay::pt(array{track1.px() + track2.px() + track3.px(), track1.py() + track2.py() + track3.py()}); - auto arrMomF1 = array{ - array{track1.px(), track1.py(), track1.pz()}, - array{track2.px(), track2.py(), track2.pz()}, - array{track3.px(), track3.py(), track3.pz()}}; - auto arrMom23 = array{ - array{track2.px(), track2.py(), track2.pz()}, - array{track3.px(), track3.py(), track3.pz()}}; - masskKs0 = RecoDecay::m(arrMom23, array{massKa, massK0s}); - massF1 = RecoDecay::m(arrMomF1, array{massPi, massKa, massK0s}); + pT = RecoDecay::pt(std::array{track1.px() + track2.px() + track3.px(), track1.py() + track2.py() + track3.py()}); + auto arrMomF1 = std::array{ + std::array{track1.px(), track1.py(), track1.pz()}, + std::array{track2.px(), track2.py(), track2.pz()}, + std::array{track3.px(), track3.py(), track3.pz()}}; + auto arrMom23 = std::array{ + std::array{track2.px(), track2.py(), track2.pz()}, + std::array{track3.px(), track3.py(), track3.pz()}}; + masskKs0 = RecoDecay::m(arrMom23, std::array{massKa, massK0s}); + massF1 = RecoDecay::m(arrMomF1, std::array{massPi, massKa, massK0s}); qaRegistry.fill(HIST("hInvMassKKs0"), masskKs0); if ((masskKs0 > cMaxMassKKs0) || (massF1 > cMaxMassF1) || (pT < cMinF1Pt)) { continue; diff --git a/PWGLF/TableProducer/f1protonreducedtable.cxx b/PWGLF/TableProducer/f1protonreducedtable.cxx new file mode 100644 index 00000000000..2dfcdcb3563 --- /dev/null +++ b/PWGLF/TableProducer/f1protonreducedtable.cxx @@ -0,0 +1,765 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file f1protonreducedtable.cxx +/// \brief Selection of events with triplets and pairs for femtoscopic studies +/// +/// \author Sourav Kundu, sourav.kundu@cern.ch + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PWGLF/DataModel/ReducedF1ProtonTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "CommonConstants/MathConstants.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct f1protonreducedtable { + + // Produce derived tables + Produces reducedf1protonevents; + Produces f1track; + Produces protontrack; + + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + + // Configs for events + Configurable ConfEvtSelectZvtx{"ConfEvtSelectZvtx", true, "Event selection includes max. z-Vertex"}; + Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + + // event spherocity calculation + Configurable trackSphDef{"trackSphDef", 0, "Spherocity Definition: |pT| = 1 -> 0, otherwise -> 1"}; + Configurable trackSphMin{"trackSphMin", 10, "Number of tracks for Spherocity Calculation"}; + + // Configs for track PID + Configurable ConfUseManualPIDproton{"ConfUseManualPIDproton", true, "True: use home-made PID solution for proton "}; + Configurable ConfUseManualPIDkaon{"ConfUseManualPIDkaon", true, "True: use home-made PID solution for kaon "}; + Configurable ConfUseManualPIDpion{"ConfUseManualPIDpion", true, "True: use home-made PID solution for pion "}; + Configurable ConfUseManualPIDdaughterPion{"ConfUseManualPIDdaughterPion", true, "True: use home-made PID solution for pion from V0"}; + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "ccdb-url"}; + Configurable ConfPIDBBProton{"ConfPIDBBProton", "Users/a/ariedel/FinalTrigger/PIDProton", "Path to the CCDB ocject for proton BB param"}; + Configurable ConfPIDBBAntiProton{"ConfPIDBBAntiProton", "Analysis/PWGHF/ML/HFTrigger/TPC/AntiProton", "Path to the CCDB ocject for anti-proton BB param"}; + Configurable ConfPIDBBKaon{"ConfPIDBBKaon", "Analysis/PWGHF/ML/HFTrigger/TPC/Kaon", "Path to the CCDB ocject for kaon BB param"}; + Configurable ConfPIDBBAntiKaon{"ConfPIDBBAntiKaon", "Analysis/PWGHF/ML/HFTrigger/TPC/AntiKaon", "Path to the CCDB ocject for anti-kaon BB param"}; + Configurable ConfPIDBBPion{"ConfPIDBBPion", "Analysis/PWGHF/ML/HFTrigger/TPC/Pion", "Path to the CCDB ocject for pion BB param"}; + Configurable ConfPIDBBAntiPion{"ConfPIDBBAntiPion", "Analysis/PWGHF/ML/HFTrigger/TPC/AntiPion", "Path to the CCDB ocject for anti-pion BB param"}; + Configurable ConfRejectNotPropagatedTracks{"ConfRejectNotPropagatedTracks", false, "True: reject not propagated tracks"}; + Configurable ConfPIDCutsTPCF1Proton{"ConfPIDCutsTPCF1Proton", 2, "Particle PID selections using TPC"}; + Configurable ConfPIDCutsTOFF1Proton{"ConfPIDCutsTOFF1Proton", 2, "Particle PID selections using TOF"}; + Configurable strategyPIDPion{"strategyPIDPion", 0, "PID strategy Pion"}; + Configurable strategyPIDKaon{"strategyPIDKaon", 0, "PID strategy Kaon"}; + Configurable strategyPIDProton{"strategyPIDProton", 1, "PID strategy Proton"}; + Configurable pionMomentumPID{"pionMomentumPID", 0.5, "pi momentum range for TPC PID selection"}; + Configurable kaonMomentumPID{"kaonMomentumPID", 0.45, "ka momentum range for TPC PID selection"}; + Configurable protonMomentumPID{"protonMomentumPID", 0.75, "pr momentum range for TPC PID selection"}; + + // Configs for track cut + Configurable ConfPtCutsF1Proton{"ConfPtCutsF1Proton", 0.1, "Particle Momentum selections"}; + Configurable ConfTrkEtaF1Proton{"ConfTrkEtaF1Proton", 0.85, "Eta"}; + Configurable ConfTPCNClustersMinF1Proton{"ConfTPCNClustersMinF1Proton", 80, " Minimum number of TPC cluster"}; + Configurable ConfTrkTPCcRowsMinF1Proton{"ConfTrkTPCcRowsMinF1Proton", 70, "Minimum number of crossed TPC rows"}; + Configurable ConfTrkTPCfClsF1Proton{"ConfTrkTPCfClsF1Proton", 0.83, "Minimum fraction of crossed rows over findable clusters"}; + Configurable ConfTrkTPCsClsMaxF1Proton{"ConfTrkTPCsClsMaxF1Proton", 160, "Maximum number of shared TPC clusters"}; + Configurable ConfTrkITSnclsMinF1Proton{"ConfTrkITSnclsMinF1Proton", 0, "Minimum number of ITS clusters"}; + Configurable ConfTrkITSnclsIbMinF1Proton{"ConfTrkITSnclsIbMinF1Proton", 0, "Minimum number of ITS clusters in the inner barrel"}; + Configurable ConfTrkDCAxyMaxF1Proton{"ConfTrkDCAxyMaxF1Proton", 0.15, "Maximum DCA_xy"}; + Configurable ConfTrkDCAzMaxF1Proton{"ConfTrkDCAzMaxF1Proton", 0.3, "Maximum DCA_z"}; + + // Checks taken from global track definition + Configurable ConfTrkRequireChi2MaxTPC{"ConfTrkRequireChi2MaxTPC", false, "True: require max chi2 per TPC cluster"}; + Configurable ConfTrkRequireChi2MaxITS{"ConfTrkRequireChi2MaxITS", false, "True: require max chi2 per ITS cluster"}; + Configurable ConfTrkMaxChi2PerClusterTPC{"ConfTrkMaxChi2PerClusterTPC", 4.0f, "Minimal track selection: max allowed chi2 per TPC cluster"}; // 4.0 is default + Configurable ConfTrkMaxChi2PerClusterITS{"ConfTrkMaxChi2PerClusterITS", 36.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"}; + + // Configs for V0 + Configurable ConfV0PtMin{"ConfV0PtMin", 0.f, "Minimum transverse momentum of V0"}; + Configurable ConfV0DCADaughMax{"ConfV0DCADaughMax", 1.8f, "Maximum DCA between the V0 daughters"}; + Configurable ConfV0CPAMin{"ConfV0CPAMin", 0.985f, "Minimum CPA of V0"}; + Configurable ConfV0TranRadV0Min{"ConfV0TranRadV0Min", 0.2f, "Minimum transverse radius"}; + Configurable ConfV0TranRadV0Max{"ConfV0TranRadV0Max", 100.f, "Maximum transverse radius"}; + Configurable ConfV0DecVtxMax{"ConfV0DecVtxMax", 100.f, "Maximum distance from primary vertex"}; + Configurable cMaxV0DCA{"cMaxV0DCA", 0.3, "Minimum V0 CosPA to PV"}; + Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 40, "Maximum V0 life time"}; + Configurable cSigmaMassKs0{"cSigmaMassKs0", 2, "Sigma cut on KS0 mass"}; + + // config for V0 daughters + Configurable ConfDaughEta{"ConfDaughEta", 0.85f, "V0 Daugh sel: max eta"}; + Configurable ConfDaughTPCnclsMin{"ConfDaughTPCnclsMin", 60.f, "V0 Daugh sel: Min. nCls TPC"}; + Configurable ConfDaughDCAMin{"ConfDaughDCAMin", 0.04f, "V0 Daugh sel: Max. DCA Daugh to PV (cm)"}; + Configurable ConfDaughPIDCuts{"ConfDaughPIDCuts", 3, "PID selections for KS0 daughters"}; + + // Configs for F1 candidate + Configurable cMaxMassKKs0{"cMaxMassKKs0", 1.04, "Mass cut on K-KS0 pair"}; + Configurable cMaxMassF1{"cMaxMassF1", 1.80001, "Mass cut on F1 resonance"}; + Configurable cMinF1Pt{"cMinF1Pt", 1.0, "Minimum pT cut on F1"}; + Configurable cMinKaonPt{"cMinKaonPt", 0.3, "Minimum pT cut on Kaon daughter"}; + Configurable cMaxProtonPt{"cMaxProtonPt", 2.0, "Maximum pT cut on Proton"}; + + // config Femto relative momentum + Configurable cMaxRelMom{"cMaxRelMom", 0.5, "Relative momentum cut"}; + + // Histogram + HistogramRegistry qaRegistry{"QAHistos", { + {"hEventstat", "hEventstat", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, + {"hInvMassf1", "hInvMassf1", {HistType::kTH2F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}}}}, + {"hInvMassf1Like", "hInvMassf1Like", {HistType::kTH2F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}}}}, + {"hInvMassf1kstar", "hInvMassf1kstar", {HistType::kTH3F, {{400, 1.1f, 1.9f}, {100, 0.0f, 10.0f}, {8, 0.0f, 0.8f}}}}, + {"hkstarDist", "hkstarDist", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, + {"hDCAxy", "hDCAxy", {HistType::kTH1F, {{100, -5.0f, 5.0f}}}}, + {"hDCAz", "hDCAz", {HistType::kTH1F, {{100, -5.0f, 5.0f}}}}, + {"hPhi", "hPhi", {HistType::kTH1F, {{1400, -7.0f, 7.0f}}}}, + {"hPhiSphero", "hPhiSphero", {HistType::kTH1F, {{1400, -7.0f, 7.0f}}}}, + {"hEta", "hEta", {HistType::kTH1F, {{20, -1.0f, 1.0f}}}}, + {"hNsigmaPtpionTPC", "hNsigmaPtpionTPC", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtpionTOF", "hNsigmaPtpionTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtkaonTPC", "hNsigmaPtkaonTPC", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtkaonTOF", "hNsigmaPtkaonTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtprotonTPC", "hNsigmaPtprotonTPC", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hNsigmaPtprotonTOF", "hNsigmaPtprotonTOF", {HistType::kTH2F, {{200, -10.0f, 10.0f}, {100, 0.0f, 10.0f}}}}, + {"hInvMassk0", "hInvMassk0", {HistType::kTH2F, {{200, 0.4f, 0.6f}, {100, 0.0f, 10.0f}}}}, + }, + OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + ccdb->setURL(url.value); + ccdbApi.init(url); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + } + + template + bool isSelectedEvent(T const& col) + { + if (ConfEvtSelectZvtx && std::abs(col.posZ()) > ConfEvtZvtx) { + return false; + } + return true; + } + + template + bool isSelectedTrack(T const& track) + { + const auto pT = track.pt(); + const auto eta = track.eta(); + const auto tpcNClsF = track.tpcNClsFound(); + const auto tpcRClsC = track.tpcCrossedRowsOverFindableCls(); + const auto tpcNClsC = track.tpcNClsCrossedRows(); + const auto tpcNClsS = track.tpcNClsShared(); + const auto itsNCls = track.itsNCls(); + const auto itsNClsIB = track.itsNClsInnerBarrel(); + const auto dcaXY = track.dcaXY(); + const auto dcaZ = track.dcaZ(); + if (pT < ConfPtCutsF1Proton) { + return false; + } + if (std::abs(eta) > ConfTrkEtaF1Proton) { + return false; + } + if (tpcNClsF < ConfTPCNClustersMinF1Proton) { + return false; + } + if (tpcRClsC < ConfTrkTPCfClsF1Proton) { + return false; + } + if (tpcNClsC < ConfTrkTPCcRowsMinF1Proton) { + return false; + } + if (tpcNClsS > ConfTrkTPCsClsMaxF1Proton) { + return false; + } + if (itsNCls < ConfTrkITSnclsMinF1Proton) { + return false; + } + if (itsNClsIB < ConfTrkITSnclsIbMinF1Proton) { + return false; + } + if (std::abs(dcaXY) > ConfTrkDCAxyMaxF1Proton) { + return false; + } + if (std::abs(dcaZ) > ConfTrkDCAzMaxF1Proton) { + return false; + } + // TODO: which dca, put dcaxy for now + if (ConfRejectNotPropagatedTracks && std::abs(dcaXY) > 1e3) { + return false; + } + if (ConfTrkRequireChi2MaxTPC && track.tpcChi2NCl() >= ConfTrkMaxChi2PerClusterTPC) { + return false; + } + if (ConfTrkRequireChi2MaxITS && track.itsChi2NCl() >= ConfTrkMaxChi2PerClusterITS) { + return false; + } + if (ConfTrkTPCRefit && !track.hasTPC()) { + return false; + } + if (ConfTrkITSRefit && !track.hasITS()) { + return false; + } + return true; + } + + template + double updatePID(T const& track, double bgScaling, std::vector BB) + { + double expBethe = tpc::BetheBlochAleph(static_cast(track.tpcInnerParam() * bgScaling), BB[0], BB[1], BB[2], BB[3], BB[4]); + double expSigma = expBethe * BB[5]; + return static_cast((track.tpcSignal() - expBethe) / expSigma); + } + + template + bool isSelectedV0Daughter(T const& track, float charge, double nsigmaV0Daughter) + { + const auto eta = track.eta(); + const auto tpcNClsF = track.tpcNClsFound(); + const auto dcaXY = track.dcaXY(); + const auto sign = track.sign(); + + if (charge < 0 && sign > 0) { + return false; + } + if (charge > 0 && sign < 0) { + return false; + } + if (std::abs(eta) > ConfDaughEta) { + return false; + } + if (tpcNClsF < ConfDaughTPCnclsMin) { + return false; + } + if (std::abs(dcaXY) < ConfDaughDCAMin) { + return false; + } + + if (std::abs(nsigmaV0Daughter) > ConfDaughPIDCuts) { + return false; + } + return true; + } + + template + bool SelectionPID(const T& candidate, int PIDstrategy, int particle, double updatensigma) + { + if (PIDstrategy == 1) { + if (particle == 0) { + if (std::abs(candidate.p()) < pionMomentumPID && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton) { + return true; + } else if (std::abs(candidate.p()) >= pionMomentumPID && candidate.hasTOF() && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaPi()) < ConfPIDCutsTOFF1Proton) { + return true; + } + } else if (particle == 1) { + if (std::abs(candidate.p()) < kaonMomentumPID && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton) { + return true; + } else if (std::abs(candidate.p()) >= kaonMomentumPID && candidate.hasTOF() && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaKa()) < ConfPIDCutsTOFF1Proton) { + return true; + } + } else if (particle == 2) { + if (std::abs(candidate.p()) < protonMomentumPID && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton) { + return true; + } else if (std::abs(candidate.p()) >= protonMomentumPID && candidate.hasTOF() && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaPr()) < ConfPIDCutsTOFF1Proton) { + return true; + } + } + } else if (PIDstrategy == 0) { + if (candidate.hasTOF()) { + if (particle == 0 && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaPi()) < ConfPIDCutsTOFF1Proton) { + return true; + } else if (particle == 1 && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaKa()) < ConfPIDCutsTOFF1Proton) { + return true; + } else if (particle == 2 && std::abs(updatensigma) < ConfPIDCutsTPCF1Proton && std::abs(candidate.tofNSigmaPr()) < ConfPIDCutsTOFF1Proton) { + return true; + } + } else if (std::abs(updatensigma) < ConfPIDCutsTPCF1Proton) { + return true; + } + } + return false; + } + + template + bool SelectionV0(Collision const& collision, V0 const& candidate) + { + if (fabs(candidate.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) > cMaxV0DCA) { + return false; + } + + const float pT = candidate.pt(); + const std::vector decVtx = {candidate.x(), candidate.y(), candidate.z()}; + const float tranRad = candidate.v0radius(); + const float dcaDaughv0 = candidate.dcaV0daughters(); + const float cpav0 = candidate.v0cosPA(collision.posX(), collision.posY(), collision.posZ()); + + float CtauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(); + float lowmasscutks0 = 0.497 - 2.0 * cSigmaMassKs0; + float highmasscutks0 = 0.497 + 2.0 * cSigmaMassKs0; + + if (pT < ConfV0PtMin) { + return false; + } + if (dcaDaughv0 > ConfV0DCADaughMax) { + return false; + } + if (cpav0 < ConfV0CPAMin) { + return false; + } + if (tranRad < ConfV0TranRadV0Min) { + return false; + } + if (tranRad > ConfV0TranRadV0Max) { + return false; + } + for (size_t i = 0; i < decVtx.size(); i++) { + if (decVtx.at(i) > ConfV0DecVtxMax) { + return false; + } + } + if (fabs(CtauK0s) > cMaxV0LifeTime || candidate.mK0Short() < lowmasscutks0 || candidate.mK0Short() > highmasscutks0) { + return false; + } + return true; + } + + float getkstar(const ROOT::Math::PtEtaPhiMVector part1, + const ROOT::Math::PtEtaPhiMVector part2) + { + const ROOT::Math::PtEtaPhiMVector trackSum = part1 + part2; + const float beta = trackSum.Beta(); + const float betax = + beta * std::cos(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betay = + beta * std::sin(trackSum.Phi()) * std::sin(trackSum.Theta()); + const float betaz = beta * std::cos(trackSum.Theta()); + ROOT::Math::PxPyPzMVector PartOneCMS(part1); + ROOT::Math::PxPyPzMVector PartTwoCMS(part2); + const ROOT::Math::Boost boostPRF = + ROOT::Math::Boost(-betax, -betay, -betaz); + PartOneCMS = boostPRF(PartOneCMS); + PartTwoCMS = boostPRF(PartTwoCMS); + const ROOT::Math::PxPyPzMVector trackRelK = PartOneCMS - PartTwoCMS; + return 0.5 * trackRelK.P(); + } + + std::vector setValuesBB(o2::ccdb::CcdbApi& ccdbApi, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string ccdbPath) + { + map metadata; + auto h = ccdbApi.retrieveFromTFileAny(ccdbPath, metadata, bunchCrossing.timestamp()); + // auto h = ccdb->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); // check if possible to use this without getting fatal + if (!h) { + std::vector dummy; + LOG(info) << "File from CCDB in path " << ccdbPath << " was not found for run " << bunchCrossing.runNumber() << "and timestamp" << bunchCrossing.timestamp() << ". Will use default PID task values!"; + return dummy; + } + LOG(info) << "File from CCDB in path " << ccdbPath << " was found for run " << bunchCrossing.runNumber() << "!"; + + TAxis* axis = h->GetXaxis(); + std::vector v{static_cast(h->GetBinContent(axis->FindBin("bb1"))), + static_cast(h->GetBinContent(axis->FindBin("bb2"))), + static_cast(h->GetBinContent(axis->FindBin("bb3"))), + static_cast(h->GetBinContent(axis->FindBin("bb4"))), + static_cast(h->GetBinContent(axis->FindBin("bb5"))), + static_cast(h->GetBinContent(axis->FindBin("Resolution")))}; + return v; + } + + /// Compute the spherocity of an event + /// Important here is that the filter on tracks does not interfere here! + /// In Run 2 we used here global tracks within |eta| < 0.8 + /// \tparam T type of the tracks + /// \param tracks All tracks + /// \return value of the spherocity of the event + template + float ComputeSpherocity(T const& tracks, int nTracksMin, int spdef) + { + // if number of tracks is not enough for spherocity estimation. + int ntrks = tracks.size(); + if (ntrks < nTracksMin) + return -99.; + + // start computing spherocity + + float ptSum = 0.; + for (auto const& track : tracks) { + + qaRegistry.fill(HIST("hPhiSphero"), track.phi()); + + if (spdef == 0) { + ptSum += 1.; + } else { + ptSum += track.pt(); + } + } + + float tempSph = 1.; + for (int i = 0; i < 360 / 0.1; ++i) { + float sum = 0., pt = 0.; + float phiparm = (TMath::Pi() * i * 0.1) / 180.; + float nx = TMath::Cos(phiparm); + float ny = TMath::Sin(phiparm); + for (auto const& trk : tracks) { + pt = trk.pt(); + if (spdef == 0) { + pt = 1.; + } + float phi = trk.phi(); + float px = pt * TMath::Cos(phi); + float py = pt * TMath::Sin(phi); + // sum += pt * abs(sin(phiparm - phi)); + sum += TMath::Abs(px * ny - py * nx); + } + float sph = TMath::Power((sum / ptSum), 2); + if (sph < tempSph) + tempSph = sph; + } + + return TMath::Power(TMath::Pi() / 2., 2) * tempSph; + } + + std::vector BBProton, BBAntiproton, BBPion, BBAntipion, BBKaon, BBAntikaon; + ROOT::Math::PtEtaPhiMVector F1Vector, F1VectorDummy, KKs0Vector, ProtonVectorDummy, ProtonVectorDummy2; + double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); + double massKa = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); + double massPr = TDatabasePDG::Instance()->GetParticle(kProton)->Mass(); + double massK0s = TDatabasePDG::Instance()->GetParticle(kK0Short)->Mass(); + + double massF1{0.}; + double masskKs0{0.}; + double pT{0.}; + int currentRunNumber = -999; + int lastRunNumber = -999; + double betaX = 0; + double betaY = 0; + double betaZ = 0; + double relativeMomentum = 999; + // Pre-filters for primary track + Filter acceptanceFilter = nabs(aod::track::eta) < ConfTrkEtaF1Proton && nabs(aod::track::pt) > ConfPtCutsF1Proton; + Filter dcaFilter = nabs(aod::track::dcaXY) < ConfTrkDCAxyMaxF1Proton && nabs(aod::track::dcaZ) < ConfTrkDCAzMaxF1Proton; + + // using EventCandidates = soa::Join; + using EventCandidates = aod::Collisions; + using ResoV0s = aod::V0Datas; + using PrimaryTrackCandidates = soa::Filtered>; + + void processF1ProtonReducedTable(EventCandidates::iterator const& collision, aod::BCsWithTimestamps const&, PrimaryTrackCandidates const& tracks, ResoV0s const& V0s) + { + bool keepEventF1Proton = false; + int numberF1 = 0; + // keep track of indices + std::vector PionIndex = {}; + std::vector KaonIndex = {}; + std::vector ProtonIndex = {}; + std::vector KshortPosDaughIndex = {}; + std::vector KshortNegDaughIndex = {}; + + ////// track indices to check share track in table + std::vector F1PionIndex = {}; + std::vector F1KaonIndex = {}; + std::vector F1ProtonIndex = {}; + std::vector F1KshortDaughterPositiveIndex = {}; + std::vector F1KshortDaughterNegativeIndex = {}; + + // keep charge of track + std::vector PionCharge = {}; + std::vector KaonCharge = {}; + std::vector ProtonCharge = {}; + std::vector ProtonChargeFinal = {}; + + // keep TPC PID of proton + std::vector ProtonTPCNsigma = {}; + std::vector ProtonTPCNsigmaFinal = {}; + + // keep TOF PID of proton + std::vector ProtonTOFNsigma = {}; + std::vector ProtonTOFNsigmaFinal = {}; + + // keep TOF Hit of proton + std::vector ProtonTOFHit = {}; + std::vector ProtonTOFHitFinal = {}; + + // keep kaon-kshort mass of f1resonance + std::vector f1kaonkshortmass = {}; + + // keep status of F1 signal unlike or wrong sign + std::vector f1signal = {}; + + // Prepare vectors for different species + std::vector protons, kaons, pions, kshorts, f1resonance, protonsfinal; + float kstar = 999.f; + + currentRunNumber = collision.bc_as().runNumber(); + auto bc = collision.bc_as(); + + if (isSelectedEvent(collision)) { + if (ConfUseManualPIDproton || ConfUseManualPIDkaon || ConfUseManualPIDpion) { + if (currentRunNumber != lastRunNumber) { + if (ConfUseManualPIDproton) { + BBProton = setValuesBB(ccdbApi, bc, ConfPIDBBProton); + BBAntiproton = setValuesBB(ccdbApi, bc, ConfPIDBBAntiProton); + } + if (ConfUseManualPIDpion) { + BBPion = setValuesBB(ccdbApi, bc, ConfPIDBBPion); + BBAntipion = setValuesBB(ccdbApi, bc, ConfPIDBBAntiPion); + } + if (ConfUseManualPIDkaon) { + BBKaon = setValuesBB(ccdbApi, bc, ConfPIDBBKaon); + BBAntikaon = setValuesBB(ccdbApi, bc, ConfPIDBBAntiKaon); + } + lastRunNumber = currentRunNumber; + } + } + + for (auto& track : tracks) { + + if (!isSelectedTrack(track)) + continue; + qaRegistry.fill(HIST("hDCAxy"), track.dcaXY()); + qaRegistry.fill(HIST("hDCAz"), track.dcaZ()); + qaRegistry.fill(HIST("hEta"), track.eta()); + qaRegistry.fill(HIST("hPhi"), track.phi()); + double nTPCSigmaP[3]{track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + double nTPCSigmaN[3]{track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + if (ConfUseManualPIDproton) { + auto bgScalingProton = 1 / massPr; // momentum scaling? + if (BBProton.size() == 6) + nTPCSigmaP[2] = updatePID(track, bgScalingProton, BBProton); + if (BBAntiproton.size() == 6) + nTPCSigmaN[2] = updatePID(track, bgScalingProton, BBAntiproton); + } + if (ConfUseManualPIDkaon) { + auto bgScalingKaon = 1 / massKa; // momentum scaling? + if (BBKaon.size() == 6) + nTPCSigmaP[1] = updatePID(track, bgScalingKaon, BBKaon); + if (BBAntikaon.size() == 6) + nTPCSigmaN[1] = updatePID(track, bgScalingKaon, BBAntikaon); + } + if (ConfUseManualPIDpion) { + auto bgScalingPion = 1 / massPi; // momentum scaling? + if (BBPion.size() == 6) + nTPCSigmaP[0] = updatePID(track, bgScalingPion, BBPion); + if (BBAntipion.size() == 6) + nTPCSigmaN[0] = updatePID(track, bgScalingPion, BBAntipion); + } + + if ((track.sign() > 0 && SelectionPID(track, strategyPIDPion, 0, nTPCSigmaP[0])) || (track.sign() < 0 && SelectionPID(track, strategyPIDPion, 0, nTPCSigmaN[0]))) { + ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), massPi); + pions.push_back(temp); + PionIndex.push_back(track.globalIndex()); + PionCharge.push_back(track.sign()); + if (track.sign() > 0) { + qaRegistry.fill(HIST("hNsigmaPtpionTPC"), nTPCSigmaP[0], track.pt()); + } + if (track.sign() < 0) { + qaRegistry.fill(HIST("hNsigmaPtpionTPC"), nTPCSigmaN[0], track.pt()); + } + if (track.hasTOF()) { + qaRegistry.fill(HIST("hNsigmaPtpionTOF"), track.tofNSigmaPi(), track.pt()); + } + } + + if ((track.pt() > cMinKaonPt && track.sign() > 0 && SelectionPID(track, strategyPIDKaon, 1, nTPCSigmaP[1])) || (track.pt() > cMinKaonPt && track.sign() < 0 && SelectionPID(track, strategyPIDKaon, 1, nTPCSigmaN[1]))) { + ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), massKa); + kaons.push_back(temp); + KaonIndex.push_back(track.globalIndex()); + KaonCharge.push_back(track.sign()); + if (track.sign() > 0) { + qaRegistry.fill(HIST("hNsigmaPtkaonTPC"), nTPCSigmaP[1], track.pt()); + } + if (track.sign() < 0) { + qaRegistry.fill(HIST("hNsigmaPtkaonTPC"), nTPCSigmaN[1], track.pt()); + } + if (track.hasTOF()) { + qaRegistry.fill(HIST("hNsigmaPtkaonTOF"), track.tofNSigmaKa(), track.pt()); + } + } + + if ((track.pt() < cMaxProtonPt && track.sign() > 0 && SelectionPID(track, strategyPIDProton, 2, nTPCSigmaP[2])) || (track.pt() < cMaxProtonPt && track.sign() < 0 && SelectionPID(track, strategyPIDProton, 2, nTPCSigmaN[2]))) { + ROOT::Math::PtEtaPhiMVector temp(track.pt(), track.eta(), track.phi(), massPr); + protons.push_back(temp); + ProtonIndex.push_back(track.globalIndex()); + ProtonCharge.push_back(track.sign()); + if (track.sign() > 0) { + qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), nTPCSigmaP[2], track.pt()); + ProtonTPCNsigma.push_back(nTPCSigmaP[2]); + } + if (track.sign() < 0) { + qaRegistry.fill(HIST("hNsigmaPtprotonTPC"), nTPCSigmaN[2], track.pt()); + ProtonTPCNsigma.push_back(nTPCSigmaN[2]); + } + if (track.hasTOF()) { + qaRegistry.fill(HIST("hNsigmaPtprotonTOF"), track.tofNSigmaPr(), track.pt()); + ProtonTOFNsigma.push_back(track.tofNSigmaPr()); + ProtonTOFHit.push_back(1); + } + if (!track.hasTOF()) { + ProtonTOFNsigma.push_back(999.0); + ProtonTOFHit.push_back(0); + } + } + } // track loop end + for (auto& v0 : V0s) { + + if (!SelectionV0(collision, v0)) { + continue; + } + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + double nTPCSigmaPos[1]{postrack.tpcNSigmaPi()}; + double nTPCSigmaNeg[1]{negtrack.tpcNSigmaPi()}; + if (ConfUseManualPIDdaughterPion) { + auto bgScalingPion = 1 / massPi; // momentum scaling? + if (BBPion.size() == 6) + nTPCSigmaPos[0] = updatePID(postrack, bgScalingPion, BBPion); + if (BBAntipion.size() == 6) + nTPCSigmaNeg[0] = updatePID(negtrack, bgScalingPion, BBAntipion); + } + if (!isSelectedV0Daughter(postrack, 1, nTPCSigmaPos[0])) { + continue; + } + if (!isSelectedV0Daughter(negtrack, -1, nTPCSigmaNeg[0])) { + continue; + } + qaRegistry.fill(HIST("hInvMassk0"), v0.mK0Short(), v0.pt()); + ROOT::Math::PtEtaPhiMVector temp(v0.pt(), v0.eta(), v0.phi(), massK0s); + kshorts.push_back(temp); + KshortPosDaughIndex.push_back(postrack.globalIndex()); + KshortNegDaughIndex.push_back(negtrack.globalIndex()); + } + + if (pions.size() != 0 && kaons.size() != 0 && kshorts.size() != 0) { + for (auto ipion = pions.begin(); ipion != pions.end(); ++ipion) { + for (auto ikaon = kaons.begin(); ikaon != kaons.end(); ++ikaon) { + auto i1 = std::distance(pions.begin(), ipion); + auto i2 = std::distance(kaons.begin(), ikaon); + if (PionIndex.at(i1) == KaonIndex.at(i2)) + continue; + for (auto ikshort = kshorts.begin(); ikshort != kshorts.end(); ++ikshort) { + auto i3 = std::distance(kshorts.begin(), ikshort); + if (PionIndex.at(i1) == KshortPosDaughIndex.at(i3)) + continue; + if (PionIndex.at(i1) == KshortNegDaughIndex.at(i3)) + continue; + KKs0Vector = kaons.at(i2) + kshorts.at(i3); + if (KKs0Vector.M() > cMaxMassKKs0) + continue; + F1Vector = KKs0Vector + pions.at(i1); + if (F1Vector.M() > cMaxMassF1) + continue; + if (F1Vector.Pt() < cMinF1Pt) + continue; + + // check if the pair is unlike or wrongsign + auto pairsign = 1; + if (PionCharge.at(i1) * KaonCharge.at(i2) > 0) { + qaRegistry.fill(HIST("hInvMassf1Like"), F1Vector.M(), F1Vector.Pt()); + pairsign = -1; + } + ROOT::Math::PtEtaPhiMVector temp(F1Vector.Pt(), F1Vector.Eta(), F1Vector.Phi(), F1Vector.M()); + f1resonance.push_back(temp); + f1signal.push_back(pairsign); + f1kaonkshortmass.push_back(KKs0Vector.M()); + F1PionIndex.push_back(PionIndex.at(i1)); + F1KaonIndex.push_back(KaonIndex.at(i2)); + F1KshortDaughterPositiveIndex.push_back(KshortPosDaughIndex.at(i3)); + F1KshortDaughterNegativeIndex.push_back(KshortNegDaughIndex.at(i3)); + + if (pairsign == 1) { + qaRegistry.fill(HIST("hInvMassf1"), F1Vector.M(), F1Vector.Pt()); + numberF1 = numberF1 + 1; + for (auto iproton = protons.begin(); iproton != protons.end(); ++iproton) { + auto i4 = std::distance(protons.begin(), iproton); + ProtonVectorDummy = protons.at(i4); + if (numberF1 == 1) { + //////////// Fill final proton information after pairing////////// + ROOT::Math::PtEtaPhiMVector temp(ProtonVectorDummy.Pt(), ProtonVectorDummy.Eta(), ProtonVectorDummy.Phi(), massPr); + protonsfinal.push_back(temp); // 4 vector + ProtonChargeFinal.push_back(ProtonCharge.at(i4)); // Charge + ProtonTOFHitFinal.push_back(ProtonTOFHit.at(i4)); // TOF Hit + ProtonTOFNsigmaFinal.push_back(ProtonTOFNsigma.at(i4)); // Nsigma TOF + ProtonTPCNsigmaFinal.push_back(ProtonTPCNsigma.at(i4)); // Nsigma TPC + F1ProtonIndex.push_back(ProtonIndex.at(i4)); // proton index for share track + } + + if ((ProtonIndex.at(i4) == PionIndex.at(i1)) || (ProtonIndex.at(i4) == KaonIndex.at(i2)) || (ProtonIndex.at(i4) == KshortPosDaughIndex.at(i3)) || (ProtonIndex.at(i4) == KshortNegDaughIndex.at(i3))) { + continue; + } + + kstar = getkstar(F1Vector, *iproton); + qaRegistry.fill(HIST("hkstarDist"), kstar); + if (kstar > cMaxRelMom) + continue; + qaRegistry.fill(HIST("hInvMassf1kstar"), F1Vector.M(), F1Vector.Pt(), kstar); + keepEventF1Proton = true; + } + } + } + } + } + } + } + qaRegistry.fill(HIST("hEventstat"), 0.5); + if (numberF1 > 0 && (f1resonance.size() == f1signal.size()) && (f1resonance.size() == f1kaonkshortmass.size())) { + qaRegistry.fill(HIST("hEventstat"), 1.5); + if (keepEventF1Proton) { + qaRegistry.fill(HIST("hEventstat"), 2.5); + auto eventspherocity = ComputeSpherocity(tracks, trackSphMin, trackSphDef); + /////////// Fill collision table/////////////// + reducedf1protonevents(bc.globalBC(), currentRunNumber, bc.timestamp(), collision.posZ(), collision.numContrib(), eventspherocity); + auto indexEvent = reducedf1protonevents.lastIndex(); + //// Fill track table for F1////////////////// + for (auto if1 = f1resonance.begin(); if1 != f1resonance.end(); ++if1) { + auto i5 = std::distance(f1resonance.begin(), if1); + F1VectorDummy = f1resonance.at(i5); + f1track(indexEvent, f1signal.at(i5), F1VectorDummy.Px(), F1VectorDummy.Py(), F1VectorDummy.Pz(), F1VectorDummy.M(), f1kaonkshortmass.at(i5), F1PionIndex.at(i5), F1KaonIndex.at(i5), F1KshortDaughterPositiveIndex.at(i5), F1KshortDaughterNegativeIndex.at(i5)); + } + //// Fill track table for proton////////////////// + for (auto iproton = protonsfinal.begin(); iproton != protonsfinal.end(); ++iproton) { + auto i6 = std::distance(protonsfinal.begin(), iproton); + ProtonVectorDummy2 = protonsfinal.at(i6); + protontrack(indexEvent, ProtonChargeFinal.at(i6), ProtonVectorDummy2.Px(), ProtonVectorDummy2.Py(), ProtonVectorDummy2.Pz(), ProtonTPCNsigmaFinal.at(i6), ProtonTOFHitFinal.at(i6), ProtonTOFNsigmaFinal.at(i6), F1ProtonIndex.at(i6)); + } + } + } + } + PROCESS_SWITCH(f1protonreducedtable, processF1ProtonReducedTable, "Process for create reduced table for f1-p analysis", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfg) +{ + return WorkflowSpec{adaptAnalysisTask(cfg)}; +} diff --git a/PWGLF/TableProducer/hStrangeCorrelationFilter.cxx b/PWGLF/TableProducer/hStrangeCorrelationFilter.cxx index 9149e8fd042..2ba170998c9 100644 --- a/PWGLF/TableProducer/hStrangeCorrelationFilter.cxx +++ b/PWGLF/TableProducer/hStrangeCorrelationFilter.cxx @@ -33,6 +33,8 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +#define bitcheck(var, nbit) ((var) & (1 << (nbit))) + struct hstrangecorrelationfilter { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -49,6 +51,8 @@ struct hstrangecorrelationfilter { // Track quality Configurable minTPCNCrossedRows{"minTPCNCrossedRows", 70, "Minimum TPC crossed rows"}; Configurable triggerRequireITS{"triggerRequireITS", true, "require ITS signal in trigger tracks"}; + Configurable triggerMaxTPCSharedClusters{"triggerMaxTPCSharedClusters", 200, "maximum number of shared TPC clusters (inclusive)"}; + Configurable triggerRequireL0{"triggerRequireL0", false, "require ITS L0 cluster for trigger"}; // Associated particle selections in phase space Configurable assocEtaMin{"assocEtaCutMin", -0.8, "triggeretamin"}; @@ -121,6 +125,8 @@ struct hstrangecorrelationfilter { HistogramRegistry registry{ "registry", {}}; + using V0LinkedTagged = soa::Join; + using CascadesLinkedTagged = soa::Join; using DauTracks = soa::Join; // using IDTracks= soa::Join; // prepared for Bayesian PID using IDTracks = soa::Join; @@ -186,6 +192,12 @@ struct hstrangecorrelationfilter { if (!track.hasITS() && triggerRequireITS) { continue; // skip, doesn't have ITS signal (skips lots of TPC-only!) } + if (track.tpcNClsShared() > triggerMaxTPCSharedClusters) { + continue; // skip, has shared clusters + } + if (!(bitcheck(track.itsClusterMap(), 0)) && triggerRequireL0) { + continue; // skip, doesn't have cluster in ITS L0 + } triggerTrack( track.collisionId(), track.globalIndex()); @@ -257,7 +269,7 @@ struct hstrangecorrelationfilter { } } - void processV0s(soa::Join::iterator const& collision, DauTracks const&, soa::Filtered const& V0s, aod::V0sLinked const&) + void processV0s(soa::Join::iterator const& collision, DauTracks const&, soa::Filtered const& V0s, V0LinkedTagged const&) { // Perform basic event selection if (!collision.sel8()) { @@ -280,6 +292,7 @@ struct hstrangecorrelationfilter { auto posdau = v0.posTrack_as(); auto negdau = v0.negTrack_as(); + auto origV0entry = v0.v0_as(); // retrieve tags if (negdau.tpcNClsCrossedRows() < minTPCNCrossedRows) continue; @@ -290,12 +303,12 @@ struct hstrangecorrelationfilter { compatibleK0Short = true; } if (TMath::Abs(posdau.tpcNSigmaPr()) < strangedEdxNSigma && TMath::Abs(negdau.tpcNSigmaPi()) < strangedEdxNSigma) { - if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < lambdaCospa) { + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > lambdaCospa) { compatibleLambda = true; } } if (TMath::Abs(posdau.tpcNSigmaPi()) < strangedEdxNSigma && TMath::Abs(negdau.tpcNSigmaPr()) < strangedEdxNSigma) { - if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < lambdaCospa) { + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > lambdaCospa) { compatibleAntiLambda = true; } } @@ -364,11 +377,14 @@ struct hstrangecorrelationfilter { (compatibleLambda && massRegLambda > 0 && massRegLambda < 4) || (compatibleAntiLambda && massRegAntiLambda > 0 && massRegAntiLambda < 4)) // end major condition check ) { - assocV0(v0.collisionId(), v0.globalIndex(), compatibleK0Short, compatibleLambda, compatibleAntiLambda, massRegK0Short, massRegLambda, massRegAntiLambda); + assocV0(v0.collisionId(), v0.globalIndex(), + compatibleK0Short, compatibleLambda, compatibleAntiLambda, + origV0entry.isTrueK0Short(), origV0entry.isTrueLambda(), origV0entry.isTrueAntiLambda(), + massRegK0Short, massRegLambda, massRegAntiLambda); } } } - void processCascades(soa::Join::iterator const& collision, DauTracks const&, soa::Filtered const& V0s, soa::Filtered const& Cascades, aod::V0sLinked const&) + void processCascades(soa::Join::iterator const& collision, DauTracks const&, soa::Filtered const& V0s, soa::Filtered const& Cascades, aod::V0sLinked const&, CascadesLinkedTagged const&) { // Perform basic event selection if (!collision.sel8()) { @@ -389,6 +405,7 @@ struct hstrangecorrelationfilter { auto bachTrackCast = casc.bachelor_as(); auto posTrackCast = v0data.posTrack_as(); auto negTrackCast = v0data.negTrack_as(); + auto origCascadeEntry = casc.cascade_as(); // minimum TPC crossed rows if (bachTrackCast.tpcNClsCrossedRows() < minTPCNCrossedRows) @@ -465,7 +482,11 @@ struct hstrangecorrelationfilter { ((compatibleXiMinus || compatibleXiPlus) && massRegXi > 0 && massRegXi < 4) || ((compatibleOmegaMinus || compatibleOmegaPlus) && massRegOmega > 0 && massRegOmega < 4)) // end major condition check ) { - assocCascades(casc.collisionId(), casc.globalIndex(), compatibleXiMinus, compatibleXiPlus, compatibleOmegaMinus, compatibleOmegaPlus, massRegXi, massRegOmega); + assocCascades(casc.collisionId(), casc.globalIndex(), + compatibleXiMinus, compatibleXiPlus, compatibleOmegaMinus, compatibleOmegaPlus, + origCascadeEntry.isTrueXiMinus(), origCascadeEntry.isTrueXiPlus(), + origCascadeEntry.isTrueOmegaMinus(), origCascadeEntry.isTrueOmegaPlus(), + massRegXi, massRegOmega); } } } diff --git a/PWGLF/TableProducer/hyperRecoTask.cxx b/PWGLF/TableProducer/hyperRecoTask.cxx index 04d07d4f1ab..84306da7ad3 100644 --- a/PWGLF/TableProducer/hyperRecoTask.cxx +++ b/PWGLF/TableProducer/hyperRecoTask.cxx @@ -56,27 +56,32 @@ std::shared_ptr hIsMatterGenTwoBody; } // namespace struct hyperCandidate { - float recoPt() const { return std::hypot(mom[0], mom[1]); } - float recoPhi() const { return std::atan2(mom[1], mom[0]); } - float recoEta() const { return std::asinh(mom[2] / recoPt()); } + float recoPtHe3() const { return std::hypot(momHe3[0], momHe3[1]); } + float recoPhiHe3() const { return std::atan2(momHe3[1], momHe3[0]); } + float recoEtaHe3() const { return std::asinh(momHe3[2] / recoPtHe3()); } + float recoPtPi() const { return std::hypot(momPi[0], momPi[1]); } + float recoPhiPi() const { return std::atan2(momPi[1], momPi[0]); } + float recoEtaPi() const { return std::asinh(momPi[2] / recoPtPi()); } float genPt() const { return std::hypot(gMom[0], gMom[1]); } + float genPtHe3() const { return std::hypot(gMomHe3[0], gMomHe3[1]); } float genPhi() const { return std::atan2(gMom[1], gMom[0]); } float genEta() const { return std::asinh(gMom[2] / genPt()); } int posTrackID; int negTrackID; - float massH3L = -10; - float massH4L = -10; float dcaV0dau = -10; float cosPA = -10; float nSigmaHe3 = -10; float he3DCAXY = -10; float piDCAXY = -10; - float momHe3 = -10.f; - float momPi = -10.f; - std::array mom; + float momHe3TPC = -10.f; + float momPiTPC = -10.f; + std::array momHe3; + std::array momPi; + std::array primVtx; std::array decVtx; std::array gMom; + std::array gMomHe3; std::array gDecVtx; uint16_t tpcSignalHe3 = 0u; uint16_t tpcSignalPi = 0u; @@ -281,8 +286,8 @@ struct hyperRecoTask { hypCand.tpcSignalHe3 = hypCand.isMatter ? posTrack.tpcSignal() : negTrack.tpcSignal(); hypCand.nTPCClustersPi = !hypCand.isMatter ? posTrack.tpcNClsFound() : negTrack.tpcNClsFound(); hypCand.tpcSignalPi = !hypCand.isMatter ? posTrack.tpcSignal() : negTrack.tpcSignal(); - hypCand.momHe3 = hypCand.isMatter ? posTrack.tpcInnerParam() : negTrack.tpcInnerParam(); - hypCand.momPi = !hypCand.isMatter ? posTrack.tpcInnerParam() : negTrack.tpcInnerParam(); + hypCand.momHe3TPC = hypCand.isMatter ? posTrack.tpcInnerParam() : negTrack.tpcInnerParam(); + hypCand.momPiTPC = !hypCand.isMatter ? posTrack.tpcInnerParam() : negTrack.tpcInnerParam(); auto posTrackCov = getTrackParCov(posTrack); auto negTrackCov = getTrackParCov(negTrack); @@ -300,63 +305,52 @@ struct hyperRecoTask { auto& hePropTrack = hypCand.isMatter ? fitter.getTrack(0) : fitter.getTrack(1); auto& piPropTrack = hypCand.isMatter ? fitter.getTrack(1) : fitter.getTrack(0); - - std::array heTrackP; - std::array piTrackP; - - hePropTrack.getPxPyPzGlo(heTrackP); - piPropTrack.getPxPyPzGlo(piTrackP); + hePropTrack.getPxPyPzGlo(hypCand.momHe3); + piPropTrack.getPxPyPzGlo(hypCand.momPi); // he momentum has to be multiplied by 2 (charge) for (int i = 0; i < 3; i++) { - heTrackP[i] *= 2; + hypCand.momHe3[i] *= 2; } - float heP2 = heTrackP[0] * heTrackP[0] + heTrackP[1] * heTrackP[1] + heTrackP[2] * heTrackP[2]; - float piP2 = piTrackP[0] * piTrackP[0] + piTrackP[1] * piTrackP[1] + piTrackP[2] * piTrackP[2]; - + float heP2 = hypCand.momHe3[0] * hypCand.momHe3[0] + hypCand.momHe3[1] * hypCand.momHe3[1] + hypCand.momHe3[2] * hypCand.momHe3[2]; + float piP2 = hypCand.momPi[0] * hypCand.momPi[0] + hypCand.momPi[1] * hypCand.momPi[1] + hypCand.momPi[2] * hypCand.momPi[2]; float he3E = std::sqrt(heP2 + he3Mass * he3Mass); float he4E = std::sqrt(heP2 + he4Mass * he4Mass); float piE = std::sqrt(piP2 + piMass * piMass); - float h3lE = he3E + piE; float h4lE = he4E + piE; - auto posPrimVtx = array{collision.posX(), collision.posY(), collision.posZ()}; - + hypCand.primVtx = array{collision.posX(), collision.posY(), collision.posZ()}; + std::array hypMom; const auto& vtx = fitter.getPCACandidate(); for (int i = 0; i < 3; i++) { hypCand.decVtx[i] = vtx[i]; - hypCand.mom[i] = heTrackP[i] + piTrackP[i]; + hypMom[i] = hypCand.momHe3[i] + hypCand.momPi[i]; } - hypCand.massH3L = std::sqrt(h3lE * h3lE - hypCand.mom[0] * hypCand.mom[0] - hypCand.mom[1] * hypCand.mom[1] - hypCand.mom[2] * hypCand.mom[2]); - hypCand.massH4L = std::sqrt(h4lE * h4lE - hypCand.mom[0] * hypCand.mom[0] - hypCand.mom[1] * hypCand.mom[1] - hypCand.mom[2] * hypCand.mom[2]); - + float massH3L = std::sqrt(h3lE * h3lE - hypMom[0] * hypMom[0] - hypMom[1] * hypMom[1] - hypMom[2] * hypMom[2]); + float massH4L = std::sqrt(h4lE * h4lE - hypMom[0] * hypMom[0] - hypMom[1] * hypMom[1] - hypMom[2] * hypMom[2]); bool isHypMass = false; - - if (hypCand.massH3L > o2::constants::physics::MassHyperTriton - masswidth && hypCand.massH3L < o2::constants::physics::MassHyperTriton + masswidth) + if (massH3L > o2::constants::physics::MassHyperTriton - masswidth && massH3L < o2::constants::physics::MassHyperTriton + masswidth) isHypMass = true; - - if (hypCand.massH4L > o2::constants::physics::MassHyperhydrog4 - masswidth && hypCand.massH4L < o2::constants::physics::MassHyperhydrog4 + masswidth) + if (massH4L > o2::constants::physics::MassHyperhydrog4 - masswidth && massH4L < o2::constants::physics::MassHyperhydrog4 + masswidth) isHypMass = true; - if (!isHypMass) continue; hypCand.dcaV0dau = std::sqrt(fitter.getChi2AtPCACandidate()); - if (hypCand.dcaV0dau > dcav0dau) { continue; } - hypCand.cosPA = RecoDecay::cpa(posPrimVtx, array{hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2]}, array{hypCand.mom[0], hypCand.mom[1], hypCand.mom[2]}); - if (hypCand.cosPA < v0cospa) { + double cosPA = RecoDecay::cpa(hypCand.primVtx, array{hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2]}, array{hypMom[0], hypMom[1], hypMom[2]}); + if (cosPA < v0cospa) { continue; } for (int i = 0; i < 3; i++) { - hypCand.decVtx[i] = hypCand.decVtx[i] - posPrimVtx[i]; + hypCand.decVtx[i] = hypCand.decVtx[i] - hypCand.primVtx[i]; } // if survived all selections, propagate decay daughters to PV @@ -403,10 +397,10 @@ struct hyperRecoTask { continue; auto posPrimVtx = array{posMother.vx(), posMother.vy(), posMother.vz()}; auto secVtx = array{mcTrackPos.vx(), mcTrackPos.vy(), mcTrackPos.vz()}; - auto posMom = array{posMother.px(), posMother.py(), posMother.pz()}; + hypCand.gMom = array{posMother.px(), posMother.py(), posMother.pz()}; + hypCand.gMomHe3 = mcTrackPos.pdgCode() == heDauPdg ? array{mcTrackPos.px(), mcTrackPos.py(), mcTrackPos.pz()} : array{mcTrackNeg.px(), mcTrackNeg.py(), mcTrackNeg.pz()}; for (int i = 0; i < 3; i++) { hypCand.gDecVtx[i] = secVtx[i] - posPrimVtx[i]; - hypCand.gMom[i] = posMom[i]; } hypCand.isSignal = true; hypCand.pdgCode = posMother.pdgCode(); @@ -424,10 +418,12 @@ struct hyperRecoTask { std::array secVtx; std::array primVtx = {mcPart.vx(), mcPart.vy(), mcPart.vz()}; std::array momMother = {mcPart.px(), mcPart.py(), mcPart.pz()}; + std::array momHe3; bool isHeFound = false; for (auto& mcDaught : mcPart.daughters_as()) { if (std::abs(mcDaught.pdgCode()) == heDauPdg) { secVtx = {mcDaught.vx(), mcDaught.vy(), mcDaught.vz()}; + momHe3 = {mcDaught.px(), mcDaught.py(), mcDaught.pz()}; isHeFound = true; break; } @@ -454,6 +450,7 @@ struct hyperRecoTask { for (int i = 0; i < 3; i++) { hypCand.gDecVtx[i] = secVtx[i] - primVtx[i]; hypCand.gMom[i] = momMother[i]; + hypCand.gMomHe3[i] = momHe3[i]; } hypCand.posTrackID = -1; hypCand.negTrackID = -1; @@ -492,12 +489,14 @@ struct hyperRecoTask { } for (auto& hypCand : hyperCandidates) { - outputDataTable(hypCand.isMatter, hypCand.recoPt(), hypCand.recoPhi(), hypCand.recoEta(), - hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.massH3L, hypCand.massH4L, - hypCand.dcaV0dau, hypCand.cosPA, hypCand.nSigmaHe3, - hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.momHe3, - hypCand.momPi, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, - hypCand.he3DCAXY, hypCand.piDCAXY); + outputDataTable(hypCand.isMatter, + hypCand.recoPtHe3(), hypCand.recoPhiHe3(), hypCand.recoEtaHe3(), + hypCand.recoPtPi(), hypCand.recoPhiPi(), hypCand.recoEtaPi(), + hypCand.primVtx[0], hypCand.primVtx[1], hypCand.primVtx[2], + hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], + hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, + hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, + hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi); } } PROCESS_SWITCH(hyperRecoTask, processData, "Data analysis", true); @@ -532,13 +531,15 @@ struct hyperRecoTask { if (!hypCand.isSignal && mcSignalOnly) continue; int chargeFactor = -1 + 2 * (hypCand.pdgCode > 0); - outputMCTable(hypCand.isMatter, hypCand.recoPt(), hypCand.recoPhi(), hypCand.recoEta(), - hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.massH3L, hypCand.massH4L, - hypCand.dcaV0dau, hypCand.cosPA, hypCand.nSigmaHe3, - hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.momHe3, - hypCand.momPi, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, - hypCand.he3DCAXY, hypCand.piDCAXY, - chargeFactor * hypCand.genPt(), hypCand.genPhi(), hypCand.genEta(), + outputMCTable(hypCand.isMatter, + hypCand.recoPtHe3(), hypCand.recoPhiHe3(), hypCand.recoEtaHe3(), + hypCand.recoPtPi(), hypCand.recoPhiPi(), hypCand.recoEtaPi(), + hypCand.primVtx[0], hypCand.primVtx[1], hypCand.primVtx[2], + hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], + hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, + hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, + hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, + chargeFactor * hypCand.genPt(), hypCand.genPhi(), hypCand.genEta(), hypCand.genPtHe3(), hypCand.gDecVtx[0], hypCand.gDecVtx[1], hypCand.gDecVtx[2], hypCand.isReco, hypCand.isSignal); } } diff --git a/PWGLF/TableProducer/hypertriton3bodybuilder.cxx b/PWGLF/TableProducer/hypertriton3bodybuilder.cxx new file mode 100644 index 00000000000..6ae18d9a4c2 --- /dev/null +++ b/PWGLF/TableProducer/hypertriton3bodybuilder.cxx @@ -0,0 +1,468 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Builder task for hypertriton 3-body decay reconstruction +// author: yuanzhe.wang@cern.ch + +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "DCAFitter/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/Vtx3BodyTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" + +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsTPC/BetheBlochAleph.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +using FullTracksExtIU = soa::Join; +using FullTracksExtMCIU = soa::Join; + +using LabeledTracks = soa::Join; + +struct hypertriton3bodyBuilder { + + Produces vtx3bodydata; + Service ccdb; + + // Configurables + Configurable d_UseAbsDCA{"d_UseAbsDCA", true, "Use Abs DCAs"}; + + HistogramRegistry registry{ + "registry", + { + {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, + {"hVtx3BodyCounter", "hVtx3BodyCounter", {HistType::kTH1F, {{7, 0.0f, 7.0f}}}}, + }, + }; + + // Selection criteria + Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; + Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; + Configurable minCosPA3body{"minCosPA3body", 0.8, "minCosPA3body"}; + Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; + + Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; + // CCDB options + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + + int mRunNumber; + float d_bz; + float maxSnp; // max sine phi for propagation + float maxStep; // max step size (cm) for propagation + o2::base::MatLayerCylSet* lut = nullptr; + o2::vertexing::DCAFitterN<3> fitter3body; + + void init(InitContext& context) + { + mRunNumber = 0; + d_bz = 0; + maxSnp = 0.85f; // could be changed later + maxStep = 2.00f; // could be changed later + fitter3body.setPropagateToPCA(true); + fitter3body.setMaxR(200.); //->maxRIni3body + fitter3body.setMinParamChange(1e-3); + fitter3body.setMinRelChi2Change(0.9); + fitter3body.setMaxDZIni(1e9); + fitter3body.setMaxChi2(1e9); + fitter3body.setUseAbsDCA(d_UseAbsDCA); + + // Material correction in the DCA fitter + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(1, "Total"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(2, "CollisionID"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(3, "TPCNcls"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(4, "HasSV"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(5, "HasSVAfterCorr"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(6, "DcaVtxDau"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(7, "CosPA"); + + // Material correction in the DCA fitter + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + if (useMatCorrType == 1) { + LOGF(info, "TGeo correction requested, loading geometry"); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; + } + if (useMatCorrType == 2) { + LOGF(info, "LUT correction requested, loading LUT"); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + } + fitter3body.setMatCorrType(matCorr); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + fitter3body.setBz(d_bz); + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + o2::parameters::GRPMagField* grpmag = 0x0; + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = bc.runNumber(); + // Set magnetic field value once known + fitter3body.setBz(d_bz); + + if (useMatCorrType == 2) { + // setMatLUT only after magfield has been initalized + // (setMatLUT has implicit and problematic init field call if not) + o2::base::Propagator::Instance()->setMatLUT(lut); + } + } + //------------------------------------------------------------------ + + void process(aod::Collision const& collision, FullTracksExtIU const& tracks, aod::Decay3Bodys const& decay3bodys, aod::BCsWithTimestamps const&) + { + + auto bc = collision.bc_as(); + initCCDB(bc); + registry.fill(HIST("hEventCounter"), 0.5); + + for (auto& vtx3body : decay3bodys) { + + registry.fill(HIST("hVtx3BodyCounter"), 0.5); + + auto t0 = vtx3body.track0_as(); + auto t1 = vtx3body.track1_as(); + auto t2 = vtx3body.track2_as(); + if (t0.collisionId() != t1.collisionId() || t0.collisionId() != t2.collisionId()) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 1.5); + + if (t0.tpcNClsCrossedRows() < mincrossedrows && t1.tpcNClsCrossedRows() < mincrossedrows && t2.tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 2.5); + + auto Track0 = getTrackParCov(t0); + auto Track1 = getTrackParCov(t1); + auto Track2 = getTrackParCov(t2); + int n3bodyVtx = fitter3body.process(Track0, Track1, Track2); + if (n3bodyVtx == 0) { // discard this pair + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 3.5); + + double finalXTrack0 = fitter3body.getTrack(0).getX(); + double finalXTrack1 = fitter3body.getTrack(1).getX(); + double finalXTrack2 = fitter3body.getTrack(2).getX(); + + // Rotate to desired alpha + Track0.rotateParam(fitter3body.getTrack(0).getAlpha()); + Track1.rotateParam(fitter3body.getTrack(1).getAlpha()); + Track2.rotateParam(fitter3body.getTrack(2).getAlpha()); + + // Retry closer to minimum with material corrections + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + if (useMatCorrType == 1) + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; + if (useMatCorrType == 2) + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + + o2::base::Propagator::Instance()->propagateToX(Track0, finalXTrack0, d_bz, maxSnp, maxStep, matCorr); + o2::base::Propagator::Instance()->propagateToX(Track1, finalXTrack1, d_bz, maxSnp, maxStep, matCorr); + o2::base::Propagator::Instance()->propagateToX(Track2, finalXTrack2, d_bz, maxSnp, maxStep, matCorr); + + n3bodyVtx = fitter3body.process(Track0, Track1, Track2); + if (n3bodyVtx == 0) { // discard this pair + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 4.5); + + std::array pos = {0.}; + const auto& vtxXYZ = fitter3body.getPCACandidate(); + for (int i = 0; i < 3; i++) { + pos[i] = vtxXYZ[i]; + } + + std::array p0 = {0.}, p1 = {0.}, p2{0.}; + Track0.getPxPyPzGlo(p0); + Track1.getPxPyPzGlo(p1); + Track2.getPxPyPzGlo(p2); + std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; + + if (fitter3body.getChi2AtPCACandidate() > dcavtxdau) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 5.5); + + float VtxcosPA = RecoDecay::cpa(array{collision.posX(), collision.posY(), collision.posZ()}, array{pos[0], pos[1], pos[2]}, array{p3B[0], p3B[1], p3B[2]}); + if (VtxcosPA < minCosPA3body) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 6.5); + + vtx3bodydata( + t0.globalIndex(), t1.globalIndex(), t2.globalIndex(), collision.globalIndex(), vtx3body.globalIndex(), + pos[0], pos[1], pos[2], + p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], + fitter3body.getChi2AtPCACandidate(), + t0.dcaXY(), t1.dcaXY(), t2.dcaXY()); + } + } +}; + +struct hypertriton3bodyDataLinkBuilder { + Produces vtxdataLink; + + void init(InitContext const&) {} + + void process(aod::Decay3Bodys const& decay3bodytable, aod::Vtx3BodyDatas const& vtxdatatable) + { + std::vector lIndices; + lIndices.reserve(decay3bodytable.size()); + for (int ii = 0; ii < decay3bodytable.size(); ii++) + lIndices[ii] = -1; + for (auto& vtxdata : vtxdatatable) { + lIndices[vtxdata.decay3bodyId()] = vtxdata.globalIndex(); + } + for (int ii = 0; ii < decay3bodytable.size(); ii++) { + vtxdataLink(lIndices[ii]); + } + } +}; + +struct hypertriton3bodyLabelBuilder { + + Produces vtxlabels; + Produces vtxfulllabels; + + // for bookkeeping purposes: how many V0s come from same mother etc + HistogramRegistry registry{ + "registry", + { + {"hLabelCounter", "hLabelCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, + {"hHypertritonCounter", "hHypertritonCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, + {"hPIDCounter", "hPIDCounter", {HistType::kTH1F, {{6, 0.0f, 6.0f}}}}, + {"hHypertritonMCPt", "hHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, + {"hAntiHypertritonMCPt", "hAntiHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, + {"hHypertritonMCMass", "hHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f}}}}, + {"hAntiHypertritonMCMass", "hAntiHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f}}}}, + {"h3dTotalTrueHypertriton", "h3dTotalTrueHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + }, + }; + + void init(InitContext const&) + { + registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(1, "Total"); + registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(2, "Same MotherParticle"); + registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(3, "True H3L"); + registry.get(HIST("hHypertritonCounter"))->GetXaxis()->SetBinLabel(1, "H3L"); + registry.get(HIST("hHypertritonCounter"))->GetXaxis()->SetBinLabel(2, "H3L daughters pass PID"); + registry.get(HIST("hHypertritonCounter"))->GetXaxis()->SetBinLabel(3, "#bar{H3L}"); + registry.get(HIST("hHypertritonCounter"))->GetXaxis()->SetBinLabel(4, "#bar{H3L} daughters pass PID"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(1, "H3L Proton PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(2, "H3L Pion PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(3, "H3L Deuteron PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(4, "#bar{H3L} Proton PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(5, "#bar{H3L} Pion PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(6, "#bar{H3L} Deuteron PID > 5"); + } + + Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; + + void processDoNotBuildLabels(aod::Collisions::iterator const& collision) + { + // dummy process function - should not be required in the future + } + PROCESS_SWITCH(hypertriton3bodyLabelBuilder, processDoNotBuildLabels, "Do not produce MC label tables", true); + + void processBuildLabels(aod::Collisions::iterator const& collision, aod::Decay3BodysLinked const& decay3bodys, aod::Vtx3BodyDatas const& vtx3bodydatas, LabeledTracks const&, aod::McParticles const& particlesMC) + { + std::vector lIndices; + lIndices.reserve(vtx3bodydatas.size()); + for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { + lIndices[ii] = -1; + } + + for (auto& decay3body : decay3bodys) { + + int lLabel = -1; + int lPDG = -1; + float lPt = -1; + double MClifetime = -1; + bool is3bodyDecay = false; + int lGlobalIndex = -1; + + auto lTrack0 = decay3body.track0_as(); + auto lTrack1 = decay3body.track1_as(); + auto lTrack2 = decay3body.track2_as(); + registry.fill(HIST("hLabelCounter"), 0.5); + + // Association check + // There might be smarter ways of doing this in the future + if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { + vtxfulllabels(-1); + continue; + } + auto lMCTrack0 = lTrack0.mcParticle_as(); + auto lMCTrack1 = lTrack1.mcParticle_as(); + auto lMCTrack2 = lTrack2.mcParticle_as(); + if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { + vtxfulllabels(-1); + continue; + } + + for (auto& lMother0 : lMCTrack0.mothers_as()) { + for (auto& lMother1 : lMCTrack1.mothers_as()) { + for (auto& lMother2 : lMCTrack2.mothers_as()) { + if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { + lGlobalIndex = lMother1.globalIndex(); + lPt = lMother1.pt(); + lPDG = lMother1.pdgCode(); + MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); + is3bodyDecay = true; // vtxs with the same mother + } + } + } + } // end association check + if (!is3bodyDecay) { + vtxfulllabels(-1); + continue; + } + registry.fill(HIST("hLabelCounter"), 1.5); + + // Intended for cross-checks only + // N.B. no rapidity cut! + if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { + lLabel = lGlobalIndex; + double hypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); + registry.fill(HIST("hLabelCounter"), 2.5); + registry.fill(HIST("hHypertritonCounter"), 0.5); + registry.fill(HIST("hHypertritonMCPt"), lPt); + registry.fill(HIST("hHypertritonMCMass"), hypertritonMCMass); + registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, hypertritonMCMass); + if (TMath::Abs(lTrack0.tpcNSigmaPr()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 0.5); + } + if (TMath::Abs(lTrack1.tpcNSigmaPi()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 1.5); + } + if (TMath::Abs(lTrack2.tpcNSigmaDe()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 2.5); + } + if (TMath::Abs(lTrack0.tpcNSigmaPr()) < TpcPidNsigmaCut && TMath::Abs(lTrack1.tpcNSigmaPi()) < TpcPidNsigmaCut && TMath::Abs(lTrack2.tpcNSigmaDe()) < TpcPidNsigmaCut) { + registry.fill(HIST("hHypertritonCounter"), 1.5); + } + } + if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { + lLabel = lGlobalIndex; + double antiHypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); + registry.fill(HIST("hLabelCounter"), 2.5); + registry.fill(HIST("hHypertritonCounter"), 2.5); + registry.fill(HIST("hAntiHypertritonMCPt"), lPt); + registry.fill(HIST("hAntiHypertritonMCMass"), antiHypertritonMCMass); + registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, antiHypertritonMCMass); + if (TMath::Abs(lTrack0.tpcNSigmaPi()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 4.5); + } + if (TMath::Abs(lTrack1.tpcNSigmaPr()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 3.5); + } + if (TMath::Abs(lTrack2.tpcNSigmaDe()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 5.5); + } + if (TMath::Abs(lTrack0.tpcNSigmaPi()) < TpcPidNsigmaCut && TMath::Abs(lTrack1.tpcNSigmaPr()) < TpcPidNsigmaCut && TMath::Abs(lTrack2.tpcNSigmaDe()) < TpcPidNsigmaCut) { + registry.fill(HIST("hHypertritonCounter"), 3.5); + } + } + + // Construct label table, only true hypertriton and true daughters with a specified order is labeled + // for matter: track0->p, track1->pi, track2->d + // for antimatter: track0->pi, track1->p, track2->d + vtxfulllabels(lLabel); + if (decay3body.vtx3BodyDataId() != -1) { + lIndices[decay3body.vtx3BodyDataId()] = lLabel; + } + } + for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { + vtxlabels(lIndices[ii]); + } + } + PROCESS_SWITCH(hypertriton3bodyLabelBuilder, processBuildLabels, "Produce MC label tables", false); +}; + +struct hypertriton3bodyInitializer { + Spawns vtx3bodydatas; + void init(InitContext const&) {} +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGLF/TableProducer/hypertriton3bodyfinder.cxx b/PWGLF/TableProducer/hypertriton3bodyfinder.cxx new file mode 100644 index 00000000000..98227ef20f8 --- /dev/null +++ b/PWGLF/TableProducer/hypertriton3bodyfinder.cxx @@ -0,0 +1,1045 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// This 3-body method is not recommended due to high cost of computing resources +// author: yuanzhe.wang@cern.ch + +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "DCAFitter/DCAFitterN.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/Vtx3BodyTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "EventFiltering/filterTables.h" + +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +using FullTracksExtIU = soa::Join; +using FullTracksExtMCIU = soa::Join; + +using LabeledTracks = soa::Join; + +namespace o2::aod +{ +namespace v0goodpostrack +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +} // namespace v0goodpostrack +DECLARE_SOA_TABLE(V0GoodPosTracks, "AOD", "V0GOODPOSTRACKS", o2::soa::Index<>, v0goodpostrack::GoodTrackId, v0goodpostrack::CollisionId, v0goodpostrack::DCAXY); +namespace v0goodnegtrack +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +} // namespace v0goodnegtrack +DECLARE_SOA_TABLE(V0GoodNegTracks, "AOD", "V0GOODNEGTRACKS", o2::soa::Index<>, v0goodnegtrack::GoodTrackId, v0goodnegtrack::CollisionId, v0goodnegtrack::DCAXY); +namespace v0goodtrack +{ +DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); +DECLARE_SOA_COLUMN(DCAXY, dcaXY, float); +} // namespace v0goodtrack +DECLARE_SOA_TABLE(V0GoodTracks, "AOD", "V0GOODTRACKS", o2::soa::Index<>, v0goodtrack::GoodTrackId, v0goodtrack::CollisionId, v0goodtrack::DCAXY); +} // namespace o2::aod + +struct trackprefilter { + HistogramRegistry registry{ + "registry", + { + {"hCrossedRows", "hCrossedRows", {HistType::kTH1F, {{50, 0.0f, 200.0f}}}}, + {"hGoodTrackCount", "hGoodTrackCount", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, + {"hGoodPosTrackCount", "hGoodPosTrackCount", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, + {"hGoodNegTrackCount", "hGoodNegTrackCount", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, + }, + }; + + // change the dca cut for helium3 + Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; + Configurable tpcrefit{"tpcrefit", 0, "demand TPC refit"}; + + Produces v0GoodPosTracks; + Produces v0GoodNegTracks; + Produces v0GoodTracks; + + void process(aod::Collision const& collision, + FullTracksExtIU const& tracks) + { + for (auto& t0 : tracks) { + registry.fill(HIST("hGoodTrackCount"), 0.5); + registry.fill(HIST("hCrossedRows"), t0.tpcNClsCrossedRows()); + if (tpcrefit) { + if (!(t0.trackType() & o2::aod::track::TPCrefit)) { + continue; // TPC refit + } + } + registry.fill(HIST("hGoodTrackCount"), 1.5); + if (t0.tpcNClsCrossedRows() < mincrossedrows) { + continue; + } + registry.fill(HIST("hGoodTrackCount"), 2.5); + if (t0.signed1Pt() > 0.0f) { + v0GoodPosTracks(t0.globalIndex(), collision.globalIndex(), t0.dcaXY()); + registry.fill(HIST("hGoodPosTrackCount"), 0.5); + registry.fill(HIST("hGoodTrackCount"), 3.5); + } + if (t0.signed1Pt() < 0.0f) { + v0GoodNegTracks(t0.globalIndex(), collision.globalIndex(), t0.dcaXY()); + registry.fill(HIST("hGoodNegTrackCount"), 0.5); + registry.fill(HIST("hGoodTrackCount"), 3.5); + } + v0GoodTracks(t0.globalIndex(), collision.globalIndex(), t0.dcaXY()); + } + } +}; + +struct hypertriton3bodyFinder { + + Produces vtx3bodydata; + Service ccdb; + + // Configurables + Configurable UseCFFilterInMC{"UseCFFilterInMC", false, "Use CFFilter with MC check"}; + + Configurable d_UseAbsDCA{"d_UseAbsDCA", true, "Use Abs DCAs"}; + Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; + + // Selection criteria + Configurable minR2ToMeanVertex = {"minR2ToMeanVertex", 0.5 * 0.5, ""}; ///< min radial distance of V0 from beam line (mean vertex) //Q: Does this cut need to be removed? + + Configurable causalityRTolerance = {"causalityRTolerance", 1., ""}; ///< V0 radius cannot exceed its contributors minR by more than this value + Configurable maxV0ToProngsRDiff = {"maxV0ToProngsRDiff", 50., ""}; ///< V0 radius cannot be lower than this ammount wrt minR of contributors + Configurable minPt2V0 = {"minPt2V0", 0.5 * 0.5, ""}; ///< v0 minimum pT + Configurable maxTgl2V0 = {"maxTgl2V0", 2. * 2., ""}; ///< maximum tgLambda of V0 + Configurable maxDCAXY2ToMeanVertex3bodyV0 = {"maxDCAXY2ToMeanVertex3bodyV0", 2 * 2, ""}; + Configurable minCosPAXYMeanVertex3bodyV0 = {"minCosPAXYMeanVertex3bodyV0", 0.9, ""}; ///< min cos of PA to beam line (mean vertex) in tr. plane for 3body V0 cand. + Configurable minCosPA3bodyV0 = {"minCosPA3bodyV0", 0.8, ""}; // min cos of PA to PV for 3body V0 + + // for 3 body reconstructed Vertex + Configurable maxRDiff3bodyV0 = {"maxRDiffV03bodyV0", 3, ""}; ///< Maximum difference between V0 and 3body radii + Configurable minPt23Body = {"minPt23Body", 0.01 * 0.01, ""}; // minimum pT of 3body Vertex + Configurable maxTgl23Body = {"maxTgl23Body", 2. * 2., ""}; // maximum tgLambda of 3body Vertex + Configurable minCosPA3body = {"minCosPA3body", 0.8, ""}; // min cos of PA to PV for 3body Vertex + + // for DCA + // Configurable dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; + + // for track cut in SVertexer, Can we use it in the production of goodtrack table? + // float maxDCAXY3Body = 0.3; // max DCA of 3 body decay to PV in XY? + // float maxDCAZ3Body = 0.3; // max DCA of 3 body decay to PV in Z + + Configurable useMatCorrType{"useMatCorrType", 2, "0: none, 1: TGeo, 2: LUT"}; + // CCDB options + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + + Preslice perCollisionGoodPosTracks = o2::aod::v0goodpostrack::collisionId; + Preslice perCollisionGoodNegTracks = o2::aod::v0goodnegtrack::collisionId; + Preslice perCollisionGoodTracks = o2::aod::v0goodtrack::collisionId; + + HistogramRegistry registry{ + "registry", + { + {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hDauTrackCounter", "hDauTrackCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, + {"hV0Counter", "hV0Counter", {HistType::kTH1F, {{10, 0.0f, 10.0f}}}}, + {"hVtx3BodyCounter", "hVtx3BodyCounter", {HistType::kTH1F, {{7, 0.0f, 7.0f}}}}, + {"hTrueV0Counter", "hTrueV0Counter", {HistType::kTH1F, {{10, 0.0f, 10.0f}}}}, + {"hTrueVtx3BodyCounter", "hTrueVtx3BodyCounter", {HistType::kTH1F, {{9, 0.0f, 9.0f}}}}, + }, + }; + + int mRunNumber; + float d_bz; + float maxSnp; // max sine phi for propagation + float maxStep; // max step size (cm) for propagation + o2::base::MatLayerCylSet* lut = nullptr; + o2::vertexing::DCAFitterN<2> fitter; + o2::vertexing::DCAFitterN<3> fitter3body; + + void init(InitContext& context) + { + mRunNumber = 0; + d_bz = 0; + maxSnp = 0.85f; // could be changed later + maxStep = 2.00f; // could be changed later + + registry.get(HIST("hDauTrackCounter"))->GetXaxis()->SetBinLabel(1, "Proton"); + registry.get(HIST("hDauTrackCounter"))->GetXaxis()->SetBinLabel(2, "Pion"); + registry.get(HIST("hDauTrackCounter"))->GetXaxis()->SetBinLabel(3, "Deuteron"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(1, "Total"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(2, "hasSV"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(3, "V0R"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(4, "TrackR-V0R(off)"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(5, "IfPropragated"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(6, "V0Pt"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(7, "tgLambda"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(8, "V0Mass"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(9, "dcaXY&CosPAXY"); + registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(10, "CosPA"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(1, "Total"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(2, "hasSV"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(3, "V0R"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(4, "TrackRi-V0R(off)"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(5, "IfPropragated"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(6, "V0Pt"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(7, "tgLambda"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(8, "V0Mass"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(9, "dcaXY&CosPAXY"); + registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(10, "CosPA"); + + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(1, "Total"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(2, "bachPt"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(3, "hasSV"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(4, "VtxR"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(5, "BachR-VtxR(off)"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(6, "IfPropragated"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(7, "VtxPt"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(8, "tgLambda"); + registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(9, "CosPA"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(1, "Total"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(2, "bachPt"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(3, "hasSV"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(4, "VtxR"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(5, "BachR-vtxR(off)"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(6, "IfPropragated"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(7, "VtxPt"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(8, "tgLambda"); + registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(9, "CosPA"); + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + // Set 2-body fitter and 3-body fitter3body + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); //->maxRIni3body + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(d_UseAbsDCA); + fitter3body.setPropagateToPCA(true); + fitter3body.setMaxR(200.); //->maxRIni3body + fitter3body.setMinParamChange(1e-3); + fitter3body.setMinRelChi2Change(0.9); + fitter3body.setMaxDZIni(1e9); + fitter3body.setMaxChi2(1e9); + fitter3body.setUseAbsDCA(d_UseAbsDCA); + + // Material correction in the DCA fitter + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + if (useMatCorrType == 1) { + LOGF(info, "TGeo correction requested, loading geometry"); + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; + } + if (useMatCorrType == 2) { + LOGF(info, "LUT correction requested, loading LUT"); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + } + fitter.setMatCorrType(matCorr); + fitter3body.setMatCorrType(matCorr); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + fitter.setBz(d_bz); + fitter3body.setBz(d_bz); + o2::parameters::GRPMagField grpmag; + if (fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + o2::parameters::GRPMagField* grpmag = 0x0; + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + mRunNumber = bc.runNumber(); + // Set magnetic field value once known + fitter.setBz(d_bz); + fitter3body.setBz(d_bz); + + if (useMatCorrType == 2) { + // setMatLUT only after magfield has been initalized + // (setMatLUT has implicit and problematic init field call if not) + o2::base::Propagator::Instance()->setMatLUT(lut); + } + } + + //------------------------------------------------------------------ + // Check the info of good tracks + template + void CheckGoodTracks(TGoodTrackTable const& dGoodtracks, aod::McParticles const& mcparticles) + { + for (auto& goodtrackid : dGoodtracks) { + auto goodtrack = goodtrackid.template goodTrack_as(); + if (!goodtrack.has_mcParticle()) { + continue; + } + auto mcgoodtrack = goodtrack.template mcParticle_as(); + if (!mcgoodtrack.has_mothers()) { + continue; + } + bool isHypertriton = false; + for (auto& mothertrack : mcgoodtrack.template mothers_as()) { + if (std::abs(mothertrack.pdgCode()) != 1010010030) { + continue; + } + bool haveProton = false, havePion = false, haveDeuteron = false; + bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; + for (auto& mcparticleDaughter : mothertrack.template daughters_as()) { + if (mcparticleDaughter.pdgCode() == 2212) { + haveProton = true; + } + if (mcparticleDaughter.pdgCode() == -2212) { + haveAntiProton = true; + } + if (mcparticleDaughter.pdgCode() == 211) { + havePion = true; + } + if (mcparticleDaughter.pdgCode() == -211) { + haveAntiPion = true; + } + if (mcparticleDaughter.pdgCode() == 1000010020) { + haveDeuteron = true; + } + if (mcparticleDaughter.pdgCode() == -1000010020) { + haveAntiDeuteron = true; + } + } + if ((haveProton && haveAntiPion && haveDeuteron && mothertrack.pdgCode() == 1010010030) || (haveAntiProton && havePion && haveAntiDeuteron && mothertrack.pdgCode() == -1010010030)) { + isHypertriton = true; + break; + } + } + if (isHypertriton && std::abs(mcgoodtrack.pdgCode()) == 2212) { + registry.fill(HIST("hDauTrackCounter"), 0.5); + } + if (isHypertriton && std::abs(mcgoodtrack.pdgCode()) == 211) { + registry.fill(HIST("hDauTrackCounter"), 1.5); + } + if (isHypertriton && std::abs(mcgoodtrack.pdgCode()) == 1000010020) { + registry.fill(HIST("hDauTrackCounter"), 2.5); + } + } + } + + o2::dataformats::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; + //------------------------------------------------------------------ + // 3body decay finder + template + void DecayFinder(TCollisionTable const& dCollision, TPosTrackTable const& dPtracks, TNegTrackTable const& dNtracks, TGoodTrackTable const& dGoodtracks) + { + for (auto& t0id : dPtracks) { // FIXME: turn into combination(...) + registry.fill(HIST("hV0Counter"), 0.5); + auto t0 = t0id.template goodTrack_as(); + auto Track0 = getTrackParCov(t0); + + for (auto& t1id : dNtracks) { + auto t1 = t1id.template goodTrack_as(); + auto Track1 = getTrackParCov(t1); + int nCand = fitter.process(Track0, Track1); + if (nCand == 0) { + continue; + } + registry.fill(HIST("hV0Counter"), 1.5); + // validate V0 radial position + // First check closeness to the beam-line as same as SVertexer + const auto& v0XYZ = fitter.getPCACandidate(); + float dxv0 = v0XYZ[0] - mMeanVertex.getX(), dyv0 = v0XYZ[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; + if (r2v0 < minR2ToMeanVertex) { + continue; + } + registry.fill(HIST("hV0Counter"), 2.5); + + float rv0 = std::sqrt(r2v0); + // Not involved: Get minR with same way in SVertexer + // float Track0minR = RecoDecay::sqrtSumOfSquares(t0.x(), t0.y()), Track1minR = RecoDecay::sqrtSumOfSquares(t1.x(), t1.y()); + // float drv0P = rv0 - Track0minR, drv0N = rv0 - Track1minR; + /*if (drv0P > causalityRTolerance || drv0P < -maxV0ToProngsRDiff || + drv0N > causalityRTolerance || drv0N < -maxV0ToProngsRDiff) { + continue; + }*/ + registry.fill(HIST("hV0Counter"), 3.5); + + // the process function should finish the propagation + if (!fitter.isPropagateTracksToVertexDone() && !fitter.propagateTracksToVertex()) { + continue; + } + registry.fill(HIST("hV0Counter"), 4.5); + + int cand = 0; + auto& trPProp = fitter.getTrack(0, cand); + auto& trNProp = fitter.getTrack(1, cand); + std::array pP, pN; + trPProp.getPxPyPzGlo(pP); + trNProp.getPxPyPzGlo(pN); + // estimate DCA of neutral V0 track to beamline: straight line with parametric equation + // x = X0 + pV0[0]*t, y = Y0 + pV0[1]*t reaches DCA to beamline (Xv, Yv) at + // t = -[ (x0-Xv)*pV0[0] + (y0-Yv)*pV0[1]) ] / ( pT(pV0)^2 ) + // Similar equation for 3D distance involving pV0[2] + std::array pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]}; + float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; + if (pt2V0 < minPt2V0) { // pt cut + continue; + } + registry.fill(HIST("hV0Counter"), 5.5); + + if (pV0[2] * pV0[2] / pt2V0 > maxTgl2V0) { // tgLambda cut + continue; + } + registry.fill(HIST("hV0Counter"), 6.5); + float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); + // apply mass selections + float massV0LambdaHyp = RecoDecay::m(array{array{pP[0], pP[1], pP[2]}, array{pN[0], pN[1], pN[2]}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + float massV0AntiLambdaHyp = RecoDecay::m(array{array{pP[0], pP[1], pP[2]}, array{pN[0], pN[1], pN[2]}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); + float massMargin = 20 * (0.001 * (1. + 0.5 * ptV0)) + 0.07; + if (massV0LambdaHyp - o2::constants::physics::MassLambda > massMargin && massV0AntiLambdaHyp - o2::constants::physics::MassLambda > massMargin) { + continue; + } + registry.fill(HIST("hV0Counter"), 7.5); + + float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; + float cosPAXY = prodXYv0 / std::sqrt(r2v0 * pt2V0); + if (dca2 > maxDCAXY2ToMeanVertex3bodyV0 || cosPAXY < minCosPAXYMeanVertex3bodyV0) { + continue; + } + registry.fill(HIST("hV0Counter"), 8.5); + + float dx = v0XYZ[0] - dCollision.posX(), dy = v0XYZ[1] - dCollision.posY(), dz = v0XYZ[2] - dCollision.posZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; + float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); + if (cosPA < minCosPA3bodyV0) { + continue; + } + registry.fill(HIST("hV0Counter"), 9.5); + + for (auto& t2id : dGoodtracks) { + if (t2id.globalIndex() == t0id.globalIndex()) { + continue; // skip the track used by V0 + } + registry.fill(HIST("hVtx3BodyCounter"), 0.5); + + auto t2 = t2id.template goodTrack_as(); + auto track0 = getTrackParCov(t0); + auto track1 = getTrackParCov(t1); + auto bach = getTrackParCov(t2); + + if (bach.getPt() < 0.6) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 1.5); + + int n3bodyVtx = fitter3body.process(track0, track1, bach); + if (n3bodyVtx == 0) { // discard this pair + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 2.5); + + int cand3B = 0; + const auto& vertexXYZ = fitter3body.getPCACandidatePos(cand3B); + // make sure the cascade radius is smaller than that of the vertex + float dxc = vertexXYZ[0] - dCollision.posX(), dyc = vertexXYZ[1] - dCollision.posY(), dzc = vertexXYZ[2] - dCollision.posZ(), r2vertex = dxc * dxc + dyc * dyc; + if (std::abs(rv0 - std::sqrt(r2vertex)) > maxRDiff3bodyV0 || r2vertex < minR2ToMeanVertex) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 3.5); + + // Not involved: bach.minR - rveretx check + registry.fill(HIST("hVtx3BodyCounter"), 4.5); + + if (!fitter3body.isPropagateTracksToVertexDone() && !fitter3body.propagateTracksToVertex()) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 5.5); + + auto& tr0 = fitter3body.getTrack(0, cand3B); + auto& tr1 = fitter3body.getTrack(1, cand3B); + auto& tr2 = fitter3body.getTrack(2, cand3B); + std::array p0, p1, p2; + tr0.getPxPyPzGlo(p0); + tr1.getPxPyPzGlo(p1); + tr2.getPxPyPzGlo(p2); + std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; + + float pt2 = p3B[0] * p3B[0] + p3B[1] * p3B[1], p2candidate = pt2 + p3B[2] * p3B[2]; + if (pt2 < minPt23Body) { // pt cut + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 6.5); + + if (p3B[2] * p3B[2] / pt2 > maxTgl23Body) { // tgLambda cut + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 7.5); + + float cosPA = (p3B[0] * dxc + p3B[1] * dyc + p3B[2] * dzc) / std::sqrt(p2candidate * (r2vertex + dzc * dzc)); + if (cosPA < minCosPA3body) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 8.5); + + // Not involved: H3L DCA Check + vtx3bodydata( + t0.globalIndex(), t1.globalIndex(), t2.globalIndex(), dCollision.globalIndex(), 0, + vertexXYZ[0], vertexXYZ[1], vertexXYZ[2], + p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], + fitter3body.getChi2AtPCACandidate(), + t0.dcaXY(), t1.dcaXY(), t2.dcaXY()); + } + } + } + } + + void processData(aod::Collision const& collision, aod::V0GoodPosTracks const& ptracks, aod::V0GoodNegTracks const& ntracks, aod::V0GoodTracks const& goodtracks, FullTracksExtIU const&, aod::BCsWithTimestamps const&) + { + auto bc = collision.bc_as(); + initCCDB(bc); + registry.fill(HIST("hEventCounter"), 0.5); + registry.fill(HIST("hEventCounter"), 1.5); + + DecayFinder(collision, ptracks, ntracks, goodtracks); + } + PROCESS_SWITCH(hypertriton3bodyFinder, processData, "Produce StoredVtx3BodyDatas without MC check", false); + + void processCFFilteredData(aod::Collisions const& collisions, aod::CFFilters const& cffilters, aod::V0GoodPosTracks const& Ptracks, aod::V0GoodNegTracks const& Ntracks, aod::V0GoodTracks const& Goodtracks, FullTracksExtIU const&, aod::BCsWithTimestamps const&) + { + for (int i{0}; i < collisions.size(); i++) { + auto collision = collisions.iteratorAt(i); + auto cffilter = cffilters.iteratorAt(i); + auto bc = collision.bc_as(); + initCCDB(bc); + registry.fill(HIST("hEventCounter"), 0.5); + + auto ptracks = Ptracks.sliceBy(perCollisionGoodPosTracks, collision.globalIndex()); + auto ntracks = Ntracks.sliceBy(perCollisionGoodNegTracks, collision.globalIndex()); + auto goodtracks = Goodtracks.sliceBy(perCollisionGoodTracks, collision.globalIndex()); + + if (!cffilter.hasLD()) { + continue; + } + registry.fill(HIST("hEventCounter"), 1.5); + + DecayFinder(collision, ptracks, ntracks, goodtracks); + } + } + PROCESS_SWITCH(hypertriton3bodyFinder, processCFFilteredData, "Produce StoredVtx3BodyDatas without MC check under cffilters", true); + + void processMC(aod::Collisions const& collisions, aod::CFFilters const& cffilters, aod::V0GoodPosTracks const& Ptracks, aod::V0GoodNegTracks const& Ntracks, aod::V0GoodTracks const& Goodtracks, aod::McParticles const& mcparticles, FullTracksExtMCIU const&, aod::BCsWithTimestamps const&) + { + for (int i{0}; i < collisions.size(); i++) { + auto collision = collisions.iteratorAt(i); + auto cffilter = cffilters.iteratorAt(i); + auto bc = collision.bc_as(); + initCCDB(bc); + registry.fill(HIST("hEventCounter"), 0.5); + + auto goodtracks = Goodtracks.sliceBy(perCollisionGoodTracks, collision.globalIndex()); + CheckGoodTracks(goodtracks, mcparticles); + + if (!cffilter.hasLD() && UseCFFilterInMC) { + continue; + } + registry.fill(HIST("hEventCounter"), 1.5); + + auto ptracks = Ptracks.sliceBy(perCollisionGoodPosTracks, collision.globalIndex()); + auto ntracks = Ntracks.sliceBy(perCollisionGoodNegTracks, collision.globalIndex()); + + for (auto& t0id : ptracks) { // FIXME: turn into combination(...) + auto t0 = t0id.goodTrack_as(); + auto Track0 = getTrackParCov(t0); + for (auto& t1id : ntracks) { + + if (t0id.collisionId() != t1id.collisionId()) { + continue; + } + auto t1 = t1id.goodTrack_as(); + auto Track1 = getTrackParCov(t1); + + bool isTrue3bodyV0 = false; + if (t0.has_mcParticle() && t1.has_mcParticle()) { + auto t0mc = t0.mcParticle_as(); + auto t1mc = t1.mcParticle_as(); + if ((t0mc.pdgCode() == 2212 && t1mc.pdgCode() == -211) || (t0mc.pdgCode() == 211 && t1mc.pdgCode() == -2212)) { + if (t0mc.has_mothers() && t1mc.has_mothers()) { + for (auto& t0mother : t0mc.mothers_as()) { + for (auto& t1mother : t1mc.mothers_as()) { + if (t0mother.globalIndex() == t1mother.globalIndex() && std::abs(t0mother.pdgCode()) == 1010010030) { + isTrue3bodyV0 = true; + } + } + } + } + } + } + + if (!isTrue3bodyV0) { + continue; + } // save time + + registry.fill(HIST("hV0Counter"), 0.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 0.5); + } + + int nCand = fitter.process(Track0, Track1); + if (nCand == 0) { + continue; + } + registry.fill(HIST("hV0Counter"), 1.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 1.5); + } + // validate V0 radial position + // First check closeness to the beam-line as same as SVertexer + const auto& v0XYZ = fitter.getPCACandidate(); + float dxv0 = v0XYZ[0] - mMeanVertex.getX(), dyv0 = v0XYZ[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; + if (r2v0 < minR2ToMeanVertex) { + continue; + } + registry.fill(HIST("hV0Counter"), 2.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 2.5); + } + + float rv0 = std::sqrt(r2v0); + // Not involved: Get minR with same way in SVertexer + // float Track0minR = RecoDecay::sqrtSumOfSquares(t0.x(), t0.y()), Track1minR = RecoDecay::sqrtSumOfSquares(t1.x(), t1.y()); + // float drv0P = rv0 - Track0minR, drv0N = rv0 - Track1minR; + // if (drv0P > causalityRTolerance || drv0P < -maxV0ToProngsRDiff || + // drv0N > causalityRTolerance || drv0N < -maxV0ToProngsRDiff) { + // continue; + // } + registry.fill(HIST("hV0Counter"), 3.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 3.5); + } + + // the process function should finish the propagation + if (!fitter.isPropagateTracksToVertexDone() && !fitter.propagateTracksToVertex()) { + continue; + } + registry.fill(HIST("hV0Counter"), 4.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 4.5); + } + + int cand = 0; + auto& trPProp = fitter.getTrack(0, cand); + auto& trNProp = fitter.getTrack(1, cand); + std::array pP, pN; + trPProp.getPxPyPzGlo(pP); + trNProp.getPxPyPzGlo(pN); + // estimate DCA of neutral V0 track to beamline: straight line with parametric equation + // x = X0 + pV0[0]*t, y = Y0 + pV0[1]*t reaches DCA to beamline (Xv, Yv) at + // t = -[ (x0-Xv)*pV0[0] + (y0-Yv)*pV0[1]) ] / ( pT(pV0)^2 ) + // Similar equation for 3D distance involving pV0[2] + std::array pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]}; + float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; + if (pt2V0 < minPt2V0) { // pt cut + continue; + } + registry.fill(HIST("hV0Counter"), 5.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 5.5); + } + + if (pV0[2] * pV0[2] / pt2V0 > maxTgl2V0) { // tgLambda cut + continue; + } + registry.fill(HIST("hV0Counter"), 6.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 6.5); + } + float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); + // apply mass selections + float massV0LambdaHyp = RecoDecay::m(array{array{pP[0], pP[1], pP[2]}, array{pN[0], pN[1], pN[2]}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + float massV0AntiLambdaHyp = RecoDecay::m(array{array{pP[0], pP[1], pP[2]}, array{pN[0], pN[1], pN[2]}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); + float massMargin = 20 * (0.001 * (1. + 0.5 * ptV0)) + 0.07; + if (massV0LambdaHyp - o2::constants::physics::MassLambda > massMargin && massV0AntiLambdaHyp - o2::constants::physics::MassLambda > massMargin) { + continue; + } + registry.fill(HIST("hV0Counter"), 7.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 7.5); + } + + float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; + float cosPAXY = prodXYv0 / std::sqrt(r2v0 * pt2V0); + if (dca2 > maxDCAXY2ToMeanVertex3bodyV0 || cosPAXY < minCosPAXYMeanVertex3bodyV0) { + continue; + } + registry.fill(HIST("hV0Counter"), 8.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 8.5); + } + + float dx = v0XYZ[0] - collision.posX(), dy = v0XYZ[1] - collision.posY(), dz = v0XYZ[2] - collision.posZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; + float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); + if (cosPA < minCosPA3bodyV0) { + continue; + } + registry.fill(HIST("hV0Counter"), 9.5); + if (isTrue3bodyV0) { + registry.fill(HIST("hTrueV0Counter"), 9.5); + } + + for (auto& t2id : goodtracks) { + if (t2id.globalIndex() == t0id.globalIndex()) { + continue; // skip the track used by V0 + } + auto t2 = t2id.goodTrack_as(); + auto track0 = getTrackParCov(t0); + auto track1 = getTrackParCov(t1); + auto bach = getTrackParCov(t2); + + bool isTrue3bodyVtx = false; + if (t0.has_mcParticle() && t1.has_mcParticle() && t2.has_mcParticle()) { + auto t0mc = t0.mcParticle_as(); + auto t1mc = t1.mcParticle_as(); + auto t2mc = t2.mcParticle_as(); + if ((t0mc.pdgCode() == 2212 && t1mc.pdgCode() == -211 && t2mc.pdgCode() == 1000010020) || (t0mc.pdgCode() == 211 && t1mc.pdgCode() == -2212 && t2mc.pdgCode() == -1000010020)) { + if (t0mc.has_mothers() && t1mc.has_mothers() && t2mc.has_mothers()) { + for (auto& t0mother : t0mc.mothers_as()) { + for (auto& t1mother : t1mc.mothers_as()) { + for (auto& t2mother : t2mc.mothers_as()) { + if (t0mother.globalIndex() == t1mother.globalIndex() && t0mother.globalIndex() == t2mother.globalIndex() && std::abs(t0mother.pdgCode()) == 1010010030) { + isTrue3bodyVtx = true; + } + } + } + } + } + } + } + + // if (!isTrue3bodyVtx){ continue;} // save time + registry.fill(HIST("hVtx3BodyCounter"), 0.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 0.5); + } + + if (bach.getPt() < 0.6) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 1.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 1.5); + } + + int n3bodyVtx = fitter3body.process(track0, track1, bach); + if (n3bodyVtx == 0) { // discard this pair + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 2.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 2.5); + } + + int cand3B = 0; + const auto& vertexXYZ = fitter3body.getPCACandidatePos(cand3B); + // make sure the cascade radius is smaller than that of the vertex + float dxc = vertexXYZ[0] - collision.posX(), dyc = vertexXYZ[1] - collision.posY(), dzc = vertexXYZ[2] - collision.posZ(), r2vertex = dxc * dxc + dyc * dyc; + if (std::abs(rv0 - std::sqrt(r2vertex)) > maxRDiff3bodyV0 || r2vertex < minR2ToMeanVertex) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 3.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 3.5); + } + + // Not involved: bach.minR - rveretx check + registry.fill(HIST("hVtx3BodyCounter"), 4.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 4.5); + } + + if (!fitter3body.isPropagateTracksToVertexDone() && !fitter3body.propagateTracksToVertex()) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 5.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 5.5); + } + + auto& tr0 = fitter3body.getTrack(0, cand3B); + auto& tr1 = fitter3body.getTrack(1, cand3B); + auto& tr2 = fitter3body.getTrack(2, cand3B); + std::array p0, p1, p2; + tr0.getPxPyPzGlo(p0); + tr1.getPxPyPzGlo(p1); + tr2.getPxPyPzGlo(p2); + std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; + + float pt2 = p3B[0] * p3B[0] + p3B[1] * p3B[1], p2candidate = pt2 + p3B[2] * p3B[2]; + if (pt2 < minPt23Body) { // pt cut + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 6.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 6.5); + } + + if (p3B[2] * p3B[2] / pt2 > maxTgl23Body) { // tgLambda cut + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 7.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 7.5); + } + + float cosPA = (p3B[0] * dxc + p3B[1] * dyc + p3B[2] * dzc) / std::sqrt(p2candidate * (r2vertex + dzc * dzc)); + if (cosPA < minCosPA3body) { + continue; + } + registry.fill(HIST("hVtx3BodyCounter"), 8.5); + if (isTrue3bodyVtx) { + registry.fill(HIST("hTrueVtx3BodyCounter"), 8.5); + } + + // Not involved: H3L DCA Check + vtx3bodydata( + t0.globalIndex(), t1.globalIndex(), t2.globalIndex(), collision.globalIndex(), 0, + vertexXYZ[0], vertexXYZ[1], vertexXYZ[2], + p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], + fitter3body.getChi2AtPCACandidate(), + t0.dcaXY(), t1.dcaXY(), t2.dcaXY()); + } + } + } + } + } + PROCESS_SWITCH(hypertriton3bodyFinder, processMC, "Produce StoredVtx3BodyDatas with MC check", false); +}; + +struct hypertriton3bodyLabelBuilder { + + Produces vtxlabels; + + // for bookkeeping purposes: how many V0s come from same mother etc + HistogramRegistry registry{ + "registry", + { + {"hLabelCounter", "hLabelCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, + {"hHypertritonCounter", "hHypertritonCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, + {"hPIDCounter", "hPIDCounter", {HistType::kTH1F, {{6, 0.0f, 6.0f}}}}, + {"hHypertritonMCPt", "hHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, + {"hAntiHypertritonMCPt", "hAntiHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, + {"hHypertritonMCMass", "hHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f}}}}, + {"hAntiHypertritonMCMass", "hAntiHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f}}}}, + {"h3dTotalTrueHypertriton", "h3dTotalTrueHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + }, + }; + + void init(InitContext const&) + { + registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(1, "Total"); + registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(2, "Same MotherParticle"); + registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(3, "True H3L"); + registry.get(HIST("hHypertritonCounter"))->GetXaxis()->SetBinLabel(1, "H3L"); + registry.get(HIST("hHypertritonCounter"))->GetXaxis()->SetBinLabel(2, "H3L daughters pass PID"); + registry.get(HIST("hHypertritonCounter"))->GetXaxis()->SetBinLabel(3, "#bar{H3L}"); + registry.get(HIST("hHypertritonCounter"))->GetXaxis()->SetBinLabel(4, "#bar{H3L} daughters pass PID"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(1, "H3L Proton PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(2, "H3L Pion PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(3, "H3L Deuteron PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(4, "#bar{H3L} Proton PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(5, "#bar{H3L} Pion PID > 5"); + registry.get(HIST("hPIDCounter"))->GetXaxis()->SetBinLabel(6, "#bar{H3L} Deuteron PID > 5"); + } + + Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; + + void processDoNotBuildLabels(aod::Collisions::iterator const& collision) + { + // dummy process function - should not be required in the future + } + PROCESS_SWITCH(hypertriton3bodyLabelBuilder, processDoNotBuildLabels, "Do not produce MC label tables", true); + + void processBuildLabels(aod::Collisions::iterator const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, LabeledTracks const&, aod::McParticles const& particlesMC) + { + std::vector lIndices; + lIndices.reserve(vtx3bodydatas.size()); + for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { + lIndices[ii] = -1; + } + + for (auto& vtx3body : vtx3bodydatas) { + + int lLabel = -1; + int lPDG = -1; + float lPt = -1; + double MClifetime = -1; + bool is3bodyDecay = false; + int lGlobalIndex = -1; + + auto lTrack0 = vtx3body.track0_as(); + auto lTrack1 = vtx3body.track1_as(); + auto lTrack2 = vtx3body.track2_as(); + registry.fill(HIST("hLabelCounter"), 0.5); + + // Association check + // There might be smarter ways of doing this in the future + if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { + vtxlabels(-1); + continue; + } + auto lMCTrack0 = lTrack0.mcParticle_as(); + auto lMCTrack1 = lTrack1.mcParticle_as(); + auto lMCTrack2 = lTrack2.mcParticle_as(); + if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { + vtxlabels(-1); + continue; + } + + for (auto& lMother0 : lMCTrack0.mothers_as()) { + for (auto& lMother1 : lMCTrack1.mothers_as()) { + for (auto& lMother2 : lMCTrack2.mothers_as()) { + if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { + lGlobalIndex = lMother1.globalIndex(); + lPt = lMother1.pt(); + lPDG = lMother1.pdgCode(); + MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); + is3bodyDecay = true; // vtxs with the same mother + } + } + } + } // end association check + if (!is3bodyDecay) { + vtxlabels(-1); + continue; + } + registry.fill(HIST("hLabelCounter"), 1.5); + + // Intended for cross-checks only + // N.B. no rapidity cut! + if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { + lLabel = lGlobalIndex; + double hypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); + registry.fill(HIST("hLabelCounter"), 2.5); + registry.fill(HIST("hHypertritonCounter"), 0.5); + registry.fill(HIST("hHypertritonMCPt"), lPt); + registry.fill(HIST("hHypertritonMCMass"), hypertritonMCMass); + registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, hypertritonMCMass); + if (TMath::Abs(lTrack0.tpcNSigmaPr()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 0.5); + } + if (TMath::Abs(lTrack1.tpcNSigmaPi()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 1.5); + } + if (TMath::Abs(lTrack2.tpcNSigmaDe()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 2.5); + } + if (TMath::Abs(lTrack0.tpcNSigmaPr()) < TpcPidNsigmaCut && TMath::Abs(lTrack1.tpcNSigmaPi()) < TpcPidNsigmaCut && TMath::Abs(lTrack2.tpcNSigmaDe()) < TpcPidNsigmaCut) { + registry.fill(HIST("hHypertritonCounter"), 1.5); + } + } + if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { + lLabel = lGlobalIndex; + double antiHypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); + registry.fill(HIST("hLabelCounter"), 2.5); + registry.fill(HIST("hHypertritonCounter"), 2.5); + registry.fill(HIST("hAntiHypertritonMCPt"), lPt); + registry.fill(HIST("hAntiHypertritonMCMass"), antiHypertritonMCMass); + registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, antiHypertritonMCMass); + if (TMath::Abs(lTrack0.tpcNSigmaPi()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 4.5); + } + if (TMath::Abs(lTrack1.tpcNSigmaPr()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 3.5); + } + if (TMath::Abs(lTrack2.tpcNSigmaDe()) > TpcPidNsigmaCut) { + registry.fill(HIST("hPIDCounter"), 5.5); + } + if (TMath::Abs(lTrack0.tpcNSigmaPi()) < TpcPidNsigmaCut && TMath::Abs(lTrack1.tpcNSigmaPr()) < TpcPidNsigmaCut && TMath::Abs(lTrack2.tpcNSigmaDe()) < TpcPidNsigmaCut) { + registry.fill(HIST("hHypertritonCounter"), 3.5); + } + } + + // Construct label table, only true hypertriton and true daughters with a specified order is labeled + // for matter: track0->p, track1->pi, track2->d + // for antimatter: track0->pi, track1->p, track2->d + vtxlabels(lLabel); + } + } + PROCESS_SWITCH(hypertriton3bodyLabelBuilder, processBuildLabels, "Produce MC label tables", false); +}; + +struct hypertriton3bodyInitializer { + Spawns vtx3bodydatas; + void init(InitContext const&) {} +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGLF/TableProducer/lambdakzerobuilder.cxx b/PWGLF/TableProducer/lambdakzerobuilder.cxx index 2ac7e052952..c48e8a72ef9 100644 --- a/PWGLF/TableProducer/lambdakzerobuilder.cxx +++ b/PWGLF/TableProducer/lambdakzerobuilder.cxx @@ -129,6 +129,7 @@ struct lambdakzeroBuilder { Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; // generate and fill extra QA histograms is requested Configurable d_doQA{"d_doQA", false, "Do basic QA"}; @@ -144,6 +145,7 @@ struct lambdakzeroBuilder { // for topo var QA ConfigurableAxis axisTopoVarPointingAngle{"axisTopoVarPointingAngle", {50, 0.0, 1.0}, "pointing angle"}; + ConfigurableAxis axisTopoVarRAP{"axisTopoVarRAP", {50, 0.0, 1.0}, "radius x pointing angle axis"}; ConfigurableAxis axisTopoVarV0Radius{"axisTopoVarV0Radius", {500, 0.0, 100.0}, "V0 decay radius (cm)"}; ConfigurableAxis axisTopoVarDCAV0Dau{"axisTopoVarDCAV0Dau", {200, 0.0, 2.0}, "DCA between V0 daughters (cm)"}; ConfigurableAxis axisTopoVarDCAToPV{"axisTopoVarDCAToPV", {200, -1, 1.0}, "single track DCA to PV (cm)"}; @@ -276,6 +278,7 @@ struct lambdakzeroBuilder { // QA plots of topological variables using axisPtQA registry.add("h2dTopoVarPointingAngle", "h2dTopoVarPointingAngle", kTH2D, {axisPtQA, axisTopoVarPointingAngle}); + registry.add("h2dTopoVarRAP", "h2dTopoVarRAP", kTH2D, {axisPtQA, axisTopoVarRAP}); registry.add("h2dTopoVarV0Radius", "h2dTopoVarV0Radius", kTH2D, {axisPtQA, axisTopoVarV0Radius}); registry.add("h2dTopoVarDCAV0Dau", "h2dTopoVarDCAV0Dau", kTH2D, {axisPtQA, axisTopoVarDCAV0Dau}); registry.add("h2dTopoVarPosDCAToPV", "h2dTopoVarPosDCAToPV", kTH2D, {axisPtQA, axisTopoVarDCAToPV}); @@ -444,8 +447,10 @@ struct lambdakzeroBuilder { } auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + o2::parameters::GRPObject* grpo = 0x0; o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); if (grpo) { o2::base::Propagator::initFieldFromGRP(grpo); // Fetch magnetic field from ccdb for current collision @@ -646,6 +651,7 @@ struct lambdakzeroBuilder { float dcaV0toPV = std::sqrt((std::pow((primaryVertex.getY() - v0candidate.pos[1]) * pz - (primaryVertex.getZ() - v0candidate.pos[2]) * py, 2) + std::pow((primaryVertex.getX() - v0candidate.pos[0]) * pz - (primaryVertex.getZ() - v0candidate.pos[2]) * px, 2) + std::pow((primaryVertex.getX() - v0candidate.pos[0]) * py - (primaryVertex.getY() - v0candidate.pos[1]) * px, 2)) / (px * px + py * py + pz * pz)); registry.fill(HIST("h2dTopoVarPointingAngle"), lPt, TMath::ACos(v0candidate.cosPA)); + registry.fill(HIST("h2dTopoVarRAP"), lPt, TMath::ACos(v0candidate.cosPA) * v0candidate.V0radius); registry.fill(HIST("h2dTopoVarV0Radius"), lPt, v0candidate.V0radius); registry.fill(HIST("h2dTopoVarDCAV0Dau"), lPt, v0candidate.dcaV0dau); registry.fill(HIST("h2dTopoVarPosDCAToPV"), lPt, v0candidate.posDCAxy); @@ -729,11 +735,14 @@ struct lambdakzeroBuilder { } PROCESS_SWITCH(lambdakzeroBuilder, processRun2, "Produce Run 2 V0 tables", false); - void processRun3(aod::Collisions const& collisions, soa::Filtered const& V0s, FullTracksExtIU const&, aod::BCsWithTimestamps const&) + void processRun3(aod::Collisions const& collisions, soa::Filtered const& V0s, FullTracksExtIU const&, aod::BCsWithTimestamps const& bcs) { // Fire up CCDB - auto collision = collisions.begin(); - auto bc = collision.bc_as(); + auto bc = collisions.size() ? collisions.begin().bc_as() : bcs.begin(); + if (!bcs.size()) { + LOGF(warn, "No BC found, skipping this DF."); + return; + } initCCDB(bc); buildStrangenessTables(V0s); } @@ -750,6 +759,8 @@ struct lambdakzeroPreselector { Configurable dIfMCgenerateGamma{"dIfMCgenerateGamma", false, "if MC, generate MC true gamma (yes/no)"}; Configurable dIfMCgenerateHypertriton{"dIfMCgenerateHypertriton", false, "if MC, generate MC true hypertritons (yes/no)"}; Configurable dIfMCgenerateAntiHypertriton{"dIfMCgenerateAntiHypertriton", false, "if MC, generate MC true antihypertritons (yes/no)"}; + Configurable dIfMCselectV0MotherPDG{"dIfMCselectV0MotherPDG", 0, "if MC, selects based on mother particle (zero for no selection)"}; + Configurable dIfMCselectPhysicalPrimary{"dIfMCselectPhysicalPrimary", true, "if MC, select MC physical primary (yes/no)"}; Configurable ddEdxPreSelectK0Short{"ddEdxPreSelectK0Short", true, "pre-select dE/dx compatibility with K0Short (yes/no)"}; Configurable ddEdxPreSelectLambda{"ddEdxPreSelectLambda", true, "pre-select dE/dx compatibility with Lambda (yes/no)"}; @@ -824,8 +835,20 @@ struct lambdakzeroPreselector { if (lMCNegTrack.has_mothers() && lMCPosTrack.has_mothers()) { for (auto& lNegMother : lMCNegTrack.template mothers_as()) { for (auto& lPosMother : lMCPosTrack.template mothers_as()) { - if (lNegMother.globalIndex() == lPosMother.globalIndex()) { + if (lNegMother.globalIndex() == lPosMother.globalIndex() && (!dIfMCselectPhysicalPrimary || lNegMother.isPhysicalPrimary())) { lPDG = lNegMother.pdgCode(); + + // additionally check PDG of the mother particle if requested + if (dIfMCselectV0MotherPDG != 0) { + lPDG = 0; // this is not the species you're looking for + if (lNegMother.has_mothers()) { + for (auto& lNegGrandMother : lNegMother.template mothers_as()) { + if (lNegGrandMother.pdgCode() == dIfMCselectV0MotherPDG) + lPDG = lNegMother.pdgCode(); + } + } + } + // end extra PDG of mother check } } } @@ -954,7 +977,7 @@ struct lambdakzeroPreselector { checkAndFinalize(); } //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* - void processBuildValiddEdxMCAssociated(aod::Collisions const& collisions, aod::V0s const& v0table, TracksExtraWithPIDandLabels const&) + void processBuildValiddEdxMCAssociated(aod::Collisions const& collisions, aod::V0s const& v0table, TracksExtraWithPIDandLabels const&, aod::McParticles const&) { initializeMasks(v0table.size()); for (auto const& v0 : v0table) { diff --git a/PWGLF/TableProducer/lambdakzeromcfinder.cxx b/PWGLF/TableProducer/lambdakzeromcfinder.cxx index 9b158b4558d..57c313ee166 100644 --- a/PWGLF/TableProducer/lambdakzeromcfinder.cxx +++ b/PWGLF/TableProducer/lambdakzeromcfinder.cxx @@ -37,9 +37,9 @@ #include "ReconstructionDataFormats/Track.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/PIDResponse.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFQATables.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" @@ -47,6 +47,7 @@ #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" #include #include @@ -80,6 +81,7 @@ struct lambdakzeromcfinder { Configurable requireITS{"requireITS", false, "require ITS information used in tracks"}; Configurable doUnassociatedV0s{"doUnassociatedV0s", true, "generate also unassociated V0s (for cascades!)"}; Configurable doQA{"doQA", true, "do qa plots"}; + Configurable doSameCollisionOnly{"doSameCollisionOnly", false, "stick to decays in which tracks are assoc to same collision"}; Configurable qaNbins{"qaNbins", 200, "qa plots: binning"}; Configurable yPreFilter{"yPreFilter", 2.5, "broad y pre-filter for speed"}; ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; @@ -91,6 +93,12 @@ struct lambdakzeromcfinder { std::vector v0negativeIndex; std::vector v0mcLabel; + std::vector searchedV0PDG; + std::vector searchedV0PositivePDG; + std::vector searchedV0NegativePDG; + std::vector searchedV0PositiveMass; + std::vector searchedV0NegativeMass; + void init(InitContext& context) { // initialize histograms @@ -134,6 +142,50 @@ struct lambdakzeromcfinder { histos.add("hPtHypertritonDaughters", "hPtHypertritonDaughters", kTH2F, {axisPtQA, axisPtQA}); histos.add("hPtAntiHypertritonDaughters", "hPtAntiHypertritonDaughters", kTH2F, {axisPtQA, axisPtQA}); } + + // initialise search vectors + if (findGamma) { + searchedV0PDG.emplace_back(22); + searchedV0PositivePDG.emplace_back(-11); + searchedV0NegativePDG.emplace_back(+11); + searchedV0PositiveMass.emplace_back(0.0f); + searchedV0NegativeMass.emplace_back(0.0f); + } + if (findK0Short) { + searchedV0PDG.emplace_back(310); + searchedV0PositivePDG.emplace_back(+211); + searchedV0NegativePDG.emplace_back(-211); + searchedV0PositiveMass.emplace_back(o2::constants::physics::MassPionCharged); + searchedV0NegativeMass.emplace_back(o2::constants::physics::MassPionCharged); + } + if (findLambda) { + searchedV0PDG.emplace_back(3122); + searchedV0PositivePDG.emplace_back(+2212); + searchedV0NegativePDG.emplace_back(-211); + searchedV0PositiveMass.emplace_back(o2::constants::physics::MassProton); + searchedV0NegativeMass.emplace_back(o2::constants::physics::MassPionCharged); + } + if (findAntiLambda) { + searchedV0PDG.emplace_back(-3122); + searchedV0PositivePDG.emplace_back(+211); + searchedV0NegativePDG.emplace_back(-2212); + searchedV0PositiveMass.emplace_back(o2::constants::physics::MassPionCharged); + searchedV0NegativeMass.emplace_back(o2::constants::physics::MassProton); + } + if (findHyperTriton) { + searchedV0PDG.emplace_back(+1010010030); + searchedV0PositivePDG.emplace_back(+1000020030); + searchedV0NegativePDG.emplace_back(-211); + searchedV0PositiveMass.emplace_back(o2::constants::physics::MassHelium3); + searchedV0NegativeMass.emplace_back(o2::constants::physics::MassPionCharged); + } + if (findAntiHyperTriton) { + searchedV0PDG.emplace_back(-1010010030); + searchedV0PositivePDG.emplace_back(+211); + searchedV0NegativePDG.emplace_back(-1000020030); + searchedV0PositiveMass.emplace_back(o2::constants::physics::MassPionCharged); + searchedV0NegativeMass.emplace_back(o2::constants::physics::MassHelium3); + } } // for sorting @@ -244,7 +296,7 @@ struct lambdakzeromcfinder { return reconstructed; } - void process(soa::Join const& mcCollisions, LabeledTracks const& tracks, aod::McParticles const& allMcParticles) + void processFromMcParticles(soa::Join const& mcCollisions, LabeledTracks const& tracks, aod::McParticles const& allMcParticles) { v0collisionId.clear(); v0positiveIndex.clear(); @@ -253,7 +305,7 @@ struct lambdakzeromcfinder { // Step 1: sweep over all mcCollisions and find all relevant candidates for (auto const& mcCollision : mcCollisions) { - histos.fill(HIST("hNTimesCollRecoed"), mcCollision.hasRecoCollision()); + histos.fill(HIST("hNTimesCollRecoed"), mcCollision.numRecoCollision()); int bestCollisionIndex = mcCollision.bestCollisionIndex(); auto mcParticles = allMcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); @@ -355,6 +407,84 @@ struct lambdakzeromcfinder { } } } + + // this improved process function does not start from MC particles, as that would be too costly + // rather, it starts from appropriately detected prongs of the correct charge. + Partition posTracks = aod::track::signed1Pt > 0.0f; + Partition negTracks = aod::track::signed1Pt < 0.0f; + + void processFromSingleProngs(aod::Collisions const& collisions, LabeledTracks const& tracks, soa::Join const& mcCollisions, aod::McParticles const& allMcParticles) + { + v0collisionId.clear(); + v0positiveIndex.clear(); + v0negativeIndex.clear(); + v0mcLabel.clear(); + + // This will take place once per TF! + for (auto& posTrack : posTracks) { //<- no grouping, deliberately + int v0pdgIndex = -1; + int motherIndex = -1; + if (!posTrack.has_mcParticle()) + continue; + auto posParticle = posTrack.mcParticle_as(); + if (!posParticle.has_mothers()) + continue; + for (auto& posMotherParticle : posParticle.mothers_as()) { + // determine if mother particle satisfies any condition curently being searched for + for (uint16_t ipdg = 0; ipdg < searchedV0PDG.size(); ipdg++) + if (searchedV0PDG[ipdg] == posMotherParticle.pdgCode()) { + v0pdgIndex = ipdg; // index mapping to desired V0 species + motherIndex = posMotherParticle.globalIndex(); + continue; + } + if (v0pdgIndex < 0 || posParticle.pdgCode() != searchedV0PositivePDG[v0pdgIndex]) + continue; // not interesting, skip + + // if we got here, we need to search for the other prong + for (auto& negTrack : negTracks) { //<- no grouping, deliberately + if (doSameCollisionOnly && negTrack.collisionId() != posTrack.collisionId()) + continue; // skip if requested to look only at the same collision (fixme: could be better) + if (!negTrack.has_mcParticle()) + continue; + auto negParticle = negTrack.mcParticle_as(); + if (!negParticle.has_mothers()) + continue; + for (auto& negMotherParticle : negParticle.mothers_as()) { + if (negMotherParticle.globalIndex() == posMotherParticle.globalIndex() && negMotherParticle.pdgCode() == searchedV0NegativePDG[v0pdgIndex]) { + // de-reference best collision + int bestCollisionIndex = -1; + auto mcCollision = posParticle.mcCollision_as>(); + if (mcCollision.numRecoCollision()) + bestCollisionIndex = mcCollision.bestCollisionIndex(); + + // place in list to be passed along, please + v0collisionId.emplace_back(bestCollisionIndex); + v0positiveIndex.emplace_back(posTrack.globalIndex()); + v0negativeIndex.emplace_back(negTrack.globalIndex()); + v0mcLabel.emplace_back(motherIndex); + } + } + } + } + } + + // sort according to collision ID + auto sortedIndices = sort_indices(v0collisionId); + + // V0 list established, populate + for (auto ic : sortedIndices) { + if (v0collisionId[ic] >= 0 || doUnassociatedV0s) { + v0(v0collisionId[ic], v0positiveIndex[ic], v0negativeIndex[ic]); + fullv0labels(v0mcLabel[ic]); + } + } + } + + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* + /// basic building options (one of them must be chosen) + PROCESS_SWITCH(lambdakzeromcfinder, processFromMcParticles, "Switch to generate from mc particle list (slower)", false); + PROCESS_SWITCH(lambdakzeromcfinder, processFromSingleProngs, "Switch to generate from single prong combinations (faster)", true); + //*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<*>-~-<* }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/TableProducer/lfTPCPID.cxx b/PWGLF/TableProducer/lfTPCPID.cxx index 3d8371c6ae0..286b43c702b 100644 --- a/PWGLF/TableProducer/lfTPCPID.cxx +++ b/PWGLF/TableProducer/lfTPCPID.cxx @@ -19,6 +19,9 @@ // ROOT includes #include "TFile.h" #include "TSystem.h" +#include "TF1.h" +#include "TGraph.h" +#include "TList.h" // O2 includes #include "CCDB/BasicCCDBManager.h" @@ -57,11 +60,25 @@ static constexpr float defaultParameters[nSpecies][nParameters]{{2.f, 2.f, 0.f, {2.f, 2.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}, {2.f, 2.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}, {2.f, 2.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}}; +static constexpr int nOptions = 4; +static const std::vector optionNames{"Bethe Bloch path", // If empty using the default/json values. Can be a CCDB path if the string starts with ccdb:// + "Post calibration path", // If empty using the default/json values. Can be a CCDB path if the string starts with ccdb:// + "Simple Bethe Bloch", // (true/false) + "RequirePostCalib"}; // (true/false) +const std::string defaultOptions[nSpecies][nOptions]{{"", "", "false", "false"}, + {"", "", "false", "false"}, + {"", "", "false", "false"}, + {"", "", "false", "false"}, + {"", "", "false", "false"}, + {"", "", "false", "false"}, + {"", "", "false", "false"}, + {"", "", "false", "false"}, + {"", "", "false", "false"}}; // Structure to hold the parameters struct bbParams { const std::string name; - bbParams(const std::string& n) : name(n){}; + bbParams(const std::string& n) : name(n) {} // Parameters for the Bethe-Bloch parametrization float bb1 = 0.03209809958934784f; // Aleph Bethe Bloch parameter 1 float bb2 = 19.9768009185791f; // Aleph Bethe Bloch parameter 2 @@ -72,15 +89,28 @@ struct bbParams { float exp = 2.299999952316284f; // Exponent of the charge factor float res = 0.1f; // Resolution + TGraph* postCorrection = nullptr; + TGraph* postCorrectionSigma = nullptr; + + TF1* postCorrectionFun = nullptr; + TF1* postCorrectionFunSigma = nullptr; + // Utility parameters for the usage - bool takeFromCcdb = false; - std::string ccdbPath = ""; - int lastRunNumber = 0; + bool betheBlochSet = true; // Flag to check if the Bethe-Bloch parameters have been set. By default is true as the default values are set. Used to check if the parameters have been set after a CCDB update + bool requirePostCalib = true; // Flag to force the post calib. to be required, if not found, it will trigger a fatal error + bool takeFromCcdb = false; // Flag to get the parameters from the CCDB + bool takePostFromCcdb = false; // Flag to get the post calib parameters from the CCDB + std::string ccdbPath = ""; // Path to the CCDB object + std::string ccdbPathPost = ""; // Path to the CCDB object for the post calib + int lastRunNumber = 0; // Last processed run + bool isSimple = false; // Flag to use only the Bethe-Bloch parameters without the charge exponent and the MIP value + /// + /// Set the values of the BetheBloch from an array of parameters bool setValues(std::vector v) { if (v.size() != 8) { - LOG(error) << "bbParams `" << name << "` :: The vector of Bethe-Bloch parameters has the wrong size"; + LOG(fatal) << "bbParams `" << name << "` :: The vector of Bethe-Bloch parameters has the wrong size " << v.size() << " while expecting 8"; return false; } LOG(info) << "bbParams `" << name << "` :: Before: set of parameters -> bb1: " << bb1 << ", bb2: " << bb2 << ", bb3: " << bb3 << ", bb4: " << bb4 << ", bb5: " << bb5 << ", mip: " << mip << ", exp: " << exp << ", resolution " << res; @@ -93,29 +123,21 @@ struct bbParams { exp = v[6]; res = v[7]; LOG(info) << "bbParams `" << name << "` :: After: set of parameters -> bb1: " << bb1 << ", bb2: " << bb2 << ", bb3: " << bb3 << ", bb4: " << bb4 << ", bb5: " << bb5 << ", mip: " << mip << ", exp: " << exp << ", resolution " << res; + betheBlochSet = true; // Bethe bloch parameters are set! return true; } - bool setValues(const char* particle, const Configurable>& p) + /// + /// Set the values of the BetheBloch from TH1F + bool setValues(TH1F* h) { - if (p->get(particle, "Set parameters") < 1.5f) { - LOG(info) << "bbParams `" << name << "` :: Using default parameters for " << particle << " as entry `Set parameters` " << p->get(particle, "Set parameters") << " < 1.5"; + if (!h) { + LOG(fatal) << "bbParams `" << name << "` :: The input histogram of Bethe-Bloch parameters is not valid"; return false; } - std::vector v{p->get(particle, "bb1"), - p->get(particle, "bb2"), - p->get(particle, "bb3"), - p->get(particle, "bb4"), - p->get(particle, "bb5"), - p->get(particle, "MIP value"), - p->get(particle, "Charge exponent"), - p->get(particle, "Resolution")}; - LOG(info) << "bbParams `" << name << "` :: Setting custom Bethe-Bloch parameters for mass hypothesis " << particle; - return setValues(v); - } - - bool setValues(TH1F* h) - { + if (isSimple) { + return setValuesSimple(h); + } const int n = h->GetNbinsX(); TAxis* axis = h->GetXaxis(); std::vector v{static_cast(h->GetBinContent(axis->FindBin("bb1"))), @@ -127,70 +149,290 @@ struct bbParams { static_cast(h->GetBinContent(axis->FindBin("Charge exponent"))), static_cast(h->GetBinContent(axis->FindBin("Resolution")))}; if (h->GetNbinsX() != n) { - LOG(error) << "The input histogram of Bethe-Bloch parameters has the wrong size " << n << " while expecting " << h->GetNbinsX(); + LOG(fatal) << "The input histogram of Bethe-Bloch parameters has the wrong size " << n << " while expecting " << h->GetNbinsX(); return false; } LOG(info) << "bbParams `" << name << "` :: Setting custom Bethe-Bloch parameters from histogram " << h->GetName(); return setValues(v); } - bool setValues(TFile* f) + /// + /// Sets only the Bethe-Bloch parameters without the charge exponent and the MIP value + bool setValuesSimple(TH1F* h) { - if (!f) { - LOG(fatal) << "The input file is not valid"; + const int n = h->GetNbinsX(); + TAxis* axis = h->GetXaxis(); + std::vector v{static_cast(h->GetBinContent(axis->FindBin("bb1"))), + static_cast(h->GetBinContent(axis->FindBin("bb2"))), + static_cast(h->GetBinContent(axis->FindBin("bb3"))), + static_cast(h->GetBinContent(axis->FindBin("bb4"))), + static_cast(h->GetBinContent(axis->FindBin("bb5"))), + 1.f, + 0.f, + static_cast(h->GetBinContent(axis->FindBin("Resolution")))}; + if (h->GetNbinsX() != n) { + LOG(fatal) << "The input histogram of Bethe-Bloch parameters has the wrong size " << n << " while expecting " << h->GetNbinsX(); + return false; } - if (!f->IsOpen()) { - LOG(fatal) << "The input file " << f->GetName() << " is not open"; + // Check that it is indeed simple + axis->FindBin("MIP value"); + axis->FindBin("Charge exponent"); + if (h->GetNbinsX() == n) { + LOG(fatal) << "The input histogram of Bethe-Bloch parameters is compatible with the full parametrization"; + return false; } - TH1F* h = nullptr; - f->GetObject("hpar", h); + LOG(info) << "bbParams `" << name << "` :: Setting simple custom Bethe-Bloch parameters from histogram " << h->GetName(); + return setValues(v); + } + + /// + /// @brief Set the Bethe Bloch calibration from a TList + /// @param l List containing the post calibration objects as TF1 or TGraph + void setValues(TList* l) + { + const char* bbname = Form("BBParameter_%s", name.c_str()); + TH1F* h = static_cast(l->FindObject(bbname)); if (!h) { - LOG(error) << "The input file does not contain the histogram hpar"; - return false; + l->ls(); + LOG(fatal) << "bbParams `" << name << "` :: did not find BetheBloch parametrization " << bbname << " in the input list"; } - LOG(info) << "bbParams `" << name << "` :: Setting parameters from TH1F " << h->GetName() << " in file " << f->GetName(); - return setValues(h); + setValues(h); } - bool setValues(const Configurable& cfg, o2::framework::Service const& ccdbObj) + /// + /// @brief Set the post calibration from a TList + /// @param l List containing the post calibration objects as TF1 or TGraph + void setPostCorrection(TList* l) { - if (cfg.value.size() <= 1) { - return false; + if (!l) { + LOG(fatal) << "bbParams `" << name << "` :: Did not find the post calib list"; + return; + } + + // Reset post calibration + postCorrectionFun = nullptr; + postCorrection = nullptr; + postCorrectionFunSigma = nullptr; + postCorrectionSigma = nullptr; + + TString objname = Form("dEdx_MinusBB_%s", name.c_str()); + TObject* obj = l->FindObject(objname); + if (!obj) { + if (requirePostCalib) { + l->ls(); + LOG(fatal) << "Did not find the post calib object " << objname << ", cannot assign post calibration"; + } + } else { + TString cn = obj->ClassName(); + if (cn.Contains("TF1")) { + postCorrectionFun = static_cast(l->FindObject(obj->GetName())); + } else if (cn.Contains("TGraph")) { + postCorrection = static_cast(l->FindObject(obj->GetName())); + } else { + LOG(fatal) << "Cannot hanlde class " << cn << " for post calib object " << objname; + } + } + + objname = Form("sigmaFitOverSigmaParam_%s", name.c_str()); + obj = l->FindObject(objname); + if (!obj) { + if (requirePostCalib) { + l->ls(); + LOG(fatal) << "Did not find the post calib sigma object " << objname << ", cannot assign post calibration"; + } + } else { + TString cn = obj->ClassName(); + if (cn.Contains("TF1")) { + postCorrectionFunSigma = static_cast(l->FindObject(obj->GetName())); + } else if (cn.Contains("TGraph")) { + postCorrectionSigma = static_cast(l->FindObject(obj->GetName())); + } else { + LOG(fatal) << "Cannot hanlde class " << cn << " for post calib sigma object " << objname; + } + } + LOG(info) << "bbParams `" << name << "` :: Setting post calibration"; + if (l->FindObject("Tag")) { + LOG(info) << " Tag: " << l->FindObject("Tag")->GetTitle(); + } + if (postCorrectionFun) { + LOG(info) << " postCorrection: " << postCorrectionFun->ClassName() << " " << postCorrectionFun->GetName(); + } else if (postCorrection) { + LOG(info) << " postCorrection: " << postCorrection->ClassName() << " " << postCorrection->GetName(); + } else { + LOG(info) << " postCorrection: Not assigned"; + } + if (postCorrectionFunSigma) { + LOG(info) << " postCorrectionSigma: " << postCorrectionFunSigma->ClassName() << " " << postCorrectionFunSigma->GetName(); + } else if (postCorrectionSigma) { + LOG(info) << " postCorrectionSigma: " << postCorrectionSigma->ClassName() << " " << postCorrectionSigma->GetName(); + } else { + LOG(info) << " postCorrectionSigma: Not assigned"; + } + } + + /// + /// Set values from a configuration. In this case also the post calibration is checked + void init(const char* particle, + const Configurable>& confParams, + // const Configurable>& cfg, + const Configurable>& cfg, + o2::framework::Service const& ccdbObj) + { + LOG(info) << "bbParams `" << name << "` :: inizializing parameters from json with particle " << particle; + // First check the json configuration + if (confParams->get(particle, "Set parameters") < 1.5f) { // Keep the default hardcoded values + LOG(info) << "bbParams `" << name << "` :: Using default parameters for " << particle << " as entry `Set parameters` " << confParams->get(particle, "Set parameters") << " < 1.5"; + } else { + LOG(info) << "bbParams `" << name << "` :: Setting custom Bethe-Bloch parameters from JSON for mass hypothesis " << particle; + std::vector v{confParams->get(particle, "bb1"), + confParams->get(particle, "bb2"), + confParams->get(particle, "bb3"), + confParams->get(particle, "bb4"), + confParams->get(particle, "bb5"), + confParams->get(particle, "MIP value"), + confParams->get(particle, "Charge exponent"), + confParams->get(particle, "Resolution")}; + setValues(v); } - LOG(info) << "bbParams `" << name << "` :: Loading parameters from configurable '" << cfg.name << "' with value '" << cfg.value << "'"; - std::string s = cfg.value; - if (s.rfind("ccdb://", 0) == 0) { - s.replace(0, 7, ""); - ccdbPath = s; - if (ccdbObj->getTimestamp() == 0) { // If the timestamp is 0 we expect to get the timestamp from the run number - takeFromCcdb = true; - LOG(info) << "bbParams `" << name << "` :: Asked to query the parameters from the CCDB and got timestamp " << ccdbObj->getTimestamp() << " -> will take the object corresponding to the run number"; - return false; + + // Check the TFile/CCDB configuration + if (cfg.value.size() != 4) { + LOG(fatal) << "bbParams `" << name << "` :: The input configurable has the wrong size " << cfg.value.size() << " while expecting 4"; + } + const std::string bb = cfg.value.at(0); + const std::string post = cfg.value.at(1); + const std::string simple = cfg.value.at(2); + requirePostCalib = (cfg.value.at(3) == "true"); + // const std::string bb = cfg->get(particle, "Bethe Bloch path"); + // const std::string post = cfg->get(particle, "Post calibration path"); + // const std::string simple = cfg->get(particle, "Simple Bethe Bloch"); + // requirePostCalib = (cfg->get(particle, "RequirePostCalib") == "true"); + LOG(info) << "bbParams `" << name << "` :: initializing from configurable '" << cfg.name << "' bb = " << bb << " post = " << post << " simple = " << simple; + if (simple == "true" || simple == "yes") { // Check if the parametrization to be used is simple + LOG(info) << "bbParams `" << name << "` :: using simple BetheBloch parametrization"; + isSimple = true; + } else { + LOG(info) << "bbParams `" << name << "` :: using full BetheBloch parametrization"; + } + + // First we check the post calib. In case the post calib is enabled, the BB parameters should be also coming from same source + if (post.size() > 1) { + if (bb.size() > 1) { + LOG(fatal) << "Cannot define post calibration path and BB parameters path at the same time as the BB parameters will be taken from the post. calib. source. Pick one!"; + } + if (requirePostCalib) { + LOG(info) << "bbParams `" << name << "` :: fatal errors if post calibrations will not be found!"; + } + LOG(info) << "bbParams `" << name << "` :: Loading calib. and post calib. from configurable '" << cfg.name << "' with value '" << post << "'"; + std::string s = post; + if (s.rfind("ccdb://", 0) == 0) { // Getting post calib. from CCDB + s.replace(0, 7, ""); + ccdbPathPost = s; + if (ccdbObj->getTimestamp() == 0) { // If the timestamp is 0 we expect to get the timestamp from the run number + takePostFromCcdb = true; + LOG(info) << "bbParams `" << name << "` :: For post calib asked to query the parameters from the CCDB and got timestamp " << ccdbObj->getTimestamp() << " -> will take the object corresponding to the run number"; + } else { + LOG(info) << "bbParams `" << name << "` :: For post calib fetching parameters from CCDB (only once) using timestamp " << ccdbObj->getTimestamp() << " and path " << s; + TList* l = ccdbObj->get(s); + setPostCorrection(l); + setValues(l); + } + } else { // Getting post calib. from file + TFile* f = TFile::Open(post.c_str(), "READ"); + if (!f) { + LOG(fatal) << "The input file " << post << " is not valid"; + } + if (!f->IsOpen()) { + LOG(fatal) << "The input file " << f->GetName() << " is not open"; + } + TList* l = static_cast(f->Get("ccdb_object")); + if (!l) { + f->ls(); + LOG(fatal) << "The input file " << post << " does not contain the TList ccdb_object"; + } + setPostCorrection(l); + setValues(l); + } + } + + // Check the BetheBloch parameters + if (bb.size() > 1) { + LOG(info) << "bbParams `" << name << "` :: Loading parameters from configurable '" << cfg.name << "' with value '" << bb << "'"; + std::string s = bb; + if (s.rfind("ccdb://", 0) == 0) { // Check if the path is a CCDB path + s.replace(0, 7, ""); + ccdbPath = s; + if (ccdbObj->getTimestamp() == 0) { // If the timestamp is 0 we expect to get the timestamp from the run number + takeFromCcdb = true; + LOG(info) << "bbParams `" << name << "` :: Asked to query the parameters from the CCDB and got timestamp " << ccdbObj->getTimestamp() << " -> will take the object corresponding to the run number"; + } else { + LOG(info) << "bbParams `" << name << "` :: Fetching parameters from CCDB (only once) using timestamp " << ccdbObj->getTimestamp() << " and path " << s; + setValues(ccdbObj->get(s)); + } + } else { // Getting BetheBloch parameters from file + TFile* f = TFile::Open(bb.c_str(), "READ"); + if (!f) { + LOG(fatal) << "The input file " << post << " is not valid"; + } + if (!f->IsOpen()) { + LOG(fatal) << "The input file " << f->GetName() << " is not open"; + } + TH1F* h = nullptr; + f->GetObject("hpar", h); + if (!h) { + // Reattempt with ccdb name + f->GetObject("ccdb_object", h); + if (!h) { + f->ls(); + LOG(fatal) << "The input file does not contain the histograms hpar or ccdb_object"; + } + } + LOG(info) << "bbParams `" << name << "` :: Setting parameters from TH1F " << h->GetName() << " in file " << f->GetName(); + setValues(h); } - LOG(info) << "bbParams `" << name << "` :: Fetching parameters from CCDB (only once) using timestamp " << ccdbObj->getTimestamp() << " and path " << s; - TH1F* h = ccdbObj->get(s); - return setValues(h); } - return setValues(TFile::Open(cfg.value.c_str(), "READ")); } /// @brief Function to update the values of the parameters from the CCDB /// @param ccdbObj Managare of the CCDB /// @param timestamp Timestamp to ask the new parameters /// @return false if not succesfull - bool updateValues(aod::BCsWithTimestamps::iterator const& bunchCrossing, o2::framework::Service const& ccdbObj) + void updateValues(aod::BCsWithTimestamps::iterator const& bunchCrossing, o2::framework::Service const& ccdbObj) { - if (!takeFromCcdb) { - LOG(debug) << "bbParams `" << name << "` :: Not taking parameters from CCDB"; - return false; + if (!takePostFromCcdb && !takeFromCcdb) { + LOG(debug) << "bbParams `" << name << "` :: Requested to not update parameters, ccdb timestamp " << ccdbObj->getTimestamp() << " != 0"; + return; } + // Check that the last updated number is different if (lastRunNumber == bunchCrossing.runNumber()) { LOG(debug) << "bbParams `" << name << "` :: Not updating parameters of " << name << " from run number " << lastRunNumber << " as they are already up to date"; - return false; + return; } + betheBlochSet = false; // Reset the set betheBloch flag as it could also be not found + + // First check the post calib + if (takePostFromCcdb) { + LOG(info) << "bbParams `" << name << "` :: Updating post calib from run number " << lastRunNumber << " to " << bunchCrossing.runNumber() << ". Taking them from CCDB path '" << ccdbPathPost << "' with timestamp " << bunchCrossing.timestamp(); + TList* postL = ccdbObj->getForTimeStamp(ccdbPathPost, bunchCrossing.timestamp()); + if (!postL) { // If the CCDB does not throw a fatal error, we use the centrally provided values + LOG(info) << "bbParams `" << name << "` :: Post calibration input not found on CCDB, using default values"; + return; + } + setPostCorrection(postL); + setValues(postL); + lastRunNumber = bunchCrossing.runNumber(); + return; + } + // Secondly we check the BB parameters LOG(info) << "bbParams `" << name << "` :: Updating parameters of " << name << " from run number " << lastRunNumber << " to " << bunchCrossing.runNumber() << ". Taking them from CCDB path '" << ccdbPath << "' with timestamp " << bunchCrossing.timestamp(); lastRunNumber = bunchCrossing.runNumber(); - return setValues(ccdbObj->getForTimeStamp(ccdbPath, bunchCrossing.timestamp())); + betheBlochSet = false; // Reset the set betheBloch flag as it could also be not found + TH1F* h = ccdbObj->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); + if (!h) { // If the CCDB does not throw a fatal error, we use the centrally provided values + LOG(info) << "bbParams `" << name << "` :: Bethe Bloch calibration input not found on CCDB, using default values"; + return; + } + setValues(h); } }; @@ -222,66 +464,76 @@ struct lfTpcPid { // Input parameters Service ccdb; + Configurable skipTPCOnly{"skipTPCOnly", true, "Flag to skip TPC only tracks (faster but affects the analyses that use TPC only tracks)"}; + Configurable fatalOnNonExisting{"fatalOnNonExisting", true, "Fatal message if calibrations not found on the CCDB"}; // Parameters setting from json Configurable> bbParameters{"bbParameters", {defaultParameters[0], nSpecies, nParameters, particleNames, parameterNames}, "Bethe Bloch parameters"}; // Parameter setting from input file (including the ccdb) - Configurable fileParamBbEl{"fileParamBbEl", - "", - "Parameters for the Bethe-Bloch parametrization for electrons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbMu{"fileParamBbMu", - "", - "Parameters for the Bethe-Bloch parametrization for muons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbPi{"fileParamBbPi", - "", - "Parameters for the Bethe-Bloch parametrization for pions. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbKa{"fileParamBbKa", - "", - "Parameters for the Bethe-Bloch parametrization for kaons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbPr{"fileParamBbPr", - "", - "Parameters for the Bethe-Bloch parametrization for protons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbDe{"fileParamBbDe", - "", - "Parameters for the Bethe-Bloch parametrization for deuterons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbTr{"fileParamBbTr", - "", - "Parameters for the Bethe-Bloch parametrization for tritons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbHe{"fileParamBbHe", - "", - "Parameters for the Bethe-Bloch parametrization for helium3. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbAl{"fileParamBbAl", - "", - "Parameters for the Bethe-Bloch parametrization for helium4. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegEl{"fileParamBbNegEl", - "", - "Parameters for the Bethe-Bloch parametrization for negative electrons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegMu{"fileParamBbNegMu", - "", - "Parameters for the Bethe-Bloch parametrization for negative muons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegPi{"fileParamBbNegPi", - "", - "Parameters for the Bethe-Bloch parametrization for negative pions. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegKa{"fileParamBbNegKa", - "", - "Parameters for the Bethe-Bloch parametrization for negative kaons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegPr{"fileParamBbNegPr", - "", - "Parameters for the Bethe-Bloch parametrization for negative protons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegDe{"fileParamBbNegDe", - "", - "Parameters for the Bethe-Bloch parametrization for negative deuterons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegTr{"fileParamBbNegTr", - "", - "Parameters for the Bethe-Bloch parametrization for negative tritons. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegHe{"fileParamBbNegHe", - "", - "Parameters for the Bethe-Bloch parametrization for negative helium3. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; - Configurable fileParamBbNegAl{"fileParamBbNegAl", - "", - "Parameters for the Bethe-Bloch parametrization for negative helium4. Input file, if empty using the default values, priority over the json configuration. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbEl{"fileParamBbEl", + {"", "", "", ""}, + "Input for the parametrization for electrons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbMu{"fileParamBbMu", + {"", "", "", ""}, + "Input for the parametrization for muons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbPi{"fileParamBbPi", + {"", "", "", ""}, + "Input for the parametrization for pions 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbKa{"fileParamBbKa", + {"", "", "", ""}, + "Input for the parametrization for kaons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbPr{"fileParamBbPr", + {"", "", "", ""}, + "Input for the parametrization for protons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbDe{"fileParamBbDe", + {"", "", "", ""}, + "Input for the parametrization for deuterons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbTr{"fileParamBbTr", + {"", "", "", ""}, + "Input for the parametrization for tritons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbHe{"fileParamBbHe", + {"", "", "", ""}, + "Input for the parametrization for helium3 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbAl{"fileParamBbAl", + {"", "", "", ""}, + "Input for the parametrization for helium4 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegEl{"fileParamBbNegEl", + {"", "", "", ""}, + "Input for the parametrization for negative electrons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegMu{"fileParamBbNegMu", + {"", "", "", ""}, + "Input for the parametrization for negative muons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegPi{"fileParamBbNegPi", + {"", "", "", ""}, + "Input for the parametrization for negative pions 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegKa{"fileParamBbNegKa", + {"", "", "", ""}, + "Input for the parametrization for negative kaons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegPr{"fileParamBbNegPr", + {"", "", "", ""}, + "Input for the parametrization for negative protons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegDe{"fileParamBbNegDe", + {"", "", "", ""}, + "Input for the parametrization for negative deuterons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegTr{"fileParamBbNegTr", + {"", "", "", ""}, + "Input for the parametrization for negative tritons 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegHe{"fileParamBbNegHe", + {"", "", "", ""}, + "Input for the parametrization for negative helium3 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + Configurable> fileParamBbNegAl{"fileParamBbNegAl", + {"", "", "", ""}, + "Input for the parametrization for negative helium4 1) BB 2) Post 3) Simple. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + + // Configurable> fileParamBbPositive{"fileParamBbPositive", + // {defaultOptions[0], nSpecies, nOptions, particleNames, optionNames}, + // "Input for the parametrization for positive particles. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; + + // Configurable> fileParamBbNegative{"fileParamBbNegative", + // {defaultOptions[0], nSpecies, nOptions, particleNames, optionNames}, + // "Input for the parametrization for negative particles. If empty using the default/json values. Can be a CCDB path if the string starts with ccdb://"}; Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbTimestamp{"ccdb-timestamp", -1, "timestamp of the object used to query in CCDB the detector response. If 0 the object corresponding to the run number is used, if < 0 the latest object is used"}; @@ -309,206 +561,217 @@ struct lfTpcPid { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; template - float BetheBlochLf(const T& track, const bbParams& params) + float BetheBlochLf(const T& track, const bbParams& params) const { static constexpr float invmass = 1.f / o2::track::pid_constants::sMasses2Z[id]; static constexpr float charge = o2::track::pid_constants::sCharges[id]; - return params.mip * o2::tpc::BetheBlochAleph(track.tpcInnerParam() * invmass, params.bb1, params.bb2, params.bb3, params.bb4, params.bb5) * std::pow(charge, params.exp); + float corr = 0.f; + if (params.postCorrection != nullptr) { + corr = params.postCorrection->Eval(track.tpcInnerParam()); + } + if (params.postCorrectionFun != nullptr) { + corr = params.postCorrectionFun->Eval(track.tpcInnerParam()); + } + if (params.isSimple) { + return o2::tpc::BetheBlochAleph(track.tpcInnerParam() * invmass, params.bb1, params.bb2, params.bb3, params.bb4, params.bb5) + corr; + } + return params.mip * o2::tpc::BetheBlochAleph(track.tpcInnerParam() * invmass, params.bb1, params.bb2, params.bb3, params.bb4, params.bb5) * std::pow(charge, params.exp) + corr; } template - float BetheBlochEl(const T& track) + float BetheBlochEl(const T& track) const { return BetheBlochLf(track, bbEl); } template - float BetheBlochMu(const T& track) + float BetheBlochMu(const T& track) const { return BetheBlochLf(track, bbMu); } template - float BetheBlochPi(const T& track) + float BetheBlochPi(const T& track) const { return BetheBlochLf(track, bbPi); } template - float BetheBlochKa(const T& track) + float BetheBlochKa(const T& track) const { return BetheBlochLf(track, bbKa); } template - float BetheBlochPr(const T& track) + float BetheBlochPr(const T& track) const { return BetheBlochLf(track, bbPr); } template - float BetheBlochDe(const T& track) + float BetheBlochDe(const T& track) const { return BetheBlochLf(track, bbDe); } template - float BetheBlochTr(const T& track) + float BetheBlochTr(const T& track) const { return BetheBlochLf(track, bbTr); } template - float BetheBlochHe(const T& track) + float BetheBlochHe(const T& track) const { return BetheBlochLf(track, bbHe); } template - float BetheBlochAl(const T& track) + float BetheBlochAl(const T& track) const { return BetheBlochLf(track, bbAl); } template - float BetheBlochNegEl(const T& track) + float BetheBlochNegEl(const T& track) const { return BetheBlochLf(track, bbNegEl); } template - float BetheBlochNegMu(const T& track) + float BetheBlochNegMu(const T& track) const { return BetheBlochLf(track, bbNegMu); } template - float BetheBlochNegPi(const T& track) + float BetheBlochNegPi(const T& track) const { return BetheBlochLf(track, bbNegPi); } template - float BetheBlochNegKa(const T& track) + float BetheBlochNegKa(const T& track) const { return BetheBlochLf(track, bbNegKa); } template - float BetheBlochNegPr(const T& track) + float BetheBlochNegPr(const T& track) const { return BetheBlochLf(track, bbNegPr); } template - float BetheBlochNegDe(const T& track) + float BetheBlochNegDe(const T& track) const { return BetheBlochLf(track, bbNegDe); } template - float BetheBlochNegTr(const T& track) + float BetheBlochNegTr(const T& track) const { return BetheBlochLf(track, bbNegTr); } template - float BetheBlochNegHe(const T& track) + float BetheBlochNegHe(const T& track) const { return BetheBlochLf(track, bbNegHe); } template - float BetheBlochNegAl(const T& track) + float BetheBlochNegAl(const T& track) const { return BetheBlochLf(track, bbNegAl); } template - float BetheBlochResolutionLf(const T& track, const bbParams& params) + float BetheBlochResolutionLf(const T& track, const bbParams& params, const float bb) const { - // static constexpr float invmass = 1.f / o2::track::pid_constants::sMasses[id]; - // static constexpr float charge = o2::track::pid_constants::sCharges[id]; - // const float dEdx = BetheBlochLf(track, params); - // const float deltaP = params.res * std::sqrt(dEdx); - // const float bgDelta = track.tpcInnerParam() * (1.f + deltaP) * invmass; - // const float dEdx2 = params.mip * o2::tpc::BetheBlochAleph(bgDelta, params.bb1, params.bb2, params.bb3, params.bb4, params.bb5) * std::pow(charge, params.exp); - return params.res * BetheBlochLf(track, params); + float corr = 1.f; + if (params.postCorrectionSigma != nullptr) { + corr = params.postCorrectionSigma->Eval(track.tpcInnerParam()); + } + if (params.postCorrectionFunSigma != nullptr) { + corr = params.postCorrectionFunSigma->Eval(track.tpcInnerParam()); + } + return params.res * bb * corr; } template - float BetheBlochResEl(const T& track) + float BetheBlochResEl(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbEl); + return BetheBlochResolutionLf(track, bbEl, bb); } template - float BetheBlochResMu(const T& track) + float BetheBlochResMu(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbMu); + return BetheBlochResolutionLf(track, bbMu, bb); } template - float BetheBlochResPi(const T& track) + float BetheBlochResPi(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbPi); + return BetheBlochResolutionLf(track, bbPi, bb); } template - float BetheBlochResKa(const T& track) + float BetheBlochResKa(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbKa); + return BetheBlochResolutionLf(track, bbKa, bb); } template - float BetheBlochResPr(const T& track) + float BetheBlochResPr(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbPr); + return BetheBlochResolutionLf(track, bbPr, bb); } template - float BetheBlochResDe(const T& track) + float BetheBlochResDe(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbDe); + return BetheBlochResolutionLf(track, bbDe, bb); } template - float BetheBlochResTr(const T& track) + float BetheBlochResTr(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbTr); + return BetheBlochResolutionLf(track, bbTr, bb); } template - float BetheBlochResHe(const T& track) + float BetheBlochResHe(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbHe); + return BetheBlochResolutionLf(track, bbHe, bb); } template - float BetheBlochResAl(const T& track) + float BetheBlochResAl(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbAl); + return BetheBlochResolutionLf(track, bbAl, bb); } template - float BetheBlochResNegEl(const T& track) + float BetheBlochResNegEl(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbEl); + return BetheBlochResolutionLf(track, bbEl, bb); } template - float BetheBlochResNegMu(const T& track) + float BetheBlochResNegMu(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbMu); + return BetheBlochResolutionLf(track, bbMu, bb); } template - float BetheBlochResNegPi(const T& track) + float BetheBlochResNegPi(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbPi); + return BetheBlochResolutionLf(track, bbPi, bb); } template - float BetheBlochResNegKa(const T& track) + float BetheBlochResNegKa(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbKa); + return BetheBlochResolutionLf(track, bbKa, bb); } template - float BetheBlochResNegPr(const T& track) + float BetheBlochResNegPr(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbPr); + return BetheBlochResolutionLf(track, bbPr, bb); } template - float BetheBlochResNegDe(const T& track) + float BetheBlochResNegDe(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbDe); + return BetheBlochResolutionLf(track, bbDe, bb); } template - float BetheBlochResNegTr(const T& track) + float BetheBlochResNegTr(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbTr); + return BetheBlochResolutionLf(track, bbTr, bb); } template - float BetheBlochResNegHe(const T& track) + float BetheBlochResNegHe(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbHe); + return BetheBlochResolutionLf(track, bbHe, bb); } template - float BetheBlochResNegAl(const T& track) + float BetheBlochResNegAl(const T& track, const float bb) const { - return BetheBlochResolutionLf(track, bbAl); + return BetheBlochResolutionLf(track, bbAl, bb); } void init(o2::framework::InitContext& initContext) @@ -524,14 +787,16 @@ struct lfTpcPid { LOGP(info, "Initialising LF TPC PID response for fixed timestamp {}:", ts); ccdb->setTimestamp(ts); } + if (!fatalOnNonExisting) { + LOG(warning) << "Setting the CCDB to not fatal when the object is not found. This means that you have no garantuee that the parameters used are correct. Expert user only!!!"; + ccdb->setFatalWhenNull(false); + } #define InitPerParticle(Particle) \ if (doprocess##Particle || doprocessFull##Particle) { \ LOG(info) << "Enabling " << #Particle; \ - bb##Particle.setValues(#Particle, bbParameters); \ - bb##Particle.setValues(fileParamBb##Particle, ccdb); \ - bbNeg##Particle.setValues(#Particle, bbParameters); \ - bbNeg##Particle.setValues(fileParamBbNeg##Particle, ccdb); \ + bb##Particle.init(#Particle, bbParameters, fileParamBb##Particle, ccdb); \ + bbNeg##Particle.init(#Particle, bbParameters, fileParamBbNeg##Particle, ccdb); \ auto h = histos.add(Form("%s", #Particle), "", kTH1F, {{10, 0, 10}}); \ h->SetBit(TH1::kIsAverage); \ h->SetBinContent(1, bb##Particle.bb1); \ @@ -566,6 +831,13 @@ struct lfTpcPid { } \ } + if (doprocessStandalone) { // If in standalone mode we enable the configuration of tables of interest + LOG(info) << "Processing in standalone mode"; + doprocessFullPi.value = true; + doprocessFullKa.value = true; + doprocessFullPr.value = true; + } + InitPerParticle(El); InitPerParticle(Mu); InitPerParticle(Pi); @@ -576,34 +848,66 @@ struct lfTpcPid { InitPerParticle(He); InitPerParticle(Al); + if (doprocessStandalone) { // If in standalone mode we disable after their configuration the process functions + doprocessFullPi.value = false; + doprocessFullKa.value = false; + doprocessFullPr.value = false; + } + #undef InitPerParticle } -#define makeProcess(Particle) \ - void process##Particle(Colls const& collisions, \ - soa::Join const& tracks, \ - aod::BCsWithTimestamps const&) \ - { \ - LOG(debug) << "Filling table for particle: " << #Particle; \ - tablePID##Particle.reserve(tracks.size()); \ - if (bbParameters->get(#Particle, "Use default tiny") >= 1.5f) { \ - for (auto const& trk : tracks) { \ - tablePID##Particle(trk.tpcNSigmaStore##Particle()); \ - } \ - } else { \ - bb##Particle.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); \ - bbNeg##Particle.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); \ - for (auto const& trk : tracks) { \ - if (trk.sign() > 0) { \ - aod::pidutils::packInTable((trk.tpcSignal() - BetheBloch##Particle(trk)) / BetheBlochRes##Particle(trk), \ - tablePID##Particle); \ - } else { \ - aod::pidutils::packInTable((trk.tpcSignal() - BetheBlochNeg##Particle(trk)) / BetheBlochResNeg##Particle(trk), \ - tablePID##Particle); \ - } \ - } \ - } \ - } \ +#define makeProcess(Particle) \ + void process##Particle(Colls const& collisions, \ + soa::Join const& tracks, \ + aod::BCsWithTimestamps const&) \ + { \ + LOG(debug) << "Filling table for particle: " << #Particle; \ + tablePID##Particle.reserve(tracks.size()); \ + if (bbParameters->get(#Particle, "Use default tiny") >= 1.5f) { \ + for (auto const& trk : tracks) { \ + tablePID##Particle(trk.tpcNSigmaStore##Particle()); \ + } \ + } else { \ + if (!collisions.size()) { \ + LOG(warn) << "No collisions in the data frame. Dummy PID table for " << #Particle; \ + for (unsigned int i{0}; i < tracks.size(); ++i) { \ + tablePID##Particle(aod::pidtpc_tiny::binning::underflowBin); \ + } \ + return; \ + } \ + bb##Particle.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); \ + bbNeg##Particle.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); \ + float bb = 0.f; \ + for (auto const& trk : tracks) { \ + if (!trk.hasTPC()) { \ + tablePID##Particle(aod::pidtpc_tiny::binning::underflowBin); \ + continue; \ + } \ + if (skipTPCOnly) { \ + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { \ + tablePID##Particle(aod::pidtpc_tiny::binning::underflowBin); \ + continue; \ + } \ + } \ + if (trk.sign() > 0) { \ + if (!bb##Particle.betheBlochSet) { \ + tablePID##Particle(trk.tpcNSigmaStore##Particle()); \ + continue; \ + } \ + bb = BetheBloch##Particle(trk); \ + } else { \ + if (!bbNeg##Particle.betheBlochSet) { \ + tablePID##Particle(trk.tpcNSigmaStore##Particle()); \ + continue; \ + } \ + bb = BetheBlochNeg##Particle(trk); \ + } \ + aod::pidutils::packInTable((trk.tpcSignal() - bb) / BetheBlochRes##Particle(trk, bb), \ + tablePID##Particle); \ + } \ + } \ + } \ PROCESS_SWITCH(lfTpcPid, process##Particle, "Produce a table for the " #Particle " hypothesis", false); makeProcess(El); @@ -631,19 +935,44 @@ struct lfTpcPid { tablePIDFull##Particle(trk.tpcExpSigma##Particle(), trk.tpcNSigma##Particle()); \ } \ } else { \ + if (!collisions.size()) { \ + LOG(warn) << "No collisions in the data frame. Dummy PID table for " << #Particle; \ + for (unsigned int i{0}; i < tracks.size(); ++i) { \ + tablePIDFull##Particle(-999.f, -999.f); \ + } \ + return; \ + } \ bb##Particle.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); \ bbNeg##Particle.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); \ + float bb = 0.f; \ float expSigma = 1.f; \ for (auto const& trk : tracks) { \ + if (!trk.hasTPC()) { \ + tablePIDFull##Particle(-999.f, -999.f); \ + continue; \ + } \ + if (skipTPCOnly) { \ + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { \ + tablePIDFull##Particle(-999.f, -999.f); \ + continue; \ + } \ + } \ if (trk.sign() > 0) { \ - expSigma = BetheBlochRes##Particle(trk); \ - tablePIDFull##Particle(expSigma, \ - (trk.tpcSignal() - BetheBloch##Particle(trk)) / expSigma); \ + if (!bb##Particle.betheBlochSet) { \ + tablePIDFull##Particle(trk.tpcExpSigma##Particle(), trk.tpcNSigma##Particle()); \ + continue; \ + } \ + bb = BetheBloch##Particle(trk); \ + expSigma = BetheBlochRes##Particle(trk, bb); \ } else { \ - expSigma = BetheBlochResNeg##Particle(trk); \ - tablePIDFull##Particle(expSigma, \ - (trk.tpcSignal() - BetheBlochNeg##Particle(trk)) / expSigma); \ + if (!bbNeg##Particle.betheBlochSet) { \ + tablePIDFull##Particle(trk.tpcExpSigma##Particle(), trk.tpcNSigma##Particle()); \ + continue; \ + } \ + bb = BetheBlochNeg##Particle(trk); \ + expSigma = BetheBlochResNeg##Particle(trk, bb); \ } \ + tablePIDFull##Particle(expSigma, (trk.tpcSignal() - bb) / expSigma); \ } \ } \ } \ @@ -660,6 +989,73 @@ struct lfTpcPid { makeProcess(Al); #undef makeProcess + + // Full tables (independent on central calibrations) + void processStandalone(Colls const& collisions, + Trks const& tracks, + aod::BCsWithTimestamps const&) + { + bool dummyPID = false; + if (!collisions.size()) { + LOG(warn) << "No collisions in the data frame. Dummy PID table for Pi-Ka-Pr"; + dummyPID = true; + } else { + tablePIDFullPi.reserve(tracks.size()); + bbPi.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); + bbNegPi.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); + tablePIDFullKa.reserve(tracks.size()); + bbKa.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); + bbNegKa.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); + tablePIDFullPr.reserve(tracks.size()); + bbPr.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); + bbNegPr.updateValues(collisions.iteratorAt(0).bc_as(), ccdb); + } + float bb = 0.f; + float expSigma = 1.f; + for (auto const& trk : tracks) { + if (!trk.hasTPC() || dummyPID) { + tablePIDFullPi(-999.f, -999.f); + tablePIDFullKa(-999.f, -999.f); + tablePIDFullPr(-999.f, -999.f); + continue; + } + if (skipTPCOnly) { + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { + tablePIDFullPi(-999.f, -999.f); + tablePIDFullKa(-999.f, -999.f); + tablePIDFullPr(-999.f, -999.f); + continue; + } + } + if (trk.sign() > 0) { + bb = BetheBlochPi(trk); + expSigma = BetheBlochResPi(trk, bb); + } else { + bb = BetheBlochNegPi(trk); + expSigma = BetheBlochResNegPi(trk, bb); + } + tablePIDFullPi(expSigma, (trk.tpcSignal() - bb) / expSigma); + + if (trk.sign() > 0) { + bb = BetheBlochKa(trk); + expSigma = BetheBlochResKa(trk, bb); + } else { + bb = BetheBlochNegKa(trk); + expSigma = BetheBlochResNegKa(trk, bb); + } + tablePIDFullKa(expSigma, (trk.tpcSignal() - bb) / expSigma); + + if (trk.sign() > 0) { + bb = BetheBlochPr(trk); + expSigma = BetheBlochResPr(trk, bb); + } else { + bb = BetheBlochNegPr(trk); + expSigma = BetheBlochResNegPr(trk, bb); + } + tablePIDFullPr(expSigma, (trk.tpcSignal() - bb) / expSigma); + } + } + PROCESS_SWITCH(lfTpcPid, processStandalone, "Produce full tables in a standalone way for Pi-Ka-Pr", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/lithium4analysis.cxx b/PWGLF/TableProducer/lithium4analysis.cxx new file mode 100644 index 00000000000..127de74ba8c --- /dev/null +++ b/PWGLF/TableProducer/lithium4analysis.cxx @@ -0,0 +1,617 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// Analysis task for anti-lithium4 analysis + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Framework/ASoAHelpers.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "CCDB/BasicCCDBManager.h" + +#include "PWGLF/DataModel/LFLithium4Tables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +namespace +{ +constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; +static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; + +constexpr float he3Mass = o2::constants::physics::MassHelium3; +constexpr float protonMass = o2::constants::physics::MassProton; +constexpr int lithium4PDG = 1000030040; +constexpr int protonPDG = 2212; +constexpr int he3PDG = 1000020030; + +enum Selections { + kNoCuts = 0, + kGlobalTrack, + kTrackCuts, + kPID, + kAll +}; + +} // namespace + +struct lithium4Candidate { + + float recoPtHe3() const { return std::hypot(momHe3[0], momHe3[1]); } + float recoPhiHe3() const { return std::atan2(momHe3[1], momHe3[0]); } + float recoEtaHe3() const { return std::asinh(momHe3[2] / recoPtHe3()); } + float recoPtPr() const { return std::hypot(momPr[0], momPr[1]); } + float recoPhiPr() const { return std::atan2(momPr[1], momPr[0]); } + float recoEtaPr() const { return std::asinh(momPr[2] / recoPtPr()); } + + std::array momHe3; + std::array momPr; + + float nSigmaHe3 = -10; + float nSigmaPr = -10; + float massTOFHe3 = -10; + float massTOFPr = -10; + + float he3DCAXY = -10; + float he3DCAZ = -10; + float protonDCAXY = -10; + float protonDCAZ = -10; + uint16_t tpcSignalHe3 = 0u; + float momHe3TPC = -10.f; + float momPrTPC = -10.f; + float invMass = -10.f; + uint8_t nTPCClustersHe3 = 0u; + + uint8_t sharedClustersHe3 = 0u; + uint8_t sharedClustersPr = 0u; + + bool isBkgUS = false; + bool isBkgEM = false; + bool isMatter = false; + + float l4PtMC = -10.f; + float l4MassMC = -10.f; +}; + +struct lithium4analysis { + + Produces outputDataTable; + Produces outputMCTable; + + std::vector l4Candidates; + + SliceCache cache; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + // events + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + // track + Configurable cfgCutPT{"cfgCutPT", 0.2, "PT cut on daughter track"}; + Configurable cfgCutMaxPrPT{"cfgCutMaxPrPT", 1.8, "Max PT cut on proton"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; + Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmaCutTOF{"nsigmaCutTOF", 3.0, "Value of the TOF Nsigma cut"}; + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; + Configurable cfgEnableBkgUS{"cfgEnableBkgUS", false, "Enable US background"}; + + // bethe bloch parameters + std::array mBBparamsHe; + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 1, 6, {"He3"}, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for He3"}; + // MC + Configurable isMC{"isMC", false, "Run MC"}; + void init(o2::framework::InitContext&) + { + + histos.add("hCentrality", "Centrality distribution", kTH1F, {{2001, -0.5, 2000.5}}); + histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); + histos.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 2000.0f}}); + histos.add("hHe3Dcaxy", ";DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hHe3Dcaz", ";DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hLitInvMass", "; M(^{3}He + p) (GeV/#it{c}^{2})", kTH1F, {{50, 3.74f, 3.85f}}); + histos.add("hHe3Pt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", kTH1F, {{200, 0.0f, 6.0f}}); + histos.add("hProtonPt", "Pt distribution; #it{p}_{T} (GeV/#it{c})", kTH1F, {{200, 0.0f, 3.0f}}); + histos.add("h2NsigmaHe3TPC", "NsigmaHe3 TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}({}^{3}He)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); + histos.add("h2NsigmaProtonTPC", "NsigmaProton TPC distribution; Signed #it{p}/#it{z} (GeV/#it{c}); n#sigma_{TPC}(p)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); + histos.add("h2NsigmaProtonTOF", "NsigmaProton TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}); + histos.add("hTrackSel", "Accepted tracks", kTH1F, {{Selections::kAll, -0.5, Selections::kAll - 0.5}}); + + for (int i = 0; i < 5; i++) { + mBBparamsHe[i] = cfgBetheBlochParams->get("He3", Form("p%i", i)); + } + mBBparamsHe[5] = cfgBetheBlochParams->get("He3", "resolution"); + + std::vector labels = {"All", "Global track", "Track selection", "PID {}^{3}He"}; + for (int i = 0; i < Selections::kAll; i++) { + histos.get(HIST("hTrackSel"))->GetXaxis()->SetBinLabel(i + 1, labels[i].c_str()); + } + } + + template + bool selectionTrack(const T& candidate) + { + + if (candidate.itsNCls() < 5 || + candidate.tpcNClsFound() < 70 || + candidate.tpcNClsCrossedRows() < 70 || + candidate.tpcNClsCrossedRows() < 0.8 * candidate.tpcNClsFindable() || + candidate.tpcChi2NCl() > 4.f || + candidate.itsChi2NCl() > 36.f) { + return false; + } + + return true; + } + + template + bool selectionPIDProton(const T& candidate) + { + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPr()) < nsigmaCutTOF && std::abs(candidate.tpcNSigmaPr()) < nsigmaCutTPC) { + histos.fill(HIST("h2NsigmaProtonTPC"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); + histos.fill(HIST("h2NsigmaProtonTOF"), candidate.p(), candidate.tofNSigmaPr()); + return true; + } + } else if (std::abs(candidate.tpcNSigmaPr()) < nsigmaCutTPC) { + histos.fill(HIST("h2NsigmaProtonTPC"), candidate.tpcInnerParam(), candidate.tpcNSigmaPr()); + return true; + } + return false; + } + + template + float computeNSigmaHe3(const T& candidate) + { + float expTPCSignal = o2::tpc::BetheBlochAleph(static_cast(candidate.tpcInnerParam() * 2 / constants::physics::MassHelium3), mBBparamsHe[0], mBBparamsHe[1], mBBparamsHe[2], mBBparamsHe[3], mBBparamsHe[4]); + double resoTPC{expTPCSignal * mBBparamsHe[5]}; + return static_cast((candidate.tpcSignal() - expTPCSignal) / resoTPC); + } + + template + bool selectionPIDHe3(const T& candidate) + { + auto nSigmaHe3 = computeNSigmaHe3(candidate); + if (std::abs(nSigmaHe3) < nsigmaCutTPC) { + return true; + } + return false; + } + + template + bool FillCandidateInfo(const T1& candidateHe3, const T2& candidatePr, bool mix, bool isMC = false) + { + lithium4Candidate l4Cand; + + l4Cand.momHe3 = array{2 * candidateHe3.px(), 2 * candidateHe3.py(), 2 * candidateHe3.pz()}; + l4Cand.momPr = array{candidatePr.px(), candidatePr.py(), candidatePr.pz()}; + + float invMass = RecoDecay::m(array{l4Cand.momHe3, l4Cand.momPr}, array{he3Mass, protonMass}); + + if (invMass < 3.74 || invMass > 3.85 || candidatePr.pt() > cfgCutMaxPrPT) { + return false; + } + + int he3Sign = candidateHe3.sign(); + int protonSign = candidatePr.sign(); + + l4Cand.isBkgUS = he3Sign * protonSign < 0; + l4Cand.isBkgEM = mix; + l4Cand.isMatter = he3Sign > 0; + l4Cand.he3DCAXY = candidateHe3.dcaXY(); + l4Cand.he3DCAZ = candidateHe3.dcaZ(); + l4Cand.protonDCAXY = candidatePr.dcaXY(); + l4Cand.protonDCAZ = candidatePr.dcaZ(); + l4Cand.tpcSignalHe3 = candidateHe3.tpcSignal(); + l4Cand.momHe3TPC = candidateHe3.tpcInnerParam(); + l4Cand.momPrTPC = candidatePr.tpcInnerParam(); + l4Cand.invMass = invMass; + + l4Cand.nTPCClustersHe3 = candidateHe3.tpcNClsFound(); + l4Cand.nSigmaHe3 = computeNSigmaHe3(candidateHe3); + l4Cand.nSigmaPr = candidatePr.tpcNSigmaPr(); + + l4Cand.sharedClustersHe3 = candidateHe3.tpcNClsShared(); + l4Cand.sharedClustersPr = candidatePr.tpcNClsShared(); + + l4Candidates.push_back(l4Cand); + return true; + } + + template + void fillHistograms(const T& l4cand) + { + int candSign = l4cand.isMatter ? 1 : -1; + histos.fill(HIST("hHe3Pt"), l4cand.recoPtHe3()); + histos.fill(HIST("hProtonPt"), l4cand.recoPtPr()); + histos.fill(HIST("hLitInvMass"), l4cand.invMass); + histos.fill(HIST("hHe3Dcaxy"), l4cand.he3DCAXY); + histos.fill(HIST("hHe3Dcaz"), l4cand.he3DCAZ); + histos.fill(HIST("h2NsigmaHe3TPC"), candSign * l4cand.momHe3TPC, l4cand.nSigmaHe3); + histos.fill(HIST("h2NsigmaProtonTPC"), candSign * l4cand.momPrTPC, l4cand.nSigmaPr); + histos.fill(HIST("h2NsigmaProtonTOF"), l4cand.recoPtPr(), l4cand.nSigmaPr); + } + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); + Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + + using EventCandidates = soa::Filtered>; + using TrackCandidates = soa::Filtered>; + using TrackCandidatesMC = soa::Filtered>; + o2::pid::tof::Beta responseBeta; + o2::pid::tof::Beta responseBetaMC; + + Preslice perCol = aod::track::collisionId; + Preslice perColMC = aod::track::collisionId; + + // binning for EM background + ConfigurableAxis axisVertex{"axisVertex", {30, -10, 10}, "vertex axis for bin"}; + using BinningType = ColumnBinningPolicy; + BinningType binningOnPositions{{axisVertex}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, &cache}; + + void processSameEvent(soa::Join const& collisions, TrackCandidates const& tracks, aod::BCs const&) + { + l4Candidates.clear(); + + for (auto& collision : collisions) { + if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) { + continue; + } + histos.fill(HIST("hNcontributor"), collision.numContrib()); + histos.fill(HIST("hVtxZ"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto TrackTable_thisCollision = tracks.sliceBy(perCol, collIdx); + TrackTable_thisCollision.bindExternalIndices(&tracks); + + for (auto track1 : TrackTable_thisCollision) { + + histos.fill(HIST("hTrackSel"), Selections::kNoCuts); + + if (!track1.isGlobalTrackWoDCA()) { + continue; + } + histos.fill(HIST("hTrackSel"), Selections::kGlobalTrack); + + if (!selectionTrack(track1)) { + continue; + } + histos.fill(HIST("hTrackSel"), Selections::kTrackCuts); + + if (!selectionPIDHe3(track1)) { + continue; + } + histos.fill(HIST("hTrackSel"), Selections::kPID); + + for (auto track2 : TrackTable_thisCollision) { + + if (track1 == track2) { + continue; + } + + if (!cfgEnableBkgUS) { + if (track1.sign() * track2.sign() < 0) { + continue; + } + } + + if (!track2.isGlobalTrackWoDCA()) { + continue; + } + + if (!selectionTrack(track2)) { + continue; + } + + if (!selectionPIDProton(track2)) { + continue; + } + + if (!FillCandidateInfo(track1, track2, false)) { + continue; + } + // fill TOF info outside to avoide responseBeta crash + auto& cand = l4Candidates.back(); + if (track1.hasTOF()) { + float beta = responseBeta.GetBeta(track1); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + cand.massTOFHe3 = track1.tpcInnerParam() * 2 * std::sqrt(1.f / (beta * beta) - 1.f); + } + if (track2.hasTOF()) { + float beta = responseBeta.GetBeta(track2); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + cand.massTOFPr = track2.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); + } + fillHistograms(cand); + } + } + } + + for (auto& l4Cand : l4Candidates) { + outputDataTable(l4Cand.isMatter, l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), + l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), + l4Cand.he3DCAXY, l4Cand.he3DCAZ, l4Cand.protonDCAXY, l4Cand.protonDCAZ, + l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.nTPCClustersHe3, l4Cand.nSigmaHe3, + l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, l4Cand.sharedClustersHe3, + l4Cand.sharedClustersPr, l4Cand.isBkgUS, l4Cand.isBkgEM); + } + } + PROCESS_SWITCH(lithium4analysis, processSameEvent, "Process Same event", false); + + void processMixedEvent(EventCandidates& collisions, TrackCandidates const& tracks) + { + l4Candidates.clear(); + for (auto& [c1, tracks1, c2, tracks2] : pair) { + if (!c1.sel8()) { + continue; + } + if (!c2.sel8()) { + continue; + } + histos.fill(HIST("hNcontributor"), c1.numContrib()); + histos.fill(HIST("hVtxZ"), c1.posZ()); + + for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + + if (!t1.isGlobalTrackWoDCA()) { + continue; + } + + if (!selectionTrack(t1)) { + continue; + } + + if (!t2.isGlobalTrackWoDCA()) { + continue; + } + + if (!selectionTrack(t2)) { + continue; + } + + TrackCandidates::iterator he3Cand, protonCand; + bool passPID = false; + if (selectionPIDHe3(t1) && selectionPIDProton(t2)) { + he3Cand = t1, protonCand = t2; + passPID = true; + } + if (selectionPIDHe3(t2) && selectionPIDProton(t1)) { + he3Cand = t2, protonCand = t1; + passPID = true; + } + if (!passPID) { + continue; + } + + if (!FillCandidateInfo(he3Cand, protonCand, true)) { + continue; + } + // fill TOF info outside to avoide responseBeta crash + auto& cand = l4Candidates.back(); + if (he3Cand.hasTOF()) { + float beta = responseBeta.GetBeta(he3Cand); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + cand.massTOFHe3 = he3Cand.tpcInnerParam() * 2 * std::sqrt(1.f / (beta * beta) - 1.f); + } + if (protonCand.hasTOF()) { + float beta = responseBeta.GetBeta(protonCand); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + cand.massTOFPr = protonCand.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); + } + fillHistograms(cand); + } + } + + for (auto& l4Cand : l4Candidates) { + outputDataTable(l4Cand.isMatter, l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), + l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), + l4Cand.he3DCAXY, l4Cand.he3DCAZ, l4Cand.protonDCAXY, l4Cand.protonDCAZ, + l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.nTPCClustersHe3, l4Cand.nSigmaHe3, + l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, l4Cand.sharedClustersHe3, + l4Cand.sharedClustersPr, l4Cand.isBkgUS, l4Cand.isBkgEM); + } + } + PROCESS_SWITCH(lithium4analysis, processMixedEvent, "Process Mixed event", false); + + void processMC(soa::Join const& collisions, aod::BCs const&, TrackCandidatesMC const& tracks, aod::McParticles const& mcParticles) + { + std::vector filledMothers; + l4Candidates.clear(); + + for (auto& collision : collisions) { + + if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) { + continue; + } + + histos.fill(HIST("hNcontributor"), collision.numContrib()); + histos.fill(HIST("hVtxZ"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto TrackTable_thisCollision = tracks.sliceBy(perColMC, collIdx); + TrackTable_thisCollision.bindExternalIndices(&tracks); + + for (auto track1 : TrackTable_thisCollision) { + + if (!track1.has_mcParticle()) { + continue; + } + + histos.fill(HIST("hTrackSel"), Selections::kNoCuts); + + if (!track1.isGlobalTrackWoDCA()) { + continue; + } + histos.fill(HIST("hTrackSel"), Selections::kGlobalTrack); + + if (!selectionTrack(track1)) { + continue; + } + histos.fill(HIST("hTrackSel"), Selections::kTrackCuts); + + if (!selectionPIDHe3(track1)) { + continue; + } + histos.fill(HIST("hTrackSel"), Selections::kPID); + + for (auto track2 : TrackTable_thisCollision) { + if (!track2.has_mcParticle()) { + continue; + } + + if (!track2.isGlobalTrackWoDCA()) { + continue; + } + + if (!selectionTrack(track2)) { + continue; + } + + if (!selectionPIDProton(track2)) { + continue; + } + + if (track1.sign() * track2.sign() < 0) { + continue; + } + + const auto mctrackHe3 = track1.mcParticle(); + const auto mctrackPr = track2.mcParticle(); + + if (std::abs(mctrackHe3.pdgCode()) != he3PDG || std::abs(mctrackPr.pdgCode()) != protonPDG) { + continue; + } + + for (auto& mothertrack : mctrackHe3.mothers_as()) { + for (auto& mothertrackPr : mctrackPr.mothers_as()) { + + if (mothertrack != mothertrackPr || std::abs(mothertrack.pdgCode()) != lithium4PDG) { + continue; + } + + if (std::abs(mothertrack.y()) > 1) { + continue; + } + + if (!FillCandidateInfo(track1, track2, false, true)) { + continue; + } + + // fill TOF info outside to avoide responseBeta crash + auto& cand = l4Candidates.back(); + if (track1.hasTOF()) { + float beta = responseBetaMC.GetBeta(track1); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + cand.massTOFHe3 = track1.tpcInnerParam() * 2 * std::sqrt(1.f / (beta * beta) - 1.f); + } + if (track2.hasTOF()) { + float beta = responseBetaMC.GetBeta(track2); + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + cand.massTOFPr = track2.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); + } + cand.l4PtMC = mothertrack.pt(); + double eLit = mctrackHe3.e() + mctrackPr.e(); + cand.l4MassMC = std::sqrt(eLit * eLit - mothertrack.p() * mothertrack.p()); + filledMothers.push_back(mothertrack.globalIndex()); + fillHistograms(cand); + } + } + } + } + } + + for (auto& mcParticle : mcParticles) { + + if (std::abs(mcParticle.pdgCode()) != lithium4PDG) { + continue; + } + + if (std::abs(mcParticle.y()) > 1 || mcParticle.isPhysicalPrimary() == false) { + continue; + } + + if (std::find(filledMothers.begin(), filledMothers.end(), mcParticle.globalIndex()) != filledMothers.end()) { + continue; + } + + auto kDaughters = mcParticle.daughters_as(); + auto daughtHe3 = false; + auto daughtPr = false; + double eLit = 0; + for (auto kCurrentDaughter : kDaughters) { + if (std::abs(kCurrentDaughter.pdgCode()) == he3PDG) { + daughtHe3 = true; + eLit += kCurrentDaughter.e(); + } else if (std::abs(kCurrentDaughter.pdgCode()) == protonPDG) { + daughtPr = true; + eLit += kCurrentDaughter.e(); + } + } + if (daughtHe3 && daughtPr) { + lithium4Candidate l4Candidate; + int sign = mcParticle.pdgCode() > 0 ? 1 : -1; + l4Candidate.l4PtMC = mcParticle.pt() * sign; + l4Candidate.l4MassMC = std::sqrt(eLit * eLit - mcParticle.p() * mcParticle.p()); + l4Candidates.push_back(l4Candidate); + } + } + + for (auto& l4Cand : l4Candidates) { + outputMCTable(l4Cand.isMatter, l4Cand.recoPtHe3(), l4Cand.recoEtaHe3(), l4Cand.recoPhiHe3(), + l4Cand.recoPtPr(), l4Cand.recoEtaPr(), l4Cand.recoPhiPr(), + l4Cand.he3DCAXY, l4Cand.he3DCAZ, l4Cand.protonDCAXY, l4Cand.protonDCAZ, + l4Cand.tpcSignalHe3, l4Cand.momHe3TPC, l4Cand.nTPCClustersHe3, l4Cand.nSigmaHe3, + l4Cand.nSigmaPr, l4Cand.massTOFHe3, l4Cand.massTOFPr, l4Cand.sharedClustersHe3, + l4Cand.sharedClustersPr, l4Cand.isBkgUS, l4Cand.isBkgEM, + l4Cand.l4PtMC, l4Cand.l4MassMC); + } + } + PROCESS_SWITCH(lithium4analysis, processMC, "Process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"lithium4analysis"})}; +} diff --git a/PWGLF/TableProducer/nucleiSpectra.cxx b/PWGLF/TableProducer/nucleiSpectra.cxx index 92b0ea5a302..c274277a548 100644 --- a/PWGLF/TableProducer/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/nucleiSpectra.cxx @@ -54,109 +54,88 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -uint8_t getBinnedValue(double val, double max) -{ - if (val >= max) { - return 255u; - } else if (val < -max) { - return 0u; - } else { - return 1u + static_cast(254 * (val - max) / (2 * max)); - } -} - -float getBinCenter(uint8_t bin, double max) -{ - if (bin == 0u) { - return -max; - } else if (bin == 255u) { - return max; - } else { - return -max + (bin + 0.5) / (2 * max); - } -} - struct NucleusCandidate { - NucleusCandidate(int idx, float aPt, float aEta, float aphi, uint8_t z, uint8_t aITSclsMap, uint8_t aTPCnCls, uint8_t aDCAxy, uint8_t aDCAz, uint16_t aFlags, uint8_t aTPCnsigma, uint8_t aTOFmass) : globalIndex{idx}, pt{aPt}, eta{aEta}, phi{aphi}, zVertex{z}, ITSclsMap{aITSclsMap}, TPCnCls{aTPCnCls}, DCAxy{aDCAxy}, DCAz{aDCAz}, flags{aFlags}, TPCnsigma{aTPCnsigma}, TOFmass{aTOFmass} - { - } int globalIndex; float pt; float eta; float phi; - uint8_t zVertex; + float tpcInnerParam; + float beta; + float zVertex; + float DCAxy; + float DCAz; + float TPCsignal; + float ITSchi2; + float TPCchi2; + uint16_t flags; + uint8_t TPCfindableCls; + uint8_t TPCcrossedRows; uint8_t ITSclsMap; uint8_t TPCnCls; - uint8_t DCAxy; - uint8_t DCAz; - uint16_t flags; - uint8_t TPCnsigma; - uint8_t TOFmass; }; namespace nuclei { -constexpr double bbMomScalingDefault[4][2]{ +constexpr double bbMomScalingDefault[5][2]{ + {1., 1.}, {1., 1.}, {1., 1.}, {1., 1.}, {1., 1.}}; -constexpr double betheBlochDefault[4][6]{ +constexpr double betheBlochDefault[5][6]{ + {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; -constexpr double nSigmaTPCdefault[4][2]{ +constexpr double nSigmaTPCdefault[5][2]{ + {-5., 5.}, {-5., 5.}, {-5., 5.}, {-5., 5.}, {-5., 5.}}; -// constexpr double nSigmaTOFdefault[4][2]{ +// constexpr double nSigmaTOFdefault[5][2]{ +// {-5., 5.}, // {-5., 5.}, // {-5., 5.}, // {-5., 5.}, // {-5., 5.}}; -constexpr double DCAcutDefault[4][2]{ +constexpr double DCAcutDefault[5][2]{ + {1., 1.}, {1., 1.}, {1., 1.}, {1., 1.}, {1., 1.}}; -constexpr int TreeConfigDefault[4][2]{ +constexpr int TreeConfigDefault[5][2]{ + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}; -constexpr double BinnedVariablesDefaultMax[5][1]{ - {1.27}, - {1.27}, - {5.08}, - {5.08}, - {5.08}}; -// constexpr bool storeTreesDefault[4]{false, false, false, false}; -constexpr int species{4}; -constexpr int codes[4]{1000010020, 1000010030, 1000020030, 1000020040}; -constexpr float charges[4]{1.f, 1.f, 2.f, 2.f}; -constexpr float masses[4]{MassDeuteron, MassTriton, MassHelium3, MassAlpha}; +// constexpr bool storeTreesDefault[5]{false, false, false, false, false}; +constexpr int species{5}; +constexpr int codes[5]{2212, 1000010020, 1000010030, 1000020030, 1000020040}; +constexpr float charges[5]{1.f, 1.f, 1.f, 2.f, 2.f}; +constexpr float masses[5]{MassProton, MassDeuteron, MassTriton, MassHelium3, MassAlpha}; static const std::vector matter{"M", "A"}; static const std::vector pidName{"TPC", "TOF"}; -static const std::vector names{"deuteron", "triton", "He3", "alpha"}; +static const std::vector names{"proton", "deuteron", "triton", "He3", "alpha"}; static const std::vector treeConfigNames{"Filter trees", "Use TOF selection"}; static const std::vector nSigmaConfigName{"nsigma_min", "nsigma_max"}; static const std::vector nDCAConfigName{"max DCAxy", "max DCAz"}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; static const std::vector binnedVariableNames{"DCAxy", "DCAz", "TPCnsigma", "TOFnsigma", "TOFmass"}; -static const std::vector binnedLabelNames{"Maximum value of binned variables"}; static const std::vector chargeLabelNames{"Positive", "Negative"}; -float pidCuts[2][4][2]; -std::shared_ptr hNsigma[2][4][2]; -std::shared_ptr hTOFmass[4][2]; -std::shared_ptr hGenNuclei[4][2]; -std::shared_ptr hMomRes[4][2]; -std::shared_ptr hNsigmaEta[2][4][2]; -std::shared_ptr hTOFmassEta[4][2]; -std::shared_ptr hDCAxy[2][4][2]; -std::shared_ptr hDCAz[2][4][2]; +float pidCuts[2][5][2]; +std::shared_ptr hNsigma[2][5][2]; +std::shared_ptr hTOFmass[5][2]; +std::shared_ptr hGenNuclei[5][2]; +std::shared_ptr hMomRes[5][2]; +std::shared_ptr hNsigmaEta[2][5][2]; +std::shared_ptr hTOFmassEta[5][2]; +std::shared_ptr hDCAxy[2][5][2]; +std::shared_ptr hDCAz[2][5][2]; std::shared_ptr hGloTOFtracks[2]; o2::base::MatLayerCylSet* lut = nullptr; @@ -165,16 +144,18 @@ std::vector candidates; struct nucleiSpectra { enum { - kDeuteron = BIT(0), - kTriton = BIT(1), - kHe3 = BIT(2), - kHe4 = BIT(3), - kHasTOF = BIT(4), - kIsReconstructed = BIT(5), - kIsAmbiguous = BIT(6), /// just a placeholder now - kIsPhysicalPrimary = BIT(8), /// MC flags starting from the second half of the short - kIsSecondaryFromMaterial = BIT(9), - kIsSecondaryFromWeakDecay = BIT(10) + kProton = BIT(0), + kDeuteron = BIT(1), + kTriton = BIT(2), + kHe3 = BIT(3), + kHe4 = BIT(4), + kHasTOF = BIT(5), + kIsReconstructed = BIT(6), + kIsAmbiguous = BIT(7), /// just a placeholder now + kPositive = BIT(8), + kIsPhysicalPrimary = BIT(9), /// MC flags starting from the second half of the short + kIsSecondaryFromMaterial = BIT(10), + kIsSecondaryFromWeakDecay = BIT(11) }; Produces nucleiTable; @@ -191,18 +172,19 @@ struct nucleiSpectra { Configurable cfgCutNclusITS{"cfgCutNclusITS", 5, "Minimum number of ITS clusters"}; Configurable cfgCutNclusTPC{"cfgCutNclusTPC", 70, "Minimum number of TPC clusters"}; - Configurable> cfgMomentumScalingBetheBloch{"cfgMomentumScalingBetheBloch", {nuclei::bbMomScalingDefault[0], 4, 2, nuclei::names, nuclei::chargeLabelNames}, "TPC Bethe-Bloch momentum scaling for light nuclei"}; - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {nuclei::betheBlochDefault[0], 4, 6, nuclei::names, nuclei::betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; - Configurable> cfgNsigmaTPC{"cfgNsigmaTPC", {nuclei::nSigmaTPCdefault[0], 4, 2, nuclei::names, nuclei::nSigmaConfigName}, "TPC nsigma selection for light nuclei"}; - Configurable> cfgDCAcut{"cfgDCAcut", {nuclei::DCAcutDefault[0], 4, 2, nuclei::names, nuclei::nDCAConfigName}, "Max DCAxy and DCAz for light nuclei"}; - Configurable> cfgTreeConfig{"cfgTreeConfig", {nuclei::TreeConfigDefault[0], 4, 2, nuclei::names, nuclei::treeConfigNames}, "Filtered trees configuration"}; - Configurable> cfgBinnedVariables{"cfgBinnedVariables", {nuclei::BinnedVariablesDefaultMax[0], 5, 1, nuclei::binnedVariableNames, nuclei::binnedLabelNames}, "Maximum value for the binned variables"}; + Configurable> cfgMomentumScalingBetheBloch{"cfgMomentumScalingBetheBloch", {nuclei::bbMomScalingDefault[0], 5, 2, nuclei::names, nuclei::chargeLabelNames}, "TPC Bethe-Bloch momentum scaling for light nuclei"}; + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {nuclei::betheBlochDefault[0], 5, 6, nuclei::names, nuclei::betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable> cfgNsigmaTPC{"cfgNsigmaTPC", {nuclei::nSigmaTPCdefault[0], 5, 2, nuclei::names, nuclei::nSigmaConfigName}, "TPC nsigma selection for light nuclei"}; + Configurable> cfgDCAcut{"cfgDCAcut", {nuclei::DCAcutDefault[0], 5, 2, nuclei::names, nuclei::nDCAConfigName}, "Max DCAxy and DCAz for light nuclei"}; + Configurable> cfgTreeConfig{"cfgTreeConfig", {nuclei::TreeConfigDefault[0], 5, 2, nuclei::names, nuclei::treeConfigNames}, "Filtered trees configuration"}; + ConfigurableAxis cfgDCAxyBinsProtons{"cfgDCAxyBinsProtons", {1500, -1.5f, 1.5f}, "DCAxy binning for Protons"}; ConfigurableAxis cfgDCAxyBinsDeuterons{"cfgDCAxyBinsDeuterons", {1500, -1.5f, 1.5f}, "DCAxy binning for Deuterons"}; ConfigurableAxis cfgDCAxyBinsTritons{"cfgDCAxyBinsTritons", {1500, -1.5f, 1.5f}, "DCAxy binning for Tritons"}; ConfigurableAxis cfgDCAxyBinsHe3{"cfgDCAxyBinsHe3", {1500, -1.5f, 1.5f}, "DCAxy binning for He3"}; ConfigurableAxis cfgDCAxyBinsAlpha{"cfgDCAxyBinsAlpha", {1500, -1.5f, 1.5f}, "DCAxy binning for Alpha"}; + ConfigurableAxis cfgPtBinsProtons{"cfgPtBinsProtons", {100, 0., 10.}, "Pt binning for Protons"}; ConfigurableAxis cfgPtBinsDeuterons{"cfgPtBinsDeuterons", {100, 0., 10.}, "Pt binning for Deuterons"}; ConfigurableAxis cfgPtBinsTritons{"cfgPtBinsTritons", {100, 0., 10.}, "Pt binning for Tritons"}; ConfigurableAxis cfgPtBinsHe3{"cfgPtBinsHe3", {100, 0., 10.}, "Pt binning for He3"}; @@ -271,17 +253,20 @@ struct nucleiSpectra { const AxisSpec tofMassAxis{cfgTOFmassBins, "TOF mass - PDG mass"}; const AxisSpec ptResAxis{cfgMomResBins, "#Delta#it{p}_{T}/#it{p}_{T}"}; - const AxisSpec ptAxes[4]{ + const AxisSpec ptAxes[5]{ + {cfgPtBinsProtons, "#it{p}_{T} (GeV/#it{c})"}, {cfgPtBinsDeuterons, "#it{p}_{T} (GeV/#it{c})"}, {cfgPtBinsTritons, "#it{p}_{T} (GeV/#it{c})"}, {cfgPtBinsHe3, "#it{p}_{T} (GeV/#it{c})"}, {cfgPtBinsAlpha, "#it{p}_{T} (GeV/#it{c})"}}; - const AxisSpec dcaxyAxes[4]{ + const AxisSpec dcaxyAxes[5]{ + {cfgDCAxyBinsProtons, "DCA_{xy} (cm)"}, {cfgDCAxyBinsDeuterons, "DCA_{xy} (cm)"}, {cfgDCAxyBinsTritons, "DCA_{xy} (cm)"}, {cfgDCAxyBinsHe3, "DCA_{xy} (cm)"}, {cfgDCAxyBinsAlpha, "DCA_{xy} (cm)"}}; - const AxisSpec dcazAxes[4]{ + const AxisSpec dcazAxes[5]{ + {cfgDCAxyBinsProtons, "DCA_{z} (cm)"}, {cfgDCAxyBinsDeuterons, "DCA_{z} (cm)"}, {cfgDCAxyBinsTritons, "DCA_{z} (cm)"}, {cfgDCAxyBinsHe3, "DCA_{z} (cm)"}, @@ -310,7 +295,7 @@ struct nucleiSpectra { } } - for (int iS{0}; iS < 4; ++iS) { + for (int iS{0}; iS < nuclei::species; ++iS) { for (int iMax{0}; iMax < 2; ++iMax) { nuclei::pidCuts[0][iS][iMax] = cfgNsigmaTPC->get(iS, iMax); } @@ -326,7 +311,6 @@ struct nucleiSpectra { auto bc = collision.bc_as(); initCCDB(bc); - nuclei::candidates.clear(); // collision process loop if (!collision.sel8()) { return; @@ -334,13 +318,13 @@ struct nucleiSpectra { spectra.fill(HIST("hRecVtxZData"), collision.posZ()); const o2::math_utils::Point3D collVtx{collision.posX(), collision.posY(), collision.posZ()}; - uint8_t zVert{getBinnedValue(collision.posZ(), 10.16)}; - const double bgScalings[4][2]{ + const double bgScalings[5][2]{ {nuclei::charges[0] * cfgMomentumScalingBetheBloch->get(0u, 0u) / nuclei::masses[0], nuclei::charges[0] * cfgMomentumScalingBetheBloch->get(0u, 1u) / nuclei::masses[0]}, {nuclei::charges[1] * cfgMomentumScalingBetheBloch->get(1u, 0u) / nuclei::masses[1], nuclei::charges[1] * cfgMomentumScalingBetheBloch->get(1u, 1u) / nuclei::masses[1]}, {nuclei::charges[2] * cfgMomentumScalingBetheBloch->get(2u, 0u) / nuclei::masses[2], nuclei::charges[2] * cfgMomentumScalingBetheBloch->get(2u, 1u) / nuclei::masses[2]}, - {nuclei::charges[3] * cfgMomentumScalingBetheBloch->get(3u, 0u) / nuclei::masses[3], nuclei::charges[3] * cfgMomentumScalingBetheBloch->get(3u, 1u) / nuclei::masses[3]}}; + {nuclei::charges[3] * cfgMomentumScalingBetheBloch->get(3u, 0u) / nuclei::masses[3], nuclei::charges[3] * cfgMomentumScalingBetheBloch->get(3u, 1u) / nuclei::masses[3]}, + {nuclei::charges[4] * cfgMomentumScalingBetheBloch->get(3u, 0u) / nuclei::masses[4], nuclei::charges[4] * cfgMomentumScalingBetheBloch->get(3u, 1u) / nuclei::masses[4]}}; int nGloTracks[2]{0, 0}, nTOFTracks[2]{0, 0}; for (auto& track : tracks) { // start loop over tracks @@ -353,9 +337,9 @@ struct nucleiSpectra { continue; } spectra.fill(HIST("hTpcSignalData"), track.tpcInnerParam() * track.sign(), track.tpcSignal()); - float nSigma[2][4]{ - {-10., -10., -10., -10.}, - {0.f, 0.f, 0.f, 0.f}}; /// then we will calibrate the TOF mass for the He3 and Alpha + float nSigma[2][5]{ + {-10., -10., -10., -10., -10.}, + {0.f, 0.f, 0.f, 0.f, 0.f}}; /// then we will calibrate the TOF mass for the He3 and Alpha const int iC{track.sign() < 0}; /// Checking if we have outliers in the TPC-TOF correlation @@ -364,7 +348,7 @@ struct nucleiSpectra { nTOFTracks[iC]++; } - bool selectedTPC[4]{false}, goodToAnalyse{false}; + bool selectedTPC[5]{false}, goodToAnalyse{false}; for (int iS{0}; iS < nuclei::species; ++iS) { double expBethe{tpc::BetheBlochAleph(static_cast(track.tpcInnerParam() * bgScalings[iS][iC]), cfgBetheBlochParams->get(iS, 0u), cfgBetheBlochParams->get(iS, 1u), cfgBetheBlochParams->get(iS, 2u), cfgBetheBlochParams->get(iS, 3u), cfgBetheBlochParams->get(iS, 4u))}; double expSigma{expBethe * cfgBetheBlochParams->get(iS, 5u)}; @@ -383,7 +367,14 @@ struct nucleiSpectra { float beta{responseBeta.GetBeta(track)}; spectra.fill(HIST("hTpcSignalDataSelected"), track.tpcInnerParam() * track.sign(), track.tpcSignal()); spectra.fill(HIST("hTofSignalData"), track.tpcInnerParam(), beta); - beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be chec + beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked + uint16_t flag{kIsReconstructed}; + if (track.hasTOF()) { + flag |= kHasTOF; + } + if (!iC) { + flag |= kPositive; + } for (int iS{0}; iS < nuclei::species; ++iS) { bool selectedTOF{false}; if (std::abs(dcaInfo[1]) > cfgDCAcut->get(iS, 1)) { @@ -391,9 +382,6 @@ struct nucleiSpectra { } ROOT::Math::LorentzVector> fvector{trackParCov.getPt() * nuclei::charges[iS], trackParCov.getEta(), trackParCov.getPhi(), nuclei::masses[iS]}; float y{fvector.Rapidity() + cfgCMrapidity}; - if (cfgCutOnReconstructedRapidity && (y < cfgCutRapidityMin || y > cfgCutRapidityMax)) { - continue; - } for (int iPID{0}; iPID < 2; ++iPID) { if (selectedTPC[iS]) { @@ -402,40 +390,35 @@ struct nucleiSpectra { } else if (iPID) { selectedTOF = true; } - nuclei::hDCAxy[iPID][iS][iC]->Fill(1., fvector.pt(), dcaInfo[0]); - nuclei::hDCAz[iPID][iS][iC]->Fill(1., fvector.pt(), dcaInfo[1]); - if (std::abs(dcaInfo[0]) < cfgDCAcut->get(iS, 0u)) { - if (!iPID) { /// temporary exclusion of the TOF nsigma PID for the He3 and Alpha - nuclei::hNsigma[iPID][iS][iC]->Fill(1., fvector.pt(), nSigma[iPID][iS]); - nuclei::hNsigmaEta[iPID][iS][iC]->Fill(fvector.eta(), fvector.pt(), nSigma[iPID][iS]); - } - if (iPID) { - float mass{track.tpcInnerParam() * nuclei::charges[iS] * std::sqrt(1.f / (beta * beta) - 1.f) - nuclei::masses[iS]}; - nuclei::hTOFmass[iS][iC]->Fill(1., fvector.pt(), mass); - nuclei::hTOFmassEta[iS][iC]->Fill(fvector.eta(), fvector.pt(), mass); + if (!cfgCutOnReconstructedRapidity || (y > cfgCutRapidityMin && y < cfgCutRapidityMax)) { + nuclei::hDCAxy[iPID][iS][iC]->Fill(1., fvector.pt(), dcaInfo[0]); + nuclei::hDCAz[iPID][iS][iC]->Fill(1., fvector.pt(), dcaInfo[1]); + if (std::abs(dcaInfo[0]) < cfgDCAcut->get(iS, 0u)) { + if (!iPID) { /// temporary exclusion of the TOF nsigma PID for the He3 and Alpha + nuclei::hNsigma[iPID][iS][iC]->Fill(1., fvector.pt(), nSigma[iPID][iS]); + nuclei::hNsigmaEta[iPID][iS][iC]->Fill(fvector.eta(), fvector.pt(), nSigma[iPID][iS]); + } + if (iPID) { + float mass{track.tpcInnerParam() * nuclei::charges[iS] * std::sqrt(1.f / (beta * beta) - 1.f) - nuclei::masses[iS]}; + nuclei::hTOFmass[iS][iC]->Fill(1., fvector.pt(), mass); + nuclei::hTOFmassEta[iS][iC]->Fill(fvector.eta(), fvector.pt(), mass); + } } } } } - uint16_t flag{kIsReconstructed}; + if (cfgTreeConfig->get(iS, 0u) && selectedTPC[iS]) { - uint8_t massTOF{0u}; if (cfgTreeConfig->get(iS, 1u) && !selectedTOF) { continue; } - if (track.hasTOF()) { - flag |= kHasTOF; - float mass{track.tpcInnerParam() * nuclei::charges[iS] * std::sqrt(1.f / (beta * beta) - 1.f) - nuclei::masses[iS]}; - massTOF = getBinnedValue(mass, cfgBinnedVariables->get(3u, 1u)); - } flag |= BIT(iS); - uint8_t dcaxy = getBinnedValue(dcaInfo[0], cfgBinnedVariables->get(0u, 1u)); - uint8_t dcaz = getBinnedValue(dcaInfo[1], cfgBinnedVariables->get(1u, 1u)); - uint8_t nsigmaTPC = getBinnedValue(nSigma[0][iS], cfgBinnedVariables->get(2u, 1u)); - - nuclei::candidates.emplace_back(track.globalIndex(), track.sign() * fvector.pt(), fvector.eta(), fvector.phi(), zVert, track.itsClusterMap(), track.tpcNClsFound(), dcaxy, dcaz, flag, nsigmaTPC, massTOF); } } + if (flag & (kProton | kDeuteron | kTriton | kHe3 | kHe4)) { + nuclei::candidates.emplace_back(NucleusCandidate{static_cast(track.globalIndex()), (1 - 2 * iC) * trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), track.tpcInnerParam(), beta, collision.posZ(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), + track.tpcChi2NCl(), flag, track.tpcNClsFindable(), static_cast(track.tpcNClsCrossedRows()), track.itsClusterMap(), static_cast(track.tpcNClsFound())}); + } } // end loop over tracks nuclei::hGloTOFtracks[0]->Fill(nGloTracks[0], nTOFTracks[0]); @@ -444,9 +427,10 @@ struct nucleiSpectra { void processData(soa::Filtered>::iterator const& collision, TrackCandidates const& tracks, aod::BCsWithTimestamps const&) { + nuclei::candidates.clear(); fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { - nucleiTable(c.pt, c.eta, c.phi, c.zVertex, c.ITSclsMap, c.TPCnCls, c.DCAxy, c.DCAz, c.flags, c.TPCnsigma, c.TOFmass); + nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls); } } PROCESS_SWITCH(nucleiSpectra, processData, "Data analysis", true); @@ -454,6 +438,7 @@ struct nucleiSpectra { Preslice tracksPerCollisions = aod::track::collisionId; void processMC(soa::Filtered> const& collisions, TrackCandidates const& tracks, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, aod::BCsWithTimestamps const&) { + nuclei::candidates.clear(); for (auto& collision : collisions) { const auto& slicedTracks = tracks.sliceBy(tracksPerCollisions, collision.globalIndex()); fillDataInfo(collision, slicedTracks); @@ -474,7 +459,7 @@ struct nucleiSpectra { c.flags |= kIsSecondaryFromMaterial; } - nucleiTableMC(c.pt, c.eta, c.phi, c.zVertex, c.ITSclsMap, c.TPCnCls, c.DCAxy, c.DCAz, c.flags, c.TPCnsigma, c.TOFmass, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode()); + nucleiTableMC(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode()); for (int iS{0}; iS < nuclei::species; ++iS) { if (std::abs(particle.pdgCode()) == nuclei::codes[iS]) { nuclei::hMomRes[iS][particle.pdgCode() < 0]->Fill(1., std::abs(c.pt), 1. - std::abs(c.pt) / particle.pt()); @@ -503,7 +488,7 @@ struct nucleiSpectra { } if (!isReconstructed[index] && (cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u))) { - nucleiTableMC(0, 0, 0, 0, 0, 0, 0, 0, flags, 0, 0, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode()); + nucleiTableMC(999., 999., 999., 0., 0., 999., 999., 999., -1, -1, -1, flags, 0, 0, 0, 0, particle.pt(), particle.eta(), particle.phi(), particle.pdgCode()); } break; } diff --git a/PWGLF/TableProducer/spectraDerivedMaker.cxx b/PWGLF/TableProducer/spectraDerivedMaker.cxx new file mode 100644 index 00000000000..e6013e70283 --- /dev/null +++ b/PWGLF/TableProducer/spectraDerivedMaker.cxx @@ -0,0 +1,391 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file spectraTOF.cxx +/// \author Nicolò Jacazio nicolo.jacazio@cern.ch +/// +/// \brief Task for the analysis of the spectra with the TOF detector. +/// Depending on the configuration it can also run on tiny tables. +/// + +// O2 includes +#include "ReconstructionDataFormats/Track.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/TrackSelection.h" +#include "Framework/StaticFor.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/spectraTOF.h" + +#include "TPDGCode.h" + +using namespace o2; +using namespace o2::track; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct spectraDerivedMaker { + Configurable cfgNSigmaCut{"cfgNSigmaCut", 10.f, "Value of the Nsigma cut"}; + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable cfgCutY{"cfgCutY", 0.5f, "Y range for tracks"}; + Configurable fractionOfEvents{"fractionOfEvents", 2.f, "Downsampling factor for the events for derived data"}; + ConfigurableAxis binsMultiplicity{"binsMultiplicity", {100, 0, 100}, "Binning for multiplicity"}; + ConfigurableAxis binsPercentile{"binsPercentile", {100, 0, 100}, "Binning for percentiles"}; + Configurable multiplicityEstimator{"multiplicityEstimator", 0, "Flag to use a multiplicity estimator: 0 no multiplicity, 1 MultFV0M, 2 MultFT0M, 3 MultFDDM, 4 MultTracklets, 5 MultTPC, 6 MultNTracksPV, 7 MultNTracksPVeta1, 8 CentralityFT0C, 9 CentralityFT0M, 10 CentralityFV0A"}; + // Custom track cuts for the cut variation study + TrackSelection customTrackCuts; + Configurable itsPattern{"itsPattern", 1, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; + Configurable requireITS{"requireITS", true, "Additional cut on the ITS requirement"}; + Configurable requireTPC{"requireTPC", true, "Additional cut on the TPC requirement"}; + Configurable requireGoldenChi2{"requireGoldenChi2", true, "Additional cut on the GoldenChi2"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 60.f, "Additional cut on the minimum number of crossed rows in the TPC"}; + Configurable minNCrossedRowsOverFindableClustersTPC{"minNCrossedRowsOverFindableClustersTPC", 0.7f, "Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC"}; + Configurable maxChi2PerClusterTPC{"maxChi2PerClusterTPC", 7.f, "Additional cut on the maximum value of the chi2 per cluster in the TPC"}; + Configurable maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Additional cut on the maximum value of the DCA xy (multiplicative factor)"}; + Configurable maxDcaZ{"maxDcaZ", 3.f, "Additional cut on the maximum value of the DCA z"}; + Configurable minTPCNClsFound{"minTPCNClsFound", 0.f, "Additional cut on the minimum value of the number of found clusters in the TPC"}; + + // Histograms + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + // Custom track cuts + LOG(info) << "Using custom track cuts from values:"; + LOG(info) << "\trequireITS=" << requireITS.value; + LOG(info) << "\trequireTPC=" << requireTPC.value; + LOG(info) << "\trequireGoldenChi2=" << requireGoldenChi2.value; + LOG(info) << "\tmaxChi2PerClusterTPC=" << maxChi2PerClusterTPC.value; + LOG(info) << "\tminNCrossedRowsTPC=" << minNCrossedRowsTPC.value; + LOG(info) << "\tminTPCNClsFound=" << minTPCNClsFound.value; + LOG(info) << "\tmaxChi2PerClusterITS=" << maxChi2PerClusterITS.value; + LOG(info) << "\tmaxDcaZ=" << maxDcaZ.value; + + customTrackCuts = getGlobalTrackSelectionRun3ITSMatch(itsPattern.value); + LOG(info) << "Customizing track cuts:"; + customTrackCuts.SetRequireITSRefit(requireITS.value); + customTrackCuts.SetRequireTPCRefit(requireTPC.value); + customTrackCuts.SetRequireGoldenChi2(requireGoldenChi2.value); + customTrackCuts.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); + customTrackCuts.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); + customTrackCuts.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); + customTrackCuts.SetMinNClustersTPC(minTPCNClsFound.value); + customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + customTrackCuts.SetMaxDcaXYPtDep([](float pt) { return 10.f; }); // No DCAxy cut will be used, this is done via the member function of the task + customTrackCuts.SetMaxDcaZ(maxDcaZ.value); + customTrackCuts.print(); + // Histograms + const AxisSpec vtxZAxis{100, -20, 20, "Vtx_{z} (cm)"}; + + histos.add("event/vertexz", "", HistType::kTH1D, {vtxZAxis}); + histos.add("event/sampledvertexz", "Sampled collisions", HistType::kTH1D, {vtxZAxis}); + auto h = histos.add("evsel", "evsel", HistType::kTH1D, {{10, 0.5, 10.5}}); + h->GetXaxis()->SetBinLabel(1, "Events read"); + h->GetXaxis()->SetBinLabel(2, "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(3, "INEL>1 (fraction)"); + h->GetXaxis()->SetBinLabel(4, "Ev. sel. passed"); + h->GetXaxis()->SetBinLabel(5, "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(6, "INEL>1 (fraction)"); + h->GetXaxis()->SetBinLabel(7, "posZ passed"); + h->GetXaxis()->SetBinLabel(8, "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(9, "INEL>1 (fraction)"); + + h = histos.add("tracksel", "tracksel", HistType::kTH1D, {{10, 0.5, 10.5}}); + h->GetXaxis()->SetBinLabel(1, "Tracks read"); + h->GetXaxis()->SetBinLabel(2, Form("|#eta| < %.2f", cfgCutEta.value)); + h->GetXaxis()->SetBinLabel(3, "Quality passed"); + h->GetXaxis()->SetBinLabel(4, "TOF passed (partial)"); + + h = histos.add("evtime_tof", "event time selections from pidEvTimeFlags", kTH1D, {{10, -0.5, 9.5}}); + h->GetXaxis()->SetBinLabel(1, "AnyEvTime"); + h->GetXaxis()->SetBinLabel(2, "EvTimeDefined"); + h->GetXaxis()->SetBinLabel(3, "EvTimeTOF"); + h->GetXaxis()->SetBinLabel(4, "EvTimeT0AC"); + h->GetXaxis()->SetBinLabel(5, "EvTimeTOFT0AC"); + h->GetXaxis()->SetBinLabel(6, "AnyEvTime (selected)"); + h->GetXaxis()->SetBinLabel(7, "EvTimeDefined (selected)"); + h->GetXaxis()->SetBinLabel(8, "EvTimeTOF (selected)"); + h->GetXaxis()->SetBinLabel(9, "EvTimeT0AC (selected)"); + h->GetXaxis()->SetBinLabel(10, "EvTimeTOFT0AC (selected)"); + + histos.add("Centrality/FV0A", "FV0A", HistType::kTH1D, {{binsPercentile, "Centrality FV0A"}}); + histos.add("Centrality/FT0M", "FT0M", HistType::kTH1D, {{binsPercentile, "Centrality FT0M"}}); + histos.add("Centrality/FT0A", "FT0A", HistType::kTH1D, {{binsPercentile, "Centrality FT0A"}}); + histos.add("Centrality/FT0C", "FT0C", HistType::kTH1D, {{binsPercentile, "Centrality FT0C"}}); + histos.add("Centrality/FDDM", "FDDM", HistType::kTH1D, {{binsPercentile, "Centrality FDDM"}}); + histos.add("Centrality/NTPV", "NTPV", HistType::kTH1D, {{binsPercentile, "Centrality NTPV"}}); + + histos.add("Mult/FV0M", "MultFV0M", HistType::kTH1D, {{binsMultiplicity, "MultFV0M"}}); + histos.add("Mult/FT0M", "MultFT0M", HistType::kTH1D, {{binsMultiplicity, "MultFT0M"}}); + histos.add("Mult/FDDM", "MultFDDM", HistType::kTH1D, {{binsMultiplicity, "MultFDDM"}}); + + histos.add("Mult/Tracklets", "MultTracklets", HistType::kTH1D, {{binsMultiplicity, "MultTracklets"}}); + histos.add("Mult/TPC", "MultTPC", HistType::kTH1D, {{binsMultiplicity, "MultTPC"}}); + histos.add("Mult/NTracksPV", "MultNTracksPV", HistType::kTH1D, {{binsMultiplicity, "MultNTracksPV"}}); + histos.add("Mult/NTracksPVeta1", "MultNTracksPVeta1", HistType::kTH1D, {{binsMultiplicity, "MultNTracksPVeta1"}}); + + if (doprocessMC) { + auto hh = histos.add("MC/GenRecoCollisions", "Generated and Reconstructed MC Collisions", kTH1D, {{10, 0.5, 10.5}}); + hh->GetXaxis()->SetBinLabel(1, "Collisions generated"); + hh->GetXaxis()->SetBinLabel(2, "Collisions reconstructed"); + hh->GetXaxis()->SetBinLabel(3, "INEL>0"); + hh->GetXaxis()->SetBinLabel(4, "INEL>1"); + hh->GetXaxis()->SetBinLabel(5, "hasParticleInFT0C && hasParticleInFT0A"); + } + } + + template + bool isEventSelected(CollisionType const& collision, TrackType const& tracks) + { + if constexpr (fillHistograms) { + histos.fill(HIST("evsel"), 1.f); + } + if constexpr (fillHistograms) { + if (collision.multNTracksPVeta1() >= 1) { + histos.fill(HIST("evsel"), 2.f); + } + if (collision.multNTracksPVeta1() >= 2) { + histos.fill(HIST("evsel"), 3.f); + } + } + if (!collision.sel8()) { + return false; + } + if constexpr (fillHistograms) { + histos.fill(HIST("evsel"), 4.f); + if (collision.multNTracksPVeta1() >= 1) { + histos.fill(HIST("evsel"), 5.f); + } + if (collision.multNTracksPVeta1() >= 2) { + histos.fill(HIST("evsel"), 6.f); + } + } + if (abs(collision.posZ()) > cfgCutVertex) { + return false; + } + if constexpr (fillHistograms) { + histos.fill(HIST("evsel"), 7.f); + if (collision.multNTracksPVeta1() >= 1) { + histos.fill(HIST("evsel"), 8.f); + } + if (collision.multNTracksPVeta1() >= 2) { + histos.fill(HIST("evsel"), 9.f); + } + histos.fill(HIST("event/vertexz"), collision.posZ()); + + if constexpr (fillMultiplicity) { + histos.fill(HIST("Centrality/FV0A"), collision.centFV0A()); + histos.fill(HIST("Centrality/FT0M"), collision.centFT0M()); + histos.fill(HIST("Centrality/FT0A"), collision.centFT0A()); + histos.fill(HIST("Centrality/FT0C"), collision.centFT0C()); + // histos.fill(HIST("Centrality/FDDM"), collision.centFDDM()); + // histos.fill(HIST("Centrality/NTPV"), collision.centNTPV()); + + histos.fill(HIST("Mult/FV0M"), collision.multZeqFV0A()); + histos.fill(HIST("Mult/FT0M"), collision.multZeqFT0A() + collision.multZeqFT0C()); + histos.fill(HIST("Mult/FDDM"), collision.multZeqFDDA() + collision.multZeqFDDC()); + + histos.fill(HIST("Mult/Tracklets"), collision.multTracklets()); + histos.fill(HIST("Mult/TPC"), collision.multTPC()); + histos.fill(HIST("Mult/NTracksPV"), collision.multZeqNTracksPV()); + histos.fill(HIST("Mult/NTracksPVeta1"), collision.multNTracksPVeta1()); + } + } + + // Last thing, check the sampling + if (fractionOfEvents < 1.f && (static_cast(rand_r(&randomSeed)) / static_cast(RAND_MAX)) > fractionOfEvents) { // Skip events that are not sampled + return false; + } + if constexpr (fillHistograms) { + histos.fill(HIST("event/sampledvertexz"), collision.posZ()); + } + return true; + } + + template + bool passesCutWoDCA(TrackType const& track) const + { + if (customTrackCuts.IsSelected(track)) { + return true; + } + return false; + } + + template + bool isTrackSelected(TrackType const& track) + { + if constexpr (fillHistograms) { + histos.fill(HIST("tracksel"), 1); + } + if (abs(track.eta()) > cfgCutEta) { + return false; + } + if constexpr (fillHistograms) { + histos.fill(HIST("tracksel"), 2); + } + + if (!passesCutWoDCA(track)) { + return false; + } + + if constexpr (fillHistograms) { + histos.fill(HIST("tracksel"), 3); + if (track.hasTOF()) { + histos.fill(HIST("tracksel"), 4); + } + } + return true; + } + + using CollisionCandidate = soa::Join; + using TrackCandidates = soa::Join; + + Produces tableColl; + Produces tableTrack; + unsigned int randomSeed = 0; + void processData(CollisionCandidate::iterator const& collision, + soa::Join const& tracks, + aod::BCs const&) + { + if (!isEventSelected(collision, tracks)) { + return; + } + + tableColl(collision.numContrib(), + collision.posX(), + collision.posY(), + collision.posZ(), + collision.centFT0M(), + collision.sel8(), + collision.multNTracksPVeta1(), + collision.bc().runNumber()); + + tableTrack.reserve(tracks.size()); + for (const auto& trk : tracks) { + if (!isTrackSelected(trk)) { + continue; + } + + tableTrack(tableColl.lastIndex(), + o2::aod::spectra::packInTable(trk.tpcNSigmaPi()), + o2::aod::spectra::packInTable(trk.tpcNSigmaKa()), + o2::aod::spectra::packInTable(trk.tpcNSigmaPr()), + o2::aod::spectra::packInTable(trk.tofNSigmaPi()), + o2::aod::spectra::packInTable(trk.tofNSigmaKa()), + o2::aod::spectra::packInTable(trk.tofNSigmaPr()), + trk.pt() * trk.sign(), trk.eta(), trk.phi(), + trk.length(), + trk.tpcSignal(), + trk.tpcChi2NCl(), trk.itsChi2NCl(), trk.tofChi2(), + trk.tpcNClsShared(), + trk.tpcNClsFindable(), + trk.tpcNClsFindableMinusFound(), + trk.tpcNClsFindableMinusCrossedRows(), + trk.isPVContributor(), + trk.itsClusterMap(), + trk.hasTRD(), + trk.tofFlags(), + o2::aod::spectra::packInTable(trk.dcaXY()), + o2::aod::spectra::packInTable(trk.dcaZ()), + trk.isGlobalTrack(), + trk.isGlobalTrackWoDCA()); + } + } + PROCESS_SWITCH(spectraDerivedMaker, processData, "Process data for derived dataset production", true); + + using CollisionCandidateMC = soa::Join; // RD + + Preslice perMCCol = aod::mcparticle::mcCollisionId; + SliceCache cache; + void processMC(soa::Join const& tracks, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions, + CollisionCandidateMC const& collisions) + { + // Fill number of generated and reconstructed collisions for normalization + histos.fill(HIST("MC/GenRecoCollisions"), 1.f, mcCollisions.size()); + histos.fill(HIST("MC/GenRecoCollisions"), 2.f, collisions.size()); + + // Loop on generated particles + for (const auto& mcParticle : mcParticles) { + if (std::abs(mcParticle.y()) > cfgCutY) { + continue; + } + } + + // Loop on reconstructed collisions + for (const auto& collision : collisions) { + if (!collision.has_mcCollision()) { + continue; + } + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, collision.mcCollision().globalIndex(), cache); + for (const auto& mcParticle : particlesInCollision) { + if (std::abs(mcParticle.y()) > cfgCutY) { + continue; + } + } + } + + // Loop on generated collisions + for (const auto& mcCollision : mcCollisions) { + const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + bool hasParticleInFT0C = false; + bool hasParticleInFT0A = false; + + int nInelPart = 0; + for (const auto& mcParticle : particlesInCollision) { + if (mcParticle.isPhysicalPrimary()) { + if (mcParticle.eta() >= -3.4f && mcParticle.eta() <= -2.3f) { // Acceptance of the FT0C + hasParticleInFT0C = true; + } + if (mcParticle.eta() >= 3.8f && mcParticle.eta() <= 5.0f) { // Acceptance of the FT0A + hasParticleInFT0A = true; + } + if (std::abs(mcParticle.eta()) < 1.f) { + nInelPart++; + } + } + + if (std::abs(mcParticle.y()) > cfgCutY) { + continue; + } + } + if (nInelPart >= 1) { + histos.fill(HIST("MC/GenRecoCollisions"), 3.f); + } + if (nInelPart >= 2) { + histos.fill(HIST("MC/GenRecoCollisions"), 4.f); + } + if (hasParticleInFT0C && hasParticleInFT0A) { + histos.fill(HIST("MC/GenRecoCollisions"), 5.f); + } + } + } + PROCESS_SWITCH(spectraDerivedMaker, processMC, "Process MC for derived dataset production", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } \ No newline at end of file diff --git a/PWGLF/TableProducer/threebodymcfinder.cxx b/PWGLF/TableProducer/threebodymcfinder.cxx index 4ecc695b077..4ddfebb3157 100644 --- a/PWGLF/TableProducer/threebodymcfinder.cxx +++ b/PWGLF/TableProducer/threebodymcfinder.cxx @@ -33,9 +33,9 @@ #include "ReconstructionDataFormats/Track.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/PIDResponse.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFQATables.h" #include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" @@ -214,7 +214,7 @@ struct threebodymcfinder { // Step 1: sweep over all mcCollisions and find all relevant candidates for (auto const& mcCollision : mcCollisions) { - histos.fill(HIST("hNTimesCollRecoed"), mcCollision.hasRecoCollision()); + histos.fill(HIST("hNTimesCollRecoed"), mcCollision.numRecoCollision()); int bestCollisionIndex = mcCollision.bestCollisionIndex(); auto mcParticles = allMcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); diff --git a/PWGLF/TableProducer/v0qaanalysis.cxx b/PWGLF/TableProducer/v0qaanalysis.cxx index 84203c823fa..a3c6d6212e8 100644 --- a/PWGLF/TableProducer/v0qaanalysis.cxx +++ b/PWGLF/TableProducer/v0qaanalysis.cxx @@ -260,7 +260,7 @@ struct v0qaanalysis { continue; } - if (std::abs(mcParticle.pdgCode() == 211)) { + if (std::abs(mcParticle.pdgCode()) == 211) { if (mcParticle.eta() <= -2.3 && mcParticle.eta() >= -3.4) { isFT0C = true; } diff --git a/PWGLF/Tasks/AntimatterAbsorptionHMPID.cxx b/PWGLF/Tasks/AntimatterAbsorptionHMPID.cxx new file mode 100644 index 00000000000..3490e7b9ec3 --- /dev/null +++ b/PWGLF/Tasks/AntimatterAbsorptionHMPID.cxx @@ -0,0 +1,673 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \author Alberto Caliva (alberto.caliva@cern.ch) +/// \since June 27, 2023 + +#include +#include +#include +#include +#include +#include + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/DataTypes.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/PID/PIDTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" + +#include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/TrackParametrization.h" +#include "ReconstructionDataFormats/TrackParametrizationWithError.h" +#include "ReconstructionDataFormats/DCA.h" + +#include "PWGLF/DataModel/LFParticleIdentification.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +struct AntimatterAbsorptionHMPID { + + // Registry Data + HistogramRegistry pos_reg{"positive_tracks", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry neg_reg{"negative_tracks", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry pion_pos_reg{"pion_pos", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry kaon_pos_reg{"kaon_pos", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry proton_reg{"proton", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry deuteron_reg{"deuteron", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry pion_neg_reg{"pion_neg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry kaon_neg_reg{"kaon_neg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry antiproton_reg{"antiproton", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry antideuteron_reg{"antideuteron", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Registry MC + HistogramRegistry pion_plus_MC_reg{"pion_plus_MC_reg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry pion_minus_MC_reg{"pion_minus_MC_reg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry kaon_plus_MC_reg{"kaon_plus_MC_reg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry kaon_minus_MC_reg{"kaon_minus_MC_reg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry proton_MC_reg{"proton_MC_reg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry antiproton_MC_reg{"antiproton_MC_reg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry deuteron_MC_reg{"deuteron_MC_reg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry antideuteron_MC_reg{"antideuteron_MC_reg", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + void init(o2::framework::InitContext&) + { + + std::vector momentum_bin_edges = {0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, 1.55, 1.6, 1.65, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2.0, 2.05, 2.1, 2.15, 2.2, 2.25, 2.3, 2.35, 2.4, 2.45, 2.5, 2.55, 2.6, 2.65, 2.7, 2.75, 2.8, 2.85, 2.9, 2.95, 3.0}; + AxisSpec pAxis = {momentum_bin_edges, "#it{p} (GeV/#it{c})"}; + + // General Histogram (Positive Tracks) + pos_reg.add("histTpcSignalData", "dE/dx", HistType::kTH2F, + {{500, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, + {1400, 0, 1400, "d#it{E}/d#it{x} (a. u.)"}}); + pos_reg.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20.0, +20.0, "z_{vtx} (cm)"}}); + pos_reg.add("histTofSignalData", "TOF signal", HistType::kTH2F, + {{500, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, + {550, 0.0, 1.1, "#beta (TOF)"}}); + pos_reg.add("histDcaxyVsPData", "dca_xy vs p", HistType::kTH2F, + {pAxis, {250, -0.5, 0.5, "DCA_{xy} (cm)"}}); + pos_reg.add("histDcaZVsPtData", "dca_z vs p", HistType::kTH2F, + {pAxis, {1000, -2.0, 2.0, "DCA_{z} (cm)"}}); + pos_reg.add("histNClusterTPC", "Number of TPC Clusters vs p", + HistType::kTH2F, {pAxis, {160, 0.0, 160.0, "nClustersTPC"}}); + pos_reg.add("histNCrossedRowTPC", "Number of TPC crossed row vs p", + HistType::kTH2F, {pAxis, {160, 0.0, 160.0, "nCrossedRowsTPC"}}); + pos_reg.add("histNClusterITS", "Number of ITS Clusters vs p", + HistType::kTH2F, {pAxis, {10, 0.0, 10.0, "nClustersITS"}}); + pos_reg.add("histChi2TPC", "chi^2 TPC vs p", HistType::kTH2F, + {pAxis, {100, 0.0, 5.0, "chi^2_{TPC}"}}); + pos_reg.add("histChi2ITS", "chi^2 ITS vs p", HistType::kTH2F, + {pAxis, {500, 0.0, 50.0, "chi^2_{ITS}"}}); + pos_reg.add("histEta", "eta", HistType::kTH2F, + {pAxis, {100, -1.0, 1.0, "eta"}}); + pos_reg.add("histPhi", "phi", HistType::kTH2F, + {pAxis, {200, 0.0, TMath::TwoPi(), "phi"}}); + + // General Histogram (Negative Tracks) + neg_reg.add("histTpcSignalData", "dE/dx", HistType::kTH2F, + {{500, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, + {1400, 0, 1400, "d#it{E}/d#it{x} (a. u.)"}}); + neg_reg.add("histTofSignalData", "TOF signal", HistType::kTH2F, + {{500, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, + {550, 0.0, 1.1, "#beta (TOF)"}}); + neg_reg.add("histDcaxyVsPData", "dca_xy vs p", HistType::kTH2F, + {pAxis, {250, -0.5, 0.5, "DCA_{xy} (cm)"}}); + neg_reg.add("histDcaZVsPtData", "dca_z vs p", HistType::kTH2F, + {pAxis, {1000, -2.0, 2.0, "DCA_{z} (cm)"}}); + neg_reg.add("histNClusterTPC", "Number of TPC Clusters vs p", + HistType::kTH2F, {pAxis, {160, 0.0, 160.0, "nClustersTPC"}}); + neg_reg.add("histNCrossedRowTPC", "Number of TPC crossed row vs p", + HistType::kTH2F, {pAxis, {160, 0.0, 160.0, "nCrossedRowsTPC"}}); + neg_reg.add("histNClusterITS", "Number of ITS Clusters vs p", + HistType::kTH2F, {pAxis, {10, 0.0, 10.0, "nClustersITS"}}); + neg_reg.add("histChi2TPC", "chi^2 TPC vs p", HistType::kTH2F, + {pAxis, {100, 0.0, 5.0, "chi^2_{TPC}"}}); + neg_reg.add("histChi2ITS", "chi^2 ITS vs p", HistType::kTH2F, + {pAxis, {500, 0.0, 50.0, "chi^2_{ITS}"}}); + neg_reg.add("histEta", "eta", HistType::kTH2F, + {pAxis, {100, -1.0, 1.0, "eta"}}); + neg_reg.add("histPhi", "phi", HistType::kTH2F, + {pAxis, {200, 0.0, TMath::TwoPi(), "phi"}}); + + // Pion Pos + pion_pos_reg.add("histTpcNsigmaData", "nsigmaTPC (#pi)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TPC} (#pi)"}}); + pion_pos_reg.add("histTofNsigmaData", "nsigmaTOF (#pi)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TOF} (#pi)"}}); + + // Kaon Pos + kaon_pos_reg.add("histTpcNsigmaData", "nsigmaTPC (K)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TPC} (K)"}}); + kaon_pos_reg.add("histTofNsigmaData", "nsigmaTOF (K)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TOF} (K)"}}); + + // Protons + proton_reg.add("histTpcNsigmaData", "nsigmaTPC (p)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TPC} (p)"}}); + proton_reg.add("histTofNsigmaData", "nsigmaTOF (p)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TOF} (p)"}}); + + // Deuterons + deuteron_reg.add("histTpcNsigmaData", "nsigmaTPC (d)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TPC} (d)"}}); + deuteron_reg.add("histTofNsigmaData", "nsigmaTOF (d)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TOF} (d)"}}); + + // Pion Neg + pion_neg_reg.add("histTpcNsigmaData", "nsigmaTPC (#pi)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TPC} (#pi)"}}); + pion_neg_reg.add("histTofNsigmaData", "nsigmaTOF (#pi)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TOF} (#pi)"}}); + + // Kaon Neg + kaon_neg_reg.add("histTpcNsigmaData", "nsigmaTPC (K)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TPC} (K)"}}); + kaon_neg_reg.add("histTofNsigmaData", "nsigmaTOF (K)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TOF} (K)"}}); + + // Antiprotons + antiproton_reg.add("histTpcNsigmaData", "nsigmaTPC (antip)", + HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TPC} (p)"}}); + antiproton_reg.add("histTofNsigmaData", "nsigmaTOF (antip)", + HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TOF} (p)"}}); + + // Antideuterons + antideuteron_reg.add("histTpcNsigmaData", "nsigmaTPC (d)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TPC} (d)"}}); + antideuteron_reg.add("histTofNsigmaData", "nsigmaTOF (d)", HistType::kTH2F, + {pAxis, {160, -20.0, +20.0, "n#sigma_{TOF} (d)"}}); + + // MC Energy loss correction maps + pion_plus_MC_reg.add("energy_loss_corr", "energy_loss_corr_piplus", HistType::kTH2F, {{300, 0.0, +3.0, "#it{p}_{vtx} (GeV/#it{c})"}, {300, 0.0, +3.0, "#it{p}_{absorber} (GeV/#it{c})"}}); + pion_minus_MC_reg.add("energy_loss_corr", "energy_loss_corr_piminus", HistType::kTH2F, {{300, 0.0, +3.0, "#it{p}_{vtx} (GeV/#it{c})"}, {300, 0.0, +3.0, "#it{p}_{absorber} (GeV/#it{c})"}}); + kaon_plus_MC_reg.add("energy_loss_corr", "energy_loss_corr_kaonplus", HistType::kTH2F, {{300, 0.0, +3.0, "#it{p}_{vtx} (GeV/#it{c})"}, {300, 0.0, +3.0, "#it{p}_{absorber} (GeV/#it{c})"}}); + kaon_minus_MC_reg.add("energy_loss_corr", "energy_loss_corr_kaonminus", HistType::kTH2F, {{300, 0.0, +3.0, "#it{p}_{vtx} (GeV/#it{c})"}, {300, 0.0, +3.0, "#it{p}_{absorber} (GeV/#it{c})"}}); + proton_MC_reg.add("energy_loss_corr", "energy_loss_corr_proton", HistType::kTH2F, {{300, 0.0, +3.0, "#it{p}_{vtx} (GeV/#it{c})"}, {300, 0.0, +3.0, "#it{p}_{absorber} (GeV/#it{c})"}}); + antiproton_MC_reg.add("energy_loss_corr", "energy_loss_antiproton", HistType::kTH2F, {{300, 0.0, +3.0, "#it{p}_{vtx} (GeV/#it{c})"}, {300, 0.0, +3.0, "#it{p}_{absorber} (GeV/#it{c})"}}); + deuteron_MC_reg.add("energy_loss_corr", "energy_loss_corr_deuteron", HistType::kTH2F, {{300, 0.0, +3.0, "#it{p}_{vtx} (GeV/#it{c})"}, {300, 0.0, +3.0, "#it{p}_{absorber} (GeV/#it{c})"}}); + antideuteron_MC_reg.add("energy_loss_corr", "energy_loss_antideuteron", HistType::kTH2F, {{300, 0.0, +3.0, "#it{p}_{vtx} (GeV/#it{c})"}, {300, 0.0, +3.0, "#it{p}_{absorber} (GeV/#it{c})"}}); + } + + // Configurables + Configurable zVertexRange{"zVertexRange", 10.0f, "zVertexRange"}; + Configurable pmin{"pmin", 0.1, "pmin"}; + Configurable pmax{"pmax", 2.0, "pmax"}; + Configurable etaMin{"etaMin", -0.8, "etaMin"}; + Configurable etaMax{"etaMax", +0.8, "etaMax"}; + Configurable phiMin{"phiMin", 0.0, "phiMin"}; + Configurable phiMax{"phiMax", TMath::TwoPi(), "phiMax"}; + Configurable nsigmaTPCMin{"nsigmaTPCMin", -3.0, "nsigmaTPCMin"}; + Configurable nsigmaTPCMax{"nsigmaTPCMax", +3.0, "nsigmaTPCMax"}; + Configurable nsigmaTOFMin{"nsigmaTOFMin", -3.0, "nsigmaTOFMin"}; + Configurable nsigmaTOFMax{"nsigmaTOFMax", +3.5, "nsigmaTOFMax"}; + Configurable minReqClusterITS{"minReqClusterITS", 1.0, "min number of clusters required in ITS"}; + Configurable minTPCnClsFound{"minTPCnClsFound", 0.0f, "minTPCnClsFound"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.0f, "min number of crossed rows TPC"}; + Configurable maxChi2ITS{"maxChi2ITS", 36.0f, "max chi2 per cluster ITS"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; + Configurable maxDCA_xy{"maxDCA_xy", 0.5f, "maxDCA_xy"}; + Configurable maxDCA_z{"maxDCA_z", 2.0f, "maxDCA_z"}; + Configurable lastRequiredTrdCluster{"lastRequiredTrdCluster", 5, "Last TRD cluster (-1 = no requirement)"}; + Configurable enable_PVcontributor_global{"enable_PVcontributor_global", true, "is PV contributor (global)"}; + Configurable enable_PVcontributor_proton{"enable_PVcontributor_proton", true, "is PV contributor (proton)"}; + Configurable enable_PVcontributor_antiproton{"enable_PVcontributor_antiproton", true, "is PV contributor (antiproton)"}; + Configurable enable_PVcontributor_deuteron{"enable_PVcontributor_deuteron", true, "is PV contributor (deuteron)"}; + Configurable enable_PVcontributor_antideuteron{"enable_PVcontributor_antideuteron", true, "is PV contributor (antideuteron)"}; + + template + void fillHistograms(const CollisionType& event, const TracksType& tracks) + { + // Event Selection + if (!event.sel8()) + return; + + // Event Counter + pos_reg.fill(HIST("histRecVtxZData"), event.posZ()); + + // Loop over Reconstructed Tracks + for (auto track : tracks) { + + // Loose Track Selection + if (!track.isGlobalTrackWoDCA()) + continue; + if (!track.passedITSRefit()) + continue; + if (!track.passedTPCRefit()) + continue; + if (track.itsNCls() < 1) + continue; + if (track.tpcNClsFound() < 0) + continue; + if (track.tpcNClsCrossedRows() < 60) + continue; + if (TMath::Abs(track.dcaXY()) > 1.0) + continue; + if (TMath::Abs(track.dcaZ()) > 1.0) + continue; + if (enable_PVcontributor_global && !(track.isPVContributor())) + continue; + + // Fill QA Histograms (Positive Tracks) + if (track.sign() > 0) { + + pos_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); + pos_reg.fill(HIST("histTofSignalData"), track.p(), track.beta()); + pos_reg.fill(HIST("histDcaxyVsPData"), track.p(), track.dcaXY()); + pos_reg.fill(HIST("histDcaZVsPtData"), track.p(), track.dcaZ()); + pos_reg.fill(HIST("histNClusterTPC"), track.p(), track.tpcNClsFound()); + pos_reg.fill(HIST("histNCrossedRowTPC"), track.p(), track.tpcNClsCrossedRows()); + pos_reg.fill(HIST("histNClusterITS"), track.p(), track.itsNCls()); + pos_reg.fill(HIST("histChi2TPC"), track.p(), track.tpcChi2NCl()); + pos_reg.fill(HIST("histChi2ITS"), track.p(), track.itsChi2NCl()); + pos_reg.fill(HIST("histEta"), track.p(), track.eta()); + pos_reg.fill(HIST("histPhi"), track.p(), track.phi()); + } + + // Fill QA Histograms (Negative Tracks) + if (track.sign() < 0) { + + neg_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); + neg_reg.fill(HIST("histTofSignalData"), track.p(), track.beta()); + neg_reg.fill(HIST("histDcaxyVsPData"), track.p(), track.dcaXY()); + neg_reg.fill(HIST("histDcaZVsPtData"), track.p(), track.dcaZ()); + neg_reg.fill(HIST("histNClusterTPC"), track.p(), track.tpcNClsFound()); + neg_reg.fill(HIST("histNCrossedRowTPC"), track.p(), track.tpcNClsCrossedRows()); + neg_reg.fill(HIST("histNClusterITS"), track.p(), track.itsNCls()); + neg_reg.fill(HIST("histChi2TPC"), track.p(), track.tpcChi2NCl()); + neg_reg.fill(HIST("histChi2ITS"), track.p(), track.itsChi2NCl()); + neg_reg.fill(HIST("histEta"), track.p(), track.eta()); + neg_reg.fill(HIST("histPhi"), track.p(), track.phi()); + } + + // Track Selection + if (!track.passedITSRefit()) + continue; + if (!track.passedTPCRefit()) + continue; + if (track.itsNCls() < minReqClusterITS) + continue; + if (track.tpcNClsFound() < minTPCnClsFound) + continue; + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) + continue; + if (track.tpcChi2NCl() > maxChi2TPC) + continue; + if (track.itsChi2NCl() > maxChi2ITS) + continue; + if (TMath::Abs(track.dcaXY()) > maxDCA_xy) + continue; + if (TMath::Abs(track.dcaZ()) > maxDCA_z) + continue; + if (track.eta() < etaMin) + continue; + if (track.eta() > etaMax) + continue; + if (track.phi() < phiMin) + continue; + if (track.phi() > phiMax) + continue; + + if (track.sign() > 0) { + pion_pos_reg.fill(HIST("histTpcNsigmaData"), track.p(), track.tpcNSigmaPi()); + kaon_pos_reg.fill(HIST("histTpcNsigmaData"), track.p(), track.tpcNSigmaKa()); + proton_reg.fill(HIST("histTpcNsigmaData"), track.p(), track.tpcNSigmaPr()); + deuteron_reg.fill(HIST("histTpcNsigmaData"), track.p(), track.tpcNSigmaDe()); + } + + if (track.sign() < 0) { + pion_neg_reg.fill(HIST("histTpcNsigmaData"), track.p(), track.tpcNSigmaPi()); + kaon_neg_reg.fill(HIST("histTpcNsigmaData"), track.p(), track.tpcNSigmaKa()); + antiproton_reg.fill(HIST("histTpcNsigmaData"), track.p(), track.tpcNSigmaPr()); + antideuteron_reg.fill(HIST("histTpcNsigmaData"), track.p(), track.tpcNSigmaDe()); + } + + bool passedPionTPCsel = false; + bool passedKaonTPCsel = false; + bool passedProtTPCsel = false; + bool passedDeutTPCsel = false; + + if (track.tpcNSigmaPi() > nsigmaTPCMin && + track.tpcNSigmaPi() < nsigmaTPCMax) + passedPionTPCsel = true; + + if (track.tpcNSigmaKa() > nsigmaTPCMin && + track.tpcNSigmaKa() < nsigmaTPCMax) + passedKaonTPCsel = true; + + if (track.tpcNSigmaPr() > nsigmaTPCMin && + track.tpcNSigmaPr() < nsigmaTPCMax) + passedProtTPCsel = true; + + if (track.tpcNSigmaDe() > nsigmaTPCMin && + track.tpcNSigmaDe() < nsigmaTPCMax) + passedDeutTPCsel = true; + + if (!track.hasTOF()) + continue; + + if (track.sign() > 0) { + if (passedPionTPCsel) + pion_pos_reg.fill(HIST("histTofNsigmaData"), track.p(), track.tofNSigmaPi()); + if (passedKaonTPCsel) + kaon_pos_reg.fill(HIST("histTofNsigmaData"), track.p(), track.tofNSigmaKa()); + if (passedProtTPCsel) + proton_reg.fill(HIST("histTofNsigmaData"), track.p(), track.tofNSigmaPr()); + if (passedDeutTPCsel) + deuteron_reg.fill(HIST("histTofNsigmaData"), track.p(), track.tofNSigmaDe()); + } + + if (track.sign() < 0) { + if (passedPionTPCsel) + pion_neg_reg.fill(HIST("histTofNsigmaData"), track.p(), track.tofNSigmaPi()); + if (passedKaonTPCsel) + kaon_neg_reg.fill(HIST("histTofNsigmaData"), track.p(), track.tofNSigmaKa()); + if (passedProtTPCsel) + antiproton_reg.fill(HIST("histTofNsigmaData"), track.p(), track.tofNSigmaPr()); + if (passedDeutTPCsel) + antideuteron_reg.fill(HIST("histTofNsigmaData"), track.p(), track.tofNSigmaDe()); + } + } + } + + // Filter collisionFilter = (nabs(aod::collision::posZ) < zVertexRange); + // Filter trackFilter = (nabs(aod::track::eta) < 0.8f && requireGlobalTrackWoDCAInFilter()); + + using EventCandidates = soa::Join; + // using EventCandidates = soa::Filtered>; + + /* + using TrackCandidates = soa::Filtered>; + */ + // Info for TPC PID + using PidInfoTPC = soa::Join; + + // Info for TOF PID + using PidInfoTOF = soa::Join; + + // Propagated tracks + using TrackCandidatesIU = soa::Join; + + // Propagated to PV tracks + using TrackCandidates = soa::Join; + + // using TrackCandidates = soa::Join; + + void processData(EventCandidates::iterator const& event, + TrackCandidatesIU const& tracksIU) + // , TrackCandidates const& tracks) + { + fillHistograms(event, tracksIU); + } + PROCESS_SWITCH(AntimatterAbsorptionHMPID, processData, "process data", true); + + // Process MC + void processMC(soa::Join::iterator const& event, + soa::Join const& tracksIU, + // soa::Join const& tracks, + aod::McParticles& mcParticles, + aod::McCollisions const& mcCollisions) + { + + float radius_hmpid = 500; + + for (auto track : tracksIU) { + + // Get MC Particle + if (!track.has_mcParticle()) + continue; + const auto particle = track.mcParticle(); + + // Track Selection + if (!track.isGlobalTrackWoDCA()) + continue; + if (!track.passedITSRefit()) + continue; + if (!track.passedTPCRefit()) + continue; + if (track.itsNCls() < minReqClusterITS) + continue; + if (track.tpcNClsFound() < minTPCnClsFound) + continue; + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) + continue; + if (track.tpcChi2NCl() > maxChi2TPC) + continue; + if (track.itsChi2NCl() > maxChi2ITS) + continue; + if (TMath::Abs(track.dcaXY()) > maxDCA_xy) + continue; + if (TMath::Abs(track.dcaZ()) > maxDCA_z) + continue; + if (enable_PVcontributor_global && !(track.isPVContributor())) + continue; + if (track.eta() < etaMin) + continue; + if (track.eta() > etaMax) + continue; + if (track.phi() < phiMin) + continue; + if (track.phi() > phiMax) + continue; + + // TOF Hit Requirement + if (!track.hasTOF()) + continue; + + // Pi Plus + if (particle.pdgCode() == 211) { + if (track.tpcNSigmaPi() < nsigmaTPCMin) + continue; + if (track.tpcNSigmaPi() > nsigmaTPCMax) + continue; + if (track.tofNSigmaPi() < nsigmaTOFMin) + continue; + if (track.tofNSigmaPi() > nsigmaTOFMax) + continue; + + double p_vtx = track.p(); + auto par_cov = getTrackParCov(track); + par_cov.setPID(2); // Pion + auto prop = o2::base::Propagator::Instance(); + float xtogo = 0; + if (!par_cov.getXatLabR(radius_hmpid, xtogo, prop->getNominalBz(), o2::track::DirType::DirOutward) || !prop->PropagateToXBxByBz(par_cov, xtogo, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + continue; + } + double p_hmpid = track.p(); + pion_plus_MC_reg.fill(HIST("energy_loss_corr"), p_vtx, p_hmpid); + } + + // Pi Minus + if (particle.pdgCode() == -211) { + if (track.tpcNSigmaPi() < nsigmaTPCMin) + continue; + if (track.tpcNSigmaPi() > nsigmaTPCMax) + continue; + if (track.tofNSigmaPi() < nsigmaTOFMin) + continue; + if (track.tofNSigmaPi() > nsigmaTOFMax) + continue; + + double p_vtx = track.p(); + auto par_cov = getTrackParCov(track); + par_cov.setPID(2); // Pion + auto prop = o2::base::Propagator::Instance(); + float xtogo = 0; + if (!par_cov.getXatLabR(radius_hmpid, xtogo, prop->getNominalBz(), o2::track::DirType::DirOutward) || !prop->PropagateToXBxByBz(par_cov, xtogo, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + continue; + } + double p_hmpid = track.p(); + pion_minus_MC_reg.fill(HIST("energy_loss_corr"), p_vtx, p_hmpid); + } + + // Kaon Plus + if (particle.pdgCode() == 321) { + if (track.tpcNSigmaKa() < nsigmaTPCMin) + continue; + if (track.tpcNSigmaKa() > nsigmaTPCMax) + continue; + if (track.tofNSigmaKa() < nsigmaTOFMin) + continue; + if (track.tofNSigmaKa() > nsigmaTOFMax) + continue; + + double p_vtx = track.p(); + auto par_cov = getTrackParCov(track); + par_cov.setPID(3); // Kaon + auto prop = o2::base::Propagator::Instance(); + float xtogo = 0; + if (!par_cov.getXatLabR(radius_hmpid, xtogo, prop->getNominalBz(), o2::track::DirType::DirOutward) || !prop->PropagateToXBxByBz(par_cov, xtogo, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + continue; + } + double p_hmpid = track.p(); + kaon_plus_MC_reg.fill(HIST("energy_loss_corr"), p_vtx, p_hmpid); + } + + // Kaon Minus + if (particle.pdgCode() == -321) { + if (track.tpcNSigmaKa() < nsigmaTPCMin) + continue; + if (track.tpcNSigmaKa() > nsigmaTPCMax) + continue; + if (track.tofNSigmaKa() < nsigmaTOFMin) + continue; + if (track.tofNSigmaKa() > nsigmaTOFMax) + continue; + + double p_vtx = track.p(); + auto par_cov = getTrackParCov(track); + par_cov.setPID(3); // Kaon + auto prop = o2::base::Propagator::Instance(); + float xtogo = 0; + if (!par_cov.getXatLabR(radius_hmpid, xtogo, prop->getNominalBz(), o2::track::DirType::DirOutward) || !prop->PropagateToXBxByBz(par_cov, xtogo, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + continue; + } + double p_hmpid = track.p(); + kaon_minus_MC_reg.fill(HIST("energy_loss_corr"), p_vtx, p_hmpid); + } + + // Proton + if (particle.pdgCode() == 2212) { + if (track.tpcNSigmaPr() < nsigmaTPCMin) + continue; + if (track.tpcNSigmaPr() > nsigmaTPCMax) + continue; + if (track.tofNSigmaPr() < nsigmaTOFMin) + continue; + if (track.tofNSigmaPr() > nsigmaTOFMax) + continue; + + double p_vtx = track.p(); + auto par_cov = getTrackParCov(track); + par_cov.setPID(4); // Proton + auto prop = o2::base::Propagator::Instance(); + float xtogo = 0; + if (!par_cov.getXatLabR(radius_hmpid, xtogo, prop->getNominalBz(), o2::track::DirType::DirOutward) || !prop->PropagateToXBxByBz(par_cov, xtogo, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + continue; + } + double p_hmpid = track.p(); + proton_MC_reg.fill(HIST("energy_loss_corr"), p_vtx, p_hmpid); + } + + // AntiProton + if (particle.pdgCode() == -2212) { + if (track.tpcNSigmaPr() < nsigmaTPCMin) + continue; + if (track.tpcNSigmaPr() > nsigmaTPCMax) + continue; + if (track.tofNSigmaPr() < nsigmaTOFMin) + continue; + if (track.tofNSigmaPr() > nsigmaTOFMax) + continue; + + double p_vtx = track.p(); + auto par_cov = getTrackParCov(track); + par_cov.setPID(4); // Proton + auto prop = o2::base::Propagator::Instance(); + float xtogo = 0; + if (!par_cov.getXatLabR(radius_hmpid, xtogo, prop->getNominalBz(), o2::track::DirType::DirOutward) || !prop->PropagateToXBxByBz(par_cov, xtogo, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + continue; + } + double p_hmpid = track.p(); + antiproton_MC_reg.fill(HIST("energy_loss_corr"), p_vtx, p_hmpid); + } + + // Deuteron + if (particle.pdgCode() == 1000010020) { + if (track.tpcNSigmaDe() < nsigmaTPCMin) + continue; + if (track.tpcNSigmaDe() > nsigmaTPCMax) + continue; + if (track.tofNSigmaDe() < nsigmaTOFMin) + continue; + if (track.tofNSigmaDe() > nsigmaTOFMax) + continue; + + double p_vtx = track.p(); + auto par_cov = getTrackParCov(track); + par_cov.setPID(5); // Deuteron + auto prop = o2::base::Propagator::Instance(); + float xtogo = 0; + if (!par_cov.getXatLabR(radius_hmpid, xtogo, prop->getNominalBz(), o2::track::DirType::DirOutward) || !prop->PropagateToXBxByBz(par_cov, xtogo, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + continue; + } + double p_hmpid = track.p(); + deuteron_MC_reg.fill(HIST("energy_loss_corr"), p_vtx, p_hmpid); + } + + // AntiDeuteron + if (particle.pdgCode() == -1000010020) { + if (track.tpcNSigmaDe() < nsigmaTPCMin) + continue; + if (track.tpcNSigmaDe() > nsigmaTPCMax) + continue; + if (track.tofNSigmaDe() < nsigmaTOFMin) + continue; + if (track.tofNSigmaDe() > nsigmaTOFMax) + continue; + + double p_vtx = track.p(); + auto par_cov = getTrackParCov(track); + par_cov.setPID(5); // Deuteron + auto prop = o2::base::Propagator::Instance(); + float xtogo = 0; + if (!par_cov.getXatLabR(radius_hmpid, xtogo, prop->getNominalBz(), o2::track::DirType::DirOutward) || !prop->PropagateToXBxByBz(par_cov, xtogo, 0.95, 10, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + continue; + } + double p_hmpid = track.p(); + antideuteron_MC_reg.fill(HIST("energy_loss_corr"), p_vtx, p_hmpid); + } + } + } + PROCESS_SWITCH(AntimatterAbsorptionHMPID, processMC, "process MC", false); +}; + +//********************************************************************************************************************************************** + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask( + cfgc)}; +} diff --git a/PWGLF/Tasks/CMakeLists.txt b/PWGLF/Tasks/CMakeLists.txt index 9d725f6f490..fbb205c3889 100644 --- a/PWGLF/Tasks/CMakeLists.txt +++ b/PWGLF/Tasks/CMakeLists.txt @@ -116,6 +116,11 @@ o2physics_add_dpl_workflow(nuclei-hist PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(qa-hist + SOURCES QAHistTask.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(cascpostprocessing SOURCES cascpostprocessing.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -131,6 +136,11 @@ o2physics_add_dpl_workflow(stqa PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(non-prompt-cascade + SOURCES nonPromptCascade.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats O2Physics::AnalysisCore O2::DetectorsBase + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(hyhefour-analysis SOURCES hyhe4analysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -155,3 +165,53 @@ o2physics_add_dpl_workflow(v0postprocessing SOURCES v0postprocessing.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(antimatter-abs-hmpid + SOURCES AntimatterAbsorptionHMPID.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::ReconstructionDataFormats O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(cascadecorrelations + SOURCES cascadecorrelations.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(kinkanalysis + SOURCES kinkAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambda1520spherocityanalysis + SOURCES lambda1520SpherocityAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(hypertriton3bodyanalysis + SOURCES hypertriton3bodyanalysis.cxx + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(hypertriton3bodymcqa + SOURCES hypertriton3bodyMCQA.cxx + PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(vzero-cascade-absorption + SOURCES vzero_cascade_absorption.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(delta-analysis + SOURCES deltaanalysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(rhoanalysis + SOURCES rhoanalysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(rsn-analysis-thnsparse + SOURCES rsnanalysisTHnSparse.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/LFNucleiBATask.cxx b/PWGLF/Tasks/LFNucleiBATask.cxx index aeeecd99351..87b7dbaaef3 100644 --- a/PWGLF/Tasks/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/LFNucleiBATask.cxx @@ -18,6 +18,7 @@ /// #include "PWGLF/DataModel/LFNucleiTables.h" #include +#include #include "ReconstructionDataFormats/Track.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -42,31 +43,48 @@ struct LFNucleiBATask { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry spectraGen{"spectraGen", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + // Enable particle for analysis Configurable enablePr{"enablePr", true, "Flag to enable proton analysis."}; Configurable enableDe{"enableDe", true, "Flag to enable deuteron analysis."}; Configurable enableTr{"enableTr", true, "Flag to enable triton analysis."}; Configurable enableHe{"enableHe", true, "Flag to enable helium-3 analysis."}; Configurable enableAl{"enableAl", true, "Flag to enable alpha analysis."}; + // Set the multiplity event limits + Configurable cfgLowMultCut{"cfgLowMultCut", 0.0f, "Accepted multiplicity percentage lower limit"}; + Configurable cfgHighMultCut{"cfgHighMultCut", 100.0f, "Accepted multiplicity percentage higher limit"}; + + // Set the z-vertex event cut limits Configurable cfgHighCutVertex{"cfgHighCutVertex", 10.0f, "Accepted z-vertex upper limit"}; Configurable cfgLowCutVertex{"cfgLowCutVertex", -10.0f, "Accepted z-vertex lower limit"}; + + // Set the quality cuts for tracks Configurable cfgCutITSClusters{"cfgCutITSClusters", -1.f, "Minimum number of ITS clusters"}; Configurable cfgCutTPCXRows{"cfgCutTPCXRows", -1.f, "Minimum number of crossed TPC rows"}; Configurable cfgCutTPCClusters{"cfgCutTPCClusters", -1.f, "Minimum number of found TPC clusters"}; + Configurable nITSLayer{"nITSLayer", 0, "ITS Layer (0-6)"}; + // Set the kinematic and PID cuts for tracks Configurable etaCut{"etaCut", 0.8f, "Value of the eta selection for spectra (default 0.8)"}; Configurable yCut{"yCut", 1.0f, "Value of the rapidity selection for spectra (default 1.0)"}; - Configurable nsigmaTPCcut{"nsigmaTPCcut", 7.f, "Value of the Nsigma TPC cut"}; - Configurable nsigmaTOFcut{"nsigmaTOFcut", 5.f, "Value of the Nsigma TOF cut"}; + + Configurable isPVContributorCut{"isPVContributorCut", false, "Flag to enable isPVContributor cut."}; + Configurable DCAxyCustomCut{"DCAxyCustomCut", 2.0f, "Value of the DCAxy selection for spectra (default 2.0 cm)"}; + Configurable DCAzCustomCut{"DCAzCustomCut", 2.0f, "Value of the DCAz selection for spectra (default 2.0 cm)"}; + Configurable nsigmaTPCPr{"nsigmaTPCPr", 3.f, "Value of the Nsigma TPC cut for protons"}; Configurable nsigmaTPCDe{"nsigmaTPCDe", 3.f, "Value of the Nsigma TPC cut for deuterons"}; Configurable nsigmaTPCTr{"nsigmaTPCTr", 3.f, "Value of the Nsigma TPC cut for tritons"}; Configurable nsigmaTPCHe{"nsigmaTPCHe", 3.f, "Value of the Nsigma TPC cut for helium-3"}; Configurable nsigmaTPCAl{"nsigmaTPCAl", 3.f, "Value of the Nsigma TPC cut for alpha"}; + + // Set additional cuts (used for debug) Configurable ProtonNsigmaTPCcutInTOFbeta{"ProtonNsigmaTPCcutInTOFbeta", 3.5f, "Value of the Nsigma TPC cut (proton) for TOF beta distribution"}; Configurable nsigmaTPCStrongCut{"nsigmaTPCStrongCut", 3.f, "Value of the Nsigma TPC (Strong) proton cut, if enabled"}; Configurable betaCut{"betaCut", 0.4f, "Value of the beta selection for TOF cut (default 0.4)"}; + // Set the axis used in this task + ConfigurableAxis binsPercentile{"binsPercentile", {100, 0, 100}, "Centrality FT0M"}; ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0}, ""}; ConfigurableAxis binsdEdx{"binsdEdx", {1000, 0.f, 1000.f}, ""}; ConfigurableAxis binsBeta{"binsBeta", {120, 0.0, 1.2}, ""}; @@ -78,20 +96,19 @@ struct LFNucleiBATask { ConfigurableAxis binsMassTr{"binsMassTr", {250, -2.5, 2.5f}, ""}; ConfigurableAxis binsMassHe{"binsMassHe", {300, -3., 3.f}, ""}; - Configurable enableFiltering{"enableFiltering", false, "Flag to enable filtering for p,d,t,He only"}; + // Enable custom cuts/debug functions + Configurable enableFiltering{"enableFiltering", false, "Flag to enable filtering for p,d,t,He only -- disable if launch on skimmed dataset!"}; + Configurable enableEvTimeSplitting{"enableEvTimeSplitting", true, "Flag to enable histograms splitting depending on the Event Time used"}; + Configurable enableDCACustomCut{"enableDCACustomCut", false, "Flag to enable DCA custom cuts - unflag to use standard isGlobalCut DCA cut"}; + + // Enable output histograms + Configurable makeDCABeforeCutPlots{"makeDCABeforeCutPlots", false, "Flag to enable plots of DCA before cuts"}; + Configurable makeDCAAfterCutPlots{"makeDCAAfterCutPlots", false, "Flag to enable plots of DCA after cuts"}; Configurable doTPCcalib{"doTPCcalib", false, "Flag to stop task after dEdX. Please set to 'processData'."}; Configurable doTOFplots{"doTOFplots", true, "Flag to export plots of tracks with 1 hit on TOF."}; Configurable enableExpSignalTPC{"enableExpSignalTPC", true, "Flag to export dEdX - dEdX(exp) plots."}; Configurable enableExpSignalTOF{"enableExpSignalTOF", false, "Flag to export T - T(exp) plots."}; - Configurable isPVContributorCut{"isPVContributorCut", false, "Flag to enable isPVContributor cut."}; - - Configurable makeDCABeforeCutPlots{"makeDCABeforeCutPlots", false, "Flag to enable plots of DCA before cuts"}; - Configurable makeDCAAfterCutPlots{"makeDCAAfterCutPlots", false, "Flag to enable plots of DCA after cuts"}; - Configurable enableDCACustomCut{"enableDCACustomCut", false, "Flag to enable DCA custom cuts - unflag to use standard isGlobalCut DCA cut"}; - Configurable DCAxyCustomCut{"DCAxyCustomCut", 2.0f, "Value of the DCAxy selection for spectra (default 2.0 cm)"}; - Configurable DCAzCustomCut{"DCAzCustomCut", 2.0f, "Value of the DCAz selection for spectra (default 2.0 cm)"}; - Configurable enableEvTimeSplitting{"enableEvTimeSplitting", true, "Flag to enable histograms splitting depending on the Event Time used"}; Configurable enablePIDplot{"enablePIDplot", false, "Flag to enable PID histograms for debug"}; Configurable enableBetaCut{"enableBetaCut", false, "Flag to enable TOF histograms with beta cut for debug"}; @@ -99,16 +116,24 @@ struct LFNucleiBATask { Configurable enableStrongCut{"enableStrongCut", false, "Flag to change | NSigma TPC(nucl)| < nSigmaTPC --> NOT | NSigma TPC(p)| > nStrongCut"}; Configurable enableNucleiHardCut{"enableNucleiHardCut", false, "Flag to enable TPC sigma histograms filled without the 'nearby' particle (at low momentum)"}; Configurable enablePtSpectra{"enablePtSpectra", false, "Flag to enable histograms for efficiency debug."}; - Configurable rapDebug{"rapDebug", false, "Flag to enable helium rapidity cut debug histograms."}; + Configurable usenITSLayer{"usenITSLayer", false, "Flag to enable ITS layer hit"}; Configurable useHasTRDConfig{"useHasTRDConfig", 0, "No selections on TRD (0); With TRD (1); Without TRD (2)"}; Configurable massTOFConfig{"massTOFConfig", 0, "Estimate massTOF using beta with (0) TPC momentum (1) TOF expected momentum"}; Configurable tritonSelConfig{"tritonSelConfig", 0, "Select tritons using (0) 3Sigma TPC triton (1) additional 3sigma TPC pi,K,p veto cut"}; Configurable helium3Pt{"helium3Pt", 0, "Select use default pT (0) or use instead 2*pT (1) for helium-3"}; - - Configurable nITSLayer{"nITSLayer", 0, "ITS Layer (0-6)"}; - Configurable usenITSLayer{"usenITSLayer", false, "Flag to enable ITS layer hit"}; - + Configurable antiDeuteronPt{"antiDeuteronPt", 0, "Select use default pT (0) or use instead pT shift (1) for antideuteron"}; + + // Additional function used for pT-shift calibration + TF1* fShift = 0; + TF1* fShiftAntiD = 0; + Configurable enablePtShift{"enablePtShift", false, "Flag to enable Pt shift (for He only)"}; + Configurable enablePtShiftAntiD{"enablePtShiftAntiD", true, "Flag to enable Pt shift (for antiDeuteron only)"}; + Configurable> parShiftPt{"parShiftPt", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for Pt shift (if enabled)."}; + Configurable> parShiftPtAntiD{"parShiftPtAntiD", {-0.0955412, 0.798164, -0.536111, 0.0887876, -1.11022e-13}, "Parameters for Pt shift (if enabled)."}; + Configurable enableCentrality{"enableCentrality", true, "Flag to enable centrality 3D histos)"}; + + // PDG codes and masses used in this analysis static constexpr int PDGPion = 211; static constexpr int PDGKaon = 321; static constexpr int PDGProton = 2212; @@ -142,6 +167,9 @@ struct LFNucleiBATask { } histos.add("event/h1VtxZ", "V_{z};V_{z} (in cm); counts", HistType::kTH1F, {{1500, -15, 15}}); + histos.add("event/hFT0M", "hFT0M", HistType::kTH1F, {{binsPercentile, "Centrality FT0M"}}); + histos.add("event/hFV0M", "hFV0M", HistType::kTH1F, {{binsPercentile, "Centrality FV0M"}}); + histos.add("tracks/h1pT", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{500, 0., 10.}}); histos.add("tracks/h1p", "Track momentum; p (GeV/#it{c}); counts", HistType::kTH1F, {{500, 0., 10.}}); @@ -208,11 +236,25 @@ struct LFNucleiBATask { } if (enablePtSpectra) { + histos.add("tracks/eff/hPtP", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/hPtantiP", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/hPtPTOF", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/hPtantiPTOF", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + + histos.add("tracks/eff/hPtPrebinned", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); + histos.add("tracks/eff/hPtantiPrebinned", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); + histos.add("tracks/eff/hPtPTOFrebinned", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); + histos.add("tracks/eff/hPtantiPTOFrebinned", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); + if (enablePr) { histos.add("tracks/eff/proton/hPtPr", "Track #it{p}_{T} (p); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); histos.add("tracks/eff/proton/hPtantiPr", "Track #it{p}_{T} (#bar{p}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); histos.add("tracks/eff/proton/hPtPrTOF", "Track #it{p}_{T} (p); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); histos.add("tracks/eff/proton/hPtantiPrTOF", "Track #it{p}_{T} (#bar{p}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/proton/hPtPrrebinned", "Track #it{p}_{T} (p); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); + histos.add("tracks/eff/proton/hPtantiPrrebinned", "Track #it{p}_{T} (#bar{p}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); + histos.add("tracks/eff/proton/hPtPrTOFrebinned", "Track #it{p}_{T} (p); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); + histos.add("tracks/eff/proton/hPtantiPrTOFrebinned", "Track #it{p}_{T} (#bar{p}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{50, 0., 5.}}); } if (enableDe) { histos.add("tracks/eff/deuteron/hPtDe", "Track #it{p}_{T} (d); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); @@ -249,8 +291,13 @@ struct LFNucleiBATask { histos.add("tracks/proton/dca/before/hDCAzVsPtantiProton", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableDe) { - histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteron", "DCAxy vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteron", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + if (enableCentrality) { + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronVsMult", "DCAxy vs Pt (d)", HistType::kTH3F, {{ptAxis}, {dcaxyAxis}, {binsPercentile}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronVsMult", "DCAxy vs Pt (#bar{d})", HistType::kTH3F, {{ptAxis}, {dcaxyAxis}, {binsPercentile}}); + } else { + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteron", "DCAxy vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteron", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + } histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteron", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } @@ -334,7 +381,7 @@ struct LFNucleiBATask { histos.add("tracks/alpha/h1AlphaSpectra", "#it{p}_{T} (#alpha)", HistType::kTH1F, {ptAxis}); histos.add("tracks/alpha/h1antiAlphaSpectra", "#it{p}_{T} (#bar{#alpha})", HistType::kTH1F, {ptAxis}); } - if (doprocessMCReco || doprocessMCRecoFiltered) { + if (doprocessMCReco || doprocessMCRecoFiltered || doprocessMCRecoFilteredLight) { // 1D pT if (enablePr) { histos.add("tracks/proton/h1ProtonSpectraTrue", "#it{p}_{T} (p)", HistType::kTH1F, {ptAxis}); @@ -399,135 +446,255 @@ struct LFNucleiBATask { } // 2D-DCAxy if (enablePr) { - histos.add("tracks/proton/dca/hDCAxyVsPtProtonTrue", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/hDCAxyVsPtProtonTrue", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/proton/dca/before/hDCAxyVsPtProtonTruePrim", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/hDCAxyVsPtProtonTrueSec", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/hDCAxyVsPtProtonTrueTransport", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrue", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProtonTruePrim", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrueSec", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrueTransport", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/hDCAxyVsPtProtonTruePrim", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/hDCAxyVsPtProtonTrueSec", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/hDCAxyVsPtProtonTrueTransport", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/after/hDCAxyVsPtProtonTrue", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/hDCAxyVsPtantiProtonTrue", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/after/hDCAxyVsPtProtonTruePrim", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/after/hDCAxyVsPtProtonTrueSec", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/after/hDCAxyVsPtProtonTrueTransport", "DCAxy vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/hDCAxyVsPtantiProtonTruePrim", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/hDCAxyVsPtantiProtonTrueSec", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/proton/dca/hDCAxyVsPtantiProtonTrueTransport", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrue", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/proton/dca/after/hDCAxyVsPtantiProtonTruePrim", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrueSec", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrueTransport", "DCAxy vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); } if (enableDe) { - histos.add("tracks/deuteron/dca/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrue", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); } if (enableTr) { - histos.add("tracks/triton/dca/hDCAxyVsPtTritonTrue", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/before/hDCAxyVsPtTritonTrue", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/triton/dca/before/hDCAxyVsPtTritonTruePrim", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/before/hDCAxyVsPtTritonTrueSec", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/before/hDCAxyVsPtTritonTrueTransport", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrue", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/triton/dca/hDCAxyVsPtTritonTruePrim", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/triton/dca/hDCAxyVsPtTritonTrueSec", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/triton/dca/hDCAxyVsPtTritonTrueTransport", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTritonTruePrim", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrueSec", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrueTransport", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/triton/dca/hDCAxyVsPtantiTritonTrue", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/after/hDCAxyVsPtTritonTrue", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/triton/dca/hDCAxyVsPtantiTritonTruePrim", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/triton/dca/hDCAxyVsPtantiTritonTrueSec", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/triton/dca/hDCAxyVsPtantiTritonTrueTransport", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/after/hDCAxyVsPtTritonTruePrim", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/after/hDCAxyVsPtTritonTrueSec", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/after/hDCAxyVsPtTritonTrueTransport", "DCAxy vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrue", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/triton/dca/after/hDCAxyVsPtantiTritonTruePrim", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrueSec", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrueTransport", "DCAxy vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); } if (enableHe) { - histos.add("tracks/helium/dca/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrue", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); } if (enableAl) { - histos.add("tracks/alpha/dca/hDCAxyVsPtAlphaTrue", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlphaTrue", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlphaTruePrim", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlphaTrueSec", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlphaTrueTransport", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/alpha/dca/hDCAxyVsPtAlphaTruePrim", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/alpha/dca/hDCAxyVsPtAlphaTrueSec", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/alpha/dca/hDCAxyVsPtAlphaTrueTransport", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTrue", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/alpha/dca/hDCAxyVsPtantiAlphaTrue", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTruePrim", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTrueSec", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTrueTransport", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/alpha/dca/hDCAxyVsPtantiAlphaTruePrim", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/alpha/dca/hDCAxyVsPtantiAlphaTrueSec", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/alpha/dca/hDCAxyVsPtantiAlphaTrueTransport", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrue", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/alpha/dca/after/hDCAxyVsPtAlphaTruePrim", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrueSec", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrueTransport", "DCAxy vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrue", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + + histos.add("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTruePrim", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrueSec", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrueTransport", "DCAxy vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); } // 2D-DCAz if (enablePr) { - histos.add("tracks/proton/dca/hDCAzVsPtProtonTrue", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/hDCAzVsPtProtonTrue", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/proton/dca/before/hDCAzVsPtProtonTruePrim", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/hDCAzVsPtProtonTrueSec", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/hDCAzVsPtProtonTrueTransport", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/proton/dca/before/hDCAzVsPtantiProtonTrue", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/proton/dca/before/hDCAzVsPtantiProtonTruePrim", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/hDCAzVsPtantiProtonTrueSec", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/before/hDCAzVsPtantiProtonTrueTransport", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/hDCAzVsPtProtonTruePrim", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/hDCAzVsPtProtonTrueSec", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/hDCAzVsPtProtonTrueTransport", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/after/hDCAzVsPtProtonTrue", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/hDCAzVsPtantiProtonTrue", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/after/hDCAzVsPtProtonTruePrim", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/after/hDCAzVsPtProtonTrueSec", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/after/hDCAzVsPtProtonTrueTransport", "DCAz vs Pt (p); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/hDCAzVsPtantiProtonTruePrim", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/hDCAzVsPtantiProtonTrueSec", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/proton/dca/hDCAzVsPtantiProtonTrueTransport", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/after/hDCAzVsPtantiProtonTrue", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/proton/dca/after/hDCAzVsPtantiProtonTruePrim", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/after/hDCAzVsPtantiProtonTrueSec", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/proton/dca/after/hDCAzVsPtantiProtonTrueTransport", "DCAz vs Pt (#bar{p}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableDe) { - histos.add("tracks/deuteron/dca/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTruePrim", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrueSec", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrueTransport", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrue", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTruePrim", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrueSec", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrueTransport", "DCAz vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableTr) { - histos.add("tracks/triton/dca/hDCAzVsPtTritonTrue", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/before/hDCAzVsPtTritonTrue", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/triton/dca/before/hDCAzVsPtTritonTruePrim", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/before/hDCAzVsPtTritonTrueSec", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/before/hDCAzVsPtTritonTrueTransport", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/triton/dca/before/hDCAzVsPtantiTritonTrue", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/triton/dca/hDCAzVsPtTritonTruePrim", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/triton/dca/hDCAzVsPtTritonTrueSec", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/triton/dca/hDCAzVsPtTritonTrueTransport", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/before/hDCAzVsPtantiTritonTruePrim", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/before/hDCAzVsPtantiTritonTrueSec", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/before/hDCAzVsPtantiTritonTrueTransport", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/triton/dca/hDCAzVsPtantiTritonTrue", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/after/hDCAzVsPtTritonTrue", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/triton/dca/hDCAzVsPtantiTritonTruePrim", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/triton/dca/hDCAzVsPtantiTritonTrueSec", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/triton/dca/hDCAzVsPtantiTritonTrueTransport", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/after/hDCAzVsPtTritonTruePrim", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/after/hDCAzVsPtTritonTrueSec", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/after/hDCAzVsPtTritonTrueTransport", "DCAz vs Pt (t); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/triton/dca/after/hDCAzVsPtantiTritonTrue", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/triton/dca/after/hDCAzVsPtantiTritonTruePrim", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/after/hDCAzVsPtantiTritonTrueSec", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/triton/dca/after/hDCAzVsPtantiTritonTrueTransport", "DCAz vs Pt (#bar{t}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableHe) { - histos.add("tracks/helium/dca/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTruePrim", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrueSec", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtHeliumTrueTransport", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrue", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTruePrim", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueSec", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueTransport", "DCAz vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableAl) { - histos.add("tracks/alpha/dca/hDCAzVsPtAlphaTrue", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/before/hDCAzVsPtAlphaTrue", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/alpha/dca/before/hDCAzVsPtAlphaTruePrim", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/before/hDCAzVsPtAlphaTrueSec", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/before/hDCAzVsPtAlphaTrueTransport", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/alpha/dca/hDCAzVsPtAlphaTruePrim", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/alpha/dca/hDCAzVsPtAlphaTrueSec", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/alpha/dca/hDCAzVsPtAlphaTrueTransport", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTrue", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/alpha/dca/hDCAzVsPtantiAlphaTrue", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTruePrim", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTrueSec", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTrueTransport", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/alpha/dca/hDCAzVsPtantiAlphaTruePrim", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/alpha/dca/hDCAzVsPtantiAlphaTrueSec", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/alpha/dca/hDCAzVsPtantiAlphaTrueTransport", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/after/hDCAzVsPtAlphaTrue", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/alpha/dca/after/hDCAzVsPtAlphaTruePrim", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/after/hDCAzVsPtAlphaTrueSec", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/after/hDCAzVsPtAlphaTrueTransport", "DCAz vs Pt (#alpha); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrue", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + + histos.add("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTruePrim", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrueSec", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrueTransport", "DCAz vs Pt (#bar{#alpha}); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } } @@ -595,8 +762,13 @@ struct LFNucleiBATask { histos.add("tracks/proton/h2antiProtonVspTNSigmaTPC", "NSigmaTPC(#bar{p}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {SigmaTPCAxis}}); } if (enableDe) { - histos.add("tracks/deuteron/h2DeuteronVspTNSigmaTPC", "NSigmaTPC(d) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {SigmaTPCAxis}}); - histos.add("tracks/deuteron/h2antiDeuteronVspTNSigmaTPC", "NSigmaTPC(#bar{d}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {SigmaTPCAxis}}); + if (enableCentrality) { + histos.add("tracks/deuteron/h3DeuteronVspTNSigmaTPCVsMult", "NSigmaTPC(d) vs pT; #it{p}_{T} (GeV/#it{c}) vs mult; NSigmaTPC", HistType::kTH3F, {{ptAxis}, {SigmaTPCAxis}, {binsPercentile}}); + histos.add("tracks/deuteron/h3antiDeuteronVspTNSigmaTPCVsMult", "NSigmaTPC(#bar{d}) vs pT; #it{p}_{T} (GeV/#it{c}) vs mult; NSigmaTPC", HistType::kTH3F, {{ptAxis}, {SigmaTPCAxis}, {binsPercentile}}); + } else { + histos.add("tracks/deuteron/h2DeuteronVspTNSigmaTPC", "NSigmaTPC(d) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {SigmaTPCAxis}}); + histos.add("tracks/deuteron/h2antiDeuteronVspTNSigmaTPC", "NSigmaTPC(#bar{d}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {SigmaTPCAxis}}); + } } if (enableTr) { histos.add("tracks/triton/h2TritonVspTNSigmaTPC", "NSigmaTPC(t) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {SigmaTPCAxis}}); @@ -611,13 +783,7 @@ struct LFNucleiBATask { histos.add("tracks/alpha/h2antiAlphaVspTNSigmaTPC", "NSigmaTPC(#bar{#alpha}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {SigmaTPCAxis}}); } if (enableNucleiHardCut) { - // Protons - // histos.add("tracks/proton/hc/h2ProtonVspTNSigmaTPC_hard", "NSigmaTPC(p) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/proton/hc/h2antiProtonVspTNSigmaTPC_hard", "NSigmaTPC(#bar{p}) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/proton/hc/h2ProtonTPCExpSignalDiffVsPt_hard", "TPC <-dE/dX> - Exp <-dE/dX> (p) | Hard Cut vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (p)", HistType::kTH2F, {{ptAxis}, {6000, -300, 300.}}); - // histos.add("tracks/proton/hc/h2antiProtonTPCExpSignalDiffVsPt_hard", "TPC <-dE/dX> - Exp <-dE/dX> (#bar{p}) | Hard Cut vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (#bar{p})", HistType::kTH2F, {{ptAxis}, {6000, -300, 300.}}); - // histos.add("tracks/proton/hc/h2ProtonVspTNSigmaTOF_hard", "NSigmaTOF(p) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/proton/hc/h2antiProtonVspTNSigmaTOF_hard", "NSigmaTOF(#bar{p}) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); + if (enablePr) { histos.add("tracks/proton/hc/h2TPCsignVsTPCmomentumProton_hard", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, 0.f, 5.f}, {dedxAxis}}); histos.add("tracks/proton/hc/h2TPCsignVsTPCmomentumantiProton_hard", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, 0.f, 5.f}, {dedxAxis}}); @@ -626,33 +792,12 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/hc/h2TPCsignVsTPCmomentumDeuteron_hard", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, 0.f, 5.f}, {dedxAxis}}); histos.add("tracks/deuteron/hc/h2TPCsignVsTPCmomentumantiDeuteron_hard", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, 0.f, 5.f}, {dedxAxis}}); } - // Deuterons - // histos.add("tracks/deuteron/hc/h2DeuteronVspTNSigmaTPC_hard", "NSigmaTPC(d) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/deuteron/hc/h2antiDeuteronVspTNSigmaTPC_hard", "NSigmaTPC(#bar{d}) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/deuteron/hc/h2DeuteronTPCExpSignalDiffVsPt_hard", "TPC <-dE/dX> - Exp <-dE/dX> (d) | Hard Cut vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (p)", HistType::kTH2F, {{ptAxis}, {6000, -300, 300.}}); - // histos.add("tracks/deuteron/hc/h2antiDeuteronTPCExpSignalDiffVsPt_hard", "TPC <-dE/dX> - Exp <-dE/dX> (#bar{d}) | Hard Cut vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (#bar{p})", HistType::kTH2F, {{ptAxis}, {6000, -300, 300.}}); - // histos.add("tracks/deuteron/hc/h2DeuteronVspTNSigmaTOF_hard", "NSigmaTOF(d) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/deuteron/hc/h2antiDeuteronVspTNSigmaTOF_hard", "NSigmaTOF(#bar{d}) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - - // Tritons - // histos.add("tracks/triton/hc/h2TritonVspTNSigmaTPC_hard", "NSigmaTPC(t) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/triton/hc/h2antiTritonVspTNSigmaTPC_hard", "NSigmaTPC(#bar{t}) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/triton/hc/h2TritonTPCExpSignalDiffVsPt_hard", "TPC <-dE/dX> - Exp <-dE/dX> (t) | Hard Cut vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (p)", HistType::kTH2F, {{ptAxis}, {6000, -300, 300.}}); - // histos.add("tracks/triton/hc/h2antiTritonTPCExpSignalDiffVsPt_hard", "TPC <-dE/dX> - Exp <-dE/dX> (#bar{t}) | Hard Cut vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (#bar{p})", HistType::kTH2F, {{ptAxis}, {6000, -300, 300.}}); - // histos.add("tracks/triton/hc/h2TritonVspTNSigmaTOF_hard", "NSigmaTOF(t) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/triton/hc/h2antiTritonVspTNSigmaTOF_hard", "NSigmaTOF(#bar{t}) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); + if (enableTr) { histos.add("tracks/triton/hc/h2TPCsignVsTPCmomentumTriton_hard", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, 0.f, 5.f}, {dedxAxis}}); histos.add("tracks/triton/hc/h2TPCsignVsTPCmomentumantiTriton_hard", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, 0.f, 5.f}, {dedxAxis}}); } - // Helium - // histos.add("tracks/helium/hc/h2HeliumVspTNSigmaTPC_hard", "NSigmaTPC(He) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/helium/hc/h2antiHeliumVspTNSigmaTPC_hard", "NSigmaTPC(#bar{He}) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/helium/hc/h2HeliumTPCExpSignalDiffVsPt_hard", "TPC <-dE/dX> - Exp <-dE/dX> ({He) | Hard Cut vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (p)", HistType::kTH2F, {{ptAxis}, {6000, -300, 300.}}); - // histos.add("tracks/helium/hc/h2antiHeliumTPCExpSignalDiffVsPt_hard", "TPC <-dE/dX> - Exp <-dE/dX> (#bar{{He}) | Hard Cut vs #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); TPC <-dE/dX> ExpDiff (#bar{p})", HistType::kTH2F, {{ptAxis}, {6000, -300, 300.}}); - // histos.add("tracks/helium/hc/h2HeliumVspTNSigmaTOF_hard", "NSigmaTOF(He) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); - // histos.add("tracks/helium/hc/h2antiHeliumVspTNSigmaTOF_hard", "NSigmaTOF(#bar{He}) | Hard Cut vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptAxis}, {800, -40, 40}}); if (enableHe) { histos.add("tracks/helium/hc/h2TPCsignVsTPCmomentumHelium_hard", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, 0.f, 5.f}, {dedxAxis}}); histos.add("tracks/helium/hc/h2TPCsignVsTPCmomentumantiHelium_hard", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{250, 0.f, 5.f}, {dedxAxis}}); @@ -777,10 +922,6 @@ struct LFNucleiBATask { histos.add("tracks/helium/h2TOFmassHeliumVsPt_BetaCut", "h2TOFmassHeliumVsPt_BetaCut; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{320, 0.4, 4.}, {250, 0., 5.}}); histos.add("tracks/helium/h2TOFmassantiHeliumVsPt_BetaCut", "h2TOFmassantiHeliumVsPt_BetaCut; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{320, 0.4, 4.}, {250, 0., 5.}}); } - if (rapDebug) { - histos.add("tracks/helium/h2TOFmassHeliumVsPt_NORAPIDITYCUT", "h2TOFmassHeliumVsPt_NORAPIDITYCUT; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{320, 0.4, 4.}, {250, 0., 5.}}); - histos.add("tracks/helium/h2TOFmassantiHeliumVsPt_NORAPIDITYCUT", "h2TOFmassantiHeliumVsPt_NORAPIDITYCUT; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{320, 0.4, 4.}, {250, 0., 5.}}); - } } // TOF mass squared histograms if (enablePr) { @@ -792,8 +933,13 @@ struct LFNucleiBATask { } } if (enableDe) { - histos.add("tracks/deuteron/h2TOFmass2DeuteronVsPt", "#Delta M^{2} (d) vs #it{p}_{T}; #Delta M^{2} (d); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); - histos.add("tracks/deuteron/h2TOFmass2antiDeuteronVsPt", "#Delta M^{2} (#bar{d}) vs #it{p}_{T}; #Delta M^{2} (#bar{d}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); + if (enableCentrality) { + histos.add("tracks/deuteron/h3TOFmass2DeuteronVsPtVsMult", "#Delta M^{2} (d) vs #it{p}_{T} vs multiplicity; #Delta M^{2} (d); #it{p}_{T} (GeV/#it{c})", HistType::kTH3F, {{massDeAxis}, {250, 0., 5.}, {binsPercentile}}); + histos.add("tracks/deuteron/h3TOFmass2antiDeuteronVsPtVsMult", "#Delta M^{2} (#bar{d}) vs #it{p}_{T} vs multiplicity; #Delta M^{2} (#bar{d}); #it{p}_{T} (GeV/#it{c})", HistType::kTH3F, {{massDeAxis}, {250, 0., 5.}, {binsPercentile}}); + } else { + histos.add("tracks/deuteron/h2TOFmass2DeuteronVsPt", "#Delta M^{2} (d) vs #it{p}_{T}; #Delta M^{2} (d); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); + histos.add("tracks/deuteron/h2TOFmass2antiDeuteronVsPt", "#Delta M^{2} (#bar{d}) vs #it{p}_{T}; #Delta M^{2} (#bar{d}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); + } if (enableBetaCut) { histos.add("tracks/deuteron/h2TOFmass2DeuteronVsPt_BetaCut", "#Delta M^{2} (d) vs #it{p}_{T}; #Delta M^{2} (d); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); histos.add("tracks/deuteron/h2TOFmass2antiDeuteronVsPt_BetaCut", "#Delta M^{2} (#bar{d}) vs #it{p}_{T}; #Delta M^{2} (#bar{d}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massDeAxis}, {250, 0., 5.}}); @@ -810,6 +956,8 @@ struct LFNucleiBATask { if (enableHe) { histos.add("tracks/helium/h2TOFmass2antiHeliumVsPt", "#Delta M^{2} (#bar{He}) vs #it{p}_{T}; #Delta M^{2} (#bar{He}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {250, 0., 5.}}); histos.add("tracks/helium/h2TOFmass2HeliumVsPt", "#Delta M^{2} (He) vs #it{p}_{T}; #Delta M^{2} (He); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {250, 0., 5.}}); + histos.add("tracks/helium/h2TOFmassDeltaHeliumVsPt", "#Delta M (He) vs #it{p}_{T}; #Delta M (He); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {250, 0., 5.}}); + histos.add("tracks/helium/h2TOFmassDeltaantiHeliumVsPt", "#Delta M (#bar{He}) vs #it{p}_{T}; #Delta M (#bar{He}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {250, 0., 5.}}); if (enableBetaCut) { histos.add("tracks/helium/h2TOFmass2antiHeliumVsPt_BetaCut", "#Delta M^{2} (#bar{He}) vs #it{p}_{T}; #Delta M^{2} (#bar{He}); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {250, 0., 5.}}); histos.add("tracks/helium/h2TOFmass2HeliumVsPt_BetaCut", "#Delta M^{2} (He) vs #it{p}_{T}; #Delta M^{2} (He); #it{p}_{T} (GeV/#it{c})", HistType::kTH2F, {{massHeAxis}, {250, 0., 5.}}); @@ -1019,6 +1167,13 @@ struct LFNucleiBATask { } // MC histograms - all, primary, sec. from weak decay, sec. from material histos.add("spectraGen/histGenVetxZ", "PosZ generated events", HistType::kTH1F, {{1500, -15.f, 15.f, "Vertex Z (cm)"}}); + histos.add("spectraGen/histPtGen", "PtGen", HistType::kTH1F, {{800, 0.f, 8.f}}); + histos.add("spectraGen/histPtRec", "PtRec", HistType::kTH1F, {{1600, -8.f, 8.f}}); + histos.add("spectraGen/histPtShift_Pr", "PtReco-PtGen vs PtReco (protons) ", HistType::kTH2F, {{800, 0.f, 8.f}, {400, -4.f, 4.f}}); + + histos.add("spectraGen/histPtShift", "PtReco-PtGen vs PtReco", HistType::kTH2F, {{800, 0.f, 8.f}, {400, -4.f, 4.f}}); + histos.add("spectraGen/histPShift", "PReco-PGen vs PReco", HistType::kTH2F, {{800, 0.f, 8.f}, {400, -4.f, 4.f}}); + histos.add("spectraGen/histPtShiftVsEta", "PReco-PGen vs #eta", HistType::kTH2F, {{200, -2.f, 2.f}, {400, -4.f, 4.f}}); histos.add("spectraGen/pion/histGenPtPion", "generated particles", HistType::kTH1F, {ptAxis}); histos.add("spectraGen/pion/histGenPtPionPrim", "generated particles", HistType::kTH1F, {ptAxis}); @@ -1056,6 +1211,9 @@ struct LFNucleiBATask { histos.add("spectraGen/deuteron/histGenPtDPrim", "generated particles", HistType::kTH1F, {ptAxis}); histos.add("spectraGen/deuteron/histGenPtDSec", "generated particles", HistType::kTH1F, {ptAxis}); histos.add("spectraGen/deuteron/histSecTransportPtD", "generated particles", HistType::kTH1F, {ptAxis}); + histos.add("tracks/deuteron/histAntiDPtShiftRec", "histAntiDPtShiftRec", HistType::kTH1F, {ptAxis}); + histos.add("tracks/deuteron/histAntiDPtRec", "histAntiDPtRec", HistType::kTH1F, {ptAxis}); + histos.add("spectraGen/histPtShiftCorrection", "histPtShiftCorrection", HistType::kTH2F, {{800, 0.f, 8.f}, {400, -4.f, 4.f}}); histos.add("spectraGen/deuteron/histGenPtantiD", "generated particles", HistType::kTH1F, {ptAxis}); histos.add("spectraGen/deuteron/histGenPtantiDPrim", "generated particles", HistType::kTH1F, {ptAxis}); @@ -1109,12 +1267,23 @@ struct LFNucleiBATask { if (!event.sel8()) { return; } + if (event.centFT0M() < cfgLowMultCut || event.centFT0M() > cfgHighMultCut) { + return; + } + // if (event.centFV0M() < cfgLowMultCut || event.centFV0M() > cfgHighMultCut) { + // return; + // } if (event.posZ() < cfgLowCutVertex || event.posZ() > cfgHighCutVertex) { return; } } - float gamma = 0., massTOF = 0., hePt = 0.f; + if (event.centFT0M() < cfgLowMultCut || event.centFT0M() > cfgHighMultCut) + return; + if (event.posZ() < cfgLowCutVertex || event.posZ() > cfgHighCutVertex) + return; + + float gamma = 0., massTOF = 0., hePt = 0.f, antiDPt = 0.f; bool isTriton = kFALSE; bool deRapCut = kFALSE; bool heRapCut = kFALSE; @@ -1122,7 +1291,10 @@ struct LFNucleiBATask { // Event histos fill histos.fill(HIST("event/h1VtxZ"), event.posZ()); if (enableDebug) - histos.fill(HIST("event/h1CentV0M"), event.multFV0M()); + histos.fill(HIST("event/hFT0M"), event.centFT0M()); + if constexpr (IsFilteredData) { + histos.fill(HIST("event/hFV0M"), event.centFV0M()); + } for (auto& track : tracks) { histos.fill(HIST("tracks/h1pT"), track.pt()); @@ -1150,9 +1322,39 @@ struct LFNucleiBATask { break; } + float shift = 0.f; + + if (enablePtShift && !fShift) { + fShift = new TF1("fShift", "[0] * TMath::Exp([1] + [2] * x) + [3] + [4] * x", 0.f, 8.f); + auto par = (std::vector)parShiftPt; + fShift->SetParameters(par[0], par[1], par[2], par[3], par[4]); + } + + if (enablePtShiftAntiD && !fShiftAntiD) { + fShiftAntiD = new TF1("fShiftAntiD", "[0] * TMath::Exp([1] + [2] * x) + [3] + [4] * x", 0.f, 8.f); + auto par = (std::vector)parShiftPtAntiD; + fShiftAntiD->SetParameters(par[0], par[1], par[2], par[3], par[4]); + } + + switch (antiDeuteronPt) { + case 0: + if (enablePtShiftAntiD && fShiftAntiD) { + auto shiftAntiD = fShiftAntiD->Eval(track.pt()); + antiDPt = track.pt() - shiftAntiD; + } + break; + case 1: + antiDPt = track.pt(); + break; + } + switch (helium3Pt) { case 0: hePt = track.pt(); + if (enablePtShift && fShift) { + shift = fShift->Eval(2 * track.pt()); + hePt = track.pt() - shift / 2.f; + } break; case 1: hePt = 2.f * track.pt(); @@ -1187,11 +1389,17 @@ struct LFNucleiBATask { if (usenITSLayer && !itsClusterMap.test(nITSLayer)) continue; if (track.sign() > 0) { - histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteron"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteron"), track.pt(), track.dcaZ()); + if (enableCentrality) + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronVsMult"), antiDPt, track.dcaXY(), event.centFT0M()); + else + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteron"), antiDPt, track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteron"), antiDPt, track.dcaZ()); } else { - histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteron"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteron"), track.pt(), track.dcaZ()); + if (enableCentrality) + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronVsMult"), antiDPt, track.dcaXY(), event.centFT0M()); + else + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteron"), antiDPt, track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteron"), antiDPt, track.dcaZ()); } } } @@ -1228,6 +1436,229 @@ struct LFNucleiBATask { } } } + + if constexpr (IsMC) { + bool isPhysPrim = false; + bool isProdByGen = false; + + // PID + int pdgCode = 0; + if constexpr (IsFilteredData) { + isPhysPrim = track.isPhysicalPrimary(); + isProdByGen = track.producedByGenerator(); + pdgCode = track.pdgCode(); + } else { + if (!track.has_mcParticle()) { + continue; + } + isPhysPrim = track.mcParticle().isPhysicalPrimary(); + isProdByGen = track.mcParticle().producedByGenerator(); + pdgCode = track.mcParticle().pdgCode(); + } + switch (pdgCode) { + case PDGProton: + if (enablePr) { + histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtProtonTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtProtonTrue"), track.pt(), track.dcaZ()); + if (isPhysPrim) { + if constexpr (!IsFilteredData) { + histos.fill(HIST("spectraGen/histPtShift_Pr"), track.pt(), track.pt() - track.mcParticle().pt()); + } + histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtProtonTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtProtonTruePrim"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtProtonTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtProtonTrueSec"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtProtonTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtProtonTrueTransport"), track.pt(), track.dcaZ()); + } + } + break; + case -PDGProton: + if (enablePr) { + histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtantiProtonTrue"), track.pt(), track.dcaZ()); + + if (isPhysPrim) { + histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtantiProtonTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtantiProtonTruePrim"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtantiProtonTrueSec"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/proton/dca/before/hDCAxyVsPtantiProtonTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/before/hDCAzVsPtantiProtonTrueTransport"), track.pt(), track.dcaZ()); + } + } + break; + case PDGDeuteron: + if (enableDe) { + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrue"), track.pt(), track.dcaZ()); + if (isPhysPrim) { + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTruePrim"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrueSec"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronTrueTransport"), track.pt(), track.dcaZ()); + } + } + break; + case -PDGDeuteron: + if (enableDe) { + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTrue"), track.pt(), track.dcaZ()); + if (isPhysPrim) { + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTruePrim"), track.pt(), track.dcaZ()); + if constexpr (!IsFilteredData) { + histos.fill(HIST("spectraGen/histPtShift"), track.pt(), track.pt() - track.mcParticle().pt()); + histos.fill(HIST("spectraGen/histPtShiftVsEta"), track.eta(), track.pt() - track.mcParticle().pt()); + histos.fill(HIST("spectraGen/histPShift"), track.p(), track.p() - track.mcParticle().p()); + histos.fill(HIST("tracks/deuteron/histAntiDPtShiftRec"), antiDPt); + histos.fill(HIST("tracks/deuteron/histAntiDPtRec"), track.pt()); + histos.fill(HIST("spectraGen/histPtShiftCorrection"), antiDPt, antiDPt - track.mcParticle().pt()); + } + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTrueSec"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronTrueTransport"), track.pt(), track.dcaZ()); + } + } + break; + case PDGTriton: + if (enableTr) { + histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtTritonTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/before/hDCAzVsPtTritonTrue"), track.pt(), track.dcaZ()); + if (isPhysPrim) { + histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtTritonTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/before/hDCAzVsPtTritonTruePrim"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtTritonTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/before/hDCAzVsPtTritonTrueSec"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtTritonTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/before/hDCAzVsPtTritonTrueTransport"), track.pt(), track.dcaZ()); + } + } + break; + case -PDGTriton: + if (enableTr) { + histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/before/hDCAzVsPtantiTritonTrue"), track.pt(), track.dcaZ()); + if (isPhysPrim) { + histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtantiTritonTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/before/hDCAzVsPtantiTritonTruePrim"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/before/hDCAzVsPtantiTritonTrueSec"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/triton/dca/before/hDCAxyVsPtantiTritonTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/before/hDCAzVsPtantiTritonTrueTransport"), track.pt(), track.dcaZ()); + } + } + break; + case PDGHelium: + if (enableHe) { + histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); + if (isPhysPrim) { + histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumTrueTransport"), hePt, track.dcaZ()); + } + } + break; + case -PDGHelium: + if (enableHe) { + histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrue"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrue"), hePt, track.dcaZ()); + if (isPhysPrim) { + if constexpr (!IsFilteredData) { + histos.fill(HIST("spectraGen/histPtGen"), std::abs(track.mcParticle().pt())); + histos.fill(HIST("spectraGen/histPtRec"), (2.f * hePt)); + histos.fill(HIST("spectraGen/histPtShift"), (2.f * hePt), (2.f * hePt) - track.mcParticle().pt()); + histos.fill(HIST("spectraGen/histPtShiftVsEta"), track.eta(), (2.f * hePt) - track.mcParticle().pt()); + histos.fill(HIST("spectraGen/histPShift"), 2.f * track.p(), 2.f * track.p() - track.mcParticle().p()); + } + histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTruePrim"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumTruePrim"), hePt, track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueSec"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueSec"), hePt, track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumTrueTransport"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumTrueTransport"), hePt, track.dcaZ()); + } + } + break; + case PDGAlpha: + if (enableAl) { + histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtAlphaTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/before/hDCAzVsPtAlphaTrue"), track.pt(), track.dcaZ()); + if (isPhysPrim) { + histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtAlphaTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/before/hDCAzVsPtAlphaTruePrim"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtAlphaTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/before/hDCAzVsPtAlphaTrueSec"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtAlphaTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/before/hDCAzVsPtAlphaTrueTransport"), track.pt(), track.dcaZ()); + } + } + break; + case -PDGAlpha: + if (enableAl) { + histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTrue"), track.pt(), track.dcaZ()); + if (isPhysPrim) { + histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTruePrim"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && isProdByGen) { + histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTrueSec"), track.pt(), track.dcaZ()); + } + if (!isPhysPrim && !isProdByGen) { + histos.fill(HIST("tracks/alpha/dca/before/hDCAxyVsPtantiAlphaTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/before/hDCAzVsPtantiAlphaTrueTransport"), track.pt(), track.dcaZ()); + } + } + break; + default: + break; + } + } } // DCA Cut @@ -1355,19 +1786,15 @@ struct LFNucleiBATask { histos.fill(HIST("debug/qa/h1TPCncrHighPNeg"), track.tpcNClsCrossedRows()); } } - } - if (enablePtSpectra) - histos.fill(HIST("tracks/eff/h2pVsTPCmomentum"), track.tpcInnerParam(), track.p()); - // TPC - if (enableDebug) histos.fill(HIST("debug/h2TPCsignVsTPCmomentumFull"), track.tpcInnerParam() / (1.f * track.sign()), track.tpcSignal()); - - if (enableDebug) { histos.fill(HIST("tracks/pion/h2PionVspTNSigmaTPC"), track.pt(), track.tpcNSigmaPi()); histos.fill(HIST("tracks/kaon/h2KaonVspTNSigmaTPC"), track.pt(), track.tpcNSigmaKa()); } + if (enablePtSpectra) + histos.fill(HIST("tracks/eff/h2pVsTPCmomentum"), track.tpcInnerParam(), track.p()); + if (enableFiltering) { if (track.tpcNSigmaKa() < 5) continue; @@ -1408,7 +1835,10 @@ struct LFNucleiBATask { switch (useHasTRDConfig) { case 0: - histos.fill(HIST("tracks/deuteron/h2DeuteronVspTNSigmaTPC"), track.pt(), track.tpcNSigmaDe()); + if (enableCentrality) + histos.fill(HIST("tracks/deuteron/h3DeuteronVspTNSigmaTPCVsMult"), antiDPt, track.tpcNSigmaDe(), event.centFT0M()); + else + histos.fill(HIST("tracks/deuteron/h2DeuteronVspTNSigmaTPC"), antiDPt, track.tpcNSigmaDe()); break; case 1: if (track.hasTRD()) { @@ -1467,7 +1897,10 @@ struct LFNucleiBATask { switch (useHasTRDConfig) { case 0: - histos.fill(HIST("tracks/deuteron/h2antiDeuteronVspTNSigmaTPC"), track.pt(), track.tpcNSigmaDe()); + if (enableCentrality) + histos.fill(HIST("tracks/deuteron/h3antiDeuteronVspTNSigmaTPCVsMult"), antiDPt, track.tpcNSigmaDe(), event.centFT0M()); + else + histos.fill(HIST("tracks/deuteron/h2antiDeuteronVspTNSigmaTPC"), antiDPt, track.tpcNSigmaDe()); break; case 1: if (track.hasTRD()) { @@ -1859,11 +2292,22 @@ struct LFNucleiBATask { } // PID + if (enablePtSpectra) { + if (track.sign() > 0) { + histos.fill(HIST("tracks/eff/hPtP"), track.pt()); + histos.fill(HIST("tracks/eff/hPtPrebinned"), track.pt()); + } else { + histos.fill(HIST("tracks/eff/hPtantiP"), track.pt()); + histos.fill(HIST("tracks/eff/hPtantiPrebinned"), track.pt()); + } + } + if (enablePr) { if ((std::abs(track.tpcNSigmaPr()) < nsigmaTPCPr) && (TMath::Abs(track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton))) < yCut)) { if (track.sign() > 0) { if (enablePtSpectra) { histos.fill(HIST("tracks/eff/proton/hPtPr"), track.pt()); + histos.fill(HIST("tracks/eff/proton/hPtPrrebinned"), track.pt()); histos.fill(HIST("tracks/eff/proton/h2pVsTPCmomentumPr"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/proton/h1ProtonSpectra"), track.pt()); @@ -1875,6 +2319,7 @@ struct LFNucleiBATask { } else { if (enablePtSpectra) { histos.fill(HIST("tracks/eff/proton/hPtantiPr"), track.pt()); + histos.fill(HIST("tracks/eff/proton/hPtantiPrrebinned"), track.pt()); histos.fill(HIST("tracks/eff/proton/h2pVsTPCmomentumantiPr"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/proton/h1antiProtonSpectra"), track.pt()); @@ -1989,6 +2434,17 @@ struct LFNucleiBATask { if (doTOFplots) { if (track.hasTOF()) { + + if (enablePtSpectra) { + if (track.sign() > 0) { + histos.fill(HIST("tracks/eff/hPtPTOF"), track.pt()); + histos.fill(HIST("tracks/eff/hPtPTOFrebinned"), track.pt()); + } else { + histos.fill(HIST("tracks/eff/hPtantiPTOF"), track.pt()); + histos.fill(HIST("tracks/eff/hPtantiPTOFrebinned"), track.pt()); + } + } + histos.fill(HIST("tracks/h2TOFbetaVsP_debug"), track.p() / (1.f * track.sign()), track.beta()); if (enableBetaCut && (track.beta() > betaCut)) histos.fill(HIST("tracks/h2TOFbetaVsP_BetaCut"), track.p() / (1.f * track.sign()), track.beta()); @@ -2012,21 +2468,21 @@ struct LFNucleiBATask { } if (enablePtSpectra) - histos.fill(HIST("tracks/eff/h2TPCmomentumVsTOFExpMomentum"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/h2TPCmomentumVsTOFExpMomentum"), track.tofExpMom(), track.tpcInnerParam()); if (enablePr) { if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCPr && track.sign() > 0) { histos.fill(HIST("tracks/proton/h2ProtonTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/proton/h2pVsTOFExpMomentumPr"), track.tofExpMom(), track.p()); - histos.fill(HIST("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumPr"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumPr"), track.tofExpMom(), track.tpcInnerParam()); } } if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCPr && track.sign() < 0) { histos.fill(HIST("tracks/proton/h2antiProtonTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/proton/h2pVsTOFExpMomentumantiPr"), track.tofExpMom(), track.p()); - histos.fill(HIST("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumantiPr"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumantiPr"), track.tofExpMom(), track.tpcInnerParam()); } } } @@ -2035,14 +2491,14 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/h2DeuteronTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/deuteron/h2pVsTOFExpMomentumDe"), track.tofExpMom(), track.p()); - histos.fill(HIST("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumDe"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumDe"), track.tofExpMom(), track.tpcInnerParam()); } } if (std::abs(track.tpcNSigmaDe()) < nsigmaTPCDe && track.sign() < 0) { histos.fill(HIST("tracks/deuteron/h2antiDeuteronTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/deuteron/h2pVsTOFExpMomentumantiDe"), track.tofExpMom(), track.p()); - histos.fill(HIST("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumantiDe"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumantiDe"), track.tofExpMom(), track.tpcInnerParam()); } } } @@ -2051,14 +2507,14 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/triton/h2TritonTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/triton/h2pVsTOFExpMomentumTr"), track.tofExpMom(), track.p()); - histos.fill(HIST("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumTr"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumTr"), track.tofExpMom(), track.tpcInnerParam()); } } if (isTriton && track.sign() < 0) { histos.fill(HIST("tracks/triton/h2antiTritonTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/triton/h2pVsTOFExpMomentumantiTr"), track.tofExpMom(), track.p()); - histos.fill(HIST("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumantiTr"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumantiTr"), track.tofExpMom(), track.tpcInnerParam()); } } } @@ -2067,14 +2523,14 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2HeliumTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/helium/h2pVsTOFExpMomentumHe"), track.tofExpMom(), track.p()); - histos.fill(HIST("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumHe"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumHe"), track.tofExpMom(), track.tpcInnerParam()); } } if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCHe && track.sign() < 0) { histos.fill(HIST("tracks/helium/h2antiHeliumTOFbetaVsP"), track.p(), track.beta()); if (enablePtSpectra) { histos.fill(HIST("tracks/eff/helium/h2pVsTOFExpMomentumantiHe"), track.tofExpMom(), track.p()); - histos.fill(HIST("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumantiHe"), track.tofExpMom(), track.tpcSignal()); + histos.fill(HIST("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumantiHe"), track.tofExpMom(), track.tpcInnerParam()); } } } @@ -2142,9 +2598,11 @@ struct LFNucleiBATask { if (enablePr) { if ((std::abs(track.tpcNSigmaPr()) < nsigmaTPCPr) && (TMath::Abs(track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton))) < yCut)) { - if (enablePtSpectra) - histos.fill(HIST("tracks/eff/proton/hPtPrTOF"), track.pt()); if (track.sign() > 0) { + if (enablePtSpectra) { + histos.fill(HIST("tracks/eff/proton/hPtPrTOF"), track.pt()); + histos.fill(HIST("tracks/eff/proton/hPtPrTOFrebinned"), track.pt()); + } histos.fill(HIST("tracks/proton/h2TOFmassProtonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); if (enableBetaCut && (track.beta() > betaCut)) { @@ -2172,8 +2630,10 @@ struct LFNucleiBATask { } } } else { - if (enablePtSpectra) + if (enablePtSpectra) { histos.fill(HIST("tracks/eff/proton/hPtantiPrTOF"), track.pt()); + histos.fill(HIST("tracks/eff/proton/hPtantiPrTOFrebinned"), track.pt()); + } histos.fill(HIST("tracks/proton/h2TOFmassantiProtonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - fMassProton * fMassProton, track.pt()); if (enableBetaCut && (track.beta() > betaCut)) { @@ -2210,7 +2670,10 @@ struct LFNucleiBATask { if (enablePtSpectra) histos.fill(HIST("tracks/eff/deuteron/hPtDeTOF"), track.pt()); histos.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt"), massTOF, track.pt()); - histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, track.pt()); + if (enableCentrality) + histos.fill(HIST("tracks/deuteron/h3TOFmass2DeuteronVsPtVsMult"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, antiDPt, event.centFT0M()); + else + histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, antiDPt); if (enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_BetaCut"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, track.pt()); @@ -2240,7 +2703,10 @@ struct LFNucleiBATask { if (enablePtSpectra) histos.fill(HIST("tracks/eff/deuteron/hPtantiDeTOF"), track.pt()); histos.fill(HIST("tracks/deuteron/h2TOFmassantiDeuteronVsPt"), massTOF, track.pt()); - histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, track.pt()); + if (enableCentrality) + histos.fill(HIST("tracks/deuteron/h3TOFmass2antiDeuteronVsPtVsMult"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, antiDPt, event.centFT0M()); + else + histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, antiDPt); if (enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/deuteron/h2TOFmassantiDeuteronVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt_BetaCut"), massTOF * massTOF - fMassDeuteron * fMassDeuteron, track.pt()); @@ -2300,18 +2766,12 @@ struct LFNucleiBATask { } } if (enableHe) { - // if ((((!enableStrongCut) && (std::abs(track.tpcNSigmaHe()) < nsigmaTPCHe)) || ((enableStrongCut) && (std::abs(track.tpcNSigmaPr()) >= nsigmaTPCStrongCut))) && (TMath::Abs(track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3))) < yCut)) { - if (rapDebug && (std::abs(track.tpcNSigmaHe()) < nsigmaTPCHe)) { - if (track.sign() > 0) - histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_NORAPIDITYCUT"), 2.f * massTOF, hePt); - else - histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt_NORAPIDITYCUT"), 2.f * massTOF, hePt); - } if ((std::abs(track.tpcNSigmaHe()) < nsigmaTPCHe) && heRapCut) { if (track.sign() > 0) { if (enablePtSpectra) histos.fill(HIST("tracks/eff/helium/hPtHeTOF"), hePt); histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt"), 2.f * massTOF, hePt); + histos.fill(HIST("tracks/helium/h2TOFmassDeltaHeliumVsPt"), 2.f * massTOF - fMassHelium, hePt); histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), 2.f * massTOF * 2.f * massTOF - fMassHelium * fMassHelium, hePt); if (enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_BetaCut"), 2.f * massTOF, hePt); @@ -2326,6 +2786,7 @@ struct LFNucleiBATask { if (enablePtSpectra) histos.fill(HIST("tracks/eff/helium/hPtantiHeTOF"), hePt); histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt"), 2.f * massTOF, hePt); + histos.fill(HIST("tracks/helium/h2TOFmassDeltaantiHeliumVsPt"), 2.f * massTOF - fMassHelium, hePt); histos.fill(HIST("tracks/helium/h2TOFmass2antiHeliumVsPt"), 2.f * massTOF * 2.f * massTOF - fMassHelium * fMassHelium, hePt); if (enableBetaCut && (track.beta() > betaCut)) { histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt_BetaCut"), 2.f * massTOF, hePt); @@ -2364,240 +2825,241 @@ struct LFNucleiBATask { case PDGProton: if (enablePr) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTrue"), track.pt()); - histos.fill(HIST("tracks/proton/dca/hDCAxyVsPtProtonTrue"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/proton/dca/hDCAzVsPtProtonTrue"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProtonTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProtonTrue"), track.pt(), track.dcaZ()); if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCPr) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTrueWPID"), track.pt()); } if (isPhysPrim) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTruePrim"), track.pt()); - histos.fill(HIST("tracks/proton/dca/hDCAxyVsPtProtonTruePrim"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/proton/dca/hDCAzVsPtProtonTruePrim"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProtonTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProtonTruePrim"), track.pt(), track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTrueSec"), track.pt()); - histos.fill(HIST("tracks/proton/dca/hDCAxyVsPtProtonTrueSec"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/proton/dca/hDCAzVsPtProtonTrueSec"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProtonTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProtonTrueSec"), track.pt(), track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/proton/h1ProtonSpectraTrueTransport"), track.pt()); - histos.fill(HIST("tracks/proton/dca/hDCAxyVsPtProtonTrueTransport"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/proton/dca/hDCAzVsPtProtonTrueTransport"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProtonTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProtonTrueTransport"), track.pt(), track.dcaZ()); } - break; } + break; case -PDGProton: if (enablePr) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTrue"), track.pt()); - histos.fill(HIST("tracks/proton/dca/hDCAxyVsPtantiProtonTrue"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/proton/dca/hDCAzVsPtantiProtonTrue"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtantiProtonTrue"), track.pt(), track.dcaZ()); if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCPr) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTrueWPID"), track.pt()); } if (isPhysPrim) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTruePrim"), track.pt()); - histos.fill(HIST("tracks/proton/dca/hDCAxyVsPtantiProtonTruePrim"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/proton/dca/hDCAzVsPtantiProtonTruePrim"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtantiProtonTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtantiProtonTruePrim"), track.pt(), track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTrueSec"), track.pt()); - histos.fill(HIST("tracks/proton/dca/hDCAxyVsPtantiProtonTrueSec"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/proton/dca/hDCAzVsPtantiProtonTrueSec"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtantiProtonTrueSec"), track.pt(), track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/proton/h1antiProtonSpectraTrueTransport"), track.pt()); - histos.fill(HIST("tracks/proton/dca/hDCAxyVsPtantiProtonTrueTransport"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/proton/dca/hDCAzVsPtantiProtonTrueTransport"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtantiProtonTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/proton/dca/after/hDCAzVsPtantiProtonTrueTransport"), track.pt(), track.dcaZ()); } - break; } + break; case PDGDeuteron: if (enableDe) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrue"), track.pt()); - histos.fill(HIST("tracks/deuteron/dca/hDCAxyVsPtDeuteronTrue"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/hDCAzVsPtDeuteronTrue"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrue"), track.pt(), track.dcaZ()); if (std::abs(track.tpcNSigmaDe()) < nsigmaTPCDe) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrueWPID"), track.pt()); } if (isPhysPrim) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTruePrim"), track.pt()); - histos.fill(HIST("tracks/deuteron/dca/hDCAxyVsPtDeuteronTruePrim"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/hDCAzVsPtDeuteronTruePrim"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTruePrim"), track.pt(), track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrueSec"), track.pt()); - histos.fill(HIST("tracks/deuteron/dca/hDCAxyVsPtDeuteronTrueSec"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/hDCAzVsPtDeuteronTrueSec"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrueSec"), track.pt(), track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/deuteron/h1DeuteronSpectraTrueTransport"), track.pt()); - histos.fill(HIST("tracks/deuteron/dca/hDCAxyVsPtDeuteronTrueTransport"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/hDCAzVsPtDeuteronTrueTransport"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtDeuteronTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtDeuteronTrueTransport"), track.pt(), track.dcaZ()); } - break; } + break; case -PDGDeuteron: if (enableDe) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrue"), track.pt()); - histos.fill(HIST("tracks/deuteron/dca/hDCAxyVsPtantiDeuteronTrue"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/hDCAzVsPtantiDeuteronTrue"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrue"), track.pt(), track.dcaZ()); if (std::abs(track.tpcNSigmaDe()) < nsigmaTPCDe) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrueWPID"), track.pt()); } if (isPhysPrim) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTruePrim"), track.pt()); - histos.fill(HIST("tracks/deuteron/dca/hDCAxyVsPtantiDeuteronTruePrim"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/hDCAzVsPtantiDeuteronTruePrim"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTruePrim"), track.pt(), track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrueSec"), track.pt()); - histos.fill(HIST("tracks/deuteron/dca/hDCAxyVsPtantiDeuteronTrueSec"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/hDCAzVsPtantiDeuteronTrueSec"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrueSec"), track.pt(), track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectraTrueTransport"), track.pt()); - histos.fill(HIST("tracks/deuteron/dca/hDCAxyVsPtantiDeuteronTrueTransport"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/deuteron/dca/hDCAzVsPtantiDeuteronTrueTransport"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAxyVsPtantiDeuteronTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/deuteron/dca/after/hDCAzVsPtantiDeuteronTrueTransport"), track.pt(), track.dcaZ()); } - break; } + break; case PDGTriton: if (enableTr) { histos.fill(HIST("tracks/triton/h1TritonSpectraTrue"), track.pt()); - histos.fill(HIST("tracks/triton/dca/hDCAxyVsPtTritonTrue"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/triton/dca/hDCAzVsPtTritonTrue"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTritonTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTritonTrue"), track.pt(), track.dcaZ()); if (isPhysPrim) { histos.fill(HIST("tracks/triton/h1TritonSpectraTruePrim"), track.pt()); - histos.fill(HIST("tracks/triton/dca/hDCAxyVsPtTritonTruePrim"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/triton/dca/hDCAzVsPtTritonTruePrim"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTritonTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTritonTruePrim"), track.pt(), track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/triton/h1TritonSpectraTrueSec"), track.pt()); - histos.fill(HIST("tracks/triton/dca/hDCAxyVsPtTritonTrueSec"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/triton/dca/hDCAzVsPtTritonTrueSec"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTritonTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTritonTrueSec"), track.pt(), track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/triton/h1TritonSpectraTrueTransport"), track.pt()); - histos.fill(HIST("tracks/triton/dca/hDCAxyVsPtTritonTrueTransport"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/triton/dca/hDCAzVsPtTritonTrueTransport"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtTritonTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtTritonTrueTransport"), track.pt(), track.dcaZ()); } - break; } + break; case -PDGTriton: if (enableTr) { histos.fill(HIST("tracks/triton/h1antiTritonSpectraTrue"), track.pt()); - histos.fill(HIST("tracks/triton/dca/hDCAxyVsPtantiTritonTrue"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/triton/dca/hDCAzVsPtantiTritonTrue"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtantiTritonTrue"), track.pt(), track.dcaZ()); if (isPhysPrim) { histos.fill(HIST("tracks/triton/h1antiTritonSpectraTruePrim"), track.pt()); - histos.fill(HIST("tracks/triton/dca/hDCAxyVsPtantiTritonTruePrim"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/triton/dca/hDCAzVsPtantiTritonTruePrim"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtantiTritonTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtantiTritonTruePrim"), track.pt(), track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/triton/h1antiTritonSpectraTrueSec"), track.pt()); - histos.fill(HIST("tracks/triton/dca/hDCAxyVsPtantiTritonTrueSec"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/triton/dca/hDCAzVsPtantiTritonTrueSec"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtantiTritonTrueSec"), track.pt(), track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/triton/h1antiTritonSpectraTrueTransport"), track.pt()); - histos.fill(HIST("tracks/triton/dca/hDCAxyVsPtantiTritonTrueTransport"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/triton/dca/hDCAzVsPtantiTritonTrueTransport"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/triton/dca/after/hDCAxyVsPtantiTritonTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/triton/dca/after/hDCAzVsPtantiTritonTrueTransport"), track.pt(), track.dcaZ()); } } + break; case PDGHelium: if (enableHe) { histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue"), hePt); - histos.fill(HIST("tracks/helium/dca/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); - histos.fill(HIST("tracks/helium/dca/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); + histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHeliumTrue"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHeliumTrue"), hePt, track.dcaZ()); if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCHe) { histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueWPID"), hePt); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim"), hePt); - histos.fill(HIST("tracks/helium/dca/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); - histos.fill(HIST("tracks/helium/dca/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); + histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHeliumTruePrim"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHeliumTruePrim"), hePt, track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec"), hePt); - histos.fill(HIST("tracks/helium/dca/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); - histos.fill(HIST("tracks/helium/dca/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); + histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueSec"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHeliumTrueSec"), hePt, track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport"), hePt); - histos.fill(HIST("tracks/helium/dca/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); - histos.fill(HIST("tracks/helium/dca/hDCAzVsPtHeliumTrueTransport"), hePt, track.dcaZ()); + histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtHeliumTrueTransport"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtHeliumTrueTransport"), hePt, track.dcaZ()); } - break; } + break; case -PDGHelium: if (enableHe) { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue"), hePt); - histos.fill(HIST("tracks/helium/dca/hDCAxyVsPtantiHeliumTrue"), hePt, track.dcaXY()); - histos.fill(HIST("tracks/helium/dca/hDCAzVsPtantiHeliumTrue"), hePt, track.dcaZ()); + histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrue"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrue"), hePt, track.dcaZ()); if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCHe) { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueWPID"), hePt); } if (isPhysPrim) { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim"), hePt); - histos.fill(HIST("tracks/helium/dca/hDCAxyVsPtantiHeliumTruePrim"), hePt, track.dcaXY()); - histos.fill(HIST("tracks/helium/dca/hDCAzVsPtantiHeliumTruePrim"), hePt, track.dcaZ()); + histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTruePrim"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHeliumTruePrim"), hePt, track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec"), hePt); - histos.fill(HIST("tracks/helium/dca/hDCAxyVsPtantiHeliumTrueSec"), hePt, track.dcaXY()); - histos.fill(HIST("tracks/helium/dca/hDCAzVsPtantiHeliumTrueSec"), hePt, track.dcaZ()); + histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueSec"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueSec"), hePt, track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport"), hePt); - histos.fill(HIST("tracks/helium/dca/hDCAxyVsPtantiHeliumTrueTransport"), hePt, track.dcaXY()); - histos.fill(HIST("tracks/helium/dca/hDCAzVsPtantiHeliumTrueTransport"), hePt, track.dcaZ()); + histos.fill(HIST("tracks/helium/dca/after/hDCAxyVsPtantiHeliumTrueTransport"), hePt, track.dcaXY()); + histos.fill(HIST("tracks/helium/dca/after/hDCAzVsPtantiHeliumTrueTransport"), hePt, track.dcaZ()); } - break; } + break; case PDGAlpha: if (enableAl) { histos.fill(HIST("tracks/alpha/h1AlphaSpectraTrue"), track.pt()); - histos.fill(HIST("tracks/alpha/dca/hDCAxyVsPtAlphaTrue"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/alpha/dca/hDCAzVsPtAlphaTrue"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtAlphaTrue"), track.pt(), track.dcaZ()); if (isPhysPrim) { histos.fill(HIST("tracks/alpha/h1AlphaSpectraTruePrim"), track.pt()); - histos.fill(HIST("tracks/alpha/dca/hDCAxyVsPtAlphaTruePrim"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/alpha/dca/hDCAzVsPtAlphaTruePrim"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtAlphaTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtAlphaTruePrim"), track.pt(), track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/alpha/h1AlphaSpectraTrueSec"), track.pt()); - histos.fill(HIST("tracks/alpha/dca/hDCAxyVsPtAlphaTrueSec"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/alpha/dca/hDCAzVsPtAlphaTrueSec"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtAlphaTrueSec"), track.pt(), track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/alpha/h1AlphaSpectraTrueTransport"), track.pt()); - histos.fill(HIST("tracks/alpha/dca/hDCAxyVsPtAlphaTrueTransport"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/alpha/dca/hDCAzVsPtAlphaTrueTransport"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtAlphaTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtAlphaTrueTransport"), track.pt(), track.dcaZ()); } - break; } + break; case -PDGAlpha: if (enableAl) { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectraTrue"), track.pt()); - histos.fill(HIST("tracks/alpha/dca/hDCAxyVsPtantiAlphaTrue"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/alpha/dca/hDCAzVsPtantiAlphaTrue"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrue"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrue"), track.pt(), track.dcaZ()); if (isPhysPrim) { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectraTruePrim"), track.pt()); - histos.fill(HIST("tracks/alpha/dca/hDCAxyVsPtantiAlphaTruePrim"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/alpha/dca/hDCAzVsPtantiAlphaTruePrim"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTruePrim"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTruePrim"), track.pt(), track.dcaZ()); } if (!isPhysPrim && isProdByGen) { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectraTrueSec"), track.pt()); - histos.fill(HIST("tracks/alpha/dca/hDCAxyVsPtantiAlphaTrueSec"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/alpha/dca/hDCAzVsPtantiAlphaTrueSec"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrueSec"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrueSec"), track.pt(), track.dcaZ()); } if (!isPhysPrim && !isProdByGen) { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectraTrueTransport"), track.pt()); - histos.fill(HIST("tracks/alpha/dca/hDCAxyVsPtantiAlphaTrueTransport"), track.pt(), track.dcaXY()); - histos.fill(HIST("tracks/alpha/dca/hDCAzVsPtantiAlphaTrueTransport"), track.pt(), track.dcaZ()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAxyVsPtantiAlphaTrueTransport"), track.pt(), track.dcaXY()); + histos.fill(HIST("tracks/alpha/dca/after/hDCAzVsPtantiAlphaTrueTransport"), track.pt(), track.dcaZ()); } - break; } + break; default: break; } @@ -2605,7 +3067,7 @@ struct LFNucleiBATask { } } - using EventCandidates = soa::Join; + using EventCandidates = soa::Join; using TrackCandidates0 = soa::Join(event, tracks, true /*dummy*/); } // CLOSING PROCESS DATA ON FILTERED DATA PROCESS_SWITCH(LFNucleiBATask, processDataFiltered, "process data on the filtered data", false); + void processDataLight(o2::aod::LfNuclEvents::iterator const& event, + o2::aod::LfCandNucleusDummy const& tracks) + { + // Runs on derived tables produced with LF Tree creator nuclei task + // Takes as input derived trees + fillHistograms(event, tracks, true /*dummy*/); + } // CLOSING PROCESS DATA ON FILTERED DATA + PROCESS_SWITCH(LFNucleiBATask, processDataLight, "process data on the derived trees", false); + ///////////// // MC Reco // ///////////// @@ -2671,13 +3144,20 @@ struct LFNucleiBATask { PROCESS_SWITCH(LFNucleiBATask, processMCReco, "process mc reco", false); // Process function that runs on the filtered AO2D (for the MC) - void processMCRecoFiltered(o2::aod::LfCandNucleusFullEvents::iterator const& event, + void processMCRecoFiltered(o2::aod::LfNuclEvents::iterator const& event, soa::Join const& tracks) { fillHistograms(event, tracks, true /*dummy*/); } // CLOSING PROCESS MC RECO ON FILTERED DATA PROCESS_SWITCH(LFNucleiBATask, processMCRecoFiltered, "process mc reco on the filtered data", false); + void processMCRecoFilteredLight(o2::aod::LfNuclEvents::iterator const& event, + soa::Join const& tracks) + { + fillHistograms(event, tracks, true /*dummy*/); + } // CLOSING PROCESS MC RECO ON FILTERED DATA + PROCESS_SWITCH(LFNucleiBATask, processMCRecoFilteredLight, "process mc reco on the derived trees", false); + //////////// // MC Gen // //////////// @@ -2694,6 +3174,7 @@ struct LFNucleiBATask { bool isPhysPrim = mcParticleGen.isPhysicalPrimary(); bool isProdByGen = mcParticleGen.producedByGenerator(); + if (mcParticleGen.pdgCode() == PDGPion) { histos.fill(HIST("spectraGen/pion/histGenPtPion"), mcParticleGen.pt()); if (isPhysPrim) diff --git a/PWGLF/Tasks/NucleiHistTask.cxx b/PWGLF/Tasks/NucleiHistTask.cxx index a0f7c3119cd..8965bd0afab 100644 --- a/PWGLF/Tasks/NucleiHistTask.cxx +++ b/PWGLF/Tasks/NucleiHistTask.cxx @@ -81,18 +81,22 @@ struct NucleiHistTask { } std::vector ptBinning = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4., 5., 6., 8., 10., 12., 14.}; + std::vector ptBinning_reduced = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 1.0, 1.3, 1.6, 1.9, 2.2, 2.5, 2.8, 3.1, 3.4, 3.7, 4., 5., 6., 8., 10., 12., 14.}; std::vector centBinning = {0., 1., 5., 10., 20., 30., 40., 50., 70., 100.}; + std::vector etaBinning = {-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxis_reduced = {ptBinning_reduced, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec centAxis = {centBinning, "V0M (%)"}; AxisSpec centralityAxis = {100, 0.0, 100.0, "VT0C (%)"}; AxisSpec centralityAxis_extended = {105, 0.0, 105.0, "VT0C (%)"}; + AxisSpec etaAxis = {etaBinning, "#eta"}; // +++++++++++++++++++++ Data ++++++++++++++++++++++++ // QA histograms spectra_reg.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); - spectra_reg.add("histTpcSignalData", "Specific energy loss", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + spectra_reg.add("histTpcSignalData", "Specific energy loss", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); spectra_reg.add("histTofSignalData", "TOF signal", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); spectra_reg.add("histDcaVsPtData_particle", "dcaXY vs Pt (particle)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); spectra_reg.add("histDcaZVsPtData_particle", "dcaZ vs Pt (particle)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -101,13 +105,17 @@ struct NucleiHistTask { spectra_reg.add("histTOFm2", "TOF m^2 vs Pt", HistType::kTH2F, {ptAxis, {400, 0.0, 10.0, "m^2"}}); spectra_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); spectra_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + spectra_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); spectra_reg.add("histChi2TPC", "chi^2 TPC vs Pt", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); spectra_reg.add("histChi2ITS", "chi^2 ITS vs Pt", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); spectra_reg.add("histCentrality", "Centrality", HistType::kTH1F, {centralityAxis_extended}); + spectra_reg.add("histEtaWithOverFlow", "Pseudorapidity 0 - 105%% centrality", HistType::kTH1F, {etaAxis}); + spectra_reg.add("histEta", "Pseudorapidity with centrality cut", HistType::kTH1F, {etaAxis}); + spectra_reg.add("histEta_cent", "Pseudorapidity vs Centrality", HistType::kTH2F, {centralityAxis_extended, etaAxis}); // histograms for Proton proton_reg.add("histKeepEventData", "skimming histogram (p)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - proton_reg.add("histTpcSignalData", "Specific energy loss (p)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + proton_reg.add("histTpcSignalData", "Specific energy loss (p)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); proton_reg.add("histTofSignalData", "TOF signal (p)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); proton_reg.add("histDcaVsPtData", "dcaXY vs Pt (p)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); proton_reg.add("histDcaZVsPtData", "dcaZ vs Pt (p)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -116,15 +124,19 @@ struct NucleiHistTask { proton_reg.add("histTofNsigmaData", "n-sigma TOF (p)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}}); proton_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (p)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); proton_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (p)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + proton_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (p)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); proton_reg.add("histChi2TPC", "chi^2 TPC vs Pt (p)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); proton_reg.add("histChi2ITS", "chi^2 ITS vs Pt (p)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); proton_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (p) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, centralityAxis}); proton_reg.add("histTofNsigmaData_cent", "n-sigma TOF (p) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, centralityAxis}); proton_reg.add("histTofm2_cent", "mass^2 TOF (p) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, centralityAxis}); + proton_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (p) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + proton_reg.add("histTofNsigmaData_eta", "n-sigma TOF (p) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + proton_reg.add("histTofm2_eta", "mass^2 TOF (p) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for antiProton aproton_reg.add("histKeepEventData", "skimming histogram (antip)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - aproton_reg.add("histTpcSignalData", "Specific energy loss (antip)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + aproton_reg.add("histTpcSignalData", "Specific energy loss (antip)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); aproton_reg.add("histTofSignalData", "TOF signal (antip)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); aproton_reg.add("histDcaVsPtData", "dcaXY vs Pt (antip)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); aproton_reg.add("histDcaZVsPtData", "dcaZ vs Pt (antip)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -133,49 +145,61 @@ struct NucleiHistTask { aproton_reg.add("histTofNsigmaData", "n-sigma TOF (antip)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{antip}"}}); aproton_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (antip)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); aproton_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (antip)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + aproton_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (antip)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); aproton_reg.add("histChi2TPC", "chi^2 TPC vs Pt (antip)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); aproton_reg.add("histChi2ITS", "chi^2 ITS vs Pt (antip)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); aproton_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (antip) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antip}"}, centralityAxis}); aproton_reg.add("histTofNsigmaData_cent", "n-sigma TOF (antip) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antip}"}, centralityAxis}); aproton_reg.add("histTofm2_cent", "mass^2 TOF (antip) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{antip}"}, centralityAxis}); + aproton_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (antip) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + aproton_reg.add("histTofNsigmaData_eta", "n-sigma TOF (antip) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + aproton_reg.add("histTofm2_eta", "mass^2 TOF (antip) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for Deuterons deuteron_reg.add("histKeepEventData", "skimming histogram (d)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - deuteron_reg.add("histTpcSignalData", "Specific energy loss (d)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + deuteron_reg.add("histTpcSignalData", "Specific energy loss (d)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); deuteron_reg.add("histTofSignalData", "TOF signal (d)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); deuteron_reg.add("histDcaVsPtData", "dcaXY vs Pt (d)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); deuteron_reg.add("histDcaZVsPtData", "dcaZ vs Pt (d)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); deuteron_reg.add("histTOFm2", "TOF m^2 vs Pt (d)", HistType::kTH2F, {ptAxis, {400, 0.0, 10.0, "m^2"}}); deuteron_reg.add("histTpcNsigmaData", "n-sigma TPC (d)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); - deuteron_reg.add("histTofNsigmaData", "n-sigma TOF (d)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}}); + deuteron_reg.add("histTofNsigmaData", "n-sigma TOF (d)", HistType::kTH2F, {ptAxis_reduced, {160, -20., +20., "n#sigma_{d}"}}); deuteron_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (d)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); deuteron_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (d)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + deuteron_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (d)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); deuteron_reg.add("histChi2TPC", "chi^2 TPC vs Pt (d)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); deuteron_reg.add("histChi2ITS", "chi^2 ITS vs Pt (d)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); deuteron_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (d) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}, centralityAxis}); - deuteron_reg.add("histTofNsigmaData_cent", "n-sigma TOF (d) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{d}"}, centralityAxis}); + deuteron_reg.add("histTofNsigmaData_cent", "n-sigma TOF (d) centrality", HistType::kTH3F, {ptAxis_reduced, {160, -20., +20., "n#sigma_{d}"}, centralityAxis}); deuteron_reg.add("histTofm2_cent", "mass^2 TOF (d) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{d}"}, centralityAxis}); + deuteron_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (d) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + deuteron_reg.add("histTofNsigmaData_eta", "n-sigma TOF (d) vs eta", HistType::kTH3F, {ptAxis_reduced, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + deuteron_reg.add("histTofm2_eta", "mass^2 TOF (d) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for antiDeuterons adeuteron_reg.add("histKeepEventData", "skimming histogram (antid)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - adeuteron_reg.add("histTpcSignalData", "Specific energy loss (antid)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + adeuteron_reg.add("histTpcSignalData", "Specific energy loss (antid)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); adeuteron_reg.add("histTofSignalData", "TOF signal (antid)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); adeuteron_reg.add("histDcaVsPtData", "dcaXY vs Pt (antid)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); adeuteron_reg.add("histDcaZVsPtData", "dcaZ vs Pt (antid)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); adeuteron_reg.add("histTOFm2", "TOF m^2 vs Pt (antid)", HistType::kTH2F, {ptAxis, {400, 0.0, 10.0, "m^2"}}); adeuteron_reg.add("histTpcNsigmaData", "n-sigma TPC (antid)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{antid}"}}); - adeuteron_reg.add("histTofNsigmaData", "n-sigma TOF (antid)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{antid}"}}); + adeuteron_reg.add("histTofNsigmaData", "n-sigma TOF (antid)", HistType::kTH2F, {ptAxis_reduced, {160, -20., +20., "n#sigma_{antid}"}}); adeuteron_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (antid)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); adeuteron_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (antid)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + adeuteron_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (antid)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); adeuteron_reg.add("histChi2TPC", "chi^2 TPC vs Pt (antid)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); adeuteron_reg.add("histChi2ITS", "chi^2 ITS vs Pt (antid)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); adeuteron_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (antid) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antid}"}, centralityAxis}); - adeuteron_reg.add("histTofNsigmaData_cent", "n-sigma TOF (antid) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antid}"}, centralityAxis}); + adeuteron_reg.add("histTofNsigmaData_cent", "n-sigma TOF (antid) centrality", HistType::kTH3F, {ptAxis_reduced, {160, -20., +20., "n#sigma_{antid}"}, centralityAxis}); adeuteron_reg.add("histTofm2_cent", "mass^2 TOF (antid) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{antid}"}, centralityAxis}); + adeuteron_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (antid) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + adeuteron_reg.add("histTofNsigmaData_eta", "n-sigma TOF (antid) vs eta", HistType::kTH3F, {ptAxis_reduced, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + adeuteron_reg.add("histTofm2_eta", "mass^2 TOF (antid) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for Triton triton_reg.add("histKeepEventData", "skimming histogram (t)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - triton_reg.add("histTpcSignalData", "Specific energy loss (t)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + triton_reg.add("histTpcSignalData", "Specific energy loss (t)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); triton_reg.add("histTofSignalData", "TOF signal (t)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); triton_reg.add("histDcaVsPtData", "dcaXY vs Pt (t)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); triton_reg.add("histDcaZVsPtData", "dcaZ vs Pt (t)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -184,15 +208,19 @@ struct NucleiHistTask { triton_reg.add("histTofNsigmaData", "n-sigma TOF (t)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}}); triton_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (t)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); triton_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (t)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + triton_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (t)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); triton_reg.add("histChi2TPC", "chi^2 TPC vs Pt (t)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); triton_reg.add("histChi2ITS", "chi^2 ITS vs Pt (t)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); triton_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (t) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}, centralityAxis}); triton_reg.add("histTofNsigmaData_cent", "n-sigma TOF (t) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{t}"}, centralityAxis}); triton_reg.add("histTofm2_cent", "mass^2 TOF (t) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{t}"}, centralityAxis}); + triton_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (t) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + triton_reg.add("histTofNsigmaData_eta", "n-sigma TOF (t) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + triton_reg.add("histTofm2_eta", "mass^2 TOF (t) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for antiTriton atriton_reg.add("histKeepEventData", "skimming histogram (antit)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - atriton_reg.add("histTpcSignalData", "Specific energy loss (antit)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + atriton_reg.add("histTpcSignalData", "Specific energy loss (antit)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); atriton_reg.add("histTofSignalData", "TOF signal (antit)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); atriton_reg.add("histDcaVsPtData", "dcaXY vs Pt (antit)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); atriton_reg.add("histDcaZVsPtData", "dcaZ vs Pt (antit)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -201,15 +229,19 @@ struct NucleiHistTask { atriton_reg.add("histTofNsigmaData", "n-sigma TOF (antit)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{antit}"}}); atriton_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (antit)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); atriton_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (antit)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + atriton_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (antit)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); atriton_reg.add("histChi2TPC", "chi^2 TPC vs Pt (antit)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); atriton_reg.add("histChi2ITS", "chi^2 ITS vs Pt (antit)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); atriton_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (antit) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antit}"}, centralityAxis}); atriton_reg.add("histTofNsigmaData_cent", "n-sigma TOF (antit) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antit}"}, centralityAxis}); atriton_reg.add("histTofm2_cent", "mass^2 TOF (antit) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{antit}"}, centralityAxis}); + atriton_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (antit) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + atriton_reg.add("histTofNsigmaData_eta", "n-sigma TOF (antit) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + atriton_reg.add("histTofm2_eta", "mass^2 TOF (antit) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for Helium-3 Helium3_reg.add("histKeepEventData", "skimming histogram (He-3)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - Helium3_reg.add("histTpcSignalData", "Specific energy loss (He-3)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + Helium3_reg.add("histTpcSignalData", "Specific energy loss (He-3)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); Helium3_reg.add("histTofSignalData", "TOF signal (He-3)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); Helium3_reg.add("histDcaVsPtData", "dcaXY vs Pt (He-3)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); Helium3_reg.add("histDcaZVsPtData", "dcaZ vs Pt (He-3)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -218,15 +250,19 @@ struct NucleiHistTask { Helium3_reg.add("histTofNsigmaData", "n-sigma TOF (He-3)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-3}"}}); Helium3_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (He-3)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); Helium3_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (He-3)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + Helium3_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (He-3)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); Helium3_reg.add("histChi2TPC", "chi^2 TPC vs Pt (He-3)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); Helium3_reg.add("histChi2ITS", "chi^2 ITS vs Pt (He-3)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); Helium3_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (He-3) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{He-3}"}, centralityAxis}); Helium3_reg.add("histTofNsigmaData_cent", "n-sigma TOF (He-3) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{He-3}"}, centralityAxis}); Helium3_reg.add("histTofm2_cent", "mass^2 TOF (He-3) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{He-3}"}, centralityAxis}); + Helium3_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (He-3) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + Helium3_reg.add("histTofNsigmaData_eta", "n-sigma TOF (He-3) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + Helium3_reg.add("histTofm2_eta", "mass^2 TOF (He-3) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for antiHelium-3 aHelium3_reg.add("histKeepEventData", "skimming histogram (antiHe-3)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - aHelium3_reg.add("histTpcSignalData", "Specific energy loss (antiHe-3)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + aHelium3_reg.add("histTpcSignalData", "Specific energy loss (antiHe-3)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); aHelium3_reg.add("histTofSignalData", "TOF signal (antiHe-3)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); aHelium3_reg.add("histDcaVsPtData", "dcaXY vs Pt (antiHe-3)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); aHelium3_reg.add("histDcaZVsPtData", "dcaZ vs Pt (antiHe-3)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -235,15 +271,19 @@ struct NucleiHistTask { aHelium3_reg.add("histTofNsigmaData", "n-sigma TOF (antiHe-3)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{antiHe-3}"}}); aHelium3_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (antiHe-3)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); aHelium3_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (antiHe-3)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + aHelium3_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (antiHe-3)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); aHelium3_reg.add("histChi2TPC", "chi^2 TPC vs Pt (antiHe-3)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); aHelium3_reg.add("histChi2ITS", "chi^2 ITS vs Pt (antiHe-3)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); aHelium3_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (antiHe-3) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antiHe-3}"}, centralityAxis}); aHelium3_reg.add("histTofNsigmaData_cent", "n-sigma TOF (antiHe-3) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antiHe-3}"}, centralityAxis}); aHelium3_reg.add("histTofm2_cent", "mass^2 TOF (antiHe-3) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{antiHe-3}"}, centralityAxis}); + aHelium3_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (antiHe-3) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + aHelium3_reg.add("histTofNsigmaData_eta", "n-sigma TOF (antiHe-3) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + aHelium3_reg.add("histTofm2_eta", "mass^2 TOF (antiHe-3) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for Helium-4 (alpha) Helium4_reg.add("histKeepEventData", "skimming histogram (He-4)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - Helium4_reg.add("histTpcSignalData", "Specific energy loss (He-4)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + Helium4_reg.add("histTpcSignalData", "Specific energy loss (He-4)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); Helium4_reg.add("histTofSignalData", "TOF signal (He-4)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); Helium4_reg.add("histDcaVsPtData", "dcaXY vs Pt (He-4)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); Helium4_reg.add("histDcaZVsPtData", "dcaZ vs Pt (He-4)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -252,15 +292,19 @@ struct NucleiHistTask { Helium4_reg.add("histTofNsigmaData", "n-sigma TOF (He-4)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{He-4}"}}); Helium4_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (He-4)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); Helium4_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (He-4)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + Helium4_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (He-4)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); Helium4_reg.add("histChi2TPC", "chi^2 TPC vs Pt (He-4)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); Helium4_reg.add("histChi2ITS", "chi^2 ITS vs Pt (He-4)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); Helium4_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (He-4) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{He-4}"}, centralityAxis}); Helium4_reg.add("histTofNsigmaData_cent", "n-sigma TOF (He-4) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{He-4}"}, centralityAxis}); Helium4_reg.add("histTofm2_cent", "mass^2 TOF (He-4) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{He-4}"}, centralityAxis}); + Helium4_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (He-4) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + Helium4_reg.add("histTofNsigmaData_eta", "n-sigma TOF (He-4) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + Helium4_reg.add("histTofm2_eta", "mass^2 TOF (He-4) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // histograms for antiHelium-4 (alpha) aHelium4_reg.add("histKeepEventData", "skimming histogram (antiHe-4)", HistType::kTH1F, {{2, -0.5, +1.5, "true: keep event, false: reject event"}}); - aHelium4_reg.add("histTpcSignalData", "Specific energy loss (antiHe-4)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + aHelium4_reg.add("histTpcSignalData", "Specific energy loss (antiHe-4)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); aHelium4_reg.add("histTofSignalData", "TOF signal (antiHe-4)", HistType::kTH2F, {{600, 0., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); aHelium4_reg.add("histDcaVsPtData", "dcaXY vs Pt (antiHe-4)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); aHelium4_reg.add("histDcaZVsPtData", "dcaZ vs Pt (antiHe-4)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); @@ -269,11 +313,15 @@ struct NucleiHistTask { aHelium4_reg.add("histTofNsigmaData", "n-sigma TOF (antiHe-4)", HistType::kTH2F, {ptAxis, {160, -20., +20., "n#sigma_{antiHe-4}"}}); aHelium4_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt (antiHe-4)", HistType::kTH2F, {ptAxis, {160, 0.0, 160.0, "nCluster"}}); aHelium4_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt (antiHe-4)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + aHelium4_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt (antiHe-4)", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); aHelium4_reg.add("histChi2TPC", "chi^2 TPC vs Pt (antiHe-4)", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); aHelium4_reg.add("histChi2ITS", "chi^2 ITS vs Pt (antiHe-4)", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); aHelium4_reg.add("histTpcNsigmaData_cent", "n-sigma TPC (antiHe-4) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antiHe-4}"}, centralityAxis}); aHelium4_reg.add("histTofNsigmaData_cent", "n-sigma TOF (antiHe-4) centrality", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{antiHe-4}"}, centralityAxis}); aHelium4_reg.add("histTofm2_cent", "mass^2 TOF (antiHe-4) centrality", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{antiHe-4}"}, centralityAxis}); + aHelium4_reg.add("histTpcNsigmaData_eta", "n-sigma TPC (antiHe-4) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + aHelium4_reg.add("histTofNsigmaData_eta", "n-sigma TOF (antiHe-4) vs eta", HistType::kTH3F, {ptAxis, {160, -20., +20., "n#sigma_{p}"}, etaAxis}); + aHelium4_reg.add("histTofm2_eta", "mass^2 TOF (antiHe-4) vs eta", HistType::kTH3F, {ptAxis, {400, 0.0, 10.0, "m^2_{p}"}, etaAxis}); // +++++++++++++++++++++ MC ++++++++++++++++++++++++++ @@ -375,9 +423,13 @@ struct NucleiHistTask { Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; Configurable nsigmacutLow{"nsigmacutLow", -3.0, "Value of the Nsigma cut"}; Configurable nsigmacutHigh{"nsigmacutHigh", +3.0, "Value of the Nsigma cut"}; + Configurable minCentrality{"minCentrality", 0.0, "min Centrality used"}; + Configurable maxCentrality{"maxCentrality", 80.0, "max Centrality used"}; + Configurable enable_Centrality_cut_global{"enable_Centrality_cut_global", true, "use Centrality cut"}; // Replacement for globalTrack filter Configurable minReqClusterITS{"minReqClusterITS", 1.0, "min number of clusters required in ITS"}; // ITS_nCls + Configurable minReqClusterITSib{"minReqClusterITSib", 1.0, "min number of clusters required in ITS inner barrel"}; // ITS_nCls Configurable minTPCnClsFound{"minTPCnClsFound", 0.0f, "min number of crossed rows TPC"}; // TPC_nCls_found Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.0f, "min number of crossed rows TPC"}; // TPC_nCls_crossed_Rows Configurable minRatioCrossedRowsTPC{"minRatioCrossedRowsTPC", 0.8f, "min ratio of crossed rows over findable clusters TPC"}; // TPC_crossed_Rows_over_findable_Cls_min @@ -388,6 +440,8 @@ struct NucleiHistTask { Configurable maxDCA_Z{"maxDCA_Z", 2.0f, "max DCA to vertex z"}; Configurable lastRequiredTrdCluster{"lastRequiredTrdCluster", 5, "Last cluster to required in TRD for track selection. -1 does not require any TRD cluster"}; + Configurable event_selection_sel8{"event_selection_sel8", true, "Enable sel8 event selection"}; + Configurable enable_PVcontributor_global{"enable_PVcontributor_global", true, "is PV contributor (global)"}; Configurable enable_PVcontributor_proton{"enable_PVcontributor_proton", true, "is PV contributor (global)"}; Configurable enable_PVcontributor_antiproton{"enable_PVcontributor_antiproton", true, "is PV contributor (global)"}; @@ -417,23 +471,26 @@ struct NucleiHistTask { bool keepEvent_antiHe3 = kFALSE; bool keepEvent_antiHe4 = kFALSE; - spectra_reg.fill(HIST("histRecVtxZData"), event.posZ()); + if (event_selection_sel8 && event.sel8()) { + spectra_reg.fill(HIST("histRecVtxZData"), event.posZ()); + } + + if (!event_selection_sel8) { + spectra_reg.fill(HIST("histRecVtxZData"), event.posZ()); + } for (auto track : tracks) { // start loop over tracks + if (event_selection_sel8 && !event.sel8()) { + continue; + } + float TPCnumberClsFound = track.tpcNClsFound(); float TPC_nCls_Crossed_Rows = track.tpcNClsCrossedRows(); float RatioCrossedRowsOverFindableTPC = track.tpcCrossedRowsOverFindableCls(); float Chi2perClusterTPC = track.tpcChi2NCl(); float Chi2perClusterITS = track.itsChi2NCl(); - if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNCls()) < minReqClusterITS) { - continue; - } - if (enable_PVcontributor_global && !(track.isPVContributor())) { - continue; - } - if (track.sign() > 0) { spectra_reg.fill(HIST("histDcaVsPtData_particle"), track.pt(), track.dcaXY()); spectra_reg.fill(HIST("histDcaZVsPtData_particle"), track.pt(), track.dcaZ()); @@ -448,6 +505,16 @@ struct NucleiHistTask { continue; } + if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNClsInnerBarrel()) < minReqClusterITSib || (track.itsNCls()) < minReqClusterITS) { + continue; + } + if (enable_PVcontributor_global && !(track.isPVContributor())) { + continue; + } + if (TMath::Abs(track.dcaXY()) > maxDCA_XY || TMath::Abs(track.dcaZ()) > maxDCA_Z) { + continue; + } + // cut on rapidity TLorentzVector lorentzVector_proton{}; TLorentzVector lorentzVector_deuteron{}; @@ -479,6 +546,7 @@ struct NucleiHistTask { spectra_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam() * track.sign(), track.tpcSignal()); spectra_reg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsCrossedRows()); spectra_reg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + spectra_reg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); spectra_reg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); spectra_reg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); @@ -556,6 +624,7 @@ struct NucleiHistTask { proton_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); proton_reg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsFound()); proton_reg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + proton_reg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); proton_reg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); proton_reg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); @@ -595,6 +664,7 @@ struct NucleiHistTask { aproton_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); aproton_reg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsFound()); aproton_reg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + aproton_reg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); aproton_reg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); aproton_reg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); @@ -658,6 +728,7 @@ struct NucleiHistTask { deuteron_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); deuteron_reg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsFound()); deuteron_reg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + deuteron_reg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); deuteron_reg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); deuteron_reg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); @@ -697,6 +768,7 @@ struct NucleiHistTask { adeuteron_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); adeuteron_reg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsFound()); adeuteron_reg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + adeuteron_reg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); adeuteron_reg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); adeuteron_reg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); @@ -759,6 +831,7 @@ struct NucleiHistTask { triton_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); triton_reg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsFound()); triton_reg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + triton_reg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); triton_reg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); triton_reg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); @@ -798,6 +871,7 @@ struct NucleiHistTask { atriton_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); atriton_reg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsFound()); atriton_reg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + atriton_reg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); atriton_reg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); atriton_reg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); @@ -860,6 +934,7 @@ struct NucleiHistTask { Helium3_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam() * 2.0, track.tpcSignal()); Helium3_reg.fill(HIST("histNClusterTPC"), track.pt() * 2.0, track.tpcNClsFound()); Helium3_reg.fill(HIST("histNClusterITS"), track.pt() * 2.0, track.itsNCls()); + Helium3_reg.fill(HIST("histNClusterITSib"), track.pt() * 2.0, track.itsNClsInnerBarrel()); Helium3_reg.fill(HIST("histChi2TPC"), track.pt() * 2.0, track.tpcChi2NCl()); Helium3_reg.fill(HIST("histChi2ITS"), track.pt() * 2.0, track.itsChi2NCl()); @@ -898,6 +973,7 @@ struct NucleiHistTask { aHelium3_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam() * 2.0, track.tpcSignal()); aHelium3_reg.fill(HIST("histNClusterTPC"), track.pt() * 2.0, track.tpcNClsFound()); aHelium3_reg.fill(HIST("histNClusterITS"), track.pt() * 2.0, track.itsNCls()); + aHelium3_reg.fill(HIST("histNClusterITSib"), track.pt() * 2.0, track.itsNClsInnerBarrel()); aHelium3_reg.fill(HIST("histChi2TPC"), track.pt() * 2.0, track.tpcChi2NCl()); aHelium3_reg.fill(HIST("histChi2ITS"), track.pt() * 2.0, track.itsChi2NCl()); @@ -960,6 +1036,7 @@ struct NucleiHistTask { Helium4_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam() * 2.0, track.tpcSignal()); Helium4_reg.fill(HIST("histNClusterTPC"), track.pt() * 2.0, track.tpcNClsFound()); Helium4_reg.fill(HIST("histNClusterITS"), track.pt() * 2.0, track.itsNCls()); + Helium4_reg.fill(HIST("histNClusterITSib"), track.pt() * 2.0, track.itsNClsInnerBarrel()); Helium4_reg.fill(HIST("histChi2TPC"), track.pt() * 2.0, track.tpcChi2NCl()); Helium4_reg.fill(HIST("histChi2ITS"), track.pt() * 2.0, track.itsChi2NCl()); @@ -998,6 +1075,7 @@ struct NucleiHistTask { aHelium4_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam() * 2.0, track.tpcSignal()); aHelium4_reg.fill(HIST("histNClusterTPC"), track.pt() * 2.0, track.tpcNClsFound()); aHelium4_reg.fill(HIST("histNClusterITS"), track.pt() * 2.0, track.itsNCls()); + aHelium4_reg.fill(HIST("histNClusterITSib"), track.pt() * 2.0, track.itsNClsInnerBarrel()); aHelium4_reg.fill(HIST("histChi2TPC"), track.pt() * 2.0, track.tpcChi2NCl()); aHelium4_reg.fill(HIST("histChi2ITS"), track.pt() * 2.0, track.itsChi2NCl()); @@ -1065,10 +1143,31 @@ struct NucleiHistTask { void fillCentHistorgrams(const CollisionType& event, const TracksType& tracks) { - spectra_reg.fill(HIST("histCentrality"), event.centFT0C()); + if (event_selection_sel8 && event.sel8()) { + spectra_reg.fill(HIST("histCentrality"), event.centFT0C()); + } + + if (!event_selection_sel8) { + spectra_reg.fill(HIST("histCentrality"), event.centFT0C()); + } for (auto track : tracks) { // start loop over tracks + if (event_selection_sel8 && !event.sel8()) { + continue; + } + + if (enable_Centrality_cut_global && (event.centFT0C() < minCentrality) && (event.centFT0C() > maxCentrality)) { + continue; + } + + spectra_reg.fill(HIST("histEtaWithOverFlow"), track.eta()); + spectra_reg.fill(HIST("histEta_cent"), event.centFT0C(), track.eta()); + + if ((event.centFT0C() > minCentrality) && (event.centFT0C() < maxCentrality)) { + spectra_reg.fill(HIST("histEta"), track.eta()); + } + float TPCnumberClsFound = track.tpcNClsFound(); float TPC_nCls_Crossed_Rows = track.tpcNClsCrossedRows(); float RatioCrossedRowsOverFindableTPC = track.tpcCrossedRowsOverFindableCls(); @@ -1080,7 +1179,7 @@ struct NucleiHistTask { continue; } - if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNCls()) < minReqClusterITS) { + if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNClsInnerBarrel()) < minReqClusterITSib || (track.itsNCls()) < minReqClusterITS) { continue; } @@ -1114,31 +1213,52 @@ struct NucleiHistTask { Helium3_reg.fill(HIST("histTpcNsigmaData_cent"), track.pt() * 2.0, track.tpcNSigmaHe(), event.centFT0C()); Helium4_reg.fill(HIST("histTpcNsigmaData_cent"), track.pt() * 2.0, track.tpcNSigmaAl(), event.centFT0C()); - if (track.hasTRD() && (lastRequiredTrdCluster > 0)) { - int lastLayer = 0; - for (int l = 7; l >= 0; l--) { - if (track.trdPattern() & (1 << l)) { - lastLayer = l; - break; + if ((event.centFT0C() > minCentrality) && (event.centFT0C() < maxCentrality)) { + proton_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt(), track.tpcNSigmaPr(), track.eta()); + deuteron_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt(), track.tpcNSigmaDe(), track.eta()); + triton_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt(), track.tpcNSigmaTr(), track.eta()); + Helium3_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt() * 2.0, track.tpcNSigmaHe(), track.eta()); + Helium4_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt() * 2.0, track.tpcNSigmaAl(), track.eta()); + } + + if (track.hasTOF()) { + if (track.hasTRD() && (lastRequiredTrdCluster > 0)) { + int lastLayer = 0; + for (int l = 7; l >= 0; l--) { + if (track.trdPattern() & (1 << l)) { + lastLayer = l; + break; + } + } + if (lastLayer < lastRequiredTrdCluster) { + continue; } } - if (lastLayer < lastRequiredTrdCluster) { - continue; - } - } - proton_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaPr(), event.centFT0C()); - deuteron_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaDe(), event.centFT0C()); - triton_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaTr(), event.centFT0C()); - Helium3_reg.fill(HIST("histTofNsigmaData_cent"), track.pt() * 2.0, track.tofNSigmaHe(), event.centFT0C()); - Helium4_reg.fill(HIST("histTofNsigmaData_cent"), track.pt() * 2.0, track.tofNSigmaAl(), event.centFT0C()); + proton_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaPr(), event.centFT0C()); + deuteron_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaDe(), event.centFT0C()); + triton_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaTr(), event.centFT0C()); + Helium3_reg.fill(HIST("histTofNsigmaData_cent"), track.pt() * 2.0, track.tofNSigmaHe(), event.centFT0C()); + Helium4_reg.fill(HIST("histTofNsigmaData_cent"), track.pt() * 2.0, track.tofNSigmaAl(), event.centFT0C()); - if (track.hasTOF()) { proton_reg.fill(HIST("histTofm2_cent"), track.pt(), track.mass() * track.mass(), event.centFT0C()); deuteron_reg.fill(HIST("histTofm2_cent"), track.pt(), track.mass() * track.mass(), event.centFT0C()); triton_reg.fill(HIST("histTofm2_cent"), track.pt(), track.mass() * track.mass(), event.centFT0C()); Helium3_reg.fill(HIST("histTofm2_cent"), track.pt() * 2.0, track.mass() * track.mass(), event.centFT0C()); Helium4_reg.fill(HIST("histTofm2_cent"), track.pt() * 2.0, track.mass() * track.mass(), event.centFT0C()); + + if ((event.centFT0C() > minCentrality) && (event.centFT0C() < maxCentrality)) { + proton_reg.fill(HIST("histTofm2_eta"), track.pt(), track.mass() * track.mass(), track.eta()); + proton_reg.fill(HIST("histTofNsigmaData_eta"), track.pt(), track.tofNSigmaPr(), track.eta()); + deuteron_reg.fill(HIST("histTofm2_eta"), track.pt(), track.mass() * track.mass(), track.eta()); + deuteron_reg.fill(HIST("histTofNsigmaData_eta"), track.pt(), track.tofNSigmaDe(), track.eta()); + triton_reg.fill(HIST("histTofm2_eta"), track.pt(), track.mass() * track.mass(), track.eta()); + triton_reg.fill(HIST("histTofNsigmaData_eta"), track.pt(), track.tofNSigmaTr(), track.eta()); + Helium3_reg.fill(HIST("histTofm2_eta"), track.pt() * 2.0, track.mass() * track.mass(), track.eta()); + Helium3_reg.fill(HIST("histTofNsigmaData_eta"), track.pt() * 2.0, track.tofNSigmaHe(), track.eta()); + Helium4_reg.fill(HIST("histTofm2_eta"), track.pt() * 2.0, track.mass() * track.mass(), track.eta()); + Helium4_reg.fill(HIST("histTofNsigmaData_eta"), track.pt() * 2.0, track.tofNSigmaAl(), track.eta()); + } } } @@ -1150,31 +1270,52 @@ struct NucleiHistTask { aHelium3_reg.fill(HIST("histTpcNsigmaData_cent"), track.pt() * 2.0, track.tpcNSigmaHe(), event.centFT0C()); aHelium4_reg.fill(HIST("histTpcNsigmaData_cent"), track.pt() * 2.0, track.tpcNSigmaAl(), event.centFT0C()); - if (track.hasTRD() && (lastRequiredTrdCluster > 0)) { - int lastLayer = 0; - for (int l = 7; l >= 0; l--) { - if (track.trdPattern() & (1 << l)) { - lastLayer = l; - break; + if ((event.centFT0C() > minCentrality) && (event.centFT0C() < maxCentrality)) { + aproton_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt(), track.tpcNSigmaPr(), track.eta()); + adeuteron_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt(), track.tpcNSigmaDe(), track.eta()); + atriton_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt(), track.tpcNSigmaTr(), track.eta()); + aHelium3_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt() * 2.0, track.tpcNSigmaHe(), track.eta()); + aHelium4_reg.fill(HIST("histTpcNsigmaData_eta"), track.pt() * 2.0, track.tpcNSigmaAl(), track.eta()); + } + + if (track.hasTOF()) { + if (track.hasTRD() && (lastRequiredTrdCluster > 0)) { + int lastLayer = 0; + for (int l = 7; l >= 0; l--) { + if (track.trdPattern() & (1 << l)) { + lastLayer = l; + break; + } + } + if (lastLayer < lastRequiredTrdCluster) { + continue; } } - if (lastLayer < lastRequiredTrdCluster) { - continue; - } - } - aproton_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaPr(), event.centFT0C()); - adeuteron_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaDe(), event.centFT0C()); - atriton_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaTr(), event.centFT0C()); - aHelium3_reg.fill(HIST("histTofNsigmaData_cent"), track.pt() * 2.0, track.tofNSigmaHe(), event.centFT0C()); - aHelium4_reg.fill(HIST("histTofNsigmaData_cent"), track.pt() * 2.0, track.tofNSigmaAl(), event.centFT0C()); + aproton_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaPr(), event.centFT0C()); + adeuteron_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaDe(), event.centFT0C()); + atriton_reg.fill(HIST("histTofNsigmaData_cent"), track.pt(), track.tofNSigmaTr(), event.centFT0C()); + aHelium3_reg.fill(HIST("histTofNsigmaData_cent"), track.pt() * 2.0, track.tofNSigmaHe(), event.centFT0C()); + aHelium4_reg.fill(HIST("histTofNsigmaData_cent"), track.pt() * 2.0, track.tofNSigmaAl(), event.centFT0C()); - if (track.hasTOF()) { aproton_reg.fill(HIST("histTofm2_cent"), track.pt(), track.mass() * track.mass(), event.centFT0C()); adeuteron_reg.fill(HIST("histTofm2_cent"), track.pt(), track.mass() * track.mass(), event.centFT0C()); atriton_reg.fill(HIST("histTofm2_cent"), track.pt(), track.mass() * track.mass(), event.centFT0C()); aHelium3_reg.fill(HIST("histTofm2_cent"), track.pt() * 2.0, track.mass() * track.mass(), event.centFT0C()); aHelium4_reg.fill(HIST("histTofm2_cent"), track.pt() * 2.0, track.mass() * track.mass(), event.centFT0C()); + + if ((event.centFT0C() > minCentrality) && (event.centFT0C() < maxCentrality)) { + aproton_reg.fill(HIST("histTofm2_eta"), track.pt(), track.mass() * track.mass(), track.eta()); + aproton_reg.fill(HIST("histTofNsigmaData_eta"), track.pt(), track.tofNSigmaPr(), track.eta()); + adeuteron_reg.fill(HIST("histTofm2_eta"), track.pt(), track.mass() * track.mass(), track.eta()); + adeuteron_reg.fill(HIST("histTofNsigmaData_eta"), track.pt(), track.tofNSigmaDe(), track.eta()); + atriton_reg.fill(HIST("histTofm2_eta"), track.pt(), track.mass() * track.mass(), track.eta()); + atriton_reg.fill(HIST("histTofNsigmaData_eta"), track.pt(), track.tofNSigmaTr(), track.eta()); + aHelium3_reg.fill(HIST("histTofm2_eta"), track.pt() * 2.0, track.mass() * track.mass(), track.eta()); + aHelium3_reg.fill(HIST("histTofNsigmaData_eta"), track.pt() * 2.0, track.tofNSigmaHe(), track.eta()); + aHelium4_reg.fill(HIST("histTofm2_eta"), track.pt() * 2.0, track.mass() * track.mass(), track.eta()); + aHelium4_reg.fill(HIST("histTofNsigmaData_eta"), track.pt() * 2.0, track.tofNSigmaAl(), track.eta()); + } } } } @@ -1208,11 +1349,9 @@ struct NucleiHistTask { // MC void processMC_generated(aod::McCollision const& mcCollision, aod::McParticles& mcParticles) { - int events = 0; int particles = 0; int primaryparticles = 0; - LOGF(info, "MC. vtx-z = %f", mcCollision.posZ()); MC_spectra_reg.fill(HIST("histRecVtxZData"), mcCollision.posZ()); for (auto& mcParticle : mcParticles) { @@ -1241,15 +1380,11 @@ struct NucleiHistTask { } particles++; } - LOGF(info, "Events %i", events++ + 1); - LOGF(info, "Particles %i", particles); - LOGF(info, "Primaries %i", primaryparticles); } PROCESS_SWITCH(NucleiHistTask, processMC_generated, "process generated MC data", false); void processMC_tracked(soa::Join::iterator const& collision, soa::Filtered> const& tracks, aod::McParticles& mcParticles, aod::McCollisions const& mcCollisions) { - LOGF(info, "vtx-z (data) = %f | vtx-z (MC) = %f", collision.posZ(), collision.mcCollision().posZ()); for (auto& track : tracks) { @@ -1269,7 +1404,7 @@ struct NucleiHistTask { continue; } - if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNCls()) < minReqClusterITS) { + if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNClsInnerBarrel()) < minReqClusterITSib || (track.itsNCls()) < minReqClusterITS) { continue; } @@ -1327,7 +1462,6 @@ struct NucleiHistTask { void processMC_PID(soa::Join::iterator const& collision, soa::Filtered> const& tracks, aod::McParticles& mcParticles, aod::McCollisions const& mcCollisions) { - LOGF(info, "vtx-z (data) = %f | vtx-z (MC) = %f", collision.posZ(), collision.mcCollision().posZ()); for (auto& track : tracks) { @@ -1357,7 +1491,7 @@ struct NucleiHistTask { continue; } - if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNCls()) < minReqClusterITS) { + if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNClsInnerBarrel()) < minReqClusterITSib || (track.itsNCls()) < minReqClusterITS) { continue; } @@ -1508,7 +1642,6 @@ struct NucleiHistTask { void processMC_primary_fraction(soa::Join::iterator const& collision, soa::Filtered> const& tracks, aod::McParticles& mcParticles, aod::McCollisions const& mcCollisions) { - LOGF(info, "vtx-z (data) = %f | vtx-z (MC) = %f", collision.posZ(), collision.mcCollision().posZ()); for (auto& track : tracks) { @@ -1523,7 +1656,7 @@ struct NucleiHistTask { continue; } - if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNCls()) < minReqClusterITS) { + if (TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNClsInnerBarrel()) < minReqClusterITSib || (track.itsNCls()) < minReqClusterITS) { continue; } diff --git a/PWGLF/Tasks/QAHistTask.cxx b/PWGLF/Tasks/QAHistTask.cxx new file mode 100644 index 00000000000..8677cc1cd70 --- /dev/null +++ b/PWGLF/Tasks/QAHistTask.cxx @@ -0,0 +1,464 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// Authors: Rafael Manhart, +// Date: 05.10.2023 + +#include +#include +#include +#include + +#include "ReconstructionDataFormats/Track.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" + +#include "Framework/HistogramRegistry.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "TPDGCode.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct QAHistTask { + + // Data + HistogramRegistry QA_reg{"all_species", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry QA_species_pos{"positive", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry QA_species_neg{"negative", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + void init(o2::framework::InitContext&) + { + + if (process_proton == true && (process_deuteron == true || process_triton == true || process_He3 == true || process_He4 == true) || process_deuteron == true && (process_triton == true || process_He3 == true || process_He4 == true) || process_triton == true && (process_He3 == true || process_He4 == true) || process_He3 == true && process_He4 == true) { + LOG(fatal) << "++++++++ Can't enable more than one species at a time, use subwagons for that purpose. ++++++++"; + } + + std::string species; + + if (process_proton) + species = "p"; + if (process_deuteron) + species = "d"; + if (process_triton) + species = "t"; + if (process_He3) + species = "He3"; + if (process_He4) + species = "He4"; + + std::vector ptBinning = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4., 5., 6., 8., 10., 12., 14.}; + std::vector centBinning = {0., 1., 5., 10., 20., 30., 40., 50., 70., 100.}; + std::vector etaBinning = {-1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; + + AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec centAxis = {centBinning, "V0M (%)"}; + AxisSpec centralityAxis = {100, 0.0, 100.0, "VT0C (%)"}; + AxisSpec centralityAxis_extended = {105, 0.0, 105.0, "VT0C (%)"}; + AxisSpec etaAxis = {etaBinning, "#eta"}; + + // +++++++++++++++++++++ Data ++++++++++++++++++++++++ + + // QA all species + QA_reg.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); + QA_reg.add("histCentrality", "Centrality", HistType::kTH1F, {centralityAxis_extended}); + QA_reg.add("histTpcSignalData", "Specific energy loss", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); + QA_reg.add("histTofSignalData", "TOF signal", HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); + QA_reg.add("histDcaVsPtData_particle", "dcaXY vs Pt (particle)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); + QA_reg.add("histDcaZVsPtData_particle", "dcaZ vs Pt (particle)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); + QA_reg.add("histDcaVsPtData_antiparticle", "dcaXY vs Pt (antiparticle)", HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); + QA_reg.add("histDcaZVsPtData_antiparticle", "dcaZ vs Pt (antiparticle)", HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); + QA_reg.add("histTOFm2", "TOF m^2 vs Pt", HistType::kTH2F, {ptAxis, {400, 0.0, 10.0, "m^2"}}); + QA_reg.add("histNClusterTPC", "Number of Clusters in TPC vs Pt", HistType::kTH2F, {ptAxis, {80, 0.0, 160.0, "nCluster"}}); + QA_reg.add("histNClusterITS", "Number of Clusters in ITS vs Pt", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + QA_reg.add("histNClusterITSib", "Number of Clusters in ib of ITS vs Pt", HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + QA_reg.add("histTPCnClsFindable", "Findable TPC clusters", HistType::kTH2F, {ptAxis, {200, 0.0, 200.0, "nCluster"}}); + QA_reg.add("histTPCnClsFindableMinusFound", "TPC Clusters: Findable - Found", HistType::kTH2F, {ptAxis, {60, 0.0, 60.0, "nCluster"}}); + QA_reg.add("histTPCnClsFindableMinusCrossedRows", "TPC Clusters: Findable - crossed rows", HistType::kTH2F, {ptAxis, {60, 0.0, 60.0, "nCluster"}}); + QA_reg.add("histTPCnClsShared", "Number of shared TPC clusters", HistType::kTH2F, {ptAxis, {70, 0.0, 70.0, "nCluster"}}); + QA_reg.add("histTPCCrossedRowsOverFindableCls", "Ratio crossed rows over findable clusters", HistType::kTH1F, {{100, 0., 2.0, "Crossed Rows / Findable Cls"}}); + QA_reg.add("histTPCFoundOverFindable", "Ratio of found over findable clusters", HistType::kTH1F, {{100, 0., 2.0, "Found Cls / Findable Cls"}}); + QA_reg.add("histTPCFractionSharedCls", "Fraction of shared TPC clusters", HistType::kTH1F, {{100, -2.0, 2.0, "Shared Cls"}}); + QA_reg.add("histChi2TPC", "chi^2 TPC vs Pt", HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); + QA_reg.add("histChi2ITS", "chi^2 ITS vs Pt", HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); + QA_reg.add("histChi2TOF", "chi^2 TOF vs Pt", HistType::kTH2F, {ptAxis, {75, 0.0, 15.0, "chi^2"}}); + QA_reg.add("histEtaWithOverFlow", "Pseudorapidity 0 - 105%% centrality", HistType::kTH1F, {etaAxis}); + QA_reg.add("histEta", "Pseudorapidity with centrality cut", HistType::kTH1F, {etaAxis}); + QA_reg.add("histEta_cent", "Pseudorapidity vs Centrality", HistType::kTH2F, {centralityAxis_extended, etaAxis}); + QA_reg.add("histTrackLength", "Track length", HistType::kTH1F, {{350, 0., 700., "length (cm)"}}); + + // QA choosen species (positive) + QA_species_pos.add("histTpcSignalData", Form("Specific energy loss (%s)", species.c_str()), HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); + QA_species_pos.add("histTofSignalData", Form("TOF signal (%s)", species.c_str()), HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); + QA_species_pos.add("histDcaVsPtData", Form("dcaXY vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); + QA_species_pos.add("histDcaZVsPtData", Form("dcaZ vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); + QA_species_pos.add("histTOFm2", Form("TOF m^2 vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {400, 0.0, 10.0, "m^2"}}); + QA_species_pos.add("histNClusterTPC", Form("Number of Clusters in TPC vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {80, 0.0, 160.0, "nCluster"}}); + QA_species_pos.add("histNClusterITS", Form("Number of Clusters in ITS vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + QA_species_pos.add("histNClusterITSib", Form("Number of Clusters in ib of ITS vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + QA_species_pos.add("histTPCnClsFindable", Form("Findable TPC clusters (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {200, 0.0, 200.0, "nCluster"}}); + QA_species_pos.add("histTPCnClsFindableMinusFound", Form("TPC Clusters: Findable - Found (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {60, 0.0, 60.0, "nCluster"}}); + QA_species_pos.add("histTPCnClsFindableMinusCrossedRows", Form("TPC Clusters: Findable - crossed rows (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {60, 0.0, 60.0, "nCluster"}}); + QA_species_pos.add("histTPCnClsShared", Form("Number of shared TPC clusters (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {70, 0.0, 70.0, "nCluster"}}); + QA_species_pos.add("histTPCCrossedRowsOverFindableCls", Form("Ratio crossed rows over findable clusters (%s)", species.c_str()), HistType::kTH1F, {{100, 0., 2.0, "Crossed Rows / Findable Cls"}}); + QA_species_pos.add("histTPCFoundOverFindable", Form("Ratio of found over findable clusters (%s)", species.c_str()), HistType::kTH1F, {{100, 0., 2.0, "Found Cls / Findable Cls"}}); + QA_species_pos.add("histTPCFractionSharedCls", Form("Fraction of shared TPC clusters (%s)", species.c_str()), HistType::kTH1F, {{100, -2.0, 2.0, "Shared Cls"}}); + QA_species_pos.add("histChi2TPC", Form("chi^2 TPC vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); + QA_species_pos.add("histChi2ITS", Form("chi^2 ITS vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); + QA_species_pos.add("histChi2TOF", Form("chi^2 TOF vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {75, 0.0, 15.0, "chi^2"}}); + QA_species_pos.add("histEtaWithOverFlow", Form("Pseudorapidity 0 - 105%% centrality (%s)", species.c_str()), HistType::kTH1F, {etaAxis}); + QA_species_pos.add("histEta", Form("Pseudorapidity with centrality cut (%s)", species.c_str()), HistType::kTH1F, {etaAxis}); + QA_species_pos.add("histEta_cent", Form("Pseudorapidity vs Centrality (%s)", species.c_str()), HistType::kTH2F, {centralityAxis_extended, etaAxis}); + QA_species_pos.add("histTrackLength", Form("Track length (%s)", species.c_str()), HistType::kTH1F, {{350, 0., 700., "length (cm)"}}); + + // QA choosen species (negative) + QA_species_neg.add("histTpcSignalData", Form("Specific energy loss (anti-%s)", species.c_str()), HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {5000, 0, 5000, "d#it{E} / d#it{X} (a. u.)"}}); + QA_species_neg.add("histTofSignalData", Form("TOF signal (%s)", species.c_str()), HistType::kTH2F, {{600, -6., 6., "#it{p} (GeV/#it{c})"}, {550, 0.0, 1.1, "#beta (TOF)"}}); + QA_species_neg.add("histDcaVsPtData", Form("dcaXY vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {250, -0.5, 0.5, "dca"}}); + QA_species_neg.add("histDcaZVsPtData", Form("dcaZ vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {1000, -2.0, 2.0, "dca"}}); + QA_species_neg.add("histTOFm2", Form("TOF m^2 vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {400, 0.0, 10.0, "m^2"}}); + QA_species_neg.add("histNClusterTPC", Form("Number of Clusters in TPC vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {80, 0.0, 160.0, "nCluster"}}); + QA_species_neg.add("histNClusterITS", Form("Number of Clusters in ITS vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + QA_species_neg.add("histNClusterITSib", Form("Number of Clusters in ib of ITS vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {10, 0.0, 10.0, "nCluster"}}); + QA_species_neg.add("histTPCnClsFindable", Form("Findable TPC clusters (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {200, 0.0, 200.0, "nCluster"}}); + QA_species_neg.add("histTPCnClsFindableMinusFound", Form("TPC Clusters: Findable - Found (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {60, 0.0, 60.0, "nCluster"}}); + QA_species_neg.add("histTPCnClsFindableMinusCrossedRows", Form("TPC Clusters: Findable - crossed rows (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {60, 0.0, 60.0, "nCluster"}}); + QA_species_neg.add("histTPCnClsShared", Form("Number of shared TPC clusters (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {70, 0.0, 70.0, "nCluster"}}); + QA_species_neg.add("histTPCCrossedRowsOverFindableCls", Form("Ratio crossed rows over findable clusters (%s)", species.c_str()), HistType::kTH1F, {{100, 0., 2.0, "Crossed Rows / Findable Cls"}}); + QA_species_neg.add("histTPCFoundOverFindable", Form("Ratio of found over findable clusters (%s)", species.c_str()), HistType::kTH1F, {{100, 0., 2.0, "Found Cls / Findable Cls"}}); + QA_species_neg.add("histTPCFractionSharedCls", Form("Fraction of shared TPC clusters (%s)", species.c_str()), HistType::kTH1F, {{100, -2.0, 2.0, "Shared Cls"}}); + QA_species_neg.add("histChi2TPC", Form("chi^2 TPC vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {100, 0.0, 5.0, "chi^2"}}); + QA_species_neg.add("histChi2ITS", Form("chi^2 ITS vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {500, 0.0, 50.0, "chi^2"}}); + QA_species_neg.add("histChi2TOF", Form("chi^2 TOF vs Pt (%s)", species.c_str()), HistType::kTH2F, {ptAxis, {75, 0.0, 15.0, "chi^2"}}); + QA_species_neg.add("histEtaWithOverFlow", Form("Pseudorapidity 0 - 105%% centrality (%s)", species.c_str()), HistType::kTH1F, {etaAxis}); + QA_species_neg.add("histEta", Form("Pseudorapidity with centrality cut (%s)", species.c_str()), HistType::kTH1F, {etaAxis}); + QA_species_neg.add("histEta_cent", Form("Pseudorapidity vs Centrality (%s)", species.c_str()), HistType::kTH2F, {centralityAxis_extended, etaAxis}); + QA_species_neg.add("histTrackLength", Form("Track length (%s)", species.c_str()), HistType::kTH1F, {{350, 0., 700., "length (cm)"}}); + } + + // Configurables + Configurable process_proton{"process_proton", false, "0: disabled, 1: enabled"}; + Configurable process_deuteron{"process_deuteron", false, "0: disabled, 1: enabled"}; + Configurable process_triton{"process_triton", false, "0: disabled, 1: enabled"}; + Configurable process_He3{"process_He3", false, "0: disabled, 1: enabled"}; + Configurable process_He4{"process_He4", false, "0: disabled, 1: enabled"}; + + Configurable event_selection_sel8{"event_selection_sel8", true, "0: disabled, 1: enabled"}; + Configurable yMin{"yMin", -0.5, "Maximum rapidity"}; + Configurable yMax{"yMax", 0.5, "Minimum rapidity"}; + Configurable pTmin{"pTmin", 0.1f, "min pT"}; + Configurable pTmax{"pTmax", 1e+10f, "max pT"}; + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable enable_Centrality_cut{"enable_Centrality_cut", false, "Centrality for histEta; 0: disabled, 1: enabled"}; + Configurable minCentrality{"minCentrality", 0.0, "min Centrality used (histEta)"}; + Configurable maxCentrality{"maxCentrality", 80.0, "max Centrality used (histEta)"}; + Configurable enable_PVcontributor{"enable_PVcontributor", false, "0: disabled, 1: enabled"}; + + Configurable nsigmacut{"nsigmacut", 3.0, "absolute value of the Nsigma cut"}; + + Configurable custom_Track_selection{"custom_Track_selection", false, "0: disabled, 1: enabled"}; + // custom Track selection cuts + Configurable minReqClusterITS{"minReqClusterITS", 0.0, "min number of clusters required in ITS"}; // ITS_nCls + Configurable minReqClusterITSib{"minReqClusterITSib", 0.0, "min number of clusters required in ITS inner barrel"}; // ITS_nCls + Configurable minTPCnClsFound{"minTPCnClsFound", 0.0f, "min number of crossed rows TPC"}; // TPC_nCls_found + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 0.0f, "min number of crossed rows TPC"}; // TPC_nCls_crossed_Rows + Configurable minRatioCrossedRowsTPC{"minRatioCrossedRowsTPC", 0.0f, "min ratio of crossed rows over findable clusters TPC"}; // TPC_crossed_Rows_over_findable_Cls_min + Configurable maxRatioCrossedRowsTPC{"maxRatioCrossedRowsTPC", 2.0f, "max ratio of crossed rows over findable clusters TPC"}; // TPC_crossed_Rows_over_findable_Cls_max + Configurable maxChi2ITS{"maxChi2ITS", 100.0f, "max chi2 per cluster ITS"}; + Configurable maxChi2TPC{"maxChi2TPC", 100.0f, "max chi2 per cluster TPC"}; + Configurable maxDCA_XY{"maxDCA_XY", 10.0f, "max DCA to vertex xy"}; + Configurable maxDCA_Z{"maxDCA_Z", 10.0f, "max DCA to vertex z"}; + Configurable lastRequiredTrdCluster{"lastRequiredTrdCluster", -1, "Last cluster to required in TRD for track selection. -1 does not require any TRD cluster"}; + Configurable minTrackLength{"minTrackLength", 0.0f, "min track length"}; + Configurable maxTrackLength{"maxTrackLength", 999999.0f, "max track length"}; + Configurable minTPCNClsFindable{"minTPCNClsFindable", 0.0f, "min findable TPC clusters for this track geometry"}; + Configurable maxTPCNClsShared{"maxTPCNClsShared", 999999.0f, "max number of shared TPC clusters"}; + Configurable maxChi2TOF{"maxChi2TOF", 100.0f, "max chi2 for the TOF track segment"}; + Configurable minTPCFoundOverFindable{"minTPCFoundOverFindable", 0.0f, "min ratio of found over findable clusters TPC"}; + Configurable maxTPCFoundOverFindable{"maxTPCFoundOverFindable", 2.0f, "max ratio of found over findable clusters TPC"}; + + template + void fillHistograms(const CollisionType& event, const TracksType& tracks) + { + + if (event_selection_sel8 && event.sel8()) { + QA_reg.fill(HIST("histRecVtxZData"), event.posZ()); + } + + if (!event_selection_sel8) { + QA_reg.fill(HIST("histRecVtxZData"), event.posZ()); + } + + for (auto track : tracks) { // start loop over tracks + + float nSigmaSpecies = 999; + + if (process_proton) + nSigmaSpecies = track.tpcNSigmaPr(); + if (process_deuteron) + nSigmaSpecies = track.tpcNSigmaDe(); + if (process_triton) + nSigmaSpecies = track.tpcNSigmaTr(); + if (process_He3) + nSigmaSpecies = track.tpcNSigmaHe(); + if (process_He4) + nSigmaSpecies = track.tpcNSigmaAl(); + + if (event_selection_sel8 && !event.sel8()) { + continue; + } + + QA_reg.fill(HIST("histEtaWithOverFlow"), track.eta()); + + float TPCnumberClsFound = track.tpcNClsFound(); + float TPC_nCls_Crossed_Rows = track.tpcNClsCrossedRows(); + float RatioCrossedRowsOverFindableTPC = track.tpcCrossedRowsOverFindableCls(); + float Chi2perClusterTPC = track.tpcChi2NCl(); + float Chi2perClusterITS = track.itsChi2NCl(); + + if (track.sign() > 0) { + QA_reg.fill(HIST("histDcaVsPtData_particle"), track.pt(), track.dcaXY()); + QA_reg.fill(HIST("histDcaZVsPtData_particle"), track.pt(), track.dcaZ()); + } + + if (track.sign() < 0) { + QA_reg.fill(HIST("histDcaVsPtData_antiparticle"), track.pt(), track.dcaXY()); + QA_reg.fill(HIST("histDcaZVsPtData_antiparticle"), track.pt(), track.dcaZ()); + } + + if (custom_Track_selection && (TMath::Abs(track.dcaXY()) > maxDCA_XY || TMath::Abs(track.dcaZ()) > maxDCA_Z || TPCnumberClsFound < minTPCnClsFound || TPC_nCls_Crossed_Rows < minNCrossedRowsTPC || RatioCrossedRowsOverFindableTPC < minRatioCrossedRowsTPC || RatioCrossedRowsOverFindableTPC > maxRatioCrossedRowsTPC || Chi2perClusterTPC > maxChi2TPC || Chi2perClusterITS > maxChi2ITS || !(track.passedTPCRefit()) || !(track.passedITSRefit()) || (track.itsNClsInnerBarrel()) < minReqClusterITSib || (track.itsNCls()) < minReqClusterITS || track.length() < minTrackLength || track.length() > maxTrackLength || track.tpcNClsFindable() < minTPCNClsFindable || track.tpcNClsShared() > maxTPCNClsShared || track.tpcFoundOverFindableCls() < minTPCFoundOverFindable || track.tpcFoundOverFindableCls() > maxTPCFoundOverFindable)) { + + if (track.hasTOF() && track.tofChi2() > maxChi2TOF) + continue; + continue; + } + + if (enable_PVcontributor && !(track.isPVContributor())) { + continue; + } + + // cut on rapidity + TLorentzVector lorentzVector_proton{}; + TLorentzVector lorentzVector_deuteron{}; + TLorentzVector lorentzVector_triton{}; + TLorentzVector lorentzVector_He3{}; + TLorentzVector lorentzVector_He4{}; + + lorentzVector_proton.SetPtEtaPhiM(track.pt(), track.eta(), track.phi(), constants::physics::MassProton); + lorentzVector_deuteron.SetPtEtaPhiM(track.pt(), track.eta(), track.phi(), constants::physics::MassDeuteron); + lorentzVector_triton.SetPtEtaPhiM(track.pt(), track.eta(), track.phi(), constants::physics::MassTriton); + lorentzVector_He3.SetPtEtaPhiM(track.pt() * 2.0, track.eta(), track.phi(), constants::physics::MassHelium3); + lorentzVector_He4.SetPtEtaPhiM(track.pt() * 2.0, track.eta(), track.phi(), constants::physics::MassAlpha); + + if (lorentzVector_proton.Rapidity() < yMin || lorentzVector_proton.Rapidity() > yMax || + lorentzVector_deuteron.Rapidity() < yMin || lorentzVector_deuteron.Rapidity() > yMax || + lorentzVector_triton.Rapidity() < yMin || lorentzVector_triton.Rapidity() > yMax || + lorentzVector_He3.Rapidity() < yMin || lorentzVector_He3.Rapidity() > yMax || + lorentzVector_He4.Rapidity() < yMin || lorentzVector_He4.Rapidity() > yMax) { + continue; + } + + if (track.pt() < pTmin || track.pt() > pTmax) + continue; + + QA_reg.fill(HIST("histTpcSignalData"), track.tpcInnerParam() * track.sign(), track.tpcSignal()); + QA_reg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsCrossedRows()); + QA_reg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + QA_reg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); + QA_reg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); + QA_reg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); + QA_reg.fill(HIST("histTPCnClsFindable"), track.pt(), track.tpcNClsFindable()); + QA_reg.fill(HIST("histTPCnClsFindableMinusFound"), track.pt(), track.tpcNClsFindableMinusFound()); + QA_reg.fill(HIST("histTPCnClsFindableMinusCrossedRows"), track.pt(), track.tpcNClsFindableMinusCrossedRows()); + QA_reg.fill(HIST("histTPCnClsShared"), track.pt(), track.tpcNClsShared()); + QA_reg.fill(HIST("histChi2TOF"), track.pt(), track.tofChi2()); + QA_reg.fill(HIST("histTrackLength"), track.length()); + QA_reg.fill(HIST("histTPCCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + QA_reg.fill(HIST("histTPCFoundOverFindable"), track.tpcFoundOverFindableCls()); + QA_reg.fill(HIST("histTPCFractionSharedCls"), track.tpcFractionSharedCls()); + + if (track.hasTOF()) { + + if (track.hasTRD() && (lastRequiredTrdCluster > 0) && custom_Track_selection) { + int lastLayer = 0; + for (int l = 7; l >= 0; l--) { + if (track.trdPattern() & (1 << l)) { + lastLayer = l; + break; + } + } + if (lastLayer < lastRequiredTrdCluster) { + continue; + } + } + + Float_t TOFmass2 = ((track.mass()) * (track.mass())); + + QA_reg.fill(HIST("histTOFm2"), track.pt(), TOFmass2); + QA_reg.fill(HIST("histTofSignalData"), track.tpcInnerParam() * track.sign(), track.beta()); + } + + // fill QA histograms (proton) + if (TMath::Abs(nSigmaSpecies) < nsigmacut) { + if (track.sign() > 0) { + QA_species_pos.fill(HIST("histDcaVsPtData"), track.pt(), track.dcaXY()); + QA_species_pos.fill(HIST("histDcaZVsPtData"), track.pt(), track.dcaZ()); + QA_species_pos.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); + QA_species_pos.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsCrossedRows()); + QA_species_pos.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + QA_species_pos.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); + QA_species_pos.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); + QA_species_pos.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); + QA_species_pos.fill(HIST("histTPCnClsFindable"), track.pt(), track.tpcNClsFindable()); + QA_species_pos.fill(HIST("histTPCnClsFindableMinusFound"), track.pt(), track.tpcNClsFindableMinusFound()); + QA_species_pos.fill(HIST("histTPCnClsFindableMinusCrossedRows"), track.pt(), track.tpcNClsFindableMinusCrossedRows()); + QA_species_pos.fill(HIST("histTPCnClsShared"), track.pt(), track.tpcNClsShared()); + QA_species_pos.fill(HIST("histChi2TOF"), track.pt(), track.tofChi2()); + QA_species_pos.fill(HIST("histTrackLength"), track.length()); + QA_species_pos.fill(HIST("histTPCCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + QA_species_pos.fill(HIST("histTPCFoundOverFindable"), track.tpcFoundOverFindableCls()); + QA_species_pos.fill(HIST("histTPCFractionSharedCls"), track.tpcFractionSharedCls()); + + if (track.hasTOF()) { + + if (track.hasTRD() && (lastRequiredTrdCluster > 0) && custom_Track_selection) { + int lastLayer = 0; + for (int l = 7; l >= 0; l--) { + if (track.trdPattern() & (1 << l)) { + lastLayer = l; + break; + } + } + if (lastLayer < lastRequiredTrdCluster) { + continue; + } + } + + Float_t TOFmass2 = ((track.mass()) * (track.mass())); + + QA_species_pos.fill(HIST("histTOFm2"), track.pt(), TOFmass2); + QA_species_pos.fill(HIST("histTofSignalData"), track.tpcInnerParam() * track.sign(), track.beta()); + } + } + if (track.sign() < 0) { + QA_species_neg.fill(HIST("histDcaVsPtData"), track.pt(), track.dcaXY()); + QA_species_neg.fill(HIST("histDcaZVsPtData"), track.pt(), track.dcaZ()); + QA_species_neg.fill(HIST("histTpcSignalData"), track.tpcInnerParam(), track.tpcSignal()); + QA_species_neg.fill(HIST("histNClusterTPC"), track.pt(), track.tpcNClsCrossedRows()); + QA_species_neg.fill(HIST("histNClusterITS"), track.pt(), track.itsNCls()); + QA_species_neg.fill(HIST("histNClusterITSib"), track.pt(), track.itsNClsInnerBarrel()); + QA_species_neg.fill(HIST("histChi2TPC"), track.pt(), track.tpcChi2NCl()); + QA_species_neg.fill(HIST("histChi2ITS"), track.pt(), track.itsChi2NCl()); + QA_species_neg.fill(HIST("histTPCnClsFindable"), track.pt(), track.tpcNClsFindable()); + QA_species_neg.fill(HIST("histTPCnClsFindableMinusFound"), track.pt(), track.tpcNClsFindableMinusFound()); + QA_species_neg.fill(HIST("histTPCnClsFindableMinusCrossedRows"), track.pt(), track.tpcNClsFindableMinusCrossedRows()); + QA_species_neg.fill(HIST("histTPCnClsShared"), track.pt(), track.tpcNClsShared()); + QA_species_neg.fill(HIST("histChi2TOF"), track.pt(), track.tofChi2()); + QA_species_neg.fill(HIST("histTrackLength"), track.length()); + QA_species_neg.fill(HIST("histTPCCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + QA_species_neg.fill(HIST("histTPCFoundOverFindable"), track.tpcFoundOverFindableCls()); + QA_species_neg.fill(HIST("histTPCFractionSharedCls"), track.tpcFractionSharedCls()); + + if (track.hasTOF()) { + + if (track.hasTRD() && (lastRequiredTrdCluster > 0) && custom_Track_selection) { + int lastLayer = 0; + for (int l = 7; l >= 0; l--) { + if (track.trdPattern() & (1 << l)) { + lastLayer = l; + break; + } + } + if (lastLayer < lastRequiredTrdCluster) { + continue; + } + } + + Float_t TOFmass2 = ((track.mass()) * (track.mass())); + + QA_species_neg.fill(HIST("histTOFm2"), track.pt(), TOFmass2); + QA_species_neg.fill(HIST("histTofSignalData"), track.tpcInnerParam() * track.sign(), track.beta()); + } + } + } + } // end loop over tracks + } + + //******************************************************************************************************* + + template + void fillCentHistorgrams(const CollisionType& event, const TracksType& tracks) + { + + if (event_selection_sel8 && event.sel8()) { + QA_reg.fill(HIST("histCentrality"), event.centFT0C()); + } + + if (!event_selection_sel8) { + QA_reg.fill(HIST("histCentrality"), event.centFT0C()); + } + + for (auto track : tracks) { // start loop over tracks + + if (event_selection_sel8 && !event.sel8()) { + continue; + } + + QA_reg.fill(HIST("histEta_cent"), event.centFT0C(), track.eta()); + + if ((event.centFT0C() > minCentrality) && (event.centFT0C() < maxCentrality) && enable_Centrality_cut) { + QA_reg.fill(HIST("histEta"), track.eta()); + } + } + } + + //**************************************************************************************************** + + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVertex); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta && requireGlobalTrackWoDCAInFilter()); + + using EventCandidates = soa::Filtered>; + + using EventCandidatesCent = soa::Filtered>; + + using TrackCandidates = soa::Filtered>; + + void processData(EventCandidates::iterator const& event, TrackCandidates const& tracks) + { + fillHistograms(event, tracks); + } + PROCESS_SWITCH(QAHistTask, processData, "process data", true); + + void processDataCent(EventCandidatesCent::iterator const& event, TrackCandidates const& tracks) + { + fillHistograms(event, tracks); + fillCentHistorgrams(event, tracks); + } + PROCESS_SWITCH(QAHistTask, processDataCent, "process data containing centralities", false); +}; + +//**************************************************************************************************** + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"qa-hist"})}; +} diff --git a/PWGLF/Tasks/QC/CMakeLists.txt b/PWGLF/Tasks/QC/CMakeLists.txt index 0d1f15712d3..995738e017e 100644 --- a/PWGLF/Tasks/QC/CMakeLists.txt +++ b/PWGLF/Tasks/QC/CMakeLists.txt @@ -34,7 +34,22 @@ o2physics_add_dpl_workflow(strarecostudy PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(mccollisionextra - SOURCES mcCollisionExtra.cxx +o2physics_add_dpl_workflow(kfperformancestudy + SOURCES kfPerformanceStudy.cxx PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(tpc-dedx-postcalibration + SOURCES tpc_dEdx_postcalibration.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(tpc-dedx-qa + SOURCES tpc_dedx_qa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(vertexqa + SOURCES vertexQA.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGLF/Tasks/QC/kfPerformanceStudy.cxx b/PWGLF/Tasks/QC/kfPerformanceStudy.cxx new file mode 100644 index 00000000000..464a5134959 --- /dev/null +++ b/PWGLF/Tasks/QC/kfPerformanceStudy.cxx @@ -0,0 +1,151 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +/// \brief this task allows for the direct one-to-one comparison of +// cascades computed with standard DCAFitter methods and the KFparticle +// package. It is meant for the purposes of larger-scale QA of KF reco. + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Multiplicity.h" +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +// allows for candidate-by-candidate comparison using Cascade to []CascData link table +using CascadesCrossLinked = soa::Join; + +struct kfPerformanceStudy { + // configurable binning of histograms + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + ConfigurableAxis axisLambdaMass{"axisLambdaMass", {200, 1.101f, 1.131f}, ""}; + ConfigurableAxis axisXiMass{"axisXiMass", {200, 1.222f, 1.422f}, ""}; + ConfigurableAxis axisOmegaMass{"axisOmegaMass", {200, 1.572f, 1.772f}, ""}; + ConfigurableAxis axisDCAxy{"axisDCAxy", {200, -1.0f, 1.0f}, ""}; + ConfigurableAxis axisPointingAngle{"axisPointingAngle", {200, 0.0f, 0.5f}, ""}; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + histos.add("hEventCounter", "hEventCounter", kTH1F, {{1, 0.0f, 1.0f}}); + histos.add("hChargeCounter", "hChargeCounter", kTH1F, {{3, -1.5f, 1.5f}}); + + // baseline simple histograms of mass + histos.add("hMassXiMinus", "hMassXiMinus", kTH2F, {axisPt, axisXiMass}); + histos.add("hMassXiPlus", "hMassXiPlus", kTH2F, {axisPt, axisXiMass}); + histos.add("hMassOmegaMinus", "hMassOmegaMinus", kTH2F, {axisPt, axisOmegaMass}); + histos.add("hMassOmegaPlus", "hMassOmegaPlus", kTH2F, {axisPt, axisOmegaMass}); + histos.add("hKFMassXiMinus", "hKFMassXiMinus", kTH2F, {axisPt, axisXiMass}); + histos.add("hKFMassXiPlus", "hKFMassXiPlus", kTH2F, {axisPt, axisXiMass}); + histos.add("hKFMassOmegaMinus", "hKFMassOmegaMinus", kTH2F, {axisPt, axisOmegaMass}); + histos.add("hKFMassOmegaPlus", "hKFMassOmegaPlus", kTH2F, {axisPt, axisOmegaMass}); + + histos.add("h3dMassXiMinus", "h3dMassXiMinus", kTH3F, {axisPt, axisXiMass, axisXiMass}); + histos.add("h3dMassXiPlus", "h3dMassXiPlus", kTH3F, {axisPt, axisXiMass, axisXiMass}); + histos.add("h3dMassOmegaMinus", "h3dMassOmegaMinus", kTH3F, {axisPt, axisOmegaMass, axisOmegaMass}); + histos.add("h3dMassOmegaPlus", "h3dMassOmegaPlus", kTH3F, {axisPt, axisOmegaMass, axisOmegaMass}); + + // all-in histograms + histos.add("h3dPointingAngle", "h3dPointingAngle", kTH3F, {axisPt, axisPointingAngle, axisPointingAngle}); + histos.add("h3dMassLambda", "h3dMassLambda", kTH3F, {axisPt, axisLambdaMass, axisLambdaMass}); /// for x check only + histos.add("h3dDCAxy", "h3dDCAxy", kTH3F, {axisPt, axisDCAxy, axisDCAxy}); + histos.add("hPtCorrelation", "hPtCorrelation", kTH2F, {axisPt, axisPt}); + } + + void process(aod::Collision const& collision, CascadesCrossLinked const& Cascades, aod::CascDatas const&, aod::KFCascDatas const&, aod::TracksIU const&) + { + histos.fill(HIST("hEventCounter"), 0.5); + for (auto& cascade : Cascades) { // allows for cross-referencing everything + float pt = 0.0f, ptKF = 0.0f; + float massXi = 0.0f, massXiKF = 0.0f; + float massOmega = 0.0f, massOmegaKF = 0.0f; + float massLambda = 0.0f, massLambdaKF = 0.0f; + float dcaXY = 0.0f, dcaXYKF = 0.0f; + float pointingAngle = -1.0f, pointingAngleKF = -1.0f; + int charge = 0; + + // get charge from bachelor (unambiguous wrt to building) + auto bachTrack = cascade.bachelor_as(); + if (bachTrack.sign() < 0) { + charge = -1; + } else { + charge = +1; + } + + histos.fill(HIST("hChargeCounter"), charge); + + if (cascade.has_cascData()) { + // check aod::Cascades -> aod::CascData link + // if present: this candidate was accepted by default DCAfitter building + auto cascdata = cascade.cascData(); + pt = cascdata.pt(); + massLambda = cascdata.mLambda(); + massXi = cascdata.mXi(); + massOmega = cascdata.mOmega(); + dcaXY = cascdata.dcaXYCascToPV(); + pointingAngle = TMath::ACos(cascdata.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + if (cascade.has_kfCascData()) { + // check aod::Cascades -> aod::KFCascData link + // if present: this candidate was accepted by KF building + auto cascdata = cascade.kfCascData(); + ptKF = cascdata.pt(); + massLambdaKF = cascdata.mLambda(); + massXiKF = cascdata.mXi(); + massOmegaKF = cascdata.mOmega(); + dcaXYKF = cascdata.dcaXYCascToPV(); + pointingAngleKF = TMath::ACos(cascdata.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + } + + histos.fill(HIST("hPtCorrelation"), pt, ptKF); + histos.fill(HIST("h3dMassLambda"), pt, massLambda, massLambdaKF); // <- implicit pT choice, beware + histos.fill(HIST("h3dDCAxy"), pt, dcaXY, dcaXYKF); // <- implicit pT choice, beware + histos.fill(HIST("h3dPointingAngle"), pt, pointingAngle, pointingAngleKF); // <- implicit pT choice, beware + if (charge < 0) { + histos.fill(HIST("hMassXiMinus"), pt, massXi); + histos.fill(HIST("hMassOmegaMinus"), pt, massOmega); + histos.fill(HIST("hKFMassXiMinus"), ptKF, massXiKF); + histos.fill(HIST("hKFMassOmegaMinus"), ptKF, massOmegaKF); + histos.fill(HIST("h3dMassXiMinus"), pt, massXi, massXiKF); // <- implicit pT choice, beware + histos.fill(HIST("h3dMassOmegaMinus"), pt, massOmega, massOmegaKF); // <- implicit pT choice, beware + } + if (charge > 0) { + histos.fill(HIST("hMassXiPlus"), pt, massXi); + histos.fill(HIST("hMassOmegaPlus"), pt, massOmega); + histos.fill(HIST("hKFMassXiPlus"), ptKF, massXiKF); + histos.fill(HIST("hKFMassOmegaPlus"), ptKF, massOmegaKF); + histos.fill(HIST("h3dMassXiPlus"), pt, massXi, massXiKF); // <- implicit pT choice, beware + histos.fill(HIST("h3dMassOmegaPlus"), pt, massOmega, massOmegaKF); // <- implicit pT choice, beware + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/QC/lfpidqa.cxx b/PWGLF/Tasks/QC/lfpidqa.cxx index bee3d977a92..f377f7c1d71 100644 --- a/PWGLF/Tasks/QC/lfpidqa.cxx +++ b/PWGLF/Tasks/QC/lfpidqa.cxx @@ -123,9 +123,25 @@ struct lfpidqa { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(o2::framework::InitContext&) { + if (doprocessPiKaPr && doprocessAll) { + LOG(fatal) << "Cannot enable processPiKaPr and processAll at the same time"; + } + const AxisSpec pAxis{nBinsP, minP, maxP, "#it{p} (GeV/#it{c})"}; for (int id = 0; id < Np; id++) { - + if (doprocessPiKaPr) { + bool keepIt = false; + switch (id) { + case o2::track::PID::Pion: + case o2::track::PID::Kaon: + case o2::track::PID::Proton: + keepIt = true; + break; + } + if (!keepIt) { + continue; + } + } const char* axisTitle = Form("N_{#sigma}^{TPC}(%s)", pT[id]); const AxisSpec nSigmaAxis{nBinsNSigma, minNSigma, maxNSigma, axisTitle}; histos.add(hnsigma[id].data(), axisTitle, kTH2F, {pAxis, nSigmaAxis}); @@ -197,15 +213,15 @@ struct lfpidqa { using CollisionCandidate = soa::Join; using TrackCandidates = soa::Join; - void process(soa::Filtered const& collisions, - soa::Filtered> const& tracks, - soa::Filtered> const& lftracks) + void processAll(soa::Filtered const& collisions, + soa::Filtered> const& tracks, + soa::Filtered> const& lftracks) { for (const auto& trk : tracks) { static_for<0, 8>([&](auto i) { @@ -219,6 +235,25 @@ struct lfpidqa { }); } } + PROCESS_SWITCH(lfpidqa, processAll, "Process All particles", false); + + void processPiKaPr(soa::Filtered const& collisions, + soa::Filtered> const& tracks, + soa::Filtered> const& lftracks) + { + for (const auto& trk : tracks) { + fillStd(trk); + fillStd(trk); + fillStd(trk); + } + + for (const auto& trk : lftracks) { + fillLf(trk); + fillLf(trk); + fillLf(trk); + } + } + PROCESS_SWITCH(lfpidqa, processPiKaPr, "Process only Pi Ka Pr", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Tasks/QC/straRecoStudy.cxx b/PWGLF/Tasks/QC/straRecoStudy.cxx index 5933f833818..c348fd4f6cf 100644 --- a/PWGLF/Tasks/QC/straRecoStudy.cxx +++ b/PWGLF/Tasks/QC/straRecoStudy.cxx @@ -28,9 +28,9 @@ #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFQATables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" #include "Common/Core/TrackSelection.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" @@ -346,7 +346,7 @@ struct straRecoStudy { histos.fill(HIST("hEventSelection"), ii, evselstats[ii]); } - Filter preFilterMcCollisions = aod::mccollisionprop::hasRecoCollision > 0; + Filter preFilterMcCollisions = aod::mccollisionprop::numRecoCollision > 0; Filter preFilterCascade = nabs(aod::cascdata::dcapostopv) > v0setting_dcapostopv&& nabs(aod::cascdata::dcanegtopv) > v0setting_dcanegtopv&& nabs(aod::cascdata::dcabachtopv) > cascadesetting_dcabachtopv&& aod::cascdata::dcaV0daughters < v0setting_dcav0dau&& aod::cascdata::dcacascdaughters - 1; diff --git a/PWGLF/Tasks/QC/tpc_dEdx_postcalibration.cxx b/PWGLF/Tasks/QC/tpc_dEdx_postcalibration.cxx new file mode 100644 index 00000000000..4edc56cb5d1 --- /dev/null +++ b/PWGLF/Tasks/QC/tpc_dEdx_postcalibration.cxx @@ -0,0 +1,542 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \author Alberto Caliva (alberto.caliva@cern.ch) +/// \since June 27, 2023 + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "ReconstructionDataFormats/Track.h" + +using namespace o2; +using namespace o2::framework; + +using PIDTracks = soa::Join< + aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::pidTOFbeta, + aod::pidTOFmass, aod::TrackSelection, aod::TrackSelectionExtension, + aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullDe, + aod::pidTPCFullTr, aod::pidTPCFullHe, aod::pidTOFFullPi, aod::pidTOFFullKa, + aod::pidTOFFullPr, aod::pidTOFFullDe, aod::pidTOFFullTr, aod::pidTOFFullHe>; + +using SelectedCollisions = soa::Join; + +struct tpc_dEdx_postcalibration { + + // dE/dx for all charged particles + HistogramRegistry registryCh{ + "registryCh", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + // dE/dx and nsigma_{TPC} for different hadron species + HistogramRegistry registryPi{ + "registryPi", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + HistogramRegistry registryKa{ + "registryKa", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + HistogramRegistry registryPr{ + "registryPr", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + HistogramRegistry registryDe{ + "registryDe", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + HistogramRegistry registryTr{ + "registryTr", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + HistogramRegistry registryHe{ + "registryHe", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + // External Parameters + Configurable minTPCnClsFound{"minTPCnClsFound", 70.0f, + "min number of found TPC clusters"}; + Configurable minNCrossedRowsTPC{ + "minNCrossedRowsTPC", 70.0f, "min number of found TPC crossed rows"}; + Configurable minNClsTPCdEdx{ + "minNClsTPCdEdx", 50.0f, "min number of TPC clusters for PID"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, + "max chi2 per cluster TPC"}; + Configurable maxChi2ITS{"maxChi2ITS", 36.0f, + "max chi2 per cluster ITS"}; + Configurable etaMin{"etaMin", -0.8f, "etaMin"}; + Configurable etaMax{"etaMax", +0.8f, "etaMax"}; + Configurable v0cospaMin{"v0cospaMin", 0.998, "Minimum V0 CosPA"}; + Configurable minimumV0Radius{"minimumV0Radius", 0.5f, + "Minimum V0 Radius"}; + Configurable maximumV0Radius{"maximumV0Radius", 100.0f, + "Maximum V0 Radius"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, + "Maximum DCA Daughters"}; + Configurable nsigmaTOFmax{"nsigmaTOFmax", 3.0f, "Maximum nsigma TOF"}; + Configurable minMassK0s{"minMassK0s", 0.4f, "Minimum Mass K0s"}; + Configurable maxMassK0s{"maxMassK0s", 0.6f, "Maximum Mass K0s"}; + Configurable minMassLambda{"minMassLambda", 1.1f, + "Minimum Mass Lambda"}; + Configurable maxMassLambda{"maxMassLambda", 1.2f, + "Maximum Mass Lambda"}; + Configurable minReqClusterITS{ + "minReqClusterITS", 4.0f, "min number of clusters required in ITS"}; + Configurable maxDCAxy{"maxDCAxy", 0.1f, "maxDCAxy"}; + Configurable maxDCAz{"maxDCAz", 0.1f, "maxDCAz"}; + Configurable eventSelection{"eventSelection", true, "event selection"}; + Configurable useTOFpi{"useTOFpi", true, "use TOF for pion ID"}; + Configurable useTOFpr{"useTOFpr", true, "use TOF for proton ID"}; + Configurable doContaminations{"doContaminations", false, "Flag to produce the plots for the contaminations"}; + Configurable addTOF{"addTOF", false, "Flag to produce the TOF plots"}; + Configurable usePt{"usePt", false, "Flag to use PT instead of the TPCInnerParam"}; + ConfigurableAxis pBins{"pBins", {VARIABLE_WIDTH, -10.0, -9.660508789898131, -9.332543007969905, -9.01571137605957, -8.709635899560805, -8.413951416451948, -8.128305161640986, -7.852356346100718, -7.585775750291836, -7.328245331389037, -7.07945784384138, -6.839116472814292, -6.6069344800759575, -6.3826348619054825, -6.165950018614822, -5.956621435290104, -5.754399373371567, -5.559042572704037, -5.370317963702527, -5.188000389289609, -5.011872336272719, -4.841723675840994, -4.677351412871981, -4.518559443749222, -4.365158322401657, -4.216965034285822, -4.073802778041126, -3.9355007545577725, -3.801893963205613, -3.672823004980846, -3.5481338923357533, -3.427677865464501, -3.311311214825911, -3.198895109691397, -3.0902954325135887, -2.9853826189179604, -2.8840315031266055, -2.7861211686297693, -2.691534803926914, -2.6001595631652723, -2.5118864315095797, -2.4266100950824145, -2.344228815319923, -2.2646443075930596, -2.1877616239495516, -2.1134890398366455, -2.0417379446695296, -1.9724227361148534, -1.9054607179632463, -1.8407720014689564, -1.7782794100389228, -1.7179083871575875, -1.6595869074375598, -1.6032453906900417, -1.5488166189124812, -1.4962356560944328, -1.4454397707459279, -1.3963683610559376, -1.3489628825916533, -1.3031667784522987, -1.2589254117941675, -1.2161860006463678, -1.174897554939529, -1.1350108156723142, -1.096478196143185, -1.0592537251772887, -1.0232929922807537, -0.9885530946569385, -0.9549925860214359, -0.9225714271547628, -0.8912509381337455, -0.8609937521846003, -0.8317637711026709, -0.8035261221856173, -0.7762471166286916, -0.7498942093324559, -0.7244359600749899, -0.6998419960022735, -0.6760829753919816, -0.6531305526474723, -0.630957344480193, -0.609536897240169, -0.588843655355589, -0.5688529308438414, -0.5495408738576245, -0.5308844442309882, -0.5128613839913648, -0.49545019080479, -0.47863009232263826, -0.46238102139926035, -0.44668359215096304, -0.43151907682776525, -0.4168693834703353, -0.4027170343254591, -0.3890451449942805, -0.37583740428844414, -0.3630780547701014, -0.35075187395256796, -0.33884415613920255, -0.3273406948788381, -0.31622776601683794, -0.30549211132155124, -0.29512092266663853, -0.2851018267503908, -0.2754228703338166, -0.26607250597988097, -0.25703957827688634, -0.24831331052955705, -0.239883291901949, -0.23173946499684786, -0.2238721138568339, -0.21627185237270202, -0.20892961308540386, -0.20183663636815607, -0.19498445997580455, -0.18836490894898, -0.18197008586099836, -0.1757923613958692, -0.16982436524617442, -0.16405897731995386, -0.15848931924611134, -0.15310874616820302, -0.1479108388168207, -0.1428893958511103, -0.13803842646028847, -0.1333521432163324, -0.12882495516931336, -0.1244514611771385, -0.12022644346174131, -0.11614486138403426, -0.11220184543019636, -0.10839269140212034, -0.10471285480508996, -0.10115794542598983, -0.09772372209558107, -0.09440608762859236, -0.09120108393559097, -0.08810488730080138, -0.08511380382023763, -0.08222426499470713, -0.07943282347242814, -0.0767361489361819, -0.07413102413009177, -0.0716143410212902, -0.06918309709189363, -0.06683439175686146, -0.06456542290346556, -0.06237348354824192, -0.06025595860743578, -0.05821032177708716, -0.05623413251903491, -0.05432503314924331, -0.05248074602497726, -0.050699070827470445, -0.04897788193684462, -0.04731512589614803, -0.04570881896148749, -0.044157044735331254, -0.04265795188015926, -0.04120975190973302, -0.039810717055349734, -0.03845917820453535, -0.03715352290971724, -0.03589219346450052, -0.034673685045253165, -0.03349654391578276, -0.03235936569296283, -0.03126079367123956, -0.03019951720402016, -0.02917427014001166, -0.028183829312644536, -0.027227013080779128, -0.026302679918953815, -0.02540972705549305, -0.02454708915685031, -0.023713737056616554, -0.022908676527677724, -0.022130947096056376, -0.021379620895022326, -0.02065380155810529, -0.0199526231496888, -0.019275249131909356, -0.018620871366628676, -0.017988709151287873, -0.017378008287493755, -0.016788040181225608, -0.0162181009735893, -0.015667510701081494, -0.01513561248436208, -0.014621771744567183, -0.01412537544622754, -0.013645831365889245, -0.013182567385564075, -0.012735030810166616, -0.012302687708123818, -0.011885022274370183, -0.01148153621496883, -0.01109174815262401, -0.010715193052376065, -0.010351421666793436, -0.01, 0.01, 0.010351421666793436, 0.010715193052376065, 0.01109174815262401, 0.01148153621496883, 0.011885022274370183, 0.012302687708123818, 0.012735030810166616, 0.013182567385564075, 0.013645831365889245, 0.01412537544622754, 0.014621771744567183, 0.01513561248436208, 0.015667510701081494, 0.0162181009735893, 0.016788040181225608, 0.017378008287493755, 0.017988709151287873, 0.018620871366628676, 0.019275249131909356, 0.0199526231496888, 0.02065380155810529, 0.021379620895022326, 0.022130947096056376, 0.022908676527677724, 0.023713737056616554, 0.02454708915685031, 0.02540972705549305, 0.026302679918953815, 0.027227013080779128, 0.028183829312644536, 0.02917427014001166, 0.03019951720402016, 0.03126079367123956, 0.03235936569296283, 0.03349654391578276, 0.034673685045253165, 0.03589219346450052, 0.03715352290971724, 0.03845917820453535, 0.039810717055349734, 0.04120975190973302, 0.04265795188015926, 0.044157044735331254, 0.04570881896148749, 0.04731512589614803, 0.04897788193684462, 0.050699070827470445, 0.05248074602497726, 0.05432503314924331, 0.05623413251903491, 0.05821032177708716, 0.06025595860743578, 0.06237348354824192, 0.06456542290346556, 0.06683439175686146, 0.06918309709189363, 0.0716143410212902, 0.07413102413009177, 0.0767361489361819, 0.07943282347242814, 0.08222426499470713, 0.08511380382023763, 0.08810488730080138, 0.09120108393559097, 0.09440608762859236, 0.09772372209558107, 0.10115794542598983, 0.10471285480508996, 0.10839269140212034, 0.11220184543019636, 0.11614486138403426, 0.12022644346174131, 0.1244514611771385, 0.12882495516931336, 0.1333521432163324, 0.13803842646028847, 0.1428893958511103, 0.1479108388168207, 0.15310874616820302, 0.15848931924611134, 0.16405897731995386, 0.16982436524617442, 0.1757923613958692, 0.18197008586099836, 0.18836490894898, 0.19498445997580455, 0.20183663636815607, 0.20892961308540386, 0.21627185237270202, 0.2238721138568339, 0.23173946499684786, 0.239883291901949, 0.24831331052955705, 0.25703957827688634, 0.26607250597988097, 0.2754228703338166, 0.2851018267503908, 0.29512092266663853, 0.30549211132155124, 0.31622776601683794, 0.3273406948788381, 0.33884415613920255, 0.35075187395256796, 0.3630780547701014, 0.37583740428844414, 0.3890451449942805, 0.4027170343254591, 0.4168693834703353, 0.43151907682776525, 0.44668359215096304, 0.46238102139926035, 0.47863009232263826, 0.49545019080479, 0.5128613839913648, 0.5308844442309882, 0.5495408738576245, 0.5688529308438414, 0.588843655355589, 0.609536897240169, 0.630957344480193, 0.6531305526474723, 0.6760829753919816, 0.6998419960022735, 0.7244359600749899, 0.7498942093324559, 0.7762471166286916, 0.8035261221856173, 0.8317637711026709, 0.8609937521846003, 0.8912509381337455, 0.9225714271547628, 0.9549925860214359, 0.9885530946569385, 1.0232929922807537, 1.0592537251772887, 1.096478196143185, 1.1350108156723142, 1.174897554939529, 1.2161860006463678, 1.2589254117941675, 1.3031667784522987, 1.3489628825916533, 1.3963683610559376, 1.4454397707459279, 1.4962356560944328, 1.5488166189124812, 1.6032453906900417, 1.6595869074375598, 1.7179083871575875, 1.7782794100389228, 1.8407720014689564, 1.9054607179632463, 1.9724227361148534, 2.0417379446695296, 2.1134890398366455, 2.1877616239495516, 2.2646443075930596, 2.344228815319923, 2.4266100950824145, 2.5118864315095797, 2.6001595631652723, 2.691534803926914, 2.7861211686297693, 2.8840315031266055, 2.9853826189179604, 3.0902954325135887, 3.198895109691397, 3.311311214825911, 3.427677865464501, 3.5481338923357533, 3.672823004980846, 3.801893963205613, 3.9355007545577725, 4.073802778041126, 4.216965034285822, 4.365158322401657, 4.518559443749222, 4.677351412871981, 4.841723675840994, 5.011872336272719, 5.188000389289609, 5.370317963702527, 5.559042572704037, 5.754399373371567, 5.956621435290104, 6.165950018614822, 6.3826348619054825, 6.6069344800759575, 6.839116472814292, 7.07945784384138, 7.328245331389037, 7.585775750291836, 7.852356346100718, 8.128305161640986, 8.413951416451948, 8.709635899560805, 9.01571137605957, 9.332543007969905, 9.660508789898131, 10.0}, "Binning in TPC inner param. or pT"}; + ConfigurableAxis dEdxBins{"dEdxBins", {3000, 0.f, 1500.f}, "Binning in dE/dx"}; + ConfigurableAxis nsigmaBins{"nsigmaBins", {200, -5, 5}, "Binning in nsigma"}; + + void init(InitContext const&) + { + AxisSpec pAxis{pBins, "z#upoint p (GeV/c)"}; + if (usePt) { + pAxis.title = "#it{p}_{T} (GeV/c)"; + } + const AxisSpec dedxAxis{dEdxBins, "d#it{E}/d#it{x} Arb. units"}; + const AxisSpec nsigmaAxis{nsigmaBins, "n#sigma_{TPC}"}; + + // Raw dE/dx vs. TPC momentum + registryCh.add( + "dEdx_vs_Momentum", "dE/dx", HistType::kTH2F, + {pAxis, dEdxBins}); + registryPi.add( + "dEdx_vs_Momentum_Pi", "dE/dx", HistType::kTH2F, + {pAxis, dEdxBins}); + registryKa.add( + "dEdx_vs_Momentum_Ka", "dE/dx", HistType::kTH2F, + {pAxis, dEdxBins}); + registryPr.add( + "dEdx_vs_Momentum_Pr", "dE/dx", HistType::kTH2F, + {pAxis, dEdxBins}); + registryDe.add( + "dEdx_vs_Momentum_De", "dE/dx", HistType::kTH2F, + {pAxis, dEdxBins}); + registryTr.add( + "dEdx_vs_Momentum_Tr", "dE/dx", HistType::kTH2F, + {pAxis, dEdxBins}); + registryHe.add( + "dEdx_vs_Momentum_He", "dE/dx", HistType::kTH2F, + {pAxis, dEdxBins}); + + // nsigma_(TPC) vs. TPC momentum + registryPi.add( + "nsigmaTPC_vs_Momentum_Pi", "nsigmaTPC", HistType::kTH2F, + {pAxis, nsigmaAxis}); + registryKa.add( + "nsigmaTPC_vs_Momentum_Ka", "nsigmaTPC", HistType::kTH2F, + {pAxis, nsigmaAxis}); + registryPr.add( + "nsigmaTPC_vs_Momentum_Pr", "nsigmaTPC", HistType::kTH2F, + {pAxis, nsigmaAxis}); + registryDe.add( + "nsigmaTPC_vs_Momentum_De", "nsigmaTPC", HistType::kTH2F, + {pAxis, nsigmaAxis}); + registryTr.add( + "nsigmaTPC_vs_Momentum_Tr", "nsigmaTPC", HistType::kTH2F, + {pAxis, nsigmaAxis}); + registryHe.add( + "nsigmaTPC_vs_Momentum_He", "nsigmaTPC", HistType::kTH2F, + {pAxis, nsigmaAxis}); + if (addTOF) { + registryPi.add("nsigmaTOF_vs_Momentum_Pi", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + registryKa.add("nsigmaTOF_vs_Momentum_Ka", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + registryPr.add("nsigmaTOF_vs_Momentum_Pr", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + } + + if (doContaminations) { // If requested, also produce the contaminations plots + registryPi.add("nsigmaTPC_vs_Momentum_Ka", "nsigmaTPC", HistType::kTH2F, {pAxis, nsigmaAxis}); + registryPi.add("nsigmaTPC_vs_Momentum_Pr", "nsigmaTPC", HistType::kTH2F, {pAxis, nsigmaAxis}); + + registryKa.add("nsigmaTPC_vs_Momentum_Pi", "nsigmaTPC", HistType::kTH2F, {pAxis, nsigmaAxis}); + registryKa.add("nsigmaTPC_vs_Momentum_Pr", "nsigmaTPC", HistType::kTH2F, {pAxis, nsigmaAxis}); + + registryPr.add("nsigmaTPC_vs_Momentum_Pi", "nsigmaTPC", HistType::kTH2F, {pAxis, nsigmaAxis}); + registryPr.add("nsigmaTPC_vs_Momentum_Ka", "nsigmaTPC", HistType::kTH2F, {pAxis, nsigmaAxis}); + + if (addTOF) { + registryPi.add("nsigmaTOF_vs_Momentum_Ka", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + registryPi.add("nsigmaTOF_vs_Momentum_Pr", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + + // Not ok until we remove ID with TOF + // registryKa.add("nsigmaTOF_vs_Momentum_Pi", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + // registryKa.add("nsigmaTOF_vs_Momentum_Pr", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + + registryPr.add("nsigmaTOF_vs_Momentum_Pi", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + registryPr.add("nsigmaTOF_vs_Momentum_Ka", "nsigmaTOF", HistType::kTH2F, {pAxis, nsigmaAxis}); + } + } + // Event Counter + registryCh.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20.0, +20.0, "z_{vtx} (cm)"}}); + } + + // Single-Track Selection + template + bool passedSingleTrackSelection(const T1& track, const C& collision) + { + // Single-Track Selections + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < minTPCnClsFound) + return false; + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) + return false; + // if (track.tpcSignalN() < minNClsTPCdEdx) + // return false; + if (track.tpcChi2NCl() > maxChi2TPC) + return false; + if (track.eta() < etaMin || track.eta() > etaMax) + return false; + + return true; + } + + // General V0 Selections + template + bool passedV0Selection(const T1& v0, const C& collision) + { + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < v0cospaMin) + return false; + if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + return false; + + return true; + } + + // K0s Selections + template + bool passedK0Selection(const T1& v0, const T2& ntrack, const T2& ptrack, + const C& collision) + { + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + if (ptrack.tpcInnerParam() > 0.6) { + if (!ptrack.hasTOF()) + return false; + if (TMath::Abs(ptrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > 0.6) { + if (!ntrack.hasTOF()) + return false; + if (TMath::Abs(ntrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + // Invariant-Mass Selection + if (v0.mK0Short() < minMassK0s || v0.mK0Short() > maxMassK0s) + return false; + + return true; + } + + // Lambda Selections + template + bool passedLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, + const C& collision) + { + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + if (ptrack.tpcInnerParam() > 0.6) { + if (!ptrack.hasTOF()) + return false; + if (TMath::Abs(ptrack.tofNSigmaPr()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > 0.6) { + if (!ntrack.hasTOF()) + return false; + if (TMath::Abs(ntrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + // Invariant-Mass Selection + if (v0.mLambda() < minMassLambda || v0.mLambda() > maxMassLambda) + return false; + + return true; + } + + // AntiLambda Selections + template + bool passedAntiLambdaSelection(const T1& v0, const T2& ntrack, + const T2& ptrack, const C& collision) + { + + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + if (ptrack.tpcInnerParam() > 0.6) { + if (!ptrack.hasTOF()) + return false; + if (TMath::Abs(ptrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > 0.6) { + if (!ntrack.hasTOF()) + return false; + if (TMath::Abs(ntrack.tofNSigmaPr()) > nsigmaTOFmax) + return false; + } + + // Invariant-Mass Selection + if (v0.mAntiLambda() < minMassLambda || v0.mAntiLambda() > maxMassLambda) + return false; + + return true; + } + + // Process Data + void process(SelectedCollisions::iterator const& collision, + aod::V0Datas const& fullV0s, PIDTracks const& tracks) + { + // Event Selection + if (!collision.sel8()) + return; + + // Event Counter + registryCh.fill(HIST("histRecVtxZData"), collision.posZ()); + + // Kaons and nuclei + for (auto& trk : tracks) { + + if (!passedSingleTrackSelection(trk, collision)) + continue; + if (!trk.passedTPCRefit()) + continue; + float signedP = trk.sign() * trk.tpcInnerParam(); + if (usePt) { + signedP = trk.sign() * trk.pt(); + } + + // Charged Particles + registryCh.fill(HIST("dEdx_vs_Momentum"), signedP, + trk.tpcSignal()); + + // Kaons + if (trk.tpcInnerParam() > 0.4 && trk.hasTOF() && TMath::Abs(trk.tofNSigmaKa()) < 2.0) { + registryKa.fill(HIST("dEdx_vs_Momentum_Ka"), signedP, + trk.tpcSignal()); + registryKa.fill(HIST("nsigmaTPC_vs_Momentum_Ka"), signedP, + trk.tpcNSigmaKa()); + + if (doContaminations) { + registryKa.fill(HIST("nsigmaTPC_vs_Momentum_Pi"), signedP, trk.tpcNSigmaPi()); + registryKa.fill(HIST("nsigmaTPC_vs_Momentum_Pr"), signedP, trk.tpcNSigmaPr()); + } + } + + if (trk.tpcInnerParam() < 0.4) { + registryKa.fill(HIST("dEdx_vs_Momentum_Ka"), signedP, + trk.tpcSignal()); + registryKa.fill(HIST("nsigmaTPC_vs_Momentum_Ka"), signedP, + trk.tpcNSigmaKa()); + + if (doContaminations) { + registryKa.fill(HIST("nsigmaTPC_vs_Momentum_Pi"), signedP, + trk.tpcNSigmaPi()); + registryKa.fill(HIST("nsigmaTPC_vs_Momentum_Pr"), signedP, + trk.tpcNSigmaPr()); + } + } + + // Selection of high dE/dx Objects + if (trk.tpcNSigmaDe() < -4.0) + continue; + + // Deuterons + if (trk.tpcInnerParam() > 1.0 && trk.hasTOF() && TMath::Abs(trk.tofNSigmaDe()) < 3.0) { + registryDe.fill(HIST("dEdx_vs_Momentum_De"), signedP, + trk.tpcSignal()); + registryDe.fill(HIST("nsigmaTPC_vs_Momentum_De"), signedP, + trk.tpcNSigmaDe()); + } + + if (trk.tpcInnerParam() < 1.0) { + registryDe.fill(HIST("dEdx_vs_Momentum_De"), signedP, + trk.tpcSignal()); + registryDe.fill(HIST("nsigmaTPC_vs_Momentum_De"), signedP, + trk.tpcNSigmaDe()); + } + + // Heavier Nuclei + registryTr.fill(HIST("dEdx_vs_Momentum_Tr"), signedP, + trk.tpcSignal()); + registryTr.fill(HIST("nsigmaTPC_vs_Momentum_Tr"), signedP, + trk.tpcNSigmaTr()); + registryHe.fill(HIST("dEdx_vs_Momentum_He"), 2.0 * signedP, + trk.tpcSignal()); + registryHe.fill(HIST("nsigmaTPC_vs_Momentum_He"), + 2.0 * signedP, trk.tpcNSigmaHe()); + } + + // Loop over Reconstructed V0s + for (auto& v0 : fullV0s) { + + // Standard V0 Selections + if (!passedV0Selection(v0, collision)) { + continue; + } + + if (v0.dcaV0daughters() > dcaV0DaughtersMax) { + continue; + } + + // Positive and Negative Tracks + const auto& posTrack = v0.posTrack_as(); + const auto& negTrack = v0.negTrack_as(); + + if (!posTrack.passedTPCRefit()) + continue; + if (!negTrack.passedTPCRefit()) + continue; + + float signedPpos = posTrack.sign() * posTrack.tpcInnerParam(); + float signedPneg = negTrack.sign() * negTrack.tpcInnerParam(); + if (usePt) { + signedPpos = posTrack.sign() * posTrack.pt(); + signedPneg = negTrack.sign() * negTrack.pt(); + } + + // K0s Selection + if (passedK0Selection(v0, negTrack, posTrack, collision)) { + registryPi.fill(HIST("dEdx_vs_Momentum_Pi"), signedPneg, negTrack.tpcSignal()); + registryPi.fill(HIST("dEdx_vs_Momentum_Pi"), signedPpos, posTrack.tpcSignal()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Pi"), + signedPneg, negTrack.tpcNSigmaPi()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Pi"), + signedPpos, posTrack.tpcNSigmaPi()); + if (addTOF) { + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Pi"), signedPneg, negTrack.tofNSigmaPi()); + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Pi"), signedPpos, posTrack.tofNSigmaPi()); + } + + if (doContaminations) { + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Ka"), signedPneg, negTrack.tpcNSigmaKa()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Pr"), signedPneg, negTrack.tpcNSigmaPr()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Ka"), signedPpos, posTrack.tpcNSigmaKa()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Pr"), signedPpos, posTrack.tpcNSigmaPr()); + if (addTOF) { + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Ka"), signedPneg, negTrack.tofNSigmaKa()); + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Pr"), signedPneg, negTrack.tofNSigmaPr()); + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Ka"), signedPpos, posTrack.tofNSigmaKa()); + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Pr"), signedPpos, posTrack.tofNSigmaPr()); + } + } + } + + // Lambda Selection + if (passedLambdaSelection(v0, negTrack, posTrack, collision)) { + registryPr.fill(HIST("dEdx_vs_Momentum_Pr"), signedPpos, posTrack.tpcSignal()); + registryPr.fill(HIST("nsigmaTPC_vs_Momentum_Pr"), + signedPpos, posTrack.tpcNSigmaPr()); + registryPi.fill(HIST("dEdx_vs_Momentum_Pi"), signedPneg, negTrack.tpcSignal()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Pi"), + signedPneg, negTrack.tpcNSigmaPi()); + if (addTOF) { + registryPr.fill(HIST("nsigmaTOF_vs_Momentum_Pr"), signedPpos, posTrack.tofNSigmaPr()); + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Pi"), signedPneg, negTrack.tofNSigmaPi()); + } + if (doContaminations) { + registryPr.fill(HIST("nsigmaTPC_vs_Momentum_Pi"), signedPpos, posTrack.tpcNSigmaPi()); + registryPr.fill(HIST("nsigmaTPC_vs_Momentum_Ka"), signedPpos, posTrack.tpcNSigmaKa()); + + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Ka"), signedPneg, negTrack.tpcNSigmaKa()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Pr"), signedPneg, negTrack.tpcNSigmaPr()); + if (addTOF) { + registryPr.fill(HIST("nsigmaTOF_vs_Momentum_Pi"), signedPpos, posTrack.tofNSigmaPi()); + registryPr.fill(HIST("nsigmaTOF_vs_Momentum_Ka"), signedPpos, posTrack.tofNSigmaKa()); + + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Ka"), signedPneg, negTrack.tofNSigmaKa()); + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Pr"), signedPneg, negTrack.tofNSigmaPr()); + } + } + } + + // AntiLambda Selection + if (passedAntiLambdaSelection(v0, negTrack, posTrack, collision)) { + registryPi.fill(HIST("dEdx_vs_Momentum_Pi"), signedPpos, posTrack.tpcSignal()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Pi"), + signedPpos, posTrack.tpcNSigmaPi()); + registryPr.fill(HIST("dEdx_vs_Momentum_Pr"), signedPneg, negTrack.tpcSignal()); + registryPr.fill(HIST("nsigmaTPC_vs_Momentum_Pr"), + signedPneg, negTrack.tpcNSigmaPr()); + if (addTOF) { + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Pi"), signedPpos, posTrack.tofNSigmaPi()); + registryPr.fill(HIST("nsigmaTOF_vs_Momentum_Pr"), signedPneg, negTrack.tofNSigmaPr()); + } + if (doContaminations) { + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Ka"), signedPpos, posTrack.tpcNSigmaKa()); + registryPi.fill(HIST("nsigmaTPC_vs_Momentum_Pr"), signedPpos, posTrack.tpcNSigmaPr()); + + registryPr.fill(HIST("nsigmaTPC_vs_Momentum_Pi"), signedPneg, negTrack.tpcNSigmaPi()); + registryPr.fill(HIST("nsigmaTPC_vs_Momentum_Ka"), signedPneg, negTrack.tpcNSigmaKa()); + if (addTOF) { + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Ka"), signedPpos, posTrack.tofNSigmaKa()); + registryPi.fill(HIST("nsigmaTOF_vs_Momentum_Pr"), signedPpos, posTrack.tofNSigmaPr()); + + registryPr.fill(HIST("nsigmaTOF_vs_Momentum_Pi"), signedPneg, negTrack.tofNSigmaPi()); + registryPr.fill(HIST("nsigmaTOF_vs_Momentum_Ka"), signedPneg, negTrack.tofNSigmaKa()); + } + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/QC/tpc_dedx_qa.cxx b/PWGLF/Tasks/QC/tpc_dedx_qa.cxx new file mode 100644 index 00000000000..749a9611fda --- /dev/null +++ b/PWGLF/Tasks/QC/tpc_dedx_qa.cxx @@ -0,0 +1,710 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \author Alberto Caliva (alberto.caliva@cern.ch) +/// \since September 19, 2023 + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "ReconstructionDataFormats/Track.h" + +using namespace o2; +using namespace o2::framework; + +using PIDTracks = soa::Join< + aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::pidTOFbeta, + aod::pidTOFmass, aod::TrackSelection, aod::TrackSelectionExtension, + aod::pidTPCFullPi, aod::pidTPCFullKa, aod::pidTPCFullPr, aod::pidTPCFullDe, + aod::pidTPCFullTr, aod::pidTPCFullHe, aod::pidTOFFullPi, aod::pidTOFFullKa, + aod::pidTOFFullPr, aod::pidTOFFullDe, aod::pidTOFFullTr, aod::pidTOFFullHe>; + +using SelectedCollisions = soa::Join; + +struct tpc_dedx_qa { + + // dE/dx for all charged particles + HistogramRegistry registryCh{ + "registryCh", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + // dE/dx for pions + HistogramRegistry registryPi{ + "registryPi", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + // dE/dx for kaons + HistogramRegistry registryKa{ + "registryKa", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + // dE/dx for protons + HistogramRegistry registryPr{ + "registryPr", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + // dE/dx for deuterons + HistogramRegistry registryDe{ + "registryDe", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + // dE/dx for helium-3 + HistogramRegistry registryHe{ + "registryHe", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + // Configurable Parameters + Configurable minTPCnClsFound{"minTPCnClsFound", 70.0f, + "min number of found TPC clusters"}; + Configurable minNCrossedRowsTPC{ + "minNCrossedRowsTPC", 70.0f, "min number of found TPC crossed rows"}; + Configurable minNClsTPCdEdx{ + "minNClsTPCdEdx", 50.0f, "min number of TPC clusters for PID"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, + "max chi2 per cluster TPC"}; + Configurable maxChi2ITS{"maxChi2ITS", 36.0f, + "max chi2 per cluster ITS"}; + Configurable etaMin{"etaMin", -0.8f, "etaMin"}; + Configurable etaMax{"etaMax", +0.8f, "etaMax"}; + Configurable v0cospaMin{"v0cospaMin", 0.998f, "Minimum V0 CosPA"}; + Configurable minimumV0Radius{"minimumV0Radius", 0.5f, + "Minimum V0 Radius"}; + Configurable maximumV0Radius{"maximumV0Radius", 100.0f, + "Maximum V0 Radius"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, + "Maximum DCA Daughters"}; + Configurable nsigmaTOFmax{"nsigmaTOFmax", 3.0f, "Maximum nsigma TOF"}; + Configurable minMassK0s{"minMassK0s", 0.4f, "Minimum Mass K0s"}; + Configurable maxMassK0s{"maxMassK0s", 0.6f, "Maximum Mass K0s"}; + Configurable minMassLambda{"minMassLambda", 1.1f, + "Minimum Mass Lambda"}; + Configurable maxMassLambda{"maxMassLambda", 1.2f, + "Maximum Mass Lambda"}; + Configurable minReqClusterITS{ + "minReqClusterITS", 4.0f, "min number of clusters required in ITS"}; + Configurable maxDCAxy{"maxDCAxy", 0.1f, "maxDCAxy"}; + Configurable maxDCAz{"maxDCAz", 0.1f, "maxDCAz"}; + Configurable eventSelection{"eventSelection", true, "event selection"}; + + // Reduce binning + ConfigurableAxis pBins_Pi{"pBins_Pi", {VARIABLE_WIDTH, -10.0, -5.0, -4.5, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.45, -0.4, -0.35, -0.3, -0.28, -0.26, -0.24, -0.22, -0.2, 0.0, 0.2, 0.22, 0.24, 0.26, 0.28, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 10.0}, "p bins for pions"}; + ConfigurableAxis pBins_Ka{"pBins_Ka", {VARIABLE_WIDTH, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.45, -0.4, -0.35, -0.3, -0.28, -0.26, -0.24, -0.22, -0.2, 0.0, 0.2, 0.22, 0.24, 0.26, 0.28, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0}, "p bins for kaons"}; + ConfigurableAxis pBins_Pr{"pBins_Pr", {VARIABLE_WIDTH, -5.0, -4.5, -4.0, -3.5, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.48, -0.46, -0.44, -0.42, -0.4, -0.38, -0.36, -0.34, -0.32, -0.3, 0.0, 0.3, 0.32, 0.34, 0.36, 0.38, 0.4, 0.42, 0.44, 0.46, 0.48, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.5, 4.0, 4.5, 5.0}, "p bins for protons"}; + ConfigurableAxis pBins_De{"pBins_De", {VARIABLE_WIDTH, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.75, -0.7, -0.65, -0.6, -0.55, -0.5, -0.48, -0.46, -0.44, -0.42, -0.4, -0.38, -0.36, -0.34, -0.32, -0.3, 0.0, 0.3, 0.32, 0.34, 0.36, 0.38, 0.4, 0.42, 0.44, 0.46, 0.48, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5}, "p bins for deuterons"}; + ConfigurableAxis pBins_He{"pBins_He", {VARIABLE_WIDTH, -5.0, -4.5, -4.0, -3.5, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, 0.0, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.5, 4.0, 4.5, 5.0}, "p bins for helium-3"}; + + void init(InitContext const&) + { + + // Variable binning + AxisSpec pAxis_Pi{pBins_Pi, "#it{p}/Z (GeV/c)"}; + AxisSpec pAxis_Ka{pBins_Ka, "#it{p}/Z (GeV/c)"}; + AxisSpec pAxis_Pr{pBins_Pr, "#it{p}/Z (GeV/c)"}; + AxisSpec pAxis_De{pBins_De, "#it{p}/Z (GeV/c)"}; + AxisSpec pAxis_He{pBins_He, "#it{p}/Z (GeV/c)"}; + + // Charged Particles + registryCh.add( + "dEdx_vs_Momentum", "dE/dx", HistType::kTH2F, + {{100, -10.0, 10.0, "#it{p}/Z (GeV/c)"}, {100, 0.0, 600.0, "dE/dx (a. u.)"}}); + + // Pions + registryPi.add( + "dEdx_vs_Momentum_Pi_m0906", "dE/dx", HistType::kTH3F, + {pAxis_Pi, {150, 0.0, 150.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPi.add( + "dEdx_vs_Momentum_Pi_m0604", "dE/dx", HistType::kTH3F, + {pAxis_Pi, {150, 0.0, 150.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPi.add( + "dEdx_vs_Momentum_Pi_m0402", "dE/dx", HistType::kTH3F, + {pAxis_Pi, {150, 0.0, 150.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPi.add( + "dEdx_vs_Momentum_Pi_m0200", "dE/dx", HistType::kTH3F, + {pAxis_Pi, {150, 0.0, 150.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPi.add( + "dEdx_vs_Momentum_Pi_p0002", "dE/dx", HistType::kTH3F, + {pAxis_Pi, {150, 0.0, 150.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPi.add( + "dEdx_vs_Momentum_Pi_p0204", "dE/dx", HistType::kTH3F, + {pAxis_Pi, {150, 0.0, 150.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPi.add( + "dEdx_vs_Momentum_Pi_p0406", "dE/dx", HistType::kTH3F, + {pAxis_Pi, {150, 0.0, 150.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPi.add( + "dEdx_vs_Momentum_Pi_p0609", "dE/dx", HistType::kTH3F, + {pAxis_Pi, {150, 0.0, 150.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + // Kaons + registryKa.add( + "dEdx_vs_Momentum_Ka_m0906", "dE/dx", HistType::kTH3F, + {pAxis_Ka, {200, 0.0, 400.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryKa.add( + "dEdx_vs_Momentum_Ka_m0604", "dE/dx", HistType::kTH3F, + {pAxis_Ka, {200, 0.0, 400.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryKa.add( + "dEdx_vs_Momentum_Ka_m0402", "dE/dx", HistType::kTH3F, + {pAxis_Ka, {200, 0.0, 400.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryKa.add( + "dEdx_vs_Momentum_Ka_m0200", "dE/dx", HistType::kTH3F, + {pAxis_Ka, {200, 0.0, 400.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryKa.add( + "dEdx_vs_Momentum_Ka_p0002", "dE/dx", HistType::kTH3F, + {pAxis_Ka, {200, 0.0, 400.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryKa.add( + "dEdx_vs_Momentum_Ka_p0204", "dE/dx", HistType::kTH3F, + {pAxis_Ka, {200, 0.0, 400.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryKa.add( + "dEdx_vs_Momentum_Ka_p0406", "dE/dx", HistType::kTH3F, + {pAxis_Ka, {200, 0.0, 400.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryKa.add( + "dEdx_vs_Momentum_Ka_p0609", "dE/dx", HistType::kTH3F, + {pAxis_Ka, {200, 0.0, 400.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + // Protons + registryPr.add( + "dEdx_vs_Momentum_Pr_m0906", "dE/dx", HistType::kTH3F, + {pAxis_Pr, {200, 0.0, 500.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPr.add( + "dEdx_vs_Momentum_Pr_m0604", "dE/dx", HistType::kTH3F, + {pAxis_Pr, {200, 0.0, 500.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPr.add( + "dEdx_vs_Momentum_Pr_m0402", "dE/dx", HistType::kTH3F, + {pAxis_Pr, {200, 0.0, 500.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPr.add( + "dEdx_vs_Momentum_Pr_m0200", "dE/dx", HistType::kTH3F, + {pAxis_Pr, {200, 0.0, 500.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPr.add( + "dEdx_vs_Momentum_Pr_p0002", "dE/dx", HistType::kTH3F, + {pAxis_Pr, {200, 0.0, 500.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPr.add( + "dEdx_vs_Momentum_Pr_p0204", "dE/dx", HistType::kTH3F, + {pAxis_Pr, {200, 0.0, 500.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPr.add( + "dEdx_vs_Momentum_Pr_p0406", "dE/dx", HistType::kTH3F, + {pAxis_Pr, {200, 0.0, 500.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryPr.add( + "dEdx_vs_Momentum_Pr_p0609", "dE/dx", HistType::kTH3F, + {pAxis_Pr, {200, 0.0, 500.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + // Deuterons + registryDe.add( + "dEdx_vs_Momentum_De_m0906", "dE/dx", HistType::kTH3F, + {pAxis_De, {300, 0.0, 600.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryDe.add( + "dEdx_vs_Momentum_De_m0604", "dE/dx", HistType::kTH3F, + {pAxis_De, {300, 0.0, 600.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryDe.add( + "dEdx_vs_Momentum_De_m0402", "dE/dx", HistType::kTH3F, + {pAxis_De, {300, 0.0, 600.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryDe.add( + "dEdx_vs_Momentum_De_m0200", "dE/dx", HistType::kTH3F, + {pAxis_De, {300, 0.0, 600.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryDe.add( + "dEdx_vs_Momentum_De_p0002", "dE/dx", HistType::kTH3F, + {pAxis_De, {300, 0.0, 600.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryDe.add( + "dEdx_vs_Momentum_De_p0204", "dE/dx", HistType::kTH3F, + {pAxis_De, {300, 0.0, 600.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryDe.add( + "dEdx_vs_Momentum_De_p0406", "dE/dx", HistType::kTH3F, + {pAxis_De, {300, 0.0, 600.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryDe.add( + "dEdx_vs_Momentum_De_p0609", "dE/dx", HistType::kTH3F, + {pAxis_De, {300, 0.0, 600.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + // Helium-3 + registryHe.add( + "dEdx_vs_Momentum_He_m0906", "dE/dx", HistType::kTH3F, + {pAxis_He, {400, 0.0, 800.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryHe.add( + "dEdx_vs_Momentum_He_m0604", "dE/dx", HistType::kTH3F, + {pAxis_He, {400, 0.0, 800.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryHe.add( + "dEdx_vs_Momentum_He_m0402", "dE/dx", HistType::kTH3F, + {pAxis_He, {400, 0.0, 800.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryHe.add( + "dEdx_vs_Momentum_He_m0200", "dE/dx", HistType::kTH3F, + {pAxis_He, {400, 0.0, 800.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryHe.add( + "dEdx_vs_Momentum_He_p0002", "dE/dx", HistType::kTH3F, + {pAxis_He, {400, 0.0, 800.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryHe.add( + "dEdx_vs_Momentum_He_p0204", "dE/dx", HistType::kTH3F, + {pAxis_He, {400, 0.0, 800.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryHe.add( + "dEdx_vs_Momentum_He_p0406", "dE/dx", HistType::kTH3F, + {pAxis_He, {400, 0.0, 800.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + registryHe.add( + "dEdx_vs_Momentum_He_p0609", "dE/dx", HistType::kTH3F, + {pAxis_He, {400, 0.0, 800.0, "dE/dx (a. u.)"}, {10, 0.0, 100.0, "centrality"}}); + + // Event Counter + registryCh.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{100, -20.0, +20.0, "z_{vtx} (cm)"}}); + } + + // Single-Track Selection + template + bool passedSingleTrackSelection(const T1& track, const C& collision) + { + // Single-Track Selections + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < minTPCnClsFound) + return false; + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) + return false; + if (track.tpcChi2NCl() > maxChi2TPC) + return false; + if (track.eta() < etaMin || track.eta() > etaMax) + return false; + + return true; + } + + // General V0 Selections + template + bool passedV0Selection(const T1& v0, const C& collision) + { + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < v0cospaMin) + return false; + if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + return false; + + return true; + } + + // K0s Selections + template + bool passedK0Selection(const T1& v0, const T2& ntrack, const T2& ptrack, + const C& collision) + { + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + if (ptrack.tpcInnerParam() > 0.6) { + if (!ptrack.hasTOF()) + return false; + if (TMath::Abs(ptrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > 0.6) { + if (!ntrack.hasTOF()) + return false; + if (TMath::Abs(ntrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + // Invariant-Mass Selection + if (v0.mK0Short() < minMassK0s || v0.mK0Short() > maxMassK0s) + return false; + + return true; + } + + // Lambda Selections + template + bool passedLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, + const C& collision) + { + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + if (ptrack.tpcInnerParam() > 0.6) { + if (!ptrack.hasTOF()) + return false; + if (TMath::Abs(ptrack.tofNSigmaPr()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > 0.6) { + if (!ntrack.hasTOF()) + return false; + if (TMath::Abs(ntrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + // Invariant-Mass Selection + if (v0.mLambda() < minMassLambda || v0.mLambda() > maxMassLambda) + return false; + + return true; + } + + // AntiLambda Selections + template + bool passedAntiLambdaSelection(const T1& v0, const T2& ntrack, + const T2& ptrack, const C& collision) + { + + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + if (ptrack.tpcInnerParam() > 0.6) { + if (!ptrack.hasTOF()) + return false; + if (TMath::Abs(ptrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > 0.6) { + if (!ntrack.hasTOF()) + return false; + if (TMath::Abs(ntrack.tofNSigmaPr()) > nsigmaTOFmax) + return false; + } + + // Invariant-Mass Selection + if (v0.mAntiLambda() < minMassLambda || v0.mAntiLambda() > maxMassLambda) + return false; + + return true; + } + + // Process Data + void process(SelectedCollisions::iterator const& collision, + aod::V0Datas const& fullV0s, PIDTracks const& tracks) + { + // Event Selection + if (!collision.sel8()) + return; + + // Event Counter + registryCh.fill(HIST("histRecVtxZData"), collision.posZ()); + + // Centrality + float centrality = collision.centFT0C(); + if (centrality < 0.0 || centrality > 100.0) + centrality = 1.0; + + // Kaons + for (auto& trk : tracks) { + + if (!passedSingleTrackSelection(trk, collision)) + continue; + if (!trk.passedTPCRefit()) + continue; + float signedP = trk.sign() * trk.tpcInnerParam(); + + // Charged Particles + registryCh.fill(HIST("dEdx_vs_Momentum"), signedP, trk.tpcSignal()); + + // Kaons + if (trk.tpcInnerParam() > 0.4 && trk.hasTOF() && TMath::Abs(trk.tofNSigmaKa()) < 2.0) { + if (trk.eta() > -0.9 && trk.eta() < -0.6) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_m0906"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.6 && trk.eta() < -0.4) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_m0604"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.4 && trk.eta() < -0.2) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_m0402"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.2 && trk.eta() < 0.0) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_m0200"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.0 && trk.eta() < 0.2) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_p0002"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.2 && trk.eta() < 0.4) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_p0204"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.4 && trk.eta() < 0.6) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_p0406"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.6 && trk.eta() < 0.9) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_p0609"), signedP, trk.tpcSignal(), centrality); + } + + if (trk.tpcInnerParam() < 0.4) { + if (trk.eta() > -0.9 && trk.eta() < -0.6) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_m0906"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.6 && trk.eta() < -0.4) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_m0604"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.4 && trk.eta() < -0.2) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_m0402"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.2 && trk.eta() < 0.0) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_m0200"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.0 && trk.eta() < 0.2) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_p0002"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.2 && trk.eta() < 0.4) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_p0204"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.4 && trk.eta() < 0.6) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_p0406"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.6 && trk.eta() < 0.9) + registryKa.fill(HIST("dEdx_vs_Momentum_Ka_p0609"), signedP, trk.tpcSignal(), centrality); + } + + // Deuterons + if (trk.tpcInnerParam() > 1.0 && trk.hasTOF() && TMath::Abs(trk.tofNSigmaDe()) < 3.0) { + if (trk.eta() > -0.9 && trk.eta() < -0.6) + registryDe.fill(HIST("dEdx_vs_Momentum_De_m0906"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.6 && trk.eta() < -0.4) + registryDe.fill(HIST("dEdx_vs_Momentum_De_m0604"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.4 && trk.eta() < -0.2) + registryDe.fill(HIST("dEdx_vs_Momentum_De_m0402"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.2 && trk.eta() < 0.0) + registryDe.fill(HIST("dEdx_vs_Momentum_De_m0200"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.0 && trk.eta() < 0.2) + registryDe.fill(HIST("dEdx_vs_Momentum_De_p0002"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.2 && trk.eta() < 0.4) + registryDe.fill(HIST("dEdx_vs_Momentum_De_p0204"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.4 && trk.eta() < 0.6) + registryDe.fill(HIST("dEdx_vs_Momentum_De_p0406"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.6 && trk.eta() < 0.9) + registryDe.fill(HIST("dEdx_vs_Momentum_De_p0609"), signedP, trk.tpcSignal(), centrality); + } + + if (trk.tpcInnerParam() < 1.0) { + if (trk.eta() > -0.9 && trk.eta() < -0.6) + registryDe.fill(HIST("dEdx_vs_Momentum_De_m0906"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.6 && trk.eta() < -0.4) + registryDe.fill(HIST("dEdx_vs_Momentum_De_m0604"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.4 && trk.eta() < -0.2) + registryDe.fill(HIST("dEdx_vs_Momentum_De_m0402"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.2 && trk.eta() < 0.0) + registryDe.fill(HIST("dEdx_vs_Momentum_De_m0200"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.0 && trk.eta() < 0.2) + registryDe.fill(HIST("dEdx_vs_Momentum_De_p0002"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.2 && trk.eta() < 0.4) + registryDe.fill(HIST("dEdx_vs_Momentum_De_p0204"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.4 && trk.eta() < 0.6) + registryDe.fill(HIST("dEdx_vs_Momentum_De_p0406"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.6 && trk.eta() < 0.9) + registryDe.fill(HIST("dEdx_vs_Momentum_De_p0609"), signedP, trk.tpcSignal(), centrality); + } + + // Helium-3 + if (trk.tpcSignal() > 180.0 && trk.tpcInnerParam() > 0.8 && trk.tpcNSigmaDe() > 2.0) { + if (trk.eta() > -0.9 && trk.eta() < -0.6) + registryHe.fill(HIST("dEdx_vs_Momentum_He_m0906"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.6 && trk.eta() < -0.4) + registryHe.fill(HIST("dEdx_vs_Momentum_He_m0604"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.4 && trk.eta() < -0.2) + registryHe.fill(HIST("dEdx_vs_Momentum_He_m0402"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > -0.2 && trk.eta() < 0.0) + registryHe.fill(HIST("dEdx_vs_Momentum_He_m0200"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.0 && trk.eta() < 0.2) + registryHe.fill(HIST("dEdx_vs_Momentum_He_p0002"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.2 && trk.eta() < 0.4) + registryHe.fill(HIST("dEdx_vs_Momentum_He_p0204"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.4 && trk.eta() < 0.6) + registryHe.fill(HIST("dEdx_vs_Momentum_He_p0406"), signedP, trk.tpcSignal(), centrality); + if (trk.eta() > 0.6 && trk.eta() < 0.9) + registryHe.fill(HIST("dEdx_vs_Momentum_He_p0609"), signedP, trk.tpcSignal(), centrality); + } + } + + // Loop over Reconstructed V0s + for (auto& v0 : fullV0s) { + + // Standard V0 Selections + if (!passedV0Selection(v0, collision)) { + continue; + } + + if (v0.dcaV0daughters() > dcaV0DaughtersMax) { + continue; + } + + // Positive and Negative Tracks + const auto& posTrack = v0.posTrack_as(); + const auto& negTrack = v0.negTrack_as(); + + if (!posTrack.passedTPCRefit()) + continue; + if (!negTrack.passedTPCRefit()) + continue; + + float signedPpos = posTrack.sign() * posTrack.tpcInnerParam(); + float signedPneg = negTrack.sign() * negTrack.tpcInnerParam(); + + // K0s Selection + if (passedK0Selection(v0, negTrack, posTrack, collision)) { + + if (negTrack.eta() > -0.9 && negTrack.eta() < -0.6) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0906"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.6 && negTrack.eta() < -0.4) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0604"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.4 && negTrack.eta() < -0.2) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0402"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.2 && negTrack.eta() < 0.0) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0200"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.0 && negTrack.eta() < 0.2) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0002"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.2 && negTrack.eta() < 0.4) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0204"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.4 && negTrack.eta() < 0.6) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0406"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.6 && negTrack.eta() < 0.9) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0609"), signedPneg, negTrack.tpcSignal(), centrality); + + if (posTrack.eta() > -0.9 && posTrack.eta() < -0.6) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0906"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.6 && posTrack.eta() < -0.4) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0604"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.4 && posTrack.eta() < -0.2) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0402"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.2 && posTrack.eta() < 0.0) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0200"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.0 && posTrack.eta() < 0.2) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0002"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.2 && posTrack.eta() < 0.4) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0204"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.4 && posTrack.eta() < 0.6) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0406"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.6 && posTrack.eta() < 0.9) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0609"), signedPpos, posTrack.tpcSignal(), centrality); + } + + // Lambda Selection + if (passedLambdaSelection(v0, negTrack, posTrack, collision)) { + + if (posTrack.eta() > -0.9 && posTrack.eta() < -0.6) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_m0906"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.6 && posTrack.eta() < -0.4) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_m0604"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.4 && posTrack.eta() < -0.2) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_m0402"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.2 && posTrack.eta() < 0.0) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_m0200"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.0 && posTrack.eta() < 0.2) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_p0002"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.2 && posTrack.eta() < 0.4) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_p0204"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.4 && posTrack.eta() < 0.6) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_p0406"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.6 && posTrack.eta() < 0.9) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_p0609"), signedPpos, posTrack.tpcSignal(), centrality); + + if (negTrack.eta() > -0.9 && negTrack.eta() < -0.6) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0906"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.6 && negTrack.eta() < -0.4) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0604"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.4 && negTrack.eta() < -0.2) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0402"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.2 && negTrack.eta() < 0.0) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0200"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.0 && negTrack.eta() < 0.2) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0002"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.2 && negTrack.eta() < 0.4) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0204"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.4 && negTrack.eta() < 0.6) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0406"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.6 && negTrack.eta() < 0.9) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0609"), signedPneg, negTrack.tpcSignal(), centrality); + } + + // AntiLambda Selection + if (passedAntiLambdaSelection(v0, negTrack, posTrack, collision)) { + + if (negTrack.eta() > -0.9 && negTrack.eta() < -0.6) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_m0906"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.6 && negTrack.eta() < -0.4) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_m0604"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.4 && negTrack.eta() < -0.2) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_m0402"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > -0.2 && negTrack.eta() < 0.0) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_m0200"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.0 && negTrack.eta() < 0.2) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_p0002"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.2 && negTrack.eta() < 0.4) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_p0204"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.4 && negTrack.eta() < 0.6) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_p0406"), signedPneg, negTrack.tpcSignal(), centrality); + if (negTrack.eta() > 0.6 && negTrack.eta() < 0.9) + registryPr.fill(HIST("dEdx_vs_Momentum_Pr_p0609"), signedPneg, negTrack.tpcSignal(), centrality); + + if (posTrack.eta() > -0.9 && posTrack.eta() < -0.6) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0906"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.6 && posTrack.eta() < -0.4) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0604"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.4 && posTrack.eta() < -0.2) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0402"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > -0.2 && posTrack.eta() < 0.0) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_m0200"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.0 && posTrack.eta() < 0.2) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0002"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.2 && posTrack.eta() < 0.4) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0204"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.4 && posTrack.eta() < 0.6) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0406"), signedPpos, posTrack.tpcSignal(), centrality); + if (posTrack.eta() > 0.6 && posTrack.eta() < 0.9) + registryPi.fill(HIST("dEdx_vs_Momentum_Pi_p0609"), signedPpos, posTrack.tpcSignal(), centrality); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/QC/vertexQA.cxx b/PWGLF/Tasks/QC/vertexQA.cxx new file mode 100644 index 00000000000..d4c19a57088 --- /dev/null +++ b/PWGLF/Tasks/QC/vertexQA.cxx @@ -0,0 +1,227 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using BCcoll = std::pair; + +namespace +{ +constexpr double LHCRFFreq = 400.789e6; +constexpr double LHCBunchSpacingNS = 10 * 1.e9 / LHCRFFreq; +double deltaTimeColl(BCcoll const bccoll1, BCcoll const bccoll2) +{ + auto coll1 = std::get(bccoll1); + auto coll2 = std::get(bccoll2); + auto bc1 = std::get(bccoll1); + auto bc2 = std::get(bccoll2); + int64_t tmpDT = int64_t(bc1.globalBC()) - int64_t(bc2.globalBC()); + double deltaT = tmpDT * LHCBunchSpacingNS + coll1.collisionTime() - coll2.collisionTime(); + return deltaT; +} +} // namespace + +namespace o2::aod +{ +DECLARE_SOA_TABLE(VtxQAtable, "AOD", "VTXQATABLE", + bc::GlobalBC, + collision::PosX, + collision::PosY, + collision::PosZ, + collision::CovXX, + collision::CovXY, + collision::CovYY, + collision::CovZZ, + collision::CollisionTime, + collision::CollisionTimeRes, + collision::NumContrib) +} // namespace o2::aod + +struct vertexQA { + Produces vtxQAtable; + + Configurable storeTree{"storeTree", 1000, "Store in tree collisions from BC's with more than 'storeTree' vertices, for in-depth analysis"}; + + Configurable nCollMax{"nCollMax", 20, "Maximum size of collision buffer"}; + Configurable nSigmaZ{"nSigmaZ", 1000., "Number of sigmas for z of vertices"}; + Configurable nSigmaR{"nSigmaR", 1000., "Number of sigmas for transverse displacement of vertices"}; + Configurable nSigmaT{"nSigmaT", 1000., "Number of sigmas for time of vertices"}; + Configurable maxTime{"maxTime", 100000., "Maximum time difference between split vertices in ns"}; + + ConfigurableAxis xVtxAxis{"xVtxBins", {100, -0.1f, 0.1f}, "Binning for the vertex x (y) in cm"}; + ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; + ConfigurableAxis tVtxAxis{"tVtxBins", {100, -20.f, 20.f}, "Binning for the vertex t in ns"}; + + ConfigurableAxis xDiffVtxAxis{"xDiffVtxBins", {200, -0.05f, 0.05f}, "Binning for the vertex x (y) distance in cm"}; + ConfigurableAxis xyDiffVtxAxis{"xyDiffVtxBins", {200, 0.f, 0.05f}, "Binning for the vertex xy distance in cm"}; + ConfigurableAxis zDiffVtxAxis{"zDiffVtxBins", {200, -10.f, 10.f}, "Binning for the vertex z distance in cm"}; + ConfigurableAxis zDiffVtxAxis2{"zDiffVtxBins2", {1000, -0.5f, 0.5f}, "Binning for the vertex z distance in cm (2)"}; + ConfigurableAxis tDiffVtxAxis{"tDiffVtxBins", {300, 0.f, 30.f}, "Binning for the vertex t distance in ns"}; + ConfigurableAxis tDiffVtxAxisExtend{"tDiffVtxBinsExtend", {1000, 0.f, 100000.f}, "Binning for the vertex t distance in ns, extended range"}; + ConfigurableAxis tDiffVtxAxisExtendSigned{"tDiffVtxBinsExtendSigned", {1000, -100000.f, 100000.f}, "Binning for the vertex t distance in ns, extended range, signed"}; + + ConfigurableAxis nVtxAxis{"nVtxBins", {11, -0.5, 10.5}, "Binning for the number of reconstructed vertices per BC"}; + ConfigurableAxis nVtxTwoAxis{"nVtxTwoBins", {2, 0.5, 2.5}, "Binning for the number of reconstructed vertices vs. time"}; + ConfigurableAxis nContribAxis{"nContribBins", {1000, 0, 5000}, "Binning for number of contributors to PV"}; + ConfigurableAxis nContribDiffAxis{"nContribDiffBins", {1000, -5000, 5000}, "Binning for the difference in number of contributors to PV"}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + histos.add("nVtxHistogram", ";#it{N}_{vtx}^{rec};Entries", HistType::kTH1F, {nVtxAxis}); + + histos.add("xVtxHistogram", ";#it{x}_{vtx} (cm);Entries", HistType::kTH1F, {xVtxAxis}); + histos.add("yVtxHistogram", ";#it{y}_{vtx} (cm);Entries", HistType::kTH1F, {xVtxAxis}); + histos.add("zVtxHistogram", ";#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zVtxAxis}); + histos.add("tVtxHistogram", ";#it{t}_{vtx} (ns);Entries", HistType::kTH1F, {tVtxAxis}); + + histos.add("xDistVtxHistogram", ";#Delta#it{x}_{vtx} (cm);Entries", HistType::kTH1F, {xDiffVtxAxis}); + histos.add("yDistVtxHistogram", ";#Delta#it{y}_{vtx} (cm);Entries", HistType::kTH1F, {xDiffVtxAxis}); + histos.add("xyDistVtxHistogram", ";#Delta#it{xy}_{vtx} (cm);Entries", HistType::kTH1F, {xyDiffVtxAxis}); + histos.add("zDistVtxHistogram", ";#Delta#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zDiffVtxAxis}); + histos.add("tDistVtxHistogram", ";#Delta#it{t}_{vtx} (ns);Entries", HistType::kTH1F, {tDiffVtxAxis}); + + histos.add("xTwoVtxHistogram", ";#it{x}_{vtx}^{1} (cm);#it{x}_{vtx}^{2} (cm)", HistType::kTH2F, {xVtxAxis, xVtxAxis}); + histos.add("yTwoVtxHistogram", ";#it{y}_{vtx}^{1} (cm);#it{y}_{vtx}^{2} (cm)", HistType::kTH2F, {xVtxAxis, xVtxAxis}); + histos.add("zTwoVtxHistogram", ";#it{z}_{vtx}^{1} (cm);#it{z}_{vtx}^{2} (cm)", HistType::kTH2F, {zVtxAxis, zVtxAxis}); + histos.add("tTwoVtxHistogram", ";#it{t}_{vtx}^{1} (ns);#it{t}_{vtx}^{2} (ns)", HistType::kTH2F, {tVtxAxis, tVtxAxis}); + + histos.add("nVtxTimeSeriesHistogram", ";#it{N}_{vtx}^{rec};Entries", HistType::kTH1F, {nVtxTwoAxis}); + histos.add("zDistVtxTimeSeriesHistogram", ";#Delta#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zDiffVtxAxis2}); + histos.add("tDistVtxTimeSeriesHistogram", ";#Delta#it{t}_{vtx} (ns);Entries", HistType::kTH1F, {tDiffVtxAxisExtend}); + histos.add("tCollTwoVtxTimeSeriesHistogram", ";#Delta#it{t}_{coll}^{1} (ns);#Delta#it{t}_{coll}^{2} (ns)", HistType::kTH2F, {tVtxAxis, tVtxAxis}); + histos.add("zDistVsTDistVtxTimeSeriesHistogram", ";#Delta#it{t}_{vtx} (ns);#Delta#it{z}_{vtx} (cm)", HistType::kTH2F, {tDiffVtxAxisExtend, zDiffVtxAxis2}); + histos.add("nContribTwoVtxTimeSeriesHistogram", ";#it{N}_{contrib}^{1};#it{N}_{contrib}^{2}", HistType::kTH2F, {nContribAxis, nContribAxis}); + histos.add("nContribVsTDistTimeSeriesHistogram", ";#Delta#it{t}_{vtx} (ns);#Delta#it{N}_{contrib}", HistType::kTH2F, {tDiffVtxAxisExtendSigned, nContribDiffAxis}); + } + + std::deque colls; + + void process(aod::BC const& bc, aod::Collisions const& collisions) + { + auto collSize{collisions.size()}; + std::vector collPosX; + std::vector collPosY; + std::vector collPosZ; + std::vector collPosT; + std::vector collCovXX; + std::vector collCovXY; + std::vector collCovYY; + std::vector collCovZZ; + std::vector collResT; + std::vector collContribs; + + for (auto& collision : collisions) { + auto posX{collision.posX()}; + auto posY{collision.posY()}; + auto posZ{collision.posZ()}; + auto posT{collision.collisionTime()}; + + collPosX.push_back(posX); + collPosY.push_back(posY); + collPosZ.push_back(posZ); + collPosT.push_back(posT); + collCovXX.push_back(collision.covXX()); + collCovXY.push_back(collision.covXY()); + collCovYY.push_back(collision.covYY()); + collCovZZ.push_back(collision.covZZ()); + collResT.push_back(collision.collisionTimeRes()); + collContribs.push_back(collision.numContrib()); + + histos.fill(HIST("xVtxHistogram"), posX); + histos.fill(HIST("yVtxHistogram"), posY); + histos.fill(HIST("zVtxHistogram"), posZ); + histos.fill(HIST("tVtxHistogram"), posT); + + colls.emplace_back(bc, collision); + } + + if (collSize == 2) { + histos.fill(HIST("xDistVtxHistogram"), collPosX[0] - collPosX[1]); + histos.fill(HIST("yDistVtxHistogram"), collPosY[0] - collPosY[1]); + histos.fill(HIST("xyDistVtxHistogram"), std::hypot(collPosX[0] - collPosX[1], collPosY[0] - collPosY[1])); + histos.fill(HIST("zDistVtxHistogram"), collPosZ[0] - collPosZ[1]); + histos.fill(HIST("tDistVtxHistogram"), collPosT[0] - collPosT[1]); + + histos.fill(HIST("xTwoVtxHistogram"), collPosX[0], collPosX[1]); + histos.fill(HIST("yTwoVtxHistogram"), collPosY[0], collPosY[1]); + histos.fill(HIST("zTwoVtxHistogram"), collPosZ[0], collPosZ[1]); + histos.fill(HIST("tTwoVtxHistogram"), collPosT[0], collPosT[1]); + } + + if (colls.size() > nCollMax) { + auto delta = colls.size() - nCollMax; + for (uint64_t iC{0}; iC < delta; ++iC) { + histos.fill(HIST("nVtxTimeSeriesHistogram"), 1); + colls.pop_front(); + } + } + + auto compareCollisions = [&](BCcoll other) { + auto coll1 = std::get(colls.front()); + auto coll2 = std::get(other); + double testZ = std::abs(coll1.posZ() - coll2.posZ()) / std::sqrt(coll1.covZZ() + coll2.covZZ()); + double distR = std::hypot(coll1.posX() - coll2.posX(), coll1.posY() - coll2.posY()); + double drdxCol = (coll1.posX() - coll2.posX()) / distR; + double drdxOther = -(coll1.posX() - coll2.posX()) / distR; + double drdyCol = (coll1.posY() - coll2.posY()) / distR; + double drdyOther = -(coll1.posY() - coll2.posY()) / distR; + double covR = std::pow(drdxCol, 2) * coll1.covXX() + std::pow(drdxOther, 2) * coll2.covXX() + std::pow(drdyCol, 2) * coll1.covYY() + std::pow(drdxOther, 2) * coll2.covYY() + 2 * drdxCol * drdyCol * coll1.covXY() + 2 * drdxOther * drdyOther * coll2.covXY(); + double testR = distR / std::sqrt(covR); + double deltaT = deltaTimeColl(colls.front(), other); + double testT = std::abs(deltaT) / std::sqrt(std::pow(coll1.collisionTimeRes(), 2) + std::pow(coll2.collisionTimeRes(), 2)); + return (testT < nSigmaT && testZ < nSigmaZ && testR < nSigmaR && std::abs(deltaT) < maxTime); + }; + + if (colls.size() > 1) { + auto id = std::find_if(colls.begin() + 1, colls.end(), compareCollisions); + if (id != colls.end()) { + auto coll1 = std::get(colls.front()); + auto coll2 = std::get(*id); + double deltaT = deltaTimeColl(colls.front(), *id); + histos.fill(HIST("zDistVtxTimeSeriesHistogram"), coll2.posZ() - coll1.posZ()); + histos.fill(HIST("tDistVtxTimeSeriesHistogram"), std::abs(deltaT)); + histos.fill(HIST("tCollTwoVtxTimeSeriesHistogram"), coll1.collisionTime(), coll2.collisionTime()); + histos.fill(HIST("zDistVsTDistVtxTimeSeriesHistogram"), std::abs(deltaT), coll2.posZ() - coll1.posZ()); + histos.fill(HIST("nContribTwoVtxTimeSeriesHistogram"), coll1.numContrib(), coll2.numContrib()); + histos.fill(HIST("nContribVsTDistTimeSeriesHistogram"), -deltaT, coll2.numContrib() - coll1.numContrib()); + histos.fill(HIST("nVtxTimeSeriesHistogram"), 2); + colls.erase(id); + colls.pop_front(); + } + } + + histos.fill(HIST("nVtxHistogram"), collSize); + if (collSize > storeTree) { + for (int i{0}; i < collSize; ++i) { + vtxQAtable(bc.globalBC(), collPosX[i], collPosY[i], collPosZ[i], collCovXX[i], collCovXY[i], collCovYY[i], collCovZZ[i], collPosT[i], collResT[i], collContribs[i]); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/cascadecorrelations.cxx b/PWGLF/Tasks/cascadecorrelations.cxx new file mode 100644 index 00000000000..df8eec16995 --- /dev/null +++ b/PWGLF/Tasks/cascadecorrelations.cxx @@ -0,0 +1,370 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// 2-particle correlations for cascades +// ============================= +// +// Author: Rik Spijkers (rik.spijkers@cern.ch) +// + +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::constants::math; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +// use parameters + cov mat non-propagated, aux info + (extension propagated) +using FullTracksExt = soa::Join; +using FullTracksExtIU = soa::Join; +using FullTracksExtWithPID = soa::Join; +using FullTracksExtIUWithPID = soa::Join; + +// Add a column to the cascdataext table: IsSelected. +// 0 = not selected, 1 = Xi, 2 = Omega, 3 = both +namespace o2::aod +{ +namespace cascadeflags +{ +DECLARE_SOA_COLUMN(IsSelected, isSelected, int); //~! +} // namespace cascadeflags +DECLARE_SOA_TABLE(CascadeFlags, "AOD", "CASCADEFLAGS", //! + cascadeflags::IsSelected); +using CascDataExtSelected = soa::Join; +} // namespace o2::aod + +struct cascadeSelector { + Produces cascflags; + + // Configurables + Configurable tpcNsigmaBachelor{"tpcNsigmaBachelor", 3, "TPC NSigma bachelor"}; + Configurable tpcNsigmaProton{"tpcNsigmaProton", 3, "TPC NSigma proton <- lambda"}; + Configurable tpcNsigmaPion{"tpcNsigmaPion", 3, "TPC NSigma pion <- lambda"}; + Configurable minTPCCrossedRows{"minTPCCrossedRows", 80, "min N TPC crossed rows"}; // TODO: finetune! 80 > 159/2, so no split tracks? + Configurable minITSClusters{"minITSClusters", 4, "minimum number of ITS clusters"}; + // Configurable doTPConly{"doTPConly", false, "use TPC-only tracks"}; // TODO: maybe do this for high pT only? as cascade decays after IB + + // Selection criteria - compatible with core wagon autodetect - copied from cascadeanalysis.cxx + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + Configurable v0setting_cospa{"v0setting_cospa", 0.95, "v0setting_cospa"}; + Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 1.0, "v0setting_dcav0dau"}; + Configurable v0setting_dcapostopv{"v0setting_dcapostopv", 0.1, "v0setting_dcapostopv"}; + Configurable v0setting_dcanegtopv{"v0setting_dcanegtopv", 0.1, "v0setting_dcanegtopv"}; + Configurable v0setting_radius{"v0setting_radius", 0.9, "v0setting_radius"}; + Configurable cascadesetting_cospa{"cascadesetting_cospa", 0.95, "cascadesetting_cospa"}; + Configurable cascadesetting_dcacascdau{"cascadesetting_dcacascdau", 1.0, "cascadesetting_dcacascdau"}; + Configurable cascadesetting_dcabachtopv{"cascadesetting_dcabachtopv", 0.1, "cascadesetting_dcabachtopv"}; + Configurable cascadesetting_cascradius{"cascadesetting_cascradius", 0.5, "cascadesetting_cascradius"}; + Configurable cascadesetting_v0masswindow{"cascadesetting_v0masswindow", 0.01, "cascadesetting_v0masswindow"}; + Configurable cascadesetting_mindcav0topv{"cascadesetting_mindcav0topv", 0.01, "cascadesetting_mindcav0topv"}; + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + void process(soa::Join::iterator const& collision, aod::CascDataExt const& Cascades, aod::V0sLinked const&, aod::V0Datas const&, FullTracksExtIUWithPID const&) + { + for (auto& casc : Cascades) { + auto v0 = casc.v0_as(); + if (!(v0.has_v0Data())) { + cascflags(0); + continue; // reject if no v0data + } + auto v0data = v0.v0Data(); + + // TODO: make QA histo with info on where cascades fail selections + + // Let's try to do some PID & track quality cuts + // these are the tracks: + auto bachTrack = casc.bachelor_as(); + auto posTrack = v0data.posTrack_as(); + auto negTrack = v0data.negTrack_as(); + + // TPC N crossed rows + if (posTrack.tpcNClsCrossedRows() < minTPCCrossedRows || negTrack.tpcNClsCrossedRows() < minTPCCrossedRows || bachTrack.tpcNClsCrossedRows() < minTPCCrossedRows) { + cascflags(0); + continue; + } + // ITS N clusters + if (posTrack.itsNCls() < minITSClusters || negTrack.itsNCls() < minITSClusters || bachTrack.itsNCls() < minITSClusters) { + cascflags(0); + continue; + } + + //// TOPO CUTS //// TODO: improve! + double pvx = collision.posX(); + double pvy = collision.posY(); + double pvz = collision.posZ(); + if (casc.v0radius() < v0setting_radius || + casc.cascradius() < cascadesetting_cascradius || + casc.v0cosPA(pvx, pvy, pvz) < v0setting_cospa || + casc.casccosPA(pvx, pvy, pvz) < cascadesetting_cospa || + casc.dcav0topv(pvx, pvy, pvz) < cascadesetting_mindcav0topv || + TMath::Abs(casc.mLambda() - 1.115683) > cascadesetting_v0masswindow) { + // It failed at least one topo selection + cascflags(0); + continue; + } + + // TODO: TOF (for pT > 2 GeV per track?) + + //// TPC //// + // Lambda check + if (casc.sign() < 0) { + // Proton check: + if (TMath::Abs(posTrack.tpcNSigmaPr()) > tpcNsigmaProton) { + cascflags(0); + continue; + } + // Pion check: + if (TMath::Abs(negTrack.tpcNSigmaPi()) > tpcNsigmaPion) { + cascflags(0); + continue; + } + } else { + // Proton check: + if (TMath::Abs(negTrack.tpcNSigmaPr()) > tpcNsigmaProton) { + cascflags(0); + continue; + } + // Pion check: + if (TMath::Abs(posTrack.tpcNSigmaPi()) > tpcNsigmaPion) { + cascflags(0); + continue; + } + } + // Bachelor check + if (TMath::Abs(bachTrack.tpcNSigmaPi()) < tpcNsigmaBachelor) { + if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) { + // consistent with both! + cascflags(3); + continue; + } + cascflags(1); + continue; + } else if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) { + cascflags(2); + continue; + } + // if we reach here, the bachelor was neither pion nor kaon + cascflags(0); + } // cascade loop + } // process +}; // struct + +struct cascadeCorrelations { + AxisSpec invMassAxis = {3000, 0.0f, 3.0f, "Inv. Mass (GeV/c^{2})"}; + AxisSpec deltaPhiAxis = {100, -PI / 2, 1.5 * PI, "#Delta#varphi"}; + AxisSpec deltaEtaAxis = {40, -2, 2, "#Delta#eta"}; + AxisSpec ptAxis = {200, 0, 15, "#it{p}_{T}"}; + AxisSpec selectionFlagAxis = {4, -0.5f, 3.5f, "Selection flag of casc candidate"}; + AxisSpec vertexAxis = {1000, -10.0f, 10.0f, "cm"}; + AxisSpec multiplicityAxis{100, 0, 100, "Multiplicity (MultFT0M?)"}; + + HistogramRegistry registry{ + "registry", + { + // inv mass + {"hMassXiMinus", "hMassXiMinus", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + {"hMassXiPlus", "hMassXiPlus", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + {"hMassOmegaMinus", "hMassOmegaMinus", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + {"hMassOmegaPlus", "hMassOmegaPlus", {HistType::kTH2F, {invMassAxis, ptAxis}}}, + + // basic selection variables + {"hV0Radius", "hV0Radius", {HistType::kTH1F, {{1000, 0.0f, 100.0f, "cm"}}}}, + {"hCascRadius", "hCascRadius", {HistType::kTH1F, {{1000, 0.0f, 100.0f, "cm"}}}}, + {"hV0CosPA", "hV0CosPA", {HistType::kTH1F, {{1000, 0.95f, 1.0f}}}}, + {"hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{1000, 0.95f, 1.0f}}}}, + {"hDCAPosToPV", "hDCAPosToPV", {HistType::kTH1F, {vertexAxis}}}, + {"hDCANegToPV", "hDCANegToPV", {HistType::kTH1F, {vertexAxis}}}, + {"hDCABachToPV", "hDCABachToPV", {HistType::kTH1F, {vertexAxis}}}, + {"hDCAV0ToPV", "hDCAV0ToPV", {HistType::kTH1F, {vertexAxis}}}, + {"hDCAV0Dau", "hDCAV0Dau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, + {"hDCACascDau", "hDCACascDau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, + {"hLambdaMass", "hLambdaMass", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "Inv. Mass (GeV/c^{2})"}}}}, + + {"hSelectionFlag", "hSelectionFlag", {HistType::kTH1I, {selectionFlagAxis}}}, + {"hAutoCorrelation", "hAutoCorrelation", {HistType::kTH1I, {{4, -0.5f, 3.5f, "Types of autocorrelation"}}}}, + {"hPhi", "hPhi", {HistType::kTH1F, {{100, 0, 2 * PI, "#varphi"}}}}, + {"hEta", "hEta", {HistType::kTH1F, {{100, -2, 2, "#eta"}}}}, + + // correlation histos + {"hDeltaPhiSS", "hDeltaPhiSS", {HistType::kTH1F, {deltaPhiAxis}}}, + {"hDeltaPhiOS", "hDeltaPhiOS", {HistType::kTH1F, {deltaPhiAxis}}}, + // THnSparses containing all relevant dimensions, to be extended with e.g. multiplicity + // TODO: maybe use a seperate table/tree for this? + {"hXiXiOS", "hXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + {"hXiXiSS", "hXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + {"hXiOmOS", "hXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + {"hXiOmSS", "hXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + {"hOmXiOS", "hOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + {"hOmXiSS", "hOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + {"hOmOmOS", "hOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + {"hOmOmSS", "hOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaEtaAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, selectionFlagAxis, selectionFlagAxis, vertexAxis, multiplicityAxis}}}, + }, + }; + + Filter Selector = aod::cascadeflags::isSelected > 0; + + void process(soa::Join::iterator const& collision, soa::Filtered const& Cascades, aod::V0sLinked const&, aod::V0Datas const&, FullTracksExtIU const&) + { + if (!collision.sel8()) { + return; + } + + // Some QA on the cascades + for (auto& casc : Cascades) { + + auto v0 = casc.v0_as(); + if (!(v0.has_v0Data())) { + continue; // reject if no v0data + } + + if (casc.isSelected() != 2) { // not exclusively an Omega --> consistent with Xi or both + if (casc.sign() < 0) { + registry.fill(HIST("hMassXiMinus"), casc.mXi(), casc.pt()); + } else { + registry.fill(HIST("hMassXiPlus"), casc.mXi(), casc.pt()); + } + } + if (casc.isSelected() >= 2) { // consistent with Omega or both + if (casc.sign() < 0) { + registry.fill(HIST("hMassOmegaMinus"), casc.mOmega(), casc.pt()); + } else { + registry.fill(HIST("hMassOmegaPlus"), casc.mOmega(), casc.pt()); + } + } + registry.fill(HIST("hV0Radius"), casc.v0radius()); + registry.fill(HIST("hCascRadius"), casc.cascradius()); + registry.fill(HIST("hV0CosPA"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hCascCosPA"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hDCAPosToPV"), casc.dcapostopv()); + registry.fill(HIST("hDCANegToPV"), casc.dcanegtopv()); + registry.fill(HIST("hDCABachToPV"), casc.dcabachtopv()); + registry.fill(HIST("hDCAV0ToPV"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hDCAV0Dau"), casc.dcaV0daughters()); + registry.fill(HIST("hDCACascDau"), casc.dcacascdaughters()); + registry.fill(HIST("hLambdaMass"), casc.mLambda()); + + registry.fill(HIST("hSelectionFlag"), casc.isSelected()); + registry.fill(HIST("hPhi"), casc.phi()); + registry.fill(HIST("hEta"), casc.eta()); + } // casc loop + + for (auto& [c0, c1] : combinations(Cascades, Cascades)) { // combinations automatically applies strictly upper in case of 2 identical tables + // Define the trigger as the particle with the highest pT. As we can't swap the cascade tables themselves, we swap the addresses and later dereference them + auto* triggerAddress = &c0; + auto* assocAddress = &c1; + if (assocAddress->pt() > triggerAddress->pt()) { + std::swap(triggerAddress, assocAddress); + } + auto trigger = *triggerAddress; + auto assoc = *assocAddress; + + auto lambdaTrigg = trigger.v0_as(); + auto lambdaAssoc = assoc.v0_as(); + if (!(lambdaTrigg.has_v0Data()) || !(lambdaAssoc.has_v0Data())) { + continue; // reject if no v0data in either of the lambda's + } + auto v0dataTrigg = lambdaTrigg.v0Data(); + auto v0dataAssoc = lambdaAssoc.v0Data(); + + // calculate angular correlations + double deta = trigger.eta() - assoc.eta(); + double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -0.5 * PI); + + double invMassXiTrigg = trigger.mXi(); + double invMassOmTrigg = trigger.mOmega(); + double invMassXiAssoc = assoc.mXi(); + double invMassOmAssoc = assoc.mOmega(); + + // Fill the correct histograms based on same-sign or opposite-sign + if (trigger.sign() * assoc.sign() < 0) { // opposite-sign + registry.fill(HIST("hDeltaPhiOS"), dphi); + registry.fill(HIST("hXiXiOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M()); + registry.fill(HIST("hXiOmOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M()); + registry.fill(HIST("hOmXiOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M()); + registry.fill(HIST("hOmOmOS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M()); + } else { // same-sign + // make sure to check for autocorrelations - only possible in same-sign correlations + if (v0dataTrigg.v0Id() == v0dataAssoc.v0Id()) { + // LOGF(info, "same v0 in SS correlation! %d %d", v0dataTrigg.v0Id(), v0dataAssoc.v0Id()); + registry.fill(HIST("hAutoCorrelation"), 0); + continue; + } + int bachIdTrigg = trigger.bachelorId(); + int bachIdAssoc = assoc.bachelorId(); + int posIdTrigg = v0dataTrigg.posTrackId(); + int negIdTrigg = v0dataTrigg.negTrackId(); + int posIdAssoc = v0dataAssoc.posTrackId(); + int negIdAssoc = v0dataAssoc.negTrackId(); + if (bachIdTrigg == bachIdAssoc) { + // LOGF(info, "same bachelor in SS correlation! %d %d", bachIdTrigg, bachIdAssoc); + registry.fill(HIST("hAutoCorrelation"), 1); + continue; + } + // check for same tracks in v0's of cascades + if (negIdTrigg == negIdAssoc || posIdTrigg == posIdAssoc) { + // LOGF(info, "cascades have a v0-track in common in SS correlation!"); + registry.fill(HIST("hAutoCorrelation"), 2); + continue; + } + if (trigger.sign() < 0) { // neg cascade + if (negIdTrigg == bachIdAssoc || negIdAssoc == bachIdTrigg) { + // LOGF(info, "bach of casc == v0-pion of other casc in neg SS correlation!"); + registry.fill(HIST("hAutoCorrelation"), 3); + continue; + } + } else { // pos cascade + if (posIdTrigg == bachIdAssoc || posIdAssoc == bachIdTrigg) { + // LOGF(info, "bach of casc == v0-pion of other casc in pos SS correlation!"); + registry.fill(HIST("hAutoCorrelation"), 3); + continue; + } + } + registry.fill(HIST("hDeltaPhiSS"), dphi); + registry.fill(HIST("hXiXiSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M()); + registry.fill(HIST("hXiOmSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M()); + registry.fill(HIST("hOmXiSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M()); + registry.fill(HIST("hOmOmSS"), dphi, deta, trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, trigger.isSelected(), assoc.isSelected(), collision.posZ(), collision.multFT0M()); + } + } // correlations + } // process +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/cascpostprocessing.cxx b/PWGLF/Tasks/cascpostprocessing.cxx index 03dee50593f..c89a299b15c 100644 --- a/PWGLF/Tasks/cascpostprocessing.cxx +++ b/PWGLF/Tasks/cascpostprocessing.cxx @@ -9,10 +9,12 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// -/// \brief post processing +/// \brief post processing for Cascade analysis /// \author Francesca Ercolessi (francesca.ercolessi@cern.ch) /// \modified by Chiara De Martin (chiara.de.martin@cern.ch) /// \since March 20, 2023 +/// \modified by Roman Nepeivoda (roman.nepeivoda@cern.ch) +/// \since June 1, 2023 #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" @@ -20,6 +22,8 @@ #include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" +#include "PWGLF/DataModel/cascqaanalysis.h" +#include "Framework/O2DatabasePDGPlugin.h" // constants const float ctauxiPDG = 4.91; // from PDG @@ -29,89 +33,6 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using DauTracks = soa::Join; - -namespace o2::aod -{ - -namespace mycascades -{ - -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -DECLARE_SOA_COLUMN(CollisionZ, zcoll, float); -DECLARE_SOA_COLUMN(MultFT0M, multFT0M, float); -DECLARE_SOA_COLUMN(MultFV0A, multFV0A, float); -DECLARE_SOA_COLUMN(Sign, sign, float); -DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_COLUMN(RapXi, rapxi, float); -DECLARE_SOA_COLUMN(RapOmega, rapomega, float); -DECLARE_SOA_COLUMN(Eta, eta, float); -DECLARE_SOA_COLUMN(MassXi, massxi, float); -DECLARE_SOA_COLUMN(MassOmega, massomega, float); -DECLARE_SOA_COLUMN(MassLambdaDau, masslambdadau, float); -DECLARE_SOA_COLUMN(CascRadius, cascradius, float); -DECLARE_SOA_COLUMN(V0Radius, v0radius, float); -DECLARE_SOA_COLUMN(CascCosPA, casccospa, float); -DECLARE_SOA_COLUMN(V0CosPA, v0cospa, float); -DECLARE_SOA_COLUMN(DCAPosToPV, dcapostopv, float); -DECLARE_SOA_COLUMN(DCANegToPV, dcanegtopv, float); -DECLARE_SOA_COLUMN(DCABachToPV, dcabachtopv, float); -DECLARE_SOA_COLUMN(DCACascDaughters, dcacascdaughters, float); -DECLARE_SOA_COLUMN(DCAV0Daughters, dcav0daughters, float); -DECLARE_SOA_COLUMN(DCAV0ToPV, dcav0topv, float); -DECLARE_SOA_COLUMN(PosEta, poseta, float); -DECLARE_SOA_COLUMN(NegEta, negeta, float); -DECLARE_SOA_COLUMN(BachEta, bacheta, float); -DECLARE_SOA_COLUMN(PosITSHits, positshits, float); -DECLARE_SOA_COLUMN(NegITSHits, negitshits, float); -DECLARE_SOA_COLUMN(BachITSHits, bachitshits, float); -DECLARE_SOA_COLUMN(CtauXi, ctauxi, float); -DECLARE_SOA_COLUMN(CtauOmega, ctauomega, float); -DECLARE_SOA_COLUMN(NTPCSigmaNegPr, ntpcsigmanegpr, float); -DECLARE_SOA_COLUMN(NTPCSigmaPosPr, ntpcsigmapospr, float); -DECLARE_SOA_COLUMN(NTPCSigmaNegPi, ntpcsigmanegpi, float); -DECLARE_SOA_COLUMN(NTPCSigmaPosPi, ntpcsigmapospi, float); -DECLARE_SOA_COLUMN(NTPCSigmaBachPi, ntpcsigmabachpi, float); -DECLARE_SOA_COLUMN(NTPCSigmaBachKa, ntpcsigmabachka, float); -DECLARE_SOA_COLUMN(NTOFSigmaNegPr, ntofsigmanegpr, float); -DECLARE_SOA_COLUMN(NTOFSigmaPosPr, ntofsigmapospr, float); -DECLARE_SOA_COLUMN(NTOFSigmaNegPi, ntofsigmanegpi, float); -DECLARE_SOA_COLUMN(NTOFSigmaPosPi, ntofsigmapospi, float); -DECLARE_SOA_COLUMN(NTOFSigmaBachPi, ntofsigmabachpi, float); -DECLARE_SOA_COLUMN(NTOFSigmaBachKa, ntofsigmabachka, float); -DECLARE_SOA_COLUMN(PosNTPCClusters, posntpcscls, float); -DECLARE_SOA_COLUMN(NegNTPCClusters, negntpcscls, float); -DECLARE_SOA_COLUMN(BachNTPCClusters, bachntpcscls, float); -DECLARE_SOA_COLUMN(PosHasTOF, poshastof, float); -DECLARE_SOA_COLUMN(NegHasTOF, neghastof, float); -DECLARE_SOA_COLUMN(BachHasTOF, bachhastof, float); -DECLARE_SOA_COLUMN(PosPt, pospt, float); -DECLARE_SOA_COLUMN(NegPt, negpt, float); -DECLARE_SOA_COLUMN(BachPt, bachpt, float); -DECLARE_SOA_COLUMN(McPdgCode, mcPdgCode, float); // -1 unknown -DECLARE_SOA_COLUMN(IsPrimary, isPrimary, float); // -1 unknown, 0 not primary, 1 primary -DECLARE_SOA_COLUMN(BachBaryonCosPA, bachBaryonCosPA, float); //! avoid bach-baryon correlated inv mass structure in analysis -DECLARE_SOA_COLUMN(BachBaryonDCAxyToPV, bachBaryonDCAxyToPV, float); //! avoid bach-baryon correlated inv mass structure in analysis - -} // namespace mycascades - -DECLARE_SOA_TABLE(MyCascades, "AOD", "MYCASCADES", o2::soa::Index<>, - mycascades::CollisionId, mycascades::CollisionZ, mycascades::MultFT0M, mycascades::MultFV0A, mycascades::Sign, mycascades::Pt, mycascades::RapXi, mycascades::RapOmega, mycascades::Eta, mycascades::MassXi, mycascades::MassOmega, mycascades::MassLambdaDau, mycascades::CascRadius, mycascades::V0Radius, - mycascades::CascCosPA, mycascades::V0CosPA, mycascades::DCAPosToPV, mycascades::DCANegToPV, - mycascades::DCABachToPV, mycascades::DCACascDaughters, mycascades::DCAV0Daughters, mycascades::DCAV0ToPV, mycascades::PosEta, mycascades::NegEta, - mycascades::BachEta, mycascades::PosITSHits, mycascades::NegITSHits, mycascades::BachITSHits, - mycascades::CtauXi, mycascades::CtauOmega, - mycascades::NTPCSigmaNegPr, mycascades::NTPCSigmaPosPr, mycascades::NTPCSigmaNegPi, mycascades::NTPCSigmaPosPi, mycascades::NTPCSigmaBachPi, mycascades::NTPCSigmaBachKa, - mycascades::NTOFSigmaNegPr, mycascades::NTOFSigmaPosPr, mycascades::NTOFSigmaNegPi, - mycascades::NTOFSigmaPosPi, mycascades::NTOFSigmaBachPi, mycascades::NTOFSigmaBachKa, - mycascades::PosNTPCClusters, mycascades::NegNTPCClusters, mycascades::BachNTPCClusters, - mycascades::PosHasTOF, mycascades::NegHasTOF, mycascades::BachHasTOF, - mycascades::PosPt, mycascades::NegPt, mycascades::BachPt, - mycascades::McPdgCode, mycascades::IsPrimary, - cascdata::BachBaryonCosPA, cascdata::BachBaryonDCAxyToPV); - -} // namespace o2::aod - struct cascpostprocessing { // Xi or Omega Configurable isXi{"isXi", 1, "Apply cuts for Xi identification"}; @@ -125,8 +46,10 @@ struct cascpostprocessing { Configurable masswintpc{"masswintpc", 0.075, "Mass window limit for Nsigma TPC daughters"}; Configurable rejcomp{"rejcomp", 0.008, "Competing Cascade rejection"}; Configurable lambdamasswin{"lambdamasswin", 0.008, "V0 Mass window limit"}; - Configurable v0radius{"v0radius", 1.2, "V0 Radius"}; - Configurable cascradius{"cascradius", 0.6, "Casc Radius"}; + Configurable v0radiusMin{"v0radiusMin", 1.2, "V0 Minimum Radius"}; + Configurable v0radiusMax{"v0radiusMax", 1000, "V0 Maximum Radius"}; + Configurable cascradiusMin{"cascradiusMin", 0.6, "Casc Minimum Radius"}; + Configurable cascradiusMax{"cascradiusMax", 1000, "Casc Maximum Radius"}; Configurable casccospa{"casccospa", 0.97, "Casc CosPA"}; Configurable v0cospa{"v0cospa", 0.97, "V0 CosPA"}; Configurable dcanegtopv{"dcanegtopv", 0.03, "DCA Neg To PV"}; @@ -143,15 +66,22 @@ struct cascpostprocessing { Configurable nsigmatofPi{"nsigmatofPi", 6, "N sigma TOF Pion"}; Configurable nsigmatofPr{"nsigmatofPr", 6, "N sigma TOF Proton"}; Configurable nsigmatofKa{"nsigmatofKa", 6, "N sigma TOF Kaon"}; + Configurable mintpccrrows{"mintpccrrows", 50, "min N TPC crossed rows"}; + Configurable dooobrej{"dooobrej", 0, "OOB rejection: 0 no selection, 1 = ITS||TOF, 2 = TOF only for pT > ptthrtof"}; Configurable isSelectBachBaryon{"isSelectBachBaryon", 0, "Bachelor-baryon cascade selection"}; Configurable bachBaryonCosPA{"bachBaryonCosPA", 0.9999, "Bachelor baryon CosPA"}; Configurable bachBaryonDCAxyToPV{"bachBaryonDCAxyToPV", 0.05, "DCA bachelor baryon to PV"}; - Configurable isFT0MforMC{"isFT0MforMC", 0, "Fill with FT0M information or 0s"}; + Configurable isMC{"isMC", 0, "0 - data, 1 - MC"}; + + Configurable evSelFlag{"evSelFlag", 2, "1 - INEL; 2 - INEL>0; 3 - INEL>1"}; HistogramRegistry registry{"registryts"}; + // Necessary for particle charges + Service pdgDB; + void init(InitContext const&) { @@ -161,22 +91,31 @@ struct cascpostprocessing { if (!isXi) massAxis = omegamassAxis; AxisSpec ptAxis = {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec pTPCAxis = {100, 0.0f, 10.0f, "#it{p} TPC (GeV/#it{c})"}; - AxisSpec etaAxis = {200, -2.0f, 2.0f, "#eta"}; - AxisSpec centFT0MAxis = {100, 0.0f, 100.0f, "FT0M (%)"}; - AxisSpec centFV0AAxis = {100, 0.0f, 100.0f, "FV0A (%)"}; + AxisSpec ptAxisTopoVar = {50, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisPID = {50, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis etaAxis{"etaAxis", {40, -2.0f, 2.0f}, "#eta"}; + + ConfigurableAxis centFT0MAxis{"FT0M", + {VARIABLE_WIDTH, 0., 0.01, 0.05, 0.1, 0.5, 1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 101, 105.5}, + "FT0M (%)"}; + ConfigurableAxis centFV0AAxis{"FV0A", + {VARIABLE_WIDTH, 0., 0.01, 0.05, 0.1, 0.5, 1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 101, 105.5}, + "FV0A (%)"}; + + ConfigurableAxis nChargedFT0MGenAxis{"nChargedFT0MGenAxis", {300, 0, 300}, "N_{FT0M, gen.}"}; + AxisSpec rapidityAxis = {200, -2.0f, 2.0f, "y"}; AxisSpec phiAxis = {100, -TMath::Pi() / 2, 3. * TMath::Pi() / 2, "#varphi"}; - TString CutLabel[22] = {"All", "MassWin", "y", "EtaDau", "DCADauToPV", "CascCosPA", "V0CosPA", "DCACascDau", "DCAV0Dau", "rCasc", "rV0", "DCAV0ToPV", "LambdaMass", "TPCPr", "TPCPi", "TOFPr", "TOFPi", "TPCBach", "TOFBach", "ctau", "CompDecayMass", "Bach-baryon"}; - TString CutLabelSummary[25] = {"MassWin", "y", "EtaDau", "dcapostopv", "dcanegtopv", "dcabachtopv", "CascCosPA", "V0CosPA", "DCACascDau", "DCAV0Dau", "rCasc", "rV0", "DCAV0ToPV", "LambdaMass", "TPCPr", "TPCPi", "TOFPr", "TOFPi", "TPCBach", "TOFBach", "proplifetime", "rejcomp", "ptthrtof", "bachBaryonCosPA", "bachBaryonDCAxyToPV"}; + TString CutLabel[26] = {"All", "MassWin", "y", "EtaDau", "DCADauToPV", "CascCosPA", "V0CosPA", "DCACascDau", "DCAV0Dau", "rCasc", "rCascMax", "rV0", "rV0Max", "DCAV0ToPV", "LambdaMass", "TPCPr", "TPCPi", "TOFPr", "TOFPi", "TPCBach", "TOFBach", "ctau", "CompDecayMass", "Bach-baryon", "NTPCrows", "OOBRej"}; + TString CutLabelSummary[29] = {"MassWin", "y", "EtaDau", "dcapostopv", "dcanegtopv", "dcabachtopv", "CascCosPA", "V0CosPA", "DCACascDau", "DCAV0Dau", "rCasc", "rV0", "DCAV0ToPV", "LambdaMass", "TPCPr", "TPCPi", "TOFPr", "TOFPi", "TPCBach", "TOFBach", "proplifetime", "rejcomp", "ptthrtof", "bachBaryonCosPA", "bachBaryonDCAxyToPV", "NTPCrows", "OOBRej", "rCascMax", "rV0Max"}; - registry.add("hCandidate", "hCandidate", HistType::kTH1F, {{22, -0.5, 21.5}}); + registry.add("hCandidate", "hCandidate", HistType::kTH1F, {{26, -0.5, 25.5}}); for (Int_t n = 1; n <= registry.get(HIST("hCandidate"))->GetNbinsX(); n++) { registry.get(HIST("hCandidate"))->GetXaxis()->SetBinLabel(n, CutLabel[n - 1]); } - registry.add("CascadeSelectionSummary", "CascadeSelectionSummary", HistType::kTH1F, {{25, -0.5, 24.5}}); + registry.add("CascadeSelectionSummary", "CascadeSelectionSummary", HistType::kTH1F, {{29, -0.5, 28.5}}); for (Int_t n = 1; n <= registry.get(HIST("CascadeSelectionSummary"))->GetNbinsX(); n++) { registry.get(HIST("CascadeSelectionSummary"))->GetXaxis()->SetBinLabel(n, CutLabelSummary[n - 1]); } @@ -190,8 +129,8 @@ struct cascpostprocessing { registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(8, v0cospa); registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(9, dcacascdau); registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(10, dcav0dau); - registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(11, cascradius); - registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(12, v0radius); + registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(11, cascradiusMin); + registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(12, v0radiusMin); registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(13, dcav0topv); registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(14, lambdamasswin); registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(15, nsigmatpcPr); @@ -211,12 +150,16 @@ struct cascpostprocessing { registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(24, bachBaryonCosPA); registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(25, bachBaryonDCAxyToPV); } + registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(26, mintpccrrows); + registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(27, dooobrej); + registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(28, cascradiusMax); + registry.get(HIST("CascadeSelectionSummary"))->SetBinContent(29, v0radiusMax); registry.add("hPt", "hPt", {HistType::kTH1F, {ptAxis}}); registry.add("hCascMinusInvMassvsPt", "hCascMinusInvMassvsPt", HistType::kTH2F, {ptAxis, massAxis}); registry.add("hCascPlusInvMassvsPt", "hCascPlusInvMassvsPt", HistType::kTH2F, {ptAxis, massAxis}); - registry.add("hCascMinusInvMassvsPt_FT0M", "hCascMinusInvMassvsPt_FT0M", HistType::kTH3F, {centFT0MAxis, ptAxis, massAxis}); - registry.add("hCascPlusInvMassvsPt_FT0M", "hCascPlusInvMassvsPt_FT0M", HistType::kTH3F, {centFT0MAxis, ptAxis, massAxis}); + registry.add("hCascMinusInvMassvsPt_FT0M", "hCascMinusInvMassvsPt_FT0M", HistType::kTH3F, {isMC ? nChargedFT0MGenAxis : centFT0MAxis, ptAxis, massAxis}); + registry.add("hCascPlusInvMassvsPt_FT0M", "hCascPlusInvMassvsPt_FT0M", HistType::kTH3F, {isMC ? nChargedFT0MGenAxis : centFT0MAxis, ptAxis, massAxis}); registry.add("hCascMinusInvMassvsPt_FV0A", "hCascMinusInvMassvsPt_FV0A", HistType::kTH3F, {centFV0AAxis, ptAxis, massAxis}); registry.add("hCascPlusInvMassvsPt_FV0A", "hCascPlusInvMassvsPt_FV0A", HistType::kTH3F, {centFV0AAxis, ptAxis, massAxis}); registry.add("hXiMinusInvMassvsPt_BefSels", "hXiMinusInvMassvsPt_BefSels", HistType::kTH2F, {ptAxis, ximassAxis}); @@ -225,20 +168,20 @@ struct cascpostprocessing { registry.add("hOmegaPlusInvMassvsPt_BefSels", "hOmegaPlusInvMassvsPt_BefSels", {HistType::kTH2F, {ptAxis, omegamassAxis}}); // topo - registry.add("hDCANegToPV", "hDCANegToPV", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}); - registry.add("hDCAPosToPV", "hDCAPosToPV", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}); - registry.add("hDCABachToPV", "hDCABachToPV", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}); - registry.add("hCascCosPA", "hCascCosPA", {HistType::kTH1F, {{100, 0.9f, 1.0f}}}); - registry.add("hV0CosPA", "hV0CosPA", {HistType::kTH1F, {{100, 0.9f, 1.0f}}}); - registry.add("hCascRadius", "hCascRadius", {HistType::kTH1D, {{500, 0.0f, 50.0f}}}); - registry.add("hV0Radius", "hV0Radius", {HistType::kTH1D, {{500, 0.0f, 50.0f}}}); - registry.add("hDCACascDaughters", "hDCACascDaughters", {HistType::kTH1F, {{55, 0.0f, 2.20f}}}); - registry.add("hDCAV0Daughters", "hDCAV0Daughters", {HistType::kTH1F, {{55, 0.0f, 2.20f}}}); - registry.add("hDCAV0ToPV", "hDCAV0ToPV", {HistType::kTH1F, {{55, 0.0f, 2.20f}}}); - registry.add("hMassLambdaDau", "hMassLambdaDau", {HistType::kTH1F, {{60, 1.1f, 1.13f}}}); - - registry.add("hBachBaryonCosPA", "hBachBaryonCosPA", {HistType::kTH1F, {{100, 0.0f, 1.0f}}}); - registry.add("hBachBaryonDCAxyToPV", "hBachBaryonDCAxyToPV", {HistType::kTH1F, {{300, -3.0f, 3.0f}}}); + registry.add("hDCANegToPV", "hDCANegToPV", {HistType::kTH2F, {ptAxisTopoVar, {200, -1.0f, 1.0f}}}); + registry.add("hDCAPosToPV", "hDCAPosToPV", {HistType::kTH2F, {ptAxisTopoVar, {200, -1.0f, 1.0f}}}); + registry.add("hDCABachToPV", "hDCABachToPV", {HistType::kTH2F, {ptAxisTopoVar, {200, -1.0f, 1.0f}}}); + registry.add("hCascCosPA", "hCascCosPA", {HistType::kTH2F, {ptAxisTopoVar, {100, 0.9f, 1.0f}}}); + registry.add("hV0CosPA", "hV0CosPA", {HistType::kTH2F, {ptAxisTopoVar, {100, 0.9f, 1.0f}}}); + registry.add("hCascRadius", "hCascRadius", {HistType::kTH2D, {ptAxisTopoVar, {500, 0.0f, 50.0f}}}); + registry.add("hV0Radius", "hV0Radius", {HistType::kTH2D, {ptAxisTopoVar, {500, 0.0f, 50.0f}}}); + registry.add("hDCACascDaughters", "hDCACascDaughters", {HistType::kTH2F, {ptAxisTopoVar, {55, 0.0f, 2.20f}}}); + registry.add("hDCAV0Daughters", "hDCAV0Daughters", {HistType::kTH2F, {ptAxisTopoVar, {55, 0.0f, 2.20f}}}); + registry.add("hDCAV0ToPV", "hDCAV0ToPV", {HistType::kTH2F, {ptAxisTopoVar, {55, 0.0f, 2.20f}}}); + registry.add("hMassLambdaDau", "hMassLambdaDau", {HistType::kTH2F, {ptAxis, {60, 1.1f, 1.13f}}}); + + registry.add("hBachBaryonCosPA", "hBachBaryonCosPA", {HistType::kTH2F, {ptAxisTopoVar, {100, 0.0f, 1.0f}}}); + registry.add("hBachBaryonDCAxyToPV", "hBachBaryonDCAxyToPV", {HistType::kTH2F, {ptAxisTopoVar, {300, -3.0f, 3.0f}}}); // kine registry.add("hEtaMinus", "hEtaMinus", {HistType::kTH2F, {ptAxis, etaAxis}}); @@ -253,12 +196,12 @@ struct cascpostprocessing { registry.add("hCtauPlus", "hCtauPlus", {HistType::kTH1F, {{100, 0.0f, 40.0f}}}); // daughter tracks - registry.add("hTPCNSigmaPosPi", "hTPCNSigmaPosPi", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); - registry.add("hTPCNSigmaNegPi", "hTPCNSigmaNegPi", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); - registry.add("hTPCNSigmaPosPr", "hTPCNSigmaPosPr", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); - registry.add("hTPCNSigmaNegPr", "hTPCNSigmaNegPr", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); - registry.add("hTPCNSigmaBachPi", "hTPCNSigmaBachPi", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); - registry.add("hTPCNSigmaBachKa", "hTPCNSigmaBachKa", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); + registry.add("hTPCNSigmaPosPi", "hTPCNSigmaPosPi", {HistType::kTH2F, {ptAxisPID, {120, -6.0f, 6.0f}}}); + registry.add("hTPCNSigmaNegPi", "hTPCNSigmaNegPi", {HistType::kTH2F, {ptAxisPID, {120, -6.0f, 6.0f}}}); + registry.add("hTPCNSigmaPosPr", "hTPCNSigmaPosPr", {HistType::kTH2F, {ptAxisPID, {120, -6.0f, 6.0f}}}); + registry.add("hTPCNSigmaNegPr", "hTPCNSigmaNegPr", {HistType::kTH2F, {ptAxisPID, {120, -6.0f, 6.0f}}}); + registry.add("hTPCNSigmaBachPi", "hTPCNSigmaBachPi", {HistType::kTH2F, {ptAxisPID, {120, -6.0f, 6.0f}}}); + registry.add("hTPCNSigmaBachKa", "hTPCNSigmaBachKa", {HistType::kTH2F, {ptAxisPID, {120, -6.0f, 6.0f}}}); registry.add("hTOFNSigmaPosPi", "hTOFNSigmaPosPi", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); registry.add("hTOFNSigmaNegPi", "hTOFNSigmaNegPi", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); registry.add("hTOFNSigmaPosPr", "hTOFNSigmaPosPr", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}); @@ -270,11 +213,21 @@ struct cascpostprocessing { registry.add("hCascMinusEtaBach", "hCascMinusEtaBach", {HistType::kTH1F, {{100, -1.0f, 1.0f}}}); // Info for eff x acc from MC - registry.add("hPtCascPlusTrueRec", "hPtCascPlusTrueRec", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); - registry.add("hPtCascMinusTrueRec", "hPtCascMinusTrueRec", {HistType::kTH3F, {ptAxis, rapidityAxis, centFT0MAxis}}); + registry.add("hPtCascPlusTrueRec", "hPtCascPlusTrueRec", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtCascMinusTrueRec", "hPtCascMinusTrueRec", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + if (isMC) { + registry.add("hPtXiPlusTrue", "hPtXiPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtXiMinusTrue", "hPtXiMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtOmegaPlusTrue", "hPtOmegaPlusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtOmegaMinusTrue", "hPtOmegaMinusTrue", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtXiPlusTrueAssocWithSelColl", "hPtXiPlusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtXiMinusTrueAssocWithSelColl", "hPtXiMinusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtOmegaPlusTrueAssocWithSelColl", "hPtOmegaPlusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + registry.add("hPtOmegaMinusTrueAssocWithSelColl", "hPtOmegaMinusTrueAssocWithSelColl", {HistType::kTH3F, {ptAxis, rapidityAxis, nChargedFT0MGenAxis}}); + } } - void process(aod::MyCascades const& mycascades) + void processRec(aod::MyCascades const& mycascades) { float invmass = 0; float ctau = 0; @@ -285,6 +238,27 @@ struct cascpostprocessing { for (auto& candidate : mycascades) { + switch (evSelFlag) { + case 1: { + if (!candidate.isINEL()) + continue; + break; + } + case 2: { + if (!candidate.isINELgt0()) + continue; + break; + } + case 3: { + if (!candidate.isINELgt1()) + continue; + break; + } + default: + LOGF(fatal, "incorrect evSelFlag in cascpostprocessing task"); + break; + } + counter = -1; registry.fill(HIST("hCandidate"), ++counter); @@ -299,14 +273,14 @@ struct cascpostprocessing { } if (isXi) { - if (TMath::Abs(candidate.massxi() - RecoDecay::getMassPDG(3312)) > masswin) + if (TMath::Abs(candidate.massxi() - pdgDB->Mass(3312)) > masswin) continue; registry.fill(HIST("hCandidate"), ++counter); if (TMath::Abs(candidate.rapxi()) > rap) continue; registry.fill(HIST("hCandidate"), ++counter); } else { - if (TMath::Abs(candidate.massomega() - RecoDecay::getMassPDG(3334)) > masswin) + if (TMath::Abs(candidate.massomega() - pdgDB->Mass(3334)) > masswin) continue; registry.fill(HIST("hCandidate"), ++counter); if (TMath::Abs(candidate.rapomega()) > rap) @@ -333,16 +307,22 @@ struct cascpostprocessing { if (candidate.dcav0daughters() > dcav0dau) continue; registry.fill(HIST("hCandidate"), ++counter); - if (candidate.cascradius() < cascradius) + if (candidate.cascradius() < cascradiusMin) + continue; + registry.fill(HIST("hCandidate"), ++counter); + if (candidate.cascradius() > cascradiusMax) + continue; + registry.fill(HIST("hCandidate"), ++counter); + if (candidate.v0radius() < v0radiusMin) continue; registry.fill(HIST("hCandidate"), ++counter); - if (candidate.v0radius() < v0radius) + if (candidate.v0radius() > v0radiusMax) continue; registry.fill(HIST("hCandidate"), ++counter); if (TMath::Abs(candidate.dcav0topv()) < dcav0topv) continue; registry.fill(HIST("hCandidate"), ++counter); - if (TMath::Abs(candidate.masslambdadau() - RecoDecay::getMassPDG(3122)) > lambdamasswin) + if (TMath::Abs(candidate.masslambdadau() - pdgDB->Mass(3122)) > lambdamasswin) continue; registry.fill(HIST("hCandidate"), ++counter); if (candidate.sign() < 0) { @@ -390,7 +370,7 @@ struct cascpostprocessing { if (candidate.ctauxi() > proplifetime * ctauxiPDG) continue; registry.fill(HIST("hCandidate"), ++counter); - if (TMath::Abs(candidate.massomega() - RecoDecay::getMassPDG(3334)) < rejcomp) + if (TMath::Abs(candidate.massomega() - pdgDB->Mass(3334)) < rejcomp) continue; registry.fill(HIST("hCandidate"), ++counter); rapidity = candidate.rapxi(); @@ -406,7 +386,7 @@ struct cascpostprocessing { if (candidate.ctauomega() > proplifetime * ctauomegaPDG) continue; registry.fill(HIST("hCandidate"), ++counter); - if (TMath::Abs(candidate.massxi() - RecoDecay::getMassPDG(3312)) < rejcomp) + if (TMath::Abs(candidate.massxi() - pdgDB->Mass(3312)) < rejcomp) continue; registry.fill(HIST("hCandidate"), ++counter); rapidity = candidate.rapomega(); @@ -417,22 +397,38 @@ struct cascpostprocessing { continue; } registry.fill(HIST("hCandidate"), ++counter); + if (candidate.posntpccrrows() < mintpccrrows || candidate.negntpccrrows() < mintpccrrows || candidate.bachntpccrrows() < mintpccrrows) + continue; + registry.fill(HIST("hCandidate"), ++counter); + bool kHasTOF = (candidate.poshastof() || candidate.neghastof() || candidate.bachhastof()); + bool kHasITS = ((candidate.positshits() > 1) || (candidate.negitshits() > 1) || (candidate.bachitshits() > 1)); + if (dooobrej == 1) { + if (!kHasTOF && !kHasITS) + continue; + registry.fill(HIST("hCandidate"), ++counter); + } else if (dooobrej == 2) { + if (!kHasTOF && (candidate.pt() > ptthrtof)) + continue; + registry.fill(HIST("hCandidate"), ++counter); + } else { + ++counter; + } registry.fill(HIST("hPt"), candidate.pt()); - registry.fill(HIST("hDCANegToPV"), candidate.dcanegtopv()); - registry.fill(HIST("hDCAPosToPV"), candidate.dcapostopv()); - registry.fill(HIST("hDCABachToPV"), candidate.dcabachtopv()); - registry.fill(HIST("hCascCosPA"), candidate.casccospa()); - registry.fill(HIST("hV0CosPA"), candidate.v0cospa()); - registry.fill(HIST("hCascRadius"), candidate.cascradius()); - registry.fill(HIST("hV0Radius"), candidate.v0radius()); - registry.fill(HIST("hDCACascDaughters"), candidate.dcacascdaughters()); - registry.fill(HIST("hDCAV0Daughters"), candidate.dcav0daughters()); - registry.fill(HIST("hDCAV0ToPV"), candidate.dcav0topv()); - registry.fill(HIST("hMassLambdaDau"), candidate.masslambdadau()); - - registry.fill(HIST("hBachBaryonCosPA"), candidate.bachBaryonCosPA()); - registry.fill(HIST("hBachBaryonDCAxyToPV"), candidate.bachBaryonDCAxyToPV()); + registry.fill(HIST("hDCANegToPV"), candidate.pt(), candidate.dcanegtopv()); + registry.fill(HIST("hDCAPosToPV"), candidate.pt(), candidate.dcapostopv()); + registry.fill(HIST("hDCABachToPV"), candidate.pt(), candidate.dcabachtopv()); + registry.fill(HIST("hCascCosPA"), candidate.pt(), candidate.casccospa()); + registry.fill(HIST("hV0CosPA"), candidate.pt(), candidate.v0cospa()); + registry.fill(HIST("hCascRadius"), candidate.pt(), candidate.cascradius()); + registry.fill(HIST("hV0Radius"), candidate.pt(), candidate.v0radius()); + registry.fill(HIST("hDCACascDaughters"), candidate.pt(), candidate.dcacascdaughters()); + registry.fill(HIST("hDCAV0Daughters"), candidate.pt(), candidate.dcav0daughters()); + registry.fill(HIST("hDCAV0ToPV"), candidate.pt(), candidate.dcav0topv()); + registry.fill(HIST("hMassLambdaDau"), candidate.pt(), candidate.masslambdadau()); + + registry.fill(HIST("hBachBaryonCosPA"), candidate.pt(), candidate.bachBaryonCosPA()); + registry.fill(HIST("hBachBaryonDCAxyToPV"), candidate.pt(), candidate.bachBaryonDCAxyToPV()); if (candidate.sign() > 0) { registry.fill(HIST("hCtauPlus"), ctau); registry.fill(HIST("hEtaPlus"), candidate.pt(), candidate.eta()); @@ -449,35 +445,35 @@ struct cascpostprocessing { if (isXi) { isCorrectlyRec = ((TMath::Abs(candidate.mcPdgCode()) == 3312) && (candidate.isPrimary() == 1)) ? 1 : 0; - if (TMath::Abs(candidate.massxi() - RecoDecay::getMassPDG(3312)) < masswintpc) { + if (TMath::Abs(candidate.massxi() - pdgDB->Mass(3312)) < masswintpc) { isCandidate = 1; } } else if (!isXi) { isCorrectlyRec = ((TMath::Abs(candidate.mcPdgCode()) == 3334) && (candidate.isPrimary() == 1)) ? 1 : 0; - if (TMath::Abs(candidate.massomega() - RecoDecay::getMassPDG(3334)) < masswintpc) { + if (TMath::Abs(candidate.massomega() - pdgDB->Mass(3334)) < masswintpc) { isCandidate = 1; } } if (isCandidate) { if (candidate.sign() < 0) { - registry.fill(HIST("hTPCNSigmaPosPr"), candidate.ntpcsigmapospr()); - registry.fill(HIST("hTPCNSigmaNegPi"), candidate.ntpcsigmanegpi()); + registry.fill(HIST("hTPCNSigmaPosPr"), candidate.pt(), candidate.ntpcsigmapospr()); + registry.fill(HIST("hTPCNSigmaNegPi"), candidate.pt(), candidate.ntpcsigmanegpi()); registry.fill(HIST("hTOFNSigmaPosPr"), candidate.ntofsigmapospr()); registry.fill(HIST("hTOFNSigmaNegPi"), candidate.ntofsigmanegpi()); registry.fill(HIST("hCascMinusEtaPos"), candidate.poseta()); registry.fill(HIST("hCascMinusEtaNeg"), candidate.negeta()); registry.fill(HIST("hCascMinusEtaBach"), candidate.bacheta()); } else { - registry.fill(HIST("hTPCNSigmaPosPi"), candidate.ntpcsigmapospi()); - registry.fill(HIST("hTPCNSigmaNegPr"), candidate.ntpcsigmanegpr()); + registry.fill(HIST("hTPCNSigmaPosPi"), candidate.pt(), candidate.ntpcsigmapospi()); + registry.fill(HIST("hTPCNSigmaNegPr"), candidate.pt(), candidate.ntpcsigmanegpr()); registry.fill(HIST("hTOFNSigmaPosPi"), candidate.ntofsigmapospi()); registry.fill(HIST("hTOFNSigmaNegPr"), candidate.ntofsigmanegpr()); } if (isXi) { - registry.fill(HIST("hTPCNSigmaBachPi"), candidate.ntpcsigmabachpi()); + registry.fill(HIST("hTPCNSigmaBachPi"), candidate.pt(), candidate.ntpcsigmabachpi()); registry.fill(HIST("hTOFNSigmaBachPi"), candidate.ntofsigmabachpi()); } else { - registry.fill(HIST("hTPCNSigmaBachKa"), candidate.ntpcsigmabachka()); + registry.fill(HIST("hTPCNSigmaBachKa"), candidate.pt(), candidate.ntpcsigmabachka()); registry.fill(HIST("hTOFNSigmaBachKa"), candidate.ntofsigmabachka()); } } @@ -487,22 +483,103 @@ struct cascpostprocessing { if (candidate.sign() < 0) { if (isCorrectlyRec) { - registry.fill(HIST("hPtCascMinusTrueRec"), candidate.pt(), rapidity, (isFT0MforMC ? candidate.multFT0M() : 0)); + registry.fill(HIST("hPtCascMinusTrueRec"), candidate.pt(), rapidity, candidate.multFT0M()); // 3rd axis is N charged in FT0M region from gen. MC } registry.fill(HIST("hCascMinusInvMassvsPt"), candidate.pt(), invmass); registry.fill(HIST("hCascMinusInvMassvsPt_FT0M"), candidate.multFT0M(), candidate.pt(), invmass); - registry.fill(HIST("hCascMinusInvMassvsPt_FV0A"), candidate.multFV0A(), candidate.pt(), invmass); + registry.fill(HIST("hCascMinusInvMassvsPt_FV0A"), isMC ? 0 : candidate.multFV0A(), candidate.pt(), invmass); } if (candidate.sign() > 0) { if (isCorrectlyRec) { - registry.fill(HIST("hPtCascPlusTrueRec"), candidate.pt(), rapidity, (isFT0MforMC ? candidate.multFT0M() : 0)); + registry.fill(HIST("hPtCascPlusTrueRec"), candidate.pt(), rapidity, candidate.multFT0M()); // 3rd axis is N charged in FT0M region from gen. MC } registry.fill(HIST("hCascPlusInvMassvsPt"), candidate.pt(), invmass); registry.fill(HIST("hCascPlusInvMassvsPt_FT0M"), candidate.multFT0M(), candidate.pt(), invmass); - registry.fill(HIST("hCascPlusInvMassvsPt_FV0A"), candidate.multFV0A(), candidate.pt(), invmass); + registry.fill(HIST("hCascPlusInvMassvsPt_FV0A"), isMC ? 0 : candidate.multFV0A(), candidate.pt(), invmass); + } + } + } + + PROCESS_SWITCH(cascpostprocessing, processRec, "Process Run 3 reconstructed data", true); + + void processGen(aod::MyMCCascades const& myMCcascades) + { + for (auto& genCascade : myMCcascades) { + if (genCascade.isPrimary() == 0) + continue; // Consider only primaries + + switch (evSelFlag) { + case 1: { + if (!genCascade.isINEL()) + continue; + break; + } + case 2: { + if (!genCascade.isINELgt0()) + continue; + break; + } + case 3: { + if (!genCascade.isINELgt1()) + continue; + break; + } + default: + LOGF(fatal, "incorrect evSelFlag in cascpostprocessing task"); + break; + } + + // Histos of generated cascades from generated events with accepted z vrtx + chosen event type (evSelFlag) (for signal loss correction) + if (genCascade.pdgCode() == -3312) { + registry.fill(HIST("hPtXiPlusTrue"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + } + if (genCascade.pdgCode() == 3312) { + registry.fill(HIST("hPtXiMinusTrue"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + } + if (genCascade.pdgCode() == -3334) { + registry.fill(HIST("hPtOmegaPlusTrue"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + } + if (genCascade.pdgCode() == 3334) { + registry.fill(HIST("hPtOmegaMinusTrue"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + } + + // Histos of generated cascades from generated events with good z vrtx + chosen event type (evSelFlag) + associated to the accepted reconstructed event of the same type (for signal loss + efficiency x acceptance correction) + switch (evSelFlag) { + case 1: { + if (!genCascade.isINELassoc()) + continue; + break; + } + case 2: { + if (!genCascade.isINELgt0assoc()) + continue; + break; + } + case 3: { + if (!genCascade.isINELgt1assoc()) + continue; + break; + } + default: + LOGF(fatal, "incorrect evSelFlag in cascpostprocessing task"); + break; + } + + if (genCascade.pdgCode() == -3312) { + registry.fill(HIST("hPtXiPlusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + } + if (genCascade.pdgCode() == 3312) { + registry.fill(HIST("hPtXiMinusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + } + if (genCascade.pdgCode() == -3334) { + registry.fill(HIST("hPtOmegaPlusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); + } + if (genCascade.pdgCode() == 3334) { + registry.fill(HIST("hPtOmegaMinusTrueAssocWithSelColl"), genCascade.pt(), genCascade.y(), genCascade.nChInFT0M()); } } } + PROCESS_SWITCH(cascpostprocessing, processGen, "Process Run 3 MC generated data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/deltaanalysis.cxx b/PWGLF/Tasks/deltaanalysis.cxx new file mode 100644 index 00000000000..d86c4a3833b --- /dev/null +++ b/PWGLF/Tasks/deltaanalysis.cxx @@ -0,0 +1,528 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// Analysis task for delta analysis + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/TableProducer/PID/pidTOFBase.h" + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Framework/ASoAHelpers.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "CCDB/BasicCCDBManager.h" + +#include "PWGLF/DataModel/LFLithium4Tables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +namespace +{ +constexpr float pionMass = o2::constants::physics::MassPionCharged; +constexpr float protonMass = o2::constants::physics::MassProton; +constexpr int deltaPlusPlusPDG = 2224; +constexpr int deltaZeroPDG = 2114; +constexpr int protonPDG = 2212; +constexpr int pionPDG = 211; +} // namespace + +struct deltaAnalysis { + + SliceCache cache; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + // events + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + // track + Configurable cfgCutPt{"cfgCutPt", 0.2, "Pt cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + Configurable cfgCutY{"cfgCutY", 0.5, "Y cut on reconstructed delta"}; + Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; + Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmaCutTOF{"nsigmaCutTOF", 3.0, "Value of the TOF Nsigma cut"}; + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; + + // Histogram axes + AxisSpec nSigmaTPCaxis = {100, -5., 5., "n#sigma_{TPC}"}; + AxisSpec nSigmaTOFaxis = {100, -5., 5., "n#sigma_{TOF}"}; + ConfigurableAxis cfgPtAxis{"cfgPtAxis", {VARIABLE_WIDTH, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4.}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis cfgMassAxis{"cfgDeltaPlusPlusAxis", {75, 1.05, 1.8}, ""}; + + void init(o2::framework::InitContext&) + { + // Define axes + AxisSpec deltaPlusPlusAxis{cfgMassAxis, "m(p + #pi^{+}) (GeV/#it{c}^{2})"}; + AxisSpec antiDeltaPlusPlusAxis{cfgMassAxis, "m(#bar{p} + #pi^{-}) (GeV/#it{c}^{2})"}; + AxisSpec deltaZeroAxis{cfgMassAxis, "m(p + #pi^{-}) (GeV/#it{c}^{2})"}; + AxisSpec antiDeltaZeroAxis{cfgMassAxis, "m(#bar{p} + #pi^{+}) (GeV/#it{c}^{2})"}; + + // Collision + histos.add("hCentrality", "Centrality distribution", kTH1F, {{2001, -0.5, 2000.5}}); + histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); + histos.add("hNcontributor", "Number of primary vertex contributors; n", kTH1F, {{2001, -0.5f, 2000.5f}}); + + // Single track + histos.add("hPiPlusDCAxy", "DCA_{xy} distribution for #pi^{+}; DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hPiPlusDCAz", "DCA_{z} distribution for #pi^{+}; DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hPiPlusNsigmaTPCvsPt", "n#sigma_{TPC} distribution vs #it{p}_{T} for #pi^{+}", kTH2F, {cfgPtAxis, nSigmaTPCaxis}); + histos.add("hPiPlusNsigmaTOFvsPt", "n#sigma_{TOF} distribution vs #it{p}_{T} for #pi^{+}", kTH2F, {cfgPtAxis, nSigmaTOFaxis}); + + histos.add("hPiMinusDCAxy", "DCA_{xy} distribution for #pi^{-}; DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hPiMinusDCAz", "DCA_{z} distribution for #pi^{-}; DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hPiMinusNsigmaTPCvsPt", "n#sigma_{TPC} distribution vs #it{p}_{T} for #pi^{-}", kTH2F, {cfgPtAxis, nSigmaTPCaxis}); + histos.add("hPiMinusNsigmaTOFvsPt", "n#sigma_{TOF} distribution vs #it{p}_{T} for #pi^{-}", kTH2F, {cfgPtAxis, nSigmaTOFaxis}); + + histos.add("hPrPlusDCAxy", "DCA_{xy} distribution for p; DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hPrPlusDCAz", "DCA_{z} distribution for p; DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hPrPlusNsigmaTPCvsPt", "n#sigma_{TPC} distribution vs #it{p}_{T} for p", kTH2F, {cfgPtAxis, nSigmaTPCaxis}); + histos.add("hPrPlusNsigmaTOFvsPt", "n#sigma_{TOF} distribution vs #it{p}_{T} for p", kTH2F, {cfgPtAxis, nSigmaTOFaxis}); + + histos.add("hPrMinusDCAxy", "DCA_{xy} distribution for #bar{p}; DCA_{xy} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hPrMinusDCAz", "DCA_{z} distribution for #bar{p}; DCA_{z} (cm)", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hPrMinusNsigmaTPCvsPt", "n#sigma_{TPC} distribution vs #it{p}_{T} for #bar{p}", kTH2F, {cfgPtAxis, nSigmaTPCaxis}); + histos.add("hPrMinusNsigmaTOFvsPt", "n#sigma_{TOF} distribution vs #it{p}_{T} for #bar{p}", kTH2F, {cfgPtAxis, nSigmaTOFaxis}); + + // Deltas + histos.add("hDeltaPlusPlusInvMass", "Invariant mass distribution for #Delta^{++}", kTH2F, {cfgPtAxis, deltaPlusPlusAxis}); + histos.add("hAntiDeltaPlusPlusInvMass", "Invariant mass distribution for #bar{#Delta^{++}}", kTH2F, {cfgPtAxis, antiDeltaPlusPlusAxis}); + + histos.add("hDeltaZeroInvMass", "Invariant mass distribution for #Delta^{0}", kTH2F, {cfgPtAxis, deltaZeroAxis}); + histos.add("hAntiDeltaZeroInvMass", "Invariant mass distribution for #bar{#Delta^{0}}", kTH2F, {cfgPtAxis, antiDeltaZeroAxis}); + + if (doprocessMixedEvent) { + // Deltas - Event mixing + histos.add("hDeltaPlusPlusInvMassEM", "Invariant mass distribution for #Delta^{++} - event mixing", kTH2F, {cfgPtAxis, deltaPlusPlusAxis}); + histos.add("hAntiDeltaPlusPlusInvMassEM", "Invariant mass distribution for #bar{#Delta^{++}} - event mixing", kTH2F, {cfgPtAxis, antiDeltaPlusPlusAxis}); + + histos.add("hDeltaZeroInvMassEM", "Invariant mass distribution for #Delta^{0} - event mixing", kTH2F, {cfgPtAxis, deltaZeroAxis}); + histos.add("hAntiDeltaZeroInvMassEM", "Invariant mass distribution for #bar{#Delta^{0}} - event mixing", kTH2F, {cfgPtAxis, antiDeltaZeroAxis}); + } + + if (doprocessMC) { + // generated quantities + histos.add("hDeltaPlusPlusInvMassGen", "Invariant mass distribution for #Delta^{++} - generated", kTH2F, {cfgPtAxis, deltaPlusPlusAxis}); + histos.add("hAntiDeltaPlusPlusInvMassGen", "Invariant mass distribution for #bar{#Delta^{++}} - generated", kTH2F, {cfgPtAxis, antiDeltaPlusPlusAxis}); + + histos.add("hDeltaZeroInvMassGen", "Invariant mass distribution for #Delta^{0} - generated", kTH2F, {cfgPtAxis, deltaZeroAxis}); + histos.add("hAntiDeltaZeroInvMassGen", "Invariant mass distribution for #bar{#Delta^{0}} - generated", kTH2F, {cfgPtAxis, antiDeltaZeroAxis}); + } + } + + template + bool selectionTrack(const T& track) + { + // if (!track.isGlobalTrack()) { + // return false; + // } + if (track.itsNCls() < 5) { + return false; + } + if (track.tpcNClsShared() > 0) { + return false; + } + if (track.tpcNClsFound() < 70) { + return false; + } + if (track.tpcNClsCrossedRows() < 70) { + return false; + } + if (track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable()) { + return false; + } + if (track.tpcChi2NCl() > 4.f) { + return false; + } + if (track.itsChi2NCl() > 36.f) { + return false; + } + return true; + } + + template + bool selectionPIDPion(const T& track) + { + if (track.hasTOF()) { + if (std::abs(track.tofNSigmaPi()) < nsigmaCutTOF && std::abs(track.tpcNSigmaPi()) < nsigmaCutTPC) { + if (track.sign() > 0) { + histos.fill(HIST("hPiPlusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST("hPiPlusNsigmaTOFvsPt"), track.pt(), track.tofNSigmaPi()); + histos.fill(HIST("hPiPlusDCAxy"), track.dcaXY()); + histos.fill(HIST("hPiPlusDCAz"), track.dcaZ()); + } else { + histos.fill(HIST("hPiMinusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST("hPiMinusNsigmaTOFvsPt"), track.pt(), track.tofNSigmaPi()); + histos.fill(HIST("hPiMinusDCAxy"), track.dcaXY()); + histos.fill(HIST("hPiMinusDCAz"), track.dcaZ()); + } + return true; + } + } else if (std::abs(track.tpcNSigmaPi()) < nsigmaCutTPC) { + if (track.sign() > 0) { + histos.fill(HIST("hPiPlusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST("hPiPlusDCAxy"), track.dcaXY()); + histos.fill(HIST("hPiPlusDCAz"), track.dcaZ()); + } else { + histos.fill(HIST("hPiMinusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST("hPiMinusDCAxy"), track.dcaXY()); + histos.fill(HIST("hPiMinusDCAz"), track.dcaZ()); + } + return true; + } + return false; + } + + template + bool selectionPIDProton(const T& track) + { + if (track.hasTOF()) { + if (std::abs(track.tofNSigmaPr()) < nsigmaCutTOF && std::abs(track.tpcNSigmaPr()) < nsigmaCutTPC) { + if (track.sign() > 0) { + histos.fill(HIST("hPrPlusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST("hPrPlusNsigmaTOFvsPt"), track.pt(), track.tofNSigmaPr()); + histos.fill(HIST("hPrPlusDCAxy"), track.dcaXY()); + histos.fill(HIST("hPrPlusDCAz"), track.dcaZ()); + } else { + histos.fill(HIST("hPrMinusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST("hPrMinusNsigmaTOFvsPt"), track.pt(), track.tofNSigmaPr()); + histos.fill(HIST("hPrMinusDCAxy"), track.dcaXY()); + histos.fill(HIST("hPrMinusDCAz"), track.dcaZ()); + } + return true; + } + } else if (std::abs(track.tpcNSigmaPr()) < nsigmaCutTPC) { + if (track.sign() > 0) { + histos.fill(HIST("hPrPlusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST("hPrPlusDCAxy"), track.dcaXY()); + histos.fill(HIST("hPrPlusDCAz"), track.dcaZ()); + } else { + histos.fill(HIST("hPrMinusNsigmaTPCvsPt"), track.pt(), track.tpcNSigmaPr()); + histos.fill(HIST("hPrMinusDCAxy"), track.dcaXY()); + histos.fill(HIST("hPrMinusDCAz"), track.dcaZ()); + } + return true; + } + return false; + } + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPt); + Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + + using EventCandidates = soa::Filtered>; + + using TrackCandidates = soa::Filtered>; + + using TrackCandidatesMC = soa::Filtered>; + + Preslice perCol = aod::track::collisionId; + Preslice perColMC = aod::track::collisionId; + + // Binning for event mixing + ConfigurableAxis cfgCentAxis{"cfgCentAxis", {VARIABLE_WIDTH, 0., 0.01, 0.1, 1.0, 5.0, 10., 15., 20., 30., 40., 50., 70., 100.0, 105.}, "Binning of the centrality axis"}; + ConfigurableAxis cfgVtxAxis{"cfgVtxAxis", {VARIABLE_WIDTH, -20, -15, -10, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 10, 15, 20}, "Mixing bins - z-vertex"}; + + using BinningType = ColumnBinningPolicy; + + BinningType binningOnPositions{{cfgVtxAxis}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, &cache}; + + void processSameEvent(soa::Join const& collisions, TrackCandidates const& tracks, aod::BCs const&) + { + for (auto& collision : collisions) { + if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) { + continue; + } + histos.fill(HIST("hNcontributor"), collision.numContrib()); + histos.fill(HIST("hVtxZ"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto perColTracks = tracks.sliceBy(perCol, collIdx); + perColTracks.bindExternalIndices(&tracks); + + for (auto& [t0, t1] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(perColTracks, perColTracks))) { + + if (t0.globalIndex() == t1.globalIndex()) { + continue; + } + if (!selectionTrack(t0) || !selectionTrack(t1)) { + continue; + } + if (selectionPIDProton(t0)) { + + TLorentzVector proton; + proton.SetPtEtaPhiM(t0.pt(), t0.eta(), t0.phi(), protonMass); + + if (selectionPIDPion(t1)) { + + TLorentzVector pion; + pion.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), pionMass); + + TLorentzVector delta = proton + pion; + + if (abs(delta.Rapidity()) > cfgCutY) { + continue; + } + + if (t0.sign() < 0) { + if (t1.sign() < 0) { + histos.fill(HIST("hAntiDeltaPlusPlusInvMass"), delta.Pt(), delta.M()); + } else { + histos.fill(HIST("hAntiDeltaZeroInvMass"), delta.Pt(), delta.M()); + } + } else { + if (t1.sign() < 0) { + histos.fill(HIST("hDeltaZeroInvMass"), delta.Pt(), delta.M()); + } else { + histos.fill(HIST("hDeltaPlusPlusInvMass"), delta.Pt(), delta.M()); + } + } + } + } + } + } + } + PROCESS_SWITCH(deltaAnalysis, processSameEvent, "Process same event", false); + + void processMixedEvent(EventCandidates& collisions, TrackCandidates const& tracks) + { + for (auto& [c1, tracks1, c2, tracks2] : pair) { + if (!c1.sel8()) { + continue; + } + if (!c2.sel8()) { + continue; + } + + for (auto& [t0, t1] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + + if (!selectionTrack(t0) || selectionTrack(t1)) { + continue; + } + + if (selectionPIDProton(t0)) { + + TLorentzVector proton; + proton.SetPtEtaPhiM(t0.pt(), t0.eta(), t0.phi(), protonMass); + + if (selectionPIDPion(t1)) { + + TLorentzVector pion; + pion.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), pionMass); + + TLorentzVector delta = proton + pion; + + if (t0.sign() < 0) { + if (t1.sign() < 0) { + histos.fill(HIST("hAntiDeltaPlusPlusInvMassEM"), delta.Pt(), delta.M()); + } else { + histos.fill(HIST("hAntiDeltaZeroInvMassEM"), delta.Pt(), delta.M()); + } + } else { + if (t1.sign() < 0) { + histos.fill(HIST("hDeltaZeroInvMassEM"), delta.Pt(), delta.M()); + } else { + histos.fill(HIST("hDeltaPlusPlusInvMassEM"), delta.Pt(), delta.M()); + } + } + } + } + } + } + } + PROCESS_SWITCH(deltaAnalysis, processMixedEvent, "Process Mixed event", false); + + void processMC(soa::Join const& collisions, aod::BCs const&, TrackCandidatesMC const& tracks, aod::McParticles const& mcParticles) + { + + for (auto& collision : collisions) { + + if (!collision.sel8() || std::abs(collision.posZ()) > cfgCutVertex) { + continue; + } + + histos.fill(HIST("hCentrality"), 1); + histos.fill(HIST("hNcontributor"), collision.numContrib()); + histos.fill(HIST("hVtxZ"), collision.posZ()); + + const uint64_t collIdx = collision.globalIndex(); + auto perColTracks = tracks.sliceBy(perColMC, collIdx); + perColTracks.bindExternalIndices(&tracks); + + for (auto& [t0, t1] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(perColTracks, perColTracks))) { + + if (t0.globalIndex() == t1.globalIndex()) { + continue; + } + if (!selectionTrack(t0) || !selectionTrack(t1)) { + continue; + } + if (selectionPIDProton(t0)) { + + if (!t0.has_mcParticle()) { + continue; + } + TLorentzVector proton; + proton.SetPtEtaPhiM(t0.pt(), t0.eta(), t0.phi(), protonMass); + + if (selectionPIDPion(t1)) { + + if (!t1.has_mcParticle()) { + continue; + } + TLorentzVector pion; + pion.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), pionMass); + + // select real protons and pion + const auto mcTrackProton = t0.mcParticle(); + const auto mcTrackPion = t1.mcParticle(); + + if (std::abs(mcTrackProton.pdgCode()) != protonPDG) { + continue; + } + + if (std::abs(mcTrackPion.pdgCode()) != pionPDG) { + continue; + } + + bool found_mother = false; + + for (auto& motherTrackProton : mcTrackProton.mothers_as()) { + for (auto& motherTrackPion : mcTrackPion.mothers_as()) { + if (motherTrackProton != motherTrackPion) { + continue; + } + if (std::abs(motherTrackProton.pdgCode()) != deltaPlusPlusPDG && std::abs(motherTrackProton.pdgCode()) != deltaZeroPDG) { + continue; + } + found_mother = true; + break; + } + if (found_mother) { + break; + } + } + + if (!found_mother) { + continue; + } + + TLorentzVector delta = proton + pion; + + if (abs(delta.Rapidity()) > cfgCutY) { + continue; + } + + if (t0.sign() < 0) { + if (t1.sign() < 0) { + histos.fill(HIST("hAntiDeltaPlusPlusInvMass"), delta.Pt(), delta.M()); + } else { + histos.fill(HIST("hAntiDeltaZeroInvMass"), delta.Pt(), delta.M()); + } + } else { + if (t1.sign() < 0) { + histos.fill(HIST("hDeltaZeroInvMass"), delta.Pt(), delta.M()); + } else { + histos.fill(HIST("hDeltaPlusPlusInvMass"), delta.Pt(), delta.M()); + } + } + } + } + } + } + + for (auto& mcParticle : mcParticles) { + + int pdg = mcParticle.pdgCode(); + if (std::abs(pdg) != deltaPlusPlusPDG && std::abs(pdg) != deltaZeroPDG) { + continue; + } + + if (std::abs(mcParticle.y()) > cfgCutY) { + continue; + } + + // if (!mcParticle.isPhysicalPrimary()) { + // continue; + // } + + auto daughters = mcParticle.daughters_as(); + bool daughtPr = false; + bool daughtPi = false; + double eDelta = 0.; + for (auto daught : daughters) { + if (std::abs(daught.pdgCode()) == protonPDG) { + daughtPr = true; + eDelta += daught.e(); + } else if (std::abs(daught.pdgCode()) == pionPDG) { + daughtPi = true; + eDelta += daught.e(); + } + } + + if (!daughtPr || !daughtPi) { + continue; + } + + float gen_mass = TMath::Sqrt(eDelta * eDelta - mcParticle.p() * mcParticle.p()); + + if (pdg > 0) { + if (std::abs(pdg) == deltaPlusPlusPDG) { + histos.fill(HIST("hDeltaPlusPlusInvMassGen"), mcParticle.pt(), gen_mass); + } else if (std::abs(pdg) == deltaZeroPDG) { + histos.fill(HIST("hDeltaZeroInvMassGen"), mcParticle.pt(), gen_mass); + } + } else { + if (std::abs(pdg) == deltaPlusPlusPDG) { + histos.fill(HIST("hAntiDeltaPlusPlusInvMassGen"), mcParticle.pt(), gen_mass); + } else if (std::abs(pdg) == deltaZeroPDG) { + histos.fill(HIST("hAntiDeltaZeroInvMassGen"), mcParticle.pt(), gen_mass); + } + } + } + } + PROCESS_SWITCH(deltaAnalysis, processMC, "Process MC", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"deltaAnalysis"})}; +} diff --git a/PWGLF/Tasks/f0980analysis.cxx b/PWGLF/Tasks/f0980analysis.cxx index d15ffded738..4e22c67ee00 100644 --- a/PWGLF/Tasks/f0980analysis.cxx +++ b/PWGLF/Tasks/f0980analysis.cxx @@ -12,15 +12,16 @@ /// \author Junlee Kim (jikim1290@gmail.com) #include +#include "TVector2.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Framework/AnalysisTask.h" +#include "Common/DataModel/PIDResponse.h" +#include "DataFormatsParameters/GRPObject.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "PWGLF/DataModel/LFResonanceTables.h" -#include "DataFormatsParameters/GRPObject.h" using namespace o2; using namespace o2::framework; @@ -31,41 +32,106 @@ struct f0980analysis { SliceCache cache; Preslice perRCol = aod::resodaughter::resoCollisionId; Preslice perCollision = aod::track::collisionId; - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - - Configurable cfgMinPt{"cfgMinPt", 0.15, "Minimum transverse momentum for charged track"}; - Configurable cfgMaxEta{"cfgMaxEta", 0.8, "Maximum pseudorapidiy for charged track"}; - Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.5, "Maximum transverse DCA"}; - Configurable cfgMinDCAzToPVcut{"cfgMinDCAzToPVcut", 0.0, "Minimum longitudinal DCA"}; - Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 2.0, "Maximum longitudinal DCA"}; - Configurable cfgMaxTPCStandalone{"cfgMaxTPCStandalone", 2.0, "Maximum TPC PID as standalone"}; + HistogramRegistry histos{ + "histos", + {}, + OutputObjHandlingPolicy::AnalysisObject}; + + Configurable cfgMinPt{"cfgMinPt", 0.15, + "Minimum transverse momentum for charged track"}; + Configurable cfgMaxEta{"cfgMaxEta", 0.8, + "Maximum pseudorapidiy for charged track"}; + Configurable cfgMinDCArToPVcut{"cfgMinDCArToPVcut", -0.5, + "Minimum transverse DCA"}; + Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.5, + "Maximum transverse DCA"}; + Configurable cfgMinDCAzToPVcut{"cfgMinDCAzToPVcut", -2.0, + "Minimum longitudinal DCA"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 2.0, + "Maximum longitudinal DCA"}; + Configurable cfgMaxTPCStandalone{"cfgMaxTPCStandalone", 2.0, + "Maximum TPC PID as standalone"}; Configurable cfgMaxTPC{"cfgMaxTPC", 5.0, "Maximum TPC PID with TOF"}; Configurable cfgMaxTOF{"cfgMaxTOF", 3.0, "Maximum TOF PID with TPC"}; Configurable cfgMinRap{"cfgMinRap", -0.5, "Minimum rapidity for pair"}; Configurable cfgMaxRap{"cfgMaxRap", 0.5, "Maximum rapidity for pair"}; + Configurable cfgMinTPCncr{"cfgMinTPCncr", 70, "minimum TPC cluster"}; + + Configurable cfgPrimaryTrack{ + "cfgPrimaryTrack", true, + "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{ + "cfgGlobalWoDCATrack", true, + "Global track selection without DCA"}; // kQualityTracks (kTrackType | + // kTPCNCls | kTPCCrossedRows | + // kTPCCrossedRowsOverNCls | + // kTPCChi2NDF | kTPCRefit | + // kITSNCls | kITSChi2NDF | + // kITSRefit | kITSHits) | + // kInAcceptanceTracks (kPtRange | + // kEtaRange) + Configurable cfgPVContributor{ + "cfgPVContributor", true, + "PV contributor track selection"}; // PV Contriuibutor + Configurable cfgUseTOF{ + "cfgUseTOF", false, + "Flag for the usage of TOF for PID"}; void init(o2::framework::InitContext&) { - std::vector ptBinning = { - 0.0, 0.2, 0.4, 0.6, 0.8, - 1.0, 1.5, 2.0, 2.5, 3.0, - 3.5, 4.0, 4.5, 5.0, 6.0, - 7.0, 8.0, 10.0, 13.0, 20.0}; + std::vector ptBinning = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, + 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, + 5.0, 6.0, 7.0, 8.0, 10.0, 13.0, 20.0}; + std::vector lptBinning = {0, 5.0, 13.0, 20.0, 50.0, 1000.0}; - AxisSpec centAxis = {20, 0, 100}; + AxisSpec centAxis = {22, 0, 110}; AxisSpec ptAxis = {ptBinning}; AxisSpec massAxis = {400, 0.2, 2.2}; - AxisSpec epAxis = {20, -constants::math::PI, constants::math::PI}; + AxisSpec RTAxis = {3, 0, 3}; + AxisSpec LptAxis = {lptBinning}; // Minimum leading hadron pT selection + + AxisSpec PIDqaAxis = {120, -6, 6}; + AxisSpec pTqaAxis = {200, 0, 20}; + AxisSpec phiqaAxis = {72, 0., 2.0 * constants::math::PI}; + + histos.add("hInvMass_f0980_US", "unlike invariant mass", + {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); + histos.add("hInvMass_f0980_LSpp", "++ invariant mass", + {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); + histos.add("hInvMass_f0980_LSmm", "-- invariant mass", + {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); + + histos.add("QA/Nsigma_TPC", "", {HistType::kTH2F, {pTqaAxis, PIDqaAxis}}); + histos.add("QA/Nsigma_TOF", "", {HistType::kTH2F, {pTqaAxis, PIDqaAxis}}); + histos.add("QA/TPC_TOF", "", {HistType::kTH2F, {PIDqaAxis, PIDqaAxis}}); - histos.add("hInvMass_f0980_US", "unlike invariant mass", {HistType::kTH3F, {massAxis, ptAxis, centAxis}}); - histos.add("hInvMass_f0980_LSpp", "++ invariant mass", {HistType::kTH3F, {massAxis, ptAxis, centAxis}}); - histos.add("hInvMass_f0980_LSmm", "-- invariant mass", {HistType::kTH3F, {massAxis, ptAxis, centAxis}}); + histos.add("QA/LTpt", "", {HistType::kTH3F, {pTqaAxis, centAxis, phiqaAxis}}); + + if (doprocessMCLight) { + histos.add("MCL/hpT_f0980_GEN", "generated f0 signals", HistType::kTH1F, + {pTqaAxis}); + histos.add("MCL/hpT_f0980_REC", "reconstructed f0 signals", + HistType::kTH3F, {massAxis, pTqaAxis, centAxis}); + } histos.print(); } double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); + int RTIndex(double pairphi, double lhphi) + { + double dphi = std::fabs(TVector2::Phi_mpi_pi(lhphi - pairphi)); + if (dphi < constants::math::PI / 3.0) + return 0; + if (dphi < 2.0 * constants::math::PI / 3.0 && dphi > constants::math::PI / 3.0) + return 1; + if (dphi > 2.0 * constants::math::PI / 3.0) + return 2; + + return -1; + } + template bool SelTrack(const TrackType track) { @@ -73,10 +139,16 @@ struct f0980analysis { return false; if (std::fabs(track.eta()) > cfgMaxEta) return false; - if (track.dcaXY() > cfgMaxDCArToPVcut) + if (track.dcaXY() < cfgMinDCArToPVcut || track.dcaXY() > cfgMaxDCArToPVcut) return false; if (track.dcaZ() < cfgMinDCAzToPVcut || track.dcaZ() > cfgMaxDCAzToPVcut) return false; + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; return true; } @@ -84,12 +156,13 @@ struct f0980analysis { template bool SelPion(const TrackType track) { - if ((track.tofPIDselectionFlag() & aod::resodaughter::kHasTOF) != aod::resodaughter::kHasTOF) { + if (track.hasTOF() || !cfgUseTOF) { if (std::fabs(track.tpcNSigmaPi()) > cfgMaxTPCStandalone) { return false; } } else { - if (std::fabs(track.tpcNSigmaPi()) > cfgMaxTPC || std::fabs(track.tofNSigmaPi()) > cfgMaxTOF) { + if (std::fabs(track.tpcNSigmaPi()) > cfgMaxTPC || + std::fabs(track.tofNSigmaPi()) > cfgMaxTOF) { return false; } } @@ -97,17 +170,36 @@ struct f0980analysis { } template - void fillHistograms(const CollisionType& collision, const TracksType& dTracks) + void fillHistograms(const CollisionType& collision, + const TracksType& dTracks) { + double LHpt = 0.; + double LHphi; + for (auto& trk : dTracks) { + if (trk.pt() > LHpt) { + LHpt = trk.pt(); + LHphi = trk.phi(); + } + } + histos.fill(HIST("QA/LTpt"), LHpt, collision.multV0M(), LHphi); + TLorentzVector Pion1, Pion2, Reco; - for (auto& [trk1, trk2] : combinations(CombinationsStrictlyUpperIndexPolicy(dTracks, dTracks))) { + for (auto& [trk1, trk2] : + combinations(CombinationsUpperIndexPolicy(dTracks, dTracks))) { + if (trk1.index() == trk2.index()) { + if (!SelTrack(trk1)) + continue; + histos.fill(HIST("QA/Nsigma_TPC"), trk1.pt(), trk1.tpcNSigmaPi()); + histos.fill(HIST("QA/Nsigma_TOF"), trk1.pt(), trk1.tofNSigmaPi()); + histos.fill(HIST("QA/TPC_TOF"), trk1.tpcNSigmaPi(), trk1.tofNSigmaPi()); + continue; + } + if (!SelTrack(trk1) || !SelTrack(trk2)) continue; if (!SelPion(trk1) || !SelPion(trk2)) continue; - LOGF(debug, "Accepted"); - Pion1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); Pion2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massPi); Reco = Pion1 + Pion2; @@ -115,32 +207,72 @@ struct f0980analysis { if (Reco.Rapidity() > cfgMaxRap || Reco.Rapidity() < cfgMinRap) continue; - LOGF(debug, "Rap Accepted"); if (trk1.sign() * trk2.sign() < 0) { - histos.fill(HIST("hInvMass_f0980_US"), Reco.M(), Reco.Pt(), collision.multV0M()); + histos.fill(HIST("hInvMass_f0980_US"), Reco.M(), Reco.Pt(), + collision.multV0M(), RTIndex(Reco.Phi(), LHphi), LHpt); + if constexpr (IsMC) { + if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kPiPlus) + continue; + if (trk1.motherId() != trk2.motherId()) + continue; + if (abs(trk1.motherPDG()) != 9010221) + continue; + histos.fill(HIST("MCL/hpT_f0980_REC"), Reco.M(), Reco.Pt(), + collision.multV0M()); + } } else if (trk1.sign() > 0 && trk2.sign() > 0) { - histos.fill(HIST("hInvMass_f0980_LSpp"), Reco.M(), Reco.Pt(), collision.multV0M()); + histos.fill(HIST("hInvMass_f0980_LSpp"), Reco.M(), Reco.Pt(), + collision.multV0M(), RTIndex(Reco.Phi(), LHphi), LHpt); } else if (trk1.sign() < 0 && trk2.sign() < 0) { - histos.fill(HIST("hInvMass_f0980_LSmm"), Reco.M(), Reco.Pt(), collision.multV0M()); + histos.fill(HIST("hInvMass_f0980_LSmm"), Reco.M(), Reco.Pt(), + collision.multV0M(), RTIndex(Reco.Phi(), LHphi), LHpt); } } } - void processData(aod::ResoCollisions& collisions, + void processData(aod::ResoCollision& collision, aod::ResoTracks const& resotracks) { - LOGF(debug, "[DATA] Processing %d collisions", collisions.size()); - for (auto& collision : collisions) { - Partition selectedTracks = o2::aod::track::pt > static_cast(cfgMinPt) && (nabs(o2::aod::track::dcaZ) < static_cast(cfgMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cfgMaxDCArToPVcut)); - selectedTracks.bindTable(resotracks); - auto colTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colTracks); + fillHistograms(collision, resotracks); + } + PROCESS_SWITCH(f0980analysis, processData, "Process Event for data", true); + + void processMCLight( + aod::ResoCollision& collision, + soa::Join const& resotracks, + aod::McParticles const& mcParticles) + { + fillHistograms(collision, resotracks); + } + PROCESS_SWITCH(f0980analysis, processMCLight, "Process Event for MC", false); + + void processMCTrue(aod::ResoMCParents& resoParents) + { + + for (auto& part : resoParents) { // loop over all pre-filtered MC particles + if (abs(part.pdgCode()) != 9010221) + continue; + if (!part.producedByGenerator()) + continue; + if (part.y() < cfgMinRap || part.y() > cfgMaxRap) { + continue; + } + bool pass = false; + if ((abs(part.daughterPDG1()) == kPiPlus && + abs(part.daughterPDG2()) == kPiPlus)) { + pass = true; + } + if (!pass) // If we have both decay products + continue; + + histos.fill(HIST("MCL/hpT_f0980_GEN"), part.pt()); } }; - PROCESS_SWITCH(f0980analysis, processData, "Process Event for data", true); + PROCESS_SWITCH(f0980analysis, processMCTrue, "Process Event for MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"lf-f0980analysis"})}; + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"lf-f0980analysis"})}; } diff --git a/PWGLF/Tasks/hStrangeCorrelation.cxx b/PWGLF/Tasks/hStrangeCorrelation.cxx index f950fd73b53..941502cf10e 100644 --- a/PWGLF/Tasks/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/hStrangeCorrelation.cxx @@ -31,8 +31,10 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" #include "Framework/StaticFor.h" +#include "CCDB/BasicCCDBManager.h" using namespace o2; +using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; @@ -43,6 +45,9 @@ using namespace o2::framework::expressions; using TracksComplete = soa::Join; struct correlateStrangeness { + // for efficiency corrections if requested + Service ccdb; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable doCorrelationK0Short{"doCorrelationK0Short", true, "do K0Short correlation"}; @@ -56,6 +61,7 @@ struct correlateStrangeness { Configurable zVertexCut{"zVertexCut", 10, "Cut on PV position"}; Configurable skipUnderOverflowInTHn{"skipUnderOverflowInTHn", false, "skip under/overflow in THns"}; Configurable mixingParameter{"mixingParameter", 10, "how many events are mixed"}; + Configurable doMCassociation{"doMCassociation", false, "fill everything only for MC associated"}; // Axes - configurable for smaller sizes ConfigurableAxis axisMult{"axisMult", {VARIABLE_WIDTH, 0.0f, 0.01f, 1.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 70.0f, 100.0f}, "Mixing bins - multiplicity"}; @@ -65,8 +71,24 @@ struct correlateStrangeness { ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta #varphi axis for histograms"}; ConfigurableAxis axisDeltaEta{"axisDeltaEta", {50, -1.6, 1.6}, "delta eta axis for histograms"}; ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 10.0}, "pt associated axis for histograms"}; + ConfigurableAxis axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.0, 1.0, 2.0, 3.0, 100}, "pt associated axis for histograms"}; ConfigurableAxis axisPtQA{"axisPtQA", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.8f, 1.9f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.4f, 4.8f, 5.2f, 5.6f, 6.0f, 6.5f, 7.0f, 7.5f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 17.0f, 19.0f, 21.0f, 23.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f}, "pt axis for QA histograms"}; + // Implementation of on-the-spot efficiency correction + Configurable applyEfficiencyCorrection{"applyEfficiencyCorrection", false, "apply efficiency correction"}; + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"}; + Configurable efficiencyCCDBPath{"efficiencyCCDBPath", "GLO/Config/GeometryAligned", "Path of the efficiency corrections"}; + + // objects to use for efficiency corrections + TH2F* hEfficiencyPion; + TH2F* hEfficiencyK0Short; + TH2F* hEfficiencyLambda; + TH2F* hEfficiencyAntiLambda; + TH2F* hEfficiencyXiMinus; + TH2F* hEfficiencyXiPlus; + TH2F* hEfficiencyOmegaMinus; + TH2F* hEfficiencyOmegaPlus; + using BinningType = ColumnBinningPolicy; BinningType colBinning{{axisVtxZ, axisMult}, true}; // true is for 'ignore overflows' (true by default). Underflows and overflows will have bin -1. @@ -80,6 +102,7 @@ struct correlateStrangeness { static constexpr std::string_view cascadenames[] = {"XiMinus", "XiPlus", "OmegaMinus", "OmegaPlus"}; uint8_t doCorrelation; + int mRunNumber; std::vector> axisRanges; @@ -98,6 +121,32 @@ struct correlateStrangeness { return deltaPhi; } + /// Function to load efficiencies to memory from CCDB + /// \param bc provided such that the run number can be used + void initEfficiencyFromCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + LOG(info) << "Loading efficiencies from CCDB for run " << mRunNumber << "now..."; + auto timeStamp = bc.timestamp(); + + TList* listEfficiencies = ccdb->getForTimeStamp(efficiencyCCDBPath, timeStamp); + if (!listEfficiencies) { + LOG(fatal) << "Problem getting TList object with efficiencies!"; + } + + hEfficiencyK0Short = (TH2F*)listEfficiencies->FindObject("hEfficiencyK0Short"); + hEfficiencyLambda = (TH2F*)listEfficiencies->FindObject("hEfficiencyLambda"); + hEfficiencyAntiLambda = (TH2F*)listEfficiencies->FindObject("hEfficiencyAntiLambda"); + hEfficiencyXiMinus = (TH2F*)listEfficiencies->FindObject("hEfficiencyXiMinus"); + hEfficiencyXiPlus = (TH2F*)listEfficiencies->FindObject("hEfficiencyXiPlus"); + hEfficiencyOmegaMinus = (TH2F*)listEfficiencies->FindObject("hEfficiencyOmegaMinus"); + hEfficiencyOmegaPlus = (TH2F*)listEfficiencies->FindObject("hEfficiencyOmegaPlus"); + + LOG(info) << "Efficiencies now loaded for " << mRunNumber; + } + void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, float pvz, float mult) { for (auto& triggerTrack : triggers) { @@ -119,6 +168,7 @@ struct correlateStrangeness { float deltaphi = ComputeDeltaPhi(trigg.phi(), assoc.phi()); float deltaeta = trigg.eta() - assoc.eta(); float ptassoc = assoc.pt(); + float pttrigger = trigg.pt(); // skip if basic ranges not met if (deltaphi < axisRanges[0][0] || deltaphi > axisRanges[0][1]) @@ -127,22 +177,30 @@ struct correlateStrangeness { continue; if (ptassoc < axisRanges[2][0] || ptassoc > axisRanges[2][1]) continue; + if (pttrigger < axisRanges[3][0] || pttrigger > axisRanges[3][1]) + continue; + + TH2F* hEfficiencyV0[3]; + hEfficiencyV0[0] = hEfficiencyK0Short; + hEfficiencyV0[1] = hEfficiencyLambda; + hEfficiencyV0[2] = hEfficiencyAntiLambda; static_for<0, 2>([&](auto i) { constexpr int index = i.value; if (bitcheck(doCorrelation, index)) { - if (assocCandidate.compatible(index) && !mixing && assocCandidate.invMassRegionCheck(index, 1)) - histos.fill(HIST("sameEvent/LeftBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && !mixing && assocCandidate.invMassRegionCheck(index, 2)) - histos.fill(HIST("sameEvent/Signal/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && !mixing && assocCandidate.invMassRegionCheck(index, 3)) - histos.fill(HIST("sameEvent/RightBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && mixing && assocCandidate.invMassRegionCheck(index, 1)) - histos.fill(HIST("mixedEvent/LeftBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && mixing && assocCandidate.invMassRegionCheck(index, 2)) - histos.fill(HIST("mixedEvent/Signal/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && mixing && assocCandidate.invMassRegionCheck(index, 3)) - histos.fill(HIST("mixedEvent/RightBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pvz, mult); + float weight = applyEfficiencyCorrection ? 1. / hEfficiencyV0[index]->GetBinContent(hEfficiencyV0[index]->GetXaxis()->FindBin(ptassoc), hEfficiencyV0[index]->GetYaxis()->FindBin(assoc.eta())) : 1.0f; + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 1)) + histos.fill(HIST("sameEvent/LeftBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 2)) + histos.fill(HIST("sameEvent/Signal/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 3)) + histos.fill(HIST("sameEvent/RightBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 1)) + histos.fill(HIST("mixedEvent/LeftBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 2)) + histos.fill(HIST("mixedEvent/Signal/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 3)) + histos.fill(HIST("mixedEvent/RightBg/") + HIST(v0names[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); } }); } @@ -177,6 +235,7 @@ struct correlateStrangeness { float deltaphi = ComputeDeltaPhi(trigg.phi(), assoc.phi()); float deltaeta = trigg.eta() - assoc.eta(); float ptassoc = assoc.pt(); + float pttrigger = trigg.pt(); // skip if basic ranges not met if (deltaphi < axisRanges[0][0] || deltaphi > axisRanges[0][1]) @@ -185,22 +244,31 @@ struct correlateStrangeness { continue; if (ptassoc < axisRanges[2][0] || ptassoc > axisRanges[2][1]) continue; + if (pttrigger < axisRanges[3][0] || pttrigger > axisRanges[3][1]) + continue; + + TH2F* hEfficiencyCascade[4]; + hEfficiencyCascade[0] = hEfficiencyXiMinus; + hEfficiencyCascade[1] = hEfficiencyXiPlus; + hEfficiencyCascade[2] = hEfficiencyOmegaMinus; + hEfficiencyCascade[3] = hEfficiencyOmegaPlus; static_for<0, 3>([&](auto i) { constexpr int index = i.value; if (bitcheck(doCorrelation, index + 3)) { - if (assocCandidate.compatible(index) && !mixing && assocCandidate.invMassRegionCheck(index, 1)) - histos.fill(HIST("sameEvent/LeftBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && !mixing && assocCandidate.invMassRegionCheck(index, 2)) - histos.fill(HIST("sameEvent/Signal/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && !mixing && assocCandidate.invMassRegionCheck(index, 3)) - histos.fill(HIST("sameEvent/RightBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && mixing && assocCandidate.invMassRegionCheck(index, 1)) - histos.fill(HIST("mixedEvent/LeftBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && mixing && assocCandidate.invMassRegionCheck(index, 2)) - histos.fill(HIST("mixedEvent/Signal/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pvz, mult); - if (assocCandidate.compatible(index) && mixing && assocCandidate.invMassRegionCheck(index, 3)) - histos.fill(HIST("mixedEvent/RightBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pvz, mult); + float weight = applyEfficiencyCorrection ? 1. / hEfficiencyCascade[index]->GetBinContent(hEfficiencyCascade[index]->GetXaxis()->FindBin(ptassoc), hEfficiencyCascade[index]->GetYaxis()->FindBin(assoc.eta())) : 1.0f; + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 1)) + histos.fill(HIST("sameEvent/LeftBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 2)) + histos.fill(HIST("sameEvent/Signal/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && !mixing && assocCandidate.invMassRegionCheck(index, 3)) + histos.fill(HIST("sameEvent/RightBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 1)) + histos.fill(HIST("mixedEvent/LeftBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 2)) + histos.fill(HIST("mixedEvent/Signal/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + if (assocCandidate.compatible(index) && (!doMCassociation || assocCandidate.mcTrue(index)) && mixing && assocCandidate.invMassRegionCheck(index, 3)) + histos.fill(HIST("mixedEvent/RightBg/") + HIST(cascadenames[index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); } }); } @@ -225,6 +293,7 @@ struct correlateStrangeness { float deltaphi = ComputeDeltaPhi(trigg.phi(), assoc.phi()); float deltaeta = trigg.eta() - assoc.eta(); float ptassoc = assoc.pt(); + float pttrigger = trigg.pt(); // skip if basic ranges not met if (deltaphi < axisRanges[0][0] || deltaphi > axisRanges[0][1]) @@ -233,17 +302,29 @@ struct correlateStrangeness { continue; if (ptassoc < axisRanges[2][0] || ptassoc > axisRanges[2][1]) continue; + if (pttrigger < axisRanges[3][0] || pttrigger > axisRanges[3][1]) + continue; if (!mixing) - histos.fill(HIST("sameEvent/Pion"), deltaphi, deltaeta, ptassoc, pvz, mult); + histos.fill(HIST("sameEvent/Pion"), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult); else - histos.fill(HIST("mixedEvent/Pion"), deltaphi, deltaeta, ptassoc, pvz, mult); + histos.fill(HIST("mixedEvent/Pion"), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult); } } } void init(InitContext const&) { + mRunNumber = 0; + hEfficiencyPion = 0x0; + hEfficiencyK0Short = 0x0; + hEfficiencyLambda = 0x0; + hEfficiencyAntiLambda = 0x0; + hEfficiencyXiMinus = 0x0; + hEfficiencyXiPlus = 0x0; + hEfficiencyOmegaMinus = 0x0; + hEfficiencyOmegaPlus = 0x0; + // set bitmap for convenience doCorrelation = 0; if (doCorrelationK0Short) @@ -275,6 +356,7 @@ struct correlateStrangeness { const AxisSpec preAxisDeltaPhi{axisDeltaPhi, "#Delta#varphi"}; const AxisSpec preAxisDeltaEta{axisDeltaEta, "#Delta#eta"}; const AxisSpec preAxisPtAssoc{axisPtAssoc, "#it{p}_{T}^{assoc} (GeV/c)"}; + const AxisSpec preAxisPtTrigger{axisPtTrigger, "#it{p}_{T}^{trigger} (GeV/c)"}; const AxisSpec preAxisVtxZ{axisVtxZ, "vertex Z (cm)"}; const AxisSpec preAxisMult{axisMult, "mult percentile"}; @@ -282,30 +364,35 @@ struct correlateStrangeness { histos.add("axes/hDeltaPhiAxis", "", kTH1C, {preAxisDeltaPhi}); histos.add("axes/hDeltaEtaAxis", "", kTH1C, {preAxisDeltaEta}); histos.add("axes/hPtAssocAxis", "", kTH1C, {preAxisPtAssoc}); + histos.add("axes/hPtTriggerAxis", "", kTH1C, {preAxisPtTrigger}); histos.add("axes/hVertexZAxis", "", kTH1C, {preAxisVtxZ}); histos.add("axes/hMultAxis", "", kTH1C, {preAxisMult}); std::vector edgesDeltaPhiOrig = preAxisDeltaPhi.binEdges; std::vector edgesDeltaEtaOrig = preAxisDeltaEta.binEdges; std::vector edgesPtAssocOrig = preAxisPtAssoc.binEdges; + std::vector edgesPtTriggerOrig = preAxisPtTrigger.binEdges; std::vector edgesVtxZOrig = preAxisVtxZ.binEdges; std::vector edgesMultOrig = preAxisMult.binEdges; std::vector rangesDeltaPhi = {static_cast(edgesDeltaPhiOrig[0]), static_cast(edgesDeltaPhiOrig[edgesDeltaPhiOrig.size() - 1])}; std::vector rangesDeltaEta = {static_cast(edgesDeltaEtaOrig[0]), static_cast(edgesDeltaEtaOrig[edgesDeltaEtaOrig.size() - 1])}; std::vector rangesPtAssoc = {static_cast(edgesPtAssocOrig[0]), static_cast(edgesPtAssocOrig[edgesPtAssocOrig.size() - 1])}; + std::vector rangesPtTrigger = {static_cast(edgesPtTriggerOrig[0]), static_cast(edgesPtTriggerOrig[edgesPtTriggerOrig.size() - 1])}; std::vector rangesVtxZ = {static_cast(edgesVtxZOrig[0]), static_cast(edgesVtxZOrig[edgesVtxZOrig.size() - 1])}; std::vector rangesMult = {static_cast(edgesMultOrig[0]), static_cast(edgesMultOrig[edgesMultOrig.size() - 1])}; axisRanges.emplace_back(rangesDeltaPhi); axisRanges.emplace_back(rangesDeltaEta); axisRanges.emplace_back(rangesPtAssoc); + axisRanges.emplace_back(rangesPtTrigger); axisRanges.emplace_back(rangesVtxZ); axisRanges.emplace_back(rangesMult); std::vector edgesDeltaPhi; std::vector edgesDeltaEta; std::vector edgesPtAssoc; + std::vector edgesPtTrigger; std::vector edgesVtxZ; std::vector edgesMult; @@ -353,9 +440,21 @@ struct correlateStrangeness { // fixed binning, generate the bin edges on-the-spot double min = edgesPtAssocOrig[0]; double delta = (edgesPtAssocOrig[1] - edgesPtAssocOrig[0]) / preAxisPtAssoc.nBins.value(); - for (int i = offset; i < preAxisVtxZ.nBins.value() + 1 - offset; i++) + for (int i = offset; i < preAxisPtAssoc.nBins.value() + 1 - offset; i++) edgesPtAssoc.emplace_back(min + static_cast(i) * delta); } + // ===] pt trigger [=== + if (!preAxisPtTrigger.nBins.has_value()) { + // variable binning, use bins provided + for (int i = offset; i < static_cast(edgesPtTriggerOrig.size()) - offset; i++) + edgesPtTrigger.emplace_back(edgesPtTriggerOrig[i]); + } else { + // fixed binning, generate the bin edges on-the-spot + double min = edgesPtTriggerOrig[0]; + double delta = (edgesPtTriggerOrig[1] - edgesPtTriggerOrig[0]) / preAxisPtTrigger.nBins.value(); + for (int i = offset; i < preAxisPtTrigger.nBins.value() + 1 - offset; i++) + edgesPtTrigger.emplace_back(min + static_cast(i) * delta); + } // ===] vtx Z [=== if (!preAxisVtxZ.nBins.has_value()) { // variable binning, use bins provided @@ -384,52 +483,68 @@ struct correlateStrangeness { LOGF(info, "Initialized THnF axis delta-phi with %i bins.", edgesDeltaPhi.size() - 1); LOGF(info, "Initialized THnF axis delta-eta with %i bins.", edgesDeltaEta.size() - 1); LOGF(info, "Initialized THnF axis pTassoc with %i bins.", edgesPtAssoc.size() - 1); + LOGF(info, "Initialized THnF axis pTtrigger with %i bins.", edgesPtTrigger.size() - 1); LOGF(info, "Initialized THnF axis vertex-Z with %i bins.", edgesVtxZ.size() - 1); LOGF(info, "Initialized THnF axis multiplicity with %i bins.", edgesMult.size() - 1); const AxisSpec axisDeltaPhiNDim{edgesDeltaPhi, "#Delta#varphi"}; const AxisSpec axisDeltaEtaNDim{edgesDeltaEta, "#Delta#eta"}; const AxisSpec axisPtAssocNDim{edgesPtAssoc, "#it{p}_{T}^{assoc} (GeV/c)"}; + const AxisSpec axisPtTriggerNDim{edgesPtTrigger, "#it{p}_{T}^{trigger} (GeV/c)"}; const AxisSpec axisVtxZNDim{edgesVtxZ, "vertex Z (cm)"}; const AxisSpec axisMultNDim{edgesMult, "mult percentile"}; if (bitcheck(doCorrelation, 0)) { histos.add("h3dK0ShortSpectrum", "h3dK0ShortSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); + histos.add("h3dK0ShortSpectrumY", "h3dK0ShortSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); histos.add("hK0ShortEtaVsPtVsPhi", "hK0ShortEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("sameEvent/Signal/K0Short", "K0Short", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisVtxZNDim, axisMultNDim}); + histos.add("hK0ShortEtaVsPtVsPhiBg", "hK0ShortEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("sameEvent/Signal/K0Short", "K0Short", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 1)) { histos.add("h3dLambdaSpectrum", "h3dLambdaSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); + histos.add("h3dLambdaSpectrumY", "h3dLambdaSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); histos.add("hLambdaEtaVsPtVsPhi", "hLambdaEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("sameEvent/Signal/Lambda", "Lambda", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisVtxZNDim, axisMultNDim}); + histos.add("hLambdaEtaVsPtVsPhiBg", "hLambdaEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("sameEvent/Signal/Lambda", "Lambda", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 2)) { histos.add("h3dAntiLambdaSpectrum", "h3dAntiLambdaSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); + histos.add("h3dAntiLambdaSpectrumY", "h3dAntiLambdaSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); histos.add("hAntiLambdaEtaVsPtVsPhi", "hAntiLambdaEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("sameEvent/Signal/AntiLambda", "AntiLambda", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisVtxZNDim, axisMultNDim}); + histos.add("hAntiLambdaEtaVsPtVsPhiBg", "hAntiLambdaEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("sameEvent/Signal/AntiLambda", "AntiLambda", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 3)) { histos.add("h3dXiMinusSpectrum", "h3dXiMinusSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); + histos.add("h3dXiMinusSpectrumY", "h3dXiMinusSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); histos.add("hXiMinusEtaVsPtVsPhi", "hXiMinusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("sameEvent/Signal/XiMinus", "XiMinus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisVtxZNDim, axisMultNDim}); + histos.add("hXiMinusEtaVsPtVsPhiBg", "hXiMinusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("sameEvent/Signal/XiMinus", "XiMinus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 4)) { histos.add("h3dXiPlusSpectrum", "h3dXiPlusSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); + histos.add("h3dXiPlusSpectrumY", "h3dXiPlusSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); histos.add("hXiPlusEtaVsPtVsPhi", "hXiPlusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("sameEvent/Signal/XiPlus", "XiPlus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisVtxZNDim, axisMultNDim}); + histos.add("hXiPlusEtaVsPtVsPhiBg", "hXiPlusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("sameEvent/Signal/XiPlus", "XiPlus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 5)) { histos.add("h3dOmegaMinusSpectrum", "h3dOmegaMinusSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); + histos.add("h3dOmegaMinusSpectrumY", "h3dOmegaMinusSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); histos.add("hOmegaMinusEtaVsPtVsPhi", "hOmegaMinusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("sameEvent/Signal/OmegaMinus", "OmegaMinus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisVtxZNDim, axisMultNDim}); + histos.add("hOmegaMinusEtaVsPtVsPhiBg", "hOmegaMinusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("sameEvent/Signal/OmegaMinus", "OmegaMinus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 6)) { histos.add("h3dOmegaPlusSpectrum", "h3dOmegaPlusSpectrum", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); + histos.add("h3dOmegaPlusSpectrumY", "h3dOmegaPlusSpectrumY", kTH3F, {axisPtQA, axisMult, {3, 0.5f, 3.5f}}); histos.add("hOmegaPlusEtaVsPtVsPhi", "hOmegaPlusEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); - histos.add("sameEvent/Signal/OmegaPlus", "OmegaPlus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisVtxZNDim, axisMultNDim}); + histos.add("hOmegaPlusEtaVsPtVsPhiBg", "hOmegaPlusEtaVsPtVsPhiBg", kTH3F, {axisPtQA, axisEta, axisPhi}); + histos.add("sameEvent/Signal/OmegaPlus", "OmegaPlus", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); } if (bitcheck(doCorrelation, 7)) { - histos.add("sameEvent/Pion", "Pion", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisVtxZNDim, axisMultNDim}); + histos.add("sameEvent/Pion", "Pion", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); histos.add("hPionEtaVsPtVsPhi", "hPionEtaVsPtVsPhi", kTH3F, {axisPtQA, axisEta, axisPhi}); } LOGF(info, "Init THnFs done"); @@ -461,6 +576,48 @@ struct correlateStrangeness { histos.add("EventQA/hMixingQA", "mixing QA", kTH1F, {{2, -0.5, 1.5}}); histos.add("EventQA/hMult", "Multiplicity", kTH1F, {axisMult}); histos.add("EventQA/hPvz", ";pvz;Entries", kTH1F, {{30, -15, 15}}); + + // MC generated plots + if (doprocessMCGenerated) { + histos.add("Generated/hPion", "", kTH2F, {axisPtQA, axisEta}); + histos.add("Generated/hK0Short", "", kTH2F, {axisPtQA, axisEta}); + histos.add("Generated/hLambda", "", kTH2F, {axisPtQA, axisEta}); + histos.add("Generated/hAntiLambda", "", kTH2F, {axisPtQA, axisEta}); + histos.add("Generated/hXiMinus", "", kTH2F, {axisPtQA, axisEta}); + histos.add("Generated/hXiPlus", "", kTH2F, {axisPtQA, axisEta}); + histos.add("Generated/hOmegaMinus", "", kTH2F, {axisPtQA, axisEta}); + histos.add("Generated/hOmegaPlus", "", kTH2F, {axisPtQA, axisEta}); + + histos.addClone("Generated/", "GeneratedWithPV/"); + + // histograms within |y|<0.5, vs multiplicity + histos.add("GeneratedWithPV/hPion_MidYVsMult", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hK0Short_MidYVsMult", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hLambda_MidYVsMult", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hAntiLambda_MidYVsMult", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hXiMinus_MidYVsMult", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hXiPlus_MidYVsMult", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hOmegaMinus_MidYVsMult", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hOmegaPlus_MidYVsMult", "", kTH2F, {axisPtQA, axisMult}); + + histos.add("GeneratedWithPV/hPion_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hK0Short_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hLambda_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hAntiLambda_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hXiMinus_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hXiPlus_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hOmegaMinus_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); + histos.add("GeneratedWithPV/hOmegaPlus_MidYVsMult_TwoPVsOrMore", "", kTH2F, {axisPtQA, axisMult}); + } + + // initialize CCDB *only* if efficiency correction requested + // skip if not requested, saves a bit of time + if (applyEfficiencyCorrection) { + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } } void processSameEventHV0s(soa::Join::iterator const& collision, @@ -475,7 +632,7 @@ struct correlateStrangeness { if (TMath::Abs(collision.posZ()) > zVertexCut) { return; } - if (collision.centFT0M() > axisRanges[4][1] || collision.centFT0M() < axisRanges[4][0]) { + if (collision.centFT0M() > axisRanges[5][1] || collision.centFT0M() < axisRanges[5][0]) { return; } // ________________________________________________ @@ -485,14 +642,25 @@ struct correlateStrangeness { histos.fill(HIST("EventQA/hPvz"), collision.posZ()); } // Do basic QA + TH2F* hEfficiencyV0[3]; + hEfficiencyV0[0] = hEfficiencyK0Short; + hEfficiencyV0[1] = hEfficiencyLambda; + hEfficiencyV0[2] = hEfficiencyAntiLambda; + for (auto const& v0 : associatedV0s) { auto v0Data = v0.v0Data(); static_for<0, 2>([&](auto i) { constexpr int index = i.value; - if (v0.compatible(index) && bitcheck(doCorrelation, index)) { - histos.fill(HIST("h3d") + HIST(v0names[index]) + HIST("Spectrum"), v0Data.pt(), collision.centFT0M(), v0.invMassRegion(index)); + if (v0.compatible(index) && (!doMCassociation || v0.mcTrue(index)) && bitcheck(doCorrelation, index)) { + float weight = applyEfficiencyCorrection ? 1. / hEfficiencyV0[index]->GetBinContent(hEfficiencyV0[index]->GetXaxis()->FindBin(v0Data.pt()), hEfficiencyV0[index]->GetYaxis()->FindBin(v0Data.eta())) : 1.0f; + histos.fill(HIST("h3d") + HIST(v0names[index]) + HIST("Spectrum"), v0Data.pt(), collision.centFT0M(), v0.invMassRegion(index), weight); + if (std::abs(v0Data.rapidity(index)) < 0.5) { + histos.fill(HIST("h3d") + HIST(v0names[index]) + HIST("SpectrumY"), v0Data.pt(), collision.centFT0M(), v0.invMassRegion(index), weight); + } if (v0.invMassRegionCheck(index, 2)) histos.fill(HIST("h") + HIST(v0names[index]) + HIST("EtaVsPtVsPhi"), v0Data.pt(), v0Data.eta(), v0Data.phi()); + if (v0.invMassRegionCheck(index, 1) || v0.invMassRegionCheck(index, 3)) + histos.fill(HIST("h") + HIST(v0names[index]) + HIST("EtaVsPtVsPhiBg"), v0Data.pt(), v0Data.eta(), v0Data.phi()); } }); } @@ -520,7 +688,7 @@ struct correlateStrangeness { if (TMath::Abs(collision.posZ()) > zVertexCut) { return; } - if (collision.centFT0M() > axisRanges[4][1] || collision.centFT0M() < axisRanges[4][0]) { + if (collision.centFT0M() > axisRanges[5][1] || collision.centFT0M() < axisRanges[5][0]) { return; } // ________________________________________________ @@ -528,14 +696,26 @@ struct correlateStrangeness { histos.fill(HIST("EventQA/hMult"), collision.centFT0M()); histos.fill(HIST("EventQA/hPvz"), collision.posZ()); // Do basic QA + TH2F* hEfficiencyCascade[4]; + hEfficiencyCascade[0] = hEfficiencyXiMinus; + hEfficiencyCascade[1] = hEfficiencyXiPlus; + hEfficiencyCascade[2] = hEfficiencyOmegaMinus; + hEfficiencyCascade[3] = hEfficiencyOmegaPlus; + for (auto const& casc : associatedCascades) { auto cascData = casc.cascData(); static_for<0, 3>([&](auto i) { constexpr int index = i.value; - if (casc.compatible(index) && bitcheck(doCorrelation, index + 3)) { - histos.fill(HIST("h3d") + HIST(cascadenames[index]) + HIST("Spectrum"), cascData.pt(), collision.centFT0M(), casc.invMassRegion(index)); + float weight = applyEfficiencyCorrection ? 1. / hEfficiencyCascade[index]->GetBinContent(hEfficiencyCascade[index]->GetXaxis()->FindBin(cascData.pt()), hEfficiencyCascade[index]->GetYaxis()->FindBin(cascData.eta())) : 1.0f; + if (casc.compatible(index) && (!doMCassociation || casc.mcTrue(index)) && bitcheck(doCorrelation, index + 3)) { + histos.fill(HIST("h3d") + HIST(cascadenames[index]) + HIST("Spectrum"), cascData.pt(), collision.centFT0M(), casc.invMassRegion(index), weight); + if (std::abs(cascData.rapidity(index)) < 0.5) { + histos.fill(HIST("h3d") + HIST(cascadenames[index]) + HIST("SpectrumY"), cascData.pt(), collision.centFT0M(), casc.invMassRegion(index), weight); + } if (casc.invMassRegionCheck(index, 2)) histos.fill(HIST("h") + HIST(cascadenames[index]) + HIST("EtaVsPtVsPhi"), cascData.pt(), cascData.eta(), cascData.phi()); + if (casc.invMassRegionCheck(index, 1) || casc.invMassRegionCheck(index, 3)) + histos.fill(HIST("h") + HIST(cascadenames[index]) + HIST("EtaVsPtVsPhiBg"), cascData.pt(), cascData.eta(), cascData.phi()); } }); } @@ -560,7 +740,7 @@ struct correlateStrangeness { if (TMath::Abs(collision.posZ()) > zVertexCut) { return; } - if (collision.centFT0M() > axisRanges[4][1] || collision.centFT0M() < axisRanges[4][0]) { + if (collision.centFT0M() > axisRanges[5][1] || collision.centFT0M() < axisRanges[5][0]) { return; } // ________________________________________________ @@ -596,9 +776,9 @@ struct correlateStrangeness { continue; if (TMath::Abs(collision1.posZ()) > zVertexCut || TMath::Abs(collision2.posZ()) > zVertexCut) continue; - if (collision1.centFT0M() > axisRanges[4][1] || collision1.centFT0M() < axisRanges[4][0]) + if (collision1.centFT0M() > axisRanges[5][1] || collision1.centFT0M() < axisRanges[5][0]) continue; - if (collision2.centFT0M() > axisRanges[4][1] || collision2.centFT0M() < axisRanges[4][0]) + if (collision2.centFT0M() > axisRanges[5][1] || collision2.centFT0M() < axisRanges[5][0]) continue; if (!doprocessMixedEventHCascades) { @@ -629,9 +809,9 @@ struct correlateStrangeness { continue; if (TMath::Abs(collision1.posZ()) > zVertexCut || TMath::Abs(collision2.posZ()) > zVertexCut) continue; - if (collision1.centFT0M() > axisRanges[4][1] || collision1.centFT0M() < axisRanges[4][0]) + if (collision1.centFT0M() > axisRanges[5][1] || collision1.centFT0M() < axisRanges[5][0]) continue; - if (collision2.centFT0M() > axisRanges[4][1] || collision2.centFT0M() < axisRanges[4][0]) + if (collision2.centFT0M() > axisRanges[5][1] || collision2.centFT0M() < axisRanges[5][0]) continue; if (collision1.globalIndex() == collision2.globalIndex()) { @@ -661,9 +841,9 @@ struct correlateStrangeness { continue; if (TMath::Abs(collision1.posZ()) > zVertexCut || TMath::Abs(collision2.posZ()) > zVertexCut) continue; - if (collision1.centFT0M() > axisRanges[4][1] || collision1.centFT0M() < axisRanges[4][0]) + if (collision1.centFT0M() > axisRanges[5][1] || collision1.centFT0M() < axisRanges[5][0]) continue; - if (collision2.centFT0M() > axisRanges[4][1] || collision2.centFT0M() < axisRanges[4][0]) + if (collision2.centFT0M() > axisRanges[5][1] || collision2.centFT0M() < axisRanges[5][0]) continue; if (collision1.globalIndex() == collision2.globalIndex()) { @@ -682,6 +862,119 @@ struct correlateStrangeness { fillCorrelationsPion(slicedTriggerTracks, slicedAssocPions, true, collision1.posZ(), collision1.centFT0M()); } } + void processMCGenerated(aod::McCollision const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& mcParticles) + { + for (auto const& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) + continue; + if (abs(mcParticle.pdgCode()) == 211) + histos.fill(HIST("Generated/hPion"), mcParticle.pt(), mcParticle.eta()); + if (abs(mcParticle.pdgCode()) == 310) + histos.fill(HIST("Generated/hK0Short"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == 3122) + histos.fill(HIST("Generated/hLambda"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == -3122) + histos.fill(HIST("Generated/hAntiLambda"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == 3312) + histos.fill(HIST("Generated/hXiMinus"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == -3312) + histos.fill(HIST("Generated/hXiPlus"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == 3334) + histos.fill(HIST("Generated/hOmegaMinus"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == -3334) + histos.fill(HIST("Generated/hOmegaPlus"), mcParticle.pt(), mcParticle.eta()); + } + + if (collisions.size() < 1) + return; + + // determine best collision properties + int biggestNContribs = -1; + int bestCollisionFT0Mpercentile = -1; + float bestCollisionVtxZ = 0.0f; + bool bestCollisionSel8 = false; + for (auto& collision : collisions) { + if (biggestNContribs < collision.numContrib()) { + biggestNContribs = collision.numContrib(); + bestCollisionFT0Mpercentile = collision.centFT0M(); + bestCollisionSel8 = collision.sel8(); + bestCollisionVtxZ = collision.posZ(); + } + } + + if (collisions.size() > 1) { + for (auto const& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) + continue; + if (abs(mcParticle.y()) < 0.5) { + if (abs(mcParticle.pdgCode()) == 211) + histos.fill(HIST("GeneratedWithPV/hPion_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (abs(mcParticle.pdgCode()) == 310) + histos.fill(HIST("GeneratedWithPV/hK0Short_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == 3122) + histos.fill(HIST("GeneratedWithPV/hLambda_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == -3122) + histos.fill(HIST("GeneratedWithPV/hAntiLambda_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == 3312) + histos.fill(HIST("GeneratedWithPV/hXiMinus_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == -3312) + histos.fill(HIST("GeneratedWithPV/hXiPlus_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == 3334) + histos.fill(HIST("GeneratedWithPV/hOmegaMinus_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == -3334) + histos.fill(HIST("GeneratedWithPV/hOmegaPlus_MidYVsMult_TwoPVsOrMore"), mcParticle.pt(), bestCollisionFT0Mpercentile); + } + } + } + + // do selections on best collision + // WARNING: if 2 PV case large, this will not necessarily be fine! + // caution advised! + if (!bestCollisionSel8) + return; + if (std::abs(bestCollisionVtxZ) > 10.0f) + return; + + for (auto const& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) + continue; + if (abs(mcParticle.pdgCode()) == 211) + histos.fill(HIST("GeneratedWithPV/hPion"), mcParticle.pt(), mcParticle.eta()); + if (abs(mcParticle.pdgCode()) == 310) + histos.fill(HIST("GeneratedWithPV/hK0Short"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == 3122) + histos.fill(HIST("GeneratedWithPV/hLambda"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == -3122) + histos.fill(HIST("GeneratedWithPV/hAntiLambda"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == 3312) + histos.fill(HIST("GeneratedWithPV/hXiMinus"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == -3312) + histos.fill(HIST("GeneratedWithPV/hXiPlus"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == 3334) + histos.fill(HIST("GeneratedWithPV/hOmegaMinus"), mcParticle.pt(), mcParticle.eta()); + if (mcParticle.pdgCode() == -3334) + histos.fill(HIST("GeneratedWithPV/hOmegaPlus"), mcParticle.pt(), mcParticle.eta()); + + if (abs(mcParticle.y()) < 0.5) { + if (abs(mcParticle.pdgCode()) == 211) + histos.fill(HIST("GeneratedWithPV/hPion_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (abs(mcParticle.pdgCode()) == 310) + histos.fill(HIST("GeneratedWithPV/hK0Short_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == 3122) + histos.fill(HIST("GeneratedWithPV/hLambda_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == -3122) + histos.fill(HIST("GeneratedWithPV/hAntiLambda_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == 3312) + histos.fill(HIST("GeneratedWithPV/hXiMinus_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == -3312) + histos.fill(HIST("GeneratedWithPV/hXiPlus_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == 3334) + histos.fill(HIST("GeneratedWithPV/hOmegaMinus_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + if (mcParticle.pdgCode() == -3334) + histos.fill(HIST("GeneratedWithPV/hOmegaPlus_MidYVsMult"), mcParticle.pt(), bestCollisionFT0Mpercentile); + } + } + } PROCESS_SWITCH(correlateStrangeness, processSameEventHV0s, "Process same events, h-V0s", true); PROCESS_SWITCH(correlateStrangeness, processSameEventHCascades, "Process same events, h-Cascades", true); @@ -689,6 +982,7 @@ struct correlateStrangeness { PROCESS_SWITCH(correlateStrangeness, processMixedEventHV0s, "Process mixed events, h-V0s", true); PROCESS_SWITCH(correlateStrangeness, processMixedEventHCascades, "Process mixed events, h-Cascades", true); PROCESS_SWITCH(correlateStrangeness, processMixedEventHPions, "Process mixed events, h-Pion", true); + PROCESS_SWITCH(correlateStrangeness, processMCGenerated, "Process MC generated", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/hypertriton3bodyMCQA.cxx b/PWGLF/Tasks/hypertriton3bodyMCQA.cxx new file mode 100644 index 00000000000..c90e8f44cb7 --- /dev/null +++ b/PWGLF/Tasks/hypertriton3bodyMCQA.cxx @@ -0,0 +1,1077 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// Example StoredVtx3BodyDatas analysis task +// ======================== +// +// This code loops over a StoredVtx3BodyDatas table and produces some +// standard analysis output. It requires either +// the hypertriton3bodybuilder or hypertriton3bodyfinder (not recommaended) tasks +// to have been executed in the workflow (before). +// +// author: yuanzhe.wang@cern.ch + +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/Vtx3BodyTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "CommonConstants/PhysicsConstants.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +// using MyTracks = soa::Join; +using MyTracks = soa::Join; + +struct hypertriton3bodyQaMc { + // Basic checks + HistogramRegistry registry{ + "registry", + { + {"hVtxRadius", "hVtxRadius", {HistType::kTH1F, {{1000, 0.0f, 100.0f, "cm"}}}}, + {"hVtxCosPA", "hVtxCosPA", {HistType::kTH1F, {{1000, 0.95f, 1.0f}}}}, + {"hDCATrack0ToPV", "hDCAPosToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, + {"hDCATrack1ToPV", "hDCANegToPV", {HistType::kTH1F, {{1000, 10.0f, 10.0f, "cm"}}}}, + {"hDCATrack2ToPV", "hDCANegToPV", {HistType::kTH1F, {{1000, 10.0f, 10.0f, "cm"}}}}, + {"hDCAVtxDau", "hDCAVtxDau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, + {"hVtxPt", "hVtxPt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, + {"hTrack0Pt", "hTrack0Pt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, + {"hTrack1Pt", "hTrack1Pt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, + {"hTrack2Pt", "hTrack2Pt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, + }, + }; + void init(InitContext const&) + { + AxisSpec massAxis = {120, 2.9f, 3.2f, "Inv. Mass (GeV/c^{2})"}; + + registry.add("hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {massAxis}}); + registry.add("hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {massAxis}}); + } + void process(aod::Collision const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, MyTracks const& tracks) + { + + for (auto& vtx : vtx3bodydatas) { + registry.fill(HIST("hVtxRadius"), vtx.vtxradius()); + registry.fill(HIST("hVtxCosPA"), vtx.vtxcosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hDCATrack0ToPV"), vtx.dcatrack0topv()); + registry.fill(HIST("hDCATrack1ToPV"), vtx.dcatrack1topv()); + registry.fill(HIST("hDCATrack2ToPV"), vtx.dcatrack2topv()); + registry.fill(HIST("hDCAVtxDau"), vtx.dcaVtxdaughters()); + registry.fill(HIST("hVtxPt"), vtx.pt()); + registry.fill(HIST("hTrack0Pt"), vtx.track0pt()); + registry.fill(HIST("hTrack1Pt"), vtx.track1pt()); + registry.fill(HIST("hTrack2Pt"), vtx.track2pt()); + registry.fill(HIST("hMassHypertriton"), vtx.mHypertriton()); + registry.fill(HIST("hMassAntiHypertriton"), vtx.mAntiHypertriton()); + } + } +}; + +struct hypertriton3bodyAnalysisMc { + + HistogramRegistry registry{ + "registry", + { + {"hSelectedEventCounter", "hSelectedEventCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hSelectedCandidatesCounter", "hSelectedCandidatesCounter", {HistType::kTH1F, {{9, 0.0f, 9.0f}}}}, + {"hSelectedTrueHypertritonCounter", "hSelectedTrueHypertritonCounter", {HistType::kTH1F, {{9, 0.0f, 9.0f}}}}, + {"hTestCounter", "hTestCounter", {HistType::kTH1F, {{9, 0.0f, 9.0f}}}}, + {"hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {{100, 2.95f, 3.05f}}}}, + {"hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {{100, 2.95f, 3.05f}}}}, + {"hMassHypertritonTotal", "hMassHypertritonTotal", {HistType::kTH1F, {{300, 2.9f, 3.2f}}}}, + {"hPtProton", "hPtProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtAntiPion", "hPtAntiPion", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtDeuteron", "hPtDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtPion", "hPtPion", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"h3dMassHypertriton", "h3dMassHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + {"h3dMassAntiHypertriton", "h3dMassAntiHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + {"h3dTotalHypertriton", "h3dTotalHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + {"h3dTotalTrueHypertriton", "h3dTotalTrueHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + }, + }; + + Configurable saveDcaHist{"saveDcaHist", 0, "saveDcaHist"}; + + ConfigurableAxis dcaBinning{"dca-binning", {200, 0.0f, 1.0f}, ""}; + ConfigurableAxis ptBinning{"pt-binning", {200, 0.0f, 10.0f}, ""}; + + void init(InitContext const&) + { + AxisSpec dcaAxis = {dcaBinning, "DCA (cm)"}; + AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/c)"}; + AxisSpec massAxisHypertriton = {40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}; + + if (saveDcaHist == 1) { + registry.add("h3dMassHypertritonDca", "h3dMassHypertritonDca", {HistType::kTH3F, {dcaAxis, ptAxis, massAxisHypertriton}}); + registry.add("h3dMassAntiHypertritonDca", "h3dMassAntiHypertritonDca", {HistType::kTH3F, {dcaAxis, ptAxis, massAxisHypertriton}}); + } + + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(1, "Readin"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(2, "VtxCosPA"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(3, "TrackEta"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(4, "MomRapidity"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(5, "Lifetime"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(6, "DcaV0Dau"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(7, "TPCPID"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(8, "PtCut"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(9, "PionDcatoPV"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(1, "Readin"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(2, "VtxCosPA"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(3, "TrackEta"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(4, "MomRapidity"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(5, "Lifetime"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(6, "DcaV0Dau"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(7, "TPCPID"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(8, "PtCut"); + registry.get(HIST("hSelectedTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(9, "PionDcatoPV"); + } + + // Selection criteria + Configurable vtxcospa{"vtxcospa", 0.9, "Vtx CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; // loose cut + Configurable dcapiontopv{"dcapiontopv", .00, "DCA Pion To PV"}; + Configurable etacut{"etacut", 1, "etacut"}; + Configurable rapidity{"rapidity", 1, "rapidity"}; + Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; + Configurable eventSelection{"eventSelection", true, "event selection"}; + Configurable lifetimecut{"lifetimecut", 40., "lifetimecut"}; + Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; + Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; + Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; + Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; + Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; + Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; + + void process(soa::Join::iterator const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, MyTracks const& tracks, aod::McParticles const& particlesMC) + { + registry.fill(HIST("hSelectedEventCounter"), 0.5); + if (eventSelection && !collision.sel8()) { + return; + } + registry.fill(HIST("hSelectedEventCounter"), 1.5); + + for (auto& vtx : vtx3bodydatas) { + // couldn't filter cosPA and radius variables (dynamic columns) + + // int lLabel = -1; + int lPDG = -1; + float lPt = -1; + double MClifetime = -1; + bool isFromHypertriton = false; + auto lTrack0 = vtx.track0_as(); + auto lTrack1 = vtx.track1_as(); + auto lTrack2 = vtx.track2_as(); + if (lTrack0.has_mcParticle() && lTrack1.has_mcParticle() && lTrack2.has_mcParticle()) { + auto lMCTrack0 = lTrack0.mcParticle_as(); + auto lMCTrack1 = lTrack1.mcParticle_as(); + auto lMCTrack2 = lTrack2.mcParticle_as(); + if (lMCTrack0.has_mothers() && lMCTrack1.has_mothers() && lMCTrack2.has_mothers()) { + for (auto& lMother0 : lMCTrack0.mothers_as()) { + for (auto& lMother1 : lMCTrack1.mothers_as()) { + for (auto& lMother2 : lMCTrack2.mothers_as()) { + if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { + // lLabel = lMother1.globalIndex(); + lPt = lMother1.pt(); + lPDG = lMother1.pdgCode(); + if ((lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) || + (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020)) { + isFromHypertriton = true; + MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); + } + } + } + } + } + } + } + + registry.fill(HIST("hSelectedCandidatesCounter"), 0.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 0.5); + } + + if (vtx.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()) < vtxcospa) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 1.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 1.5); + } + if (TMath::Abs(vtx.track0_as().eta()) > etacut || TMath::Abs(vtx.track1_as().eta()) > etacut || TMath::Abs(vtx.track2_as().eta()) > etacut) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 2.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 2.5); + } + if (TMath::Abs(vtx.yHypertriton()) > rapidity) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 3.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 3.5); + } + double ct = vtx.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassHyperTriton; + if (ct > lifetimecut) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 4.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 4.5); + } + if (vtx.dcaVtxdaughters() > dcavtxdau) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 5.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 5.5); + } + + // 3sigma region for Dalitz plot + double mcsigma = 0.0015; // from local MC + double lowerlimit = o2::constants::physics::MassHyperTriton - 3 * mcsigma; + double upperlimit = o2::constants::physics::MassHyperTriton + 3 * mcsigma; + + // Hypertriton + if (TMath::Abs(vtx.track0_as().tpcNSigmaPr()) < TpcPidNsigmaCut && TMath::Abs(vtx.track1_as().tpcNSigmaPi()) < TpcPidNsigmaCut && TMath::Abs(vtx.track2_as().tpcNSigmaDe()) < TpcPidNsigmaCut) { + registry.fill(HIST("hSelectedCandidatesCounter"), 6.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 6.5); + } + + registry.fill(HIST("hTestCounter"), 0.5); + if (vtx.track1pt() > minPionPt && vtx.track1pt() < maxPionPt) { + registry.fill(HIST("hTestCounter"), 1.5); + if (vtx.track0pt() > minProtonPt && vtx.track0pt() < maxProtonPt) { + registry.fill(HIST("hTestCounter"), 2.5); + if (vtx.pt() > minDeuteronPt && vtx.pt() < maxDeuteronPt) { + registry.fill(HIST("hTestCounter"), 3.5); + } + } + } + + if (vtx.track0pt() > minProtonPt && vtx.track0pt() < maxProtonPt && vtx.track1pt() > minPionPt && vtx.track1pt() < maxPionPt && vtx.track2pt() > minDeuteronPt && vtx.track2pt() < maxDeuteronPt) { + registry.fill(HIST("hSelectedCandidatesCounter"), 7.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 7.5); + } + + if (TMath::Abs(vtx.dcatrack1topv()) > dcapiontopv) { + registry.fill(HIST("hSelectedCandidatesCounter"), 8.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 8.5); + } + + registry.fill(HIST("hPtProton"), vtx.track0pt()); + registry.fill(HIST("hPtAntiPion"), vtx.track1pt()); + registry.fill(HIST("hPtDeuteron"), vtx.track2pt()); + registry.fill(HIST("hMassHypertriton"), vtx.mHypertriton()); + registry.fill(HIST("hMassHypertritonTotal"), vtx.mHypertriton()); + registry.fill(HIST("h3dMassHypertriton"), 0., vtx.pt(), vtx.mHypertriton()); // collision.centV0M() instead of 0. once available + registry.fill(HIST("h3dTotalHypertriton"), ct, vtx.pt(), vtx.mHypertriton()); + if (vtx.mHypertriton() > lowerlimit && vtx.mHypertriton() < upperlimit) { + registry.fill(HIST("hDalitz"), RecoDecay::m2(array{array{vtx.pxtrack0(), vtx.pytrack0(), vtx.pztrack0()}, array{vtx.pxtrack2(), vtx.pytrack2(), vtx.pztrack2()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), + RecoDecay::m2(array{array{vtx.pxtrack0(), vtx.pytrack0(), vtx.pztrack0()}, array{vtx.pxtrack1(), vtx.pytrack1(), vtx.pztrack1()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); + } + + if (isFromHypertriton) { + registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, vtx.mHypertriton()); + } + if (saveDcaHist == 1) { + registry.fill(HIST("h3dMassHypertritonDca"), vtx.dcaVtxdaughters(), vtx.pt(), vtx.mHypertriton()); + } + } + } + } + + // AntiHypertriton + if (TMath::Abs(vtx.track0_as().tpcNSigmaPi()) < TpcPidNsigmaCut && TMath::Abs(vtx.track1_as().tpcNSigmaPr()) < TpcPidNsigmaCut && TMath::Abs(vtx.track2_as().tpcNSigmaDe()) < TpcPidNsigmaCut) { + + registry.fill(HIST("hSelectedCandidatesCounter"), 6.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 6.5); + } + + registry.fill(HIST("hTestCounter"), 0.5); + if (vtx.track0pt() > minPionPt && vtx.track0pt() < maxPionPt) { + registry.fill(HIST("hTestCounter"), 1.5); + if (vtx.track1pt() > minProtonPt && vtx.track1pt() < maxProtonPt) { + registry.fill(HIST("hTestCounter"), 2.5); + if (vtx.pt() > minDeuteronPt && vtx.pt() < maxDeuteronPt) { + registry.fill(HIST("hTestCounter"), 3.5); + } + } + } + + if (vtx.track1pt() > minPionPt && vtx.track1pt() < maxPionPt && vtx.track0pt() > minProtonPt && vtx.track0pt() < maxProtonPt && vtx.track2pt() > minDeuteronPt && vtx.track2pt() < maxDeuteronPt) { + registry.fill(HIST("hSelectedCandidatesCounter"), 7.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 7.5); + } + if (TMath::Abs(vtx.dcatrack0topv()) > dcapiontopv) { + registry.fill(HIST("hSelectedCandidatesCounter"), 8.5); + if (isFromHypertriton) { + registry.fill(HIST("hSelectedTrueHypertritonCounter"), 8.5); + } + + registry.fill(HIST("hPtAntiProton"), vtx.track1pt()); + registry.fill(HIST("hPtPion"), vtx.track0pt()); + registry.fill(HIST("hPtAntiDeuteron"), vtx.track2pt()); + registry.fill(HIST("hMassAntiHypertriton"), vtx.mAntiHypertriton()); + registry.fill(HIST("hMassHypertritonTotal"), vtx.mAntiHypertriton()); + registry.fill(HIST("h3dMassAntiHypertriton"), 0., vtx.pt(), vtx.mAntiHypertriton()); // collision.centV0M() instead of 0. once available + registry.fill(HIST("h3dTotalHypertriton"), ct, vtx.pt(), vtx.mAntiHypertriton()); + if (vtx.mAntiHypertriton() > lowerlimit && vtx.mAntiHypertriton() < upperlimit) { + registry.fill(HIST("hDalitz"), RecoDecay::m2(array{array{vtx.pxtrack1(), vtx.pytrack1(), vtx.pztrack1()}, array{vtx.pxtrack2(), vtx.pytrack2(), vtx.pztrack2()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), + RecoDecay::m2(array{array{vtx.pxtrack1(), vtx.pytrack1(), vtx.pztrack1()}, array{vtx.pxtrack0(), vtx.pytrack0(), vtx.pztrack0()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); + } + + if (isFromHypertriton) { + registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, vtx.mAntiHypertriton()); + } + if (saveDcaHist == 1) { + registry.fill(HIST("h3dMassAntiHypertritonDca"), vtx.dcaVtxdaughters(), vtx.pt(), vtx.mAntiHypertriton()); + } + } + } + } + } + } +}; + +// check vtx3body with mclabels +struct hypertriton3bodyLabelCheck { + HistogramRegistry registry{ + "registry", + { + {"hLabeledVtxCounter", "hLabeledVtxCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hMassTrueH3L", "hMassTrueH3L", {HistType::kTH1F, {{100, 2.95f, 3.05f}}}}, + {"hMassTrueH3LMatter", "hMassTrueH3LMatter", {HistType::kTH1F, {{100, 2.95f, 3.05f}}}}, + {"hMassTrueH3LAntiMatter", "hMassTrueH3LAntiMatter", {HistType::kTH1F, {{100, 2.95f, 3.05f}}}}, + }, + }; + + void init(InitContext const&) + { + registry.get(HIST("hLabeledVtxCounter"))->GetXaxis()->SetBinLabel(1, "Readin"); + registry.get(HIST("hLabeledVtxCounter"))->GetXaxis()->SetBinLabel(2, "TrueMCH3L"); + } + + Configurable eventSelection{"eventSelection", true, "event selection"}; + + void process(soa::Join::iterator const& collision, soa::Join const& vtx3bodydatas, MyTracks const& tracks, aod::McParticles const& particlesMC) + { + if (eventSelection && !collision.sel8()) { + return; + } + + for (auto& vtx : vtx3bodydatas) { + registry.fill(HIST("hLabeledVtxCounter"), 0.5); + if (vtx.mcParticleId() != -1) { + auto mcparticle = vtx.mcParticle_as(); + if (mcparticle.pdgCode() == 1010010030) { + registry.fill(HIST("hLabeledVtxCounter"), 1.5); + registry.fill(HIST("hMassTrueH3L"), vtx.mHypertriton()); + registry.fill(HIST("hMassTrueH3LMatter"), vtx.mHypertriton()); + } else if (mcparticle.pdgCode() == -1010010030) { + registry.fill(HIST("hLabeledVtxCounter"), 1.5); + registry.fill(HIST("hMassTrueH3L"), vtx.mAntiHypertriton()); + registry.fill(HIST("hMassTrueH3LAntiMatter"), vtx.mAntiHypertriton()); + } + } + } + } +}; + +// check the properties of daughters candidates and true daughters +struct hypertriton3bodyTrackMcinfo { + // Basic checks + HistogramRegistry registry{ + "registry", + { + {"hTotalCollCounter", "hTotalCollCounter", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, + {"hParticleCount", "hParticleCount", {HistType::kTH1F, {{7, 0.0f, 7.0f}}}}, + {"hParticleCount2", "hParticleCount2", {HistType::kTH1F, {{7, 0.0f, 7.0f}}}}, // for tpcncls > 70 + {"hProtonCount", "hProtonCount", {HistType::kTH1F, {{6, 0.0f, 6.0f}}}}, + {"hPionCount", "hPionCount", {HistType::kTH1F, {{7, 0.0f, 7.0f}}}}, + {"hDeuteronCount", "hDeuteronCount", {HistType::kTH1F, {{6, 0.0f, 6.0f}}}}, + {"hBackgroundPionCount", "hBackgroundPionCount", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, + + {"hTPCNClsCrossedRows", "hTPCNClsCrossedRows", {HistType::kTH1F, {{240, 0.0f, 240.0f}}}}, + {"hTrackEta", "hTrackEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hTrackITSNcls", "hTrackITSNcls", {HistType::kTH1F, {{10, 0.0f, 10.0f}}}}, + {"hTrackMcRapidity", "hTrackMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hTrackNsigmaProton", "hTrackNsigmaProton", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hTrackNsigmaPion", "hTrackNsigmaPion", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hTrackNsigmaDeuteron", "hTrackNsigmaDeuteron", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + + {"hHypertritonEta", "hHypertritomEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hHypertritonMcRapidity", "hHypertritonMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hHypertritonMcPt", "hHypertritonMcPt", {HistType::kTH1F, {{300, 0.0f, 15.0f}}}}, + {"hProtonEta", "hProtonEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hProtonMcRapidity", "hProtonMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hPionEta", "hPionEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hPionMcRapidity", "hPionMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hDeuteronEta", "hDeuteronEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + {"hDeuteronMcRapidity", "hDeuteronMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, + + {"hDauProtonPt", "hDauProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDauProtonMcPt", "hDauProtonMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDauProtonNsigmaProton", "hDauProtonNsigmaProton", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hDauProtonNsigmaProtonAfterMomCut", "hDauProtonNsigmaProtonAfterMomCut", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hProtonPt", "hProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hProtonP", "hProtonP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hProtonMcPt", "hProtonMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hProtonMcP", "hProtonMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hProtonNsigmaProton", "hProtonNsigmaProton", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hProtonTPCNClsCrossedRows", "hProtonTPCNClsCrossedRows", {HistType::kTH1F, {{240, 0.0f, 240.0f}}}}, + {"hProtonTPCBB", "hProtonTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + {"hProtonTPCBBAfterTPCNclsCut", "hProtonTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + + {"hDauPionPt", "hDauPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDauPionMcPt", "hDauPionMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDauPionNsigmaPion", "hDauPionNsigmaPion", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hDauPionNsigmaPionAfterMomCut", "hDauPionNsigmaPionAfterMomCut", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hPionPt", "hPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPionP", "hPionP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPionMcPt", "hPionMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPionMcP", "hPionMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPionNsigmaPion", "hPionNsigmaPion", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hPionTPCNClsCrossedRows", "hPionTPCNClsCrossedRows", {HistType::kTH1F, {{240, 0.0f, 240.0f}}}}, + {"hPionTPCBB", "hPionTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + {"hPionTPCBBAfterTPCNclsCut", "hPionTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + + {"hDauDeuteronPt", "hDauDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDauDeuteronMcPt", "hDauDeuteronMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDauDeuteronNsigmaDeuteron", "hDauDeuteronNsigmaDeuteron", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hDauDeuteronNsigmaDeuteronAfterMomCut", "hDauDeuteronNsigmaDeuteronAfterMomCut", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hDeuteronPt", "hDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDeuteronP", "hDeuteronP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDeuteronMcPt", "hDeuteronMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDeuteronMcP", "hDeuteronMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hDeuteronNsigmaDeuteron", "hDeuteronNsigmaDeuteron", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hDeuteronTPCNClsCrossedRows", "hDeuteronTPCNClsCrossedRows", {HistType::kTH1F, {{240, 0.0f, 240.0f}}}}, + {"hDeuteronTPCBB", "hDeuteronTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + {"hDeuteronTPCBBAfterTPCNclsCut", "hDeuteronTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + + {"hTPCBB", "hTPCBB", {HistType::kTH2F, {{120, -8.0f, 8.0f, "p/z(GeV/c)"}, {100, 0.0f, 1000.0f, "TPCSignal"}}}}, + }, + }; + + void init(InitContext&) + { + registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(1, "Readin"); + registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(2, "Has_mcparticle"); + registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(3, "Rapidity Cut(off)"); + registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(4, "McisHypertriton"); + registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(5, "McisProton"); + registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(6, "McisPion"); + registry.get(HIST("hParticleCount"))->GetXaxis()->SetBinLabel(7, "McisDeuteron"); + + registry.get(HIST("hParticleCount2"))->GetXaxis()->SetBinLabel(1, "Readin"); + registry.get(HIST("hParticleCount2"))->GetXaxis()->SetBinLabel(2, "Has_mcparticle"); + registry.get(HIST("hParticleCount2"))->GetXaxis()->SetBinLabel(3, "Rapidity Cut(off)"); + registry.get(HIST("hParticleCount2"))->GetXaxis()->SetBinLabel(4, "McisHypertriton"); + registry.get(HIST("hParticleCount2"))->GetXaxis()->SetBinLabel(5, "McisProton"); + registry.get(HIST("hParticleCount2"))->GetXaxis()->SetBinLabel(6, "McisPion"); + registry.get(HIST("hParticleCount2"))->GetXaxis()->SetBinLabel(7, "McisDeuteron"); + + registry.get(HIST("hProtonCount"))->GetXaxis()->SetBinLabel(1, "hasMom"); + registry.get(HIST("hProtonCount"))->GetXaxis()->SetBinLabel(2, "FromHypertriton"); + registry.get(HIST("hProtonCount"))->GetXaxis()->SetBinLabel(3, "TPCNcls"); + registry.get(HIST("hProtonCount"))->GetXaxis()->SetBinLabel(4, "Eta"); + registry.get(HIST("hProtonCount"))->GetXaxis()->SetBinLabel(5, "Pt"); + registry.get(HIST("hProtonCount"))->GetXaxis()->SetBinLabel(6, "TPCPID"); + registry.get(HIST("hPionCount"))->GetXaxis()->SetBinLabel(1, "hasMom"); + registry.get(HIST("hPionCount"))->GetXaxis()->SetBinLabel(2, "FromHypertriton"); + registry.get(HIST("hPionCount"))->GetXaxis()->SetBinLabel(3, "TPCNcls"); + registry.get(HIST("hPionCount"))->GetXaxis()->SetBinLabel(4, "Eta"); + registry.get(HIST("hPionCount"))->GetXaxis()->SetBinLabel(5, "Pt"); + registry.get(HIST("hPionCount"))->GetXaxis()->SetBinLabel(6, "TPCPID"); + registry.get(HIST("hPionCount"))->GetXaxis()->SetBinLabel(7, "DcatoPV"); + registry.get(HIST("hDeuteronCount"))->GetXaxis()->SetBinLabel(1, "hasMom"); + registry.get(HIST("hDeuteronCount"))->GetXaxis()->SetBinLabel(2, "FromHypertriton"); + registry.get(HIST("hDeuteronCount"))->GetXaxis()->SetBinLabel(3, "TPCNcls"); + registry.get(HIST("hDeuteronCount"))->GetXaxis()->SetBinLabel(4, "Eta"); + registry.get(HIST("hDeuteronCount"))->GetXaxis()->SetBinLabel(5, "Pt"); + registry.get(HIST("hDeuteronCount"))->GetXaxis()->SetBinLabel(6, "TPCPID"); + registry.get(HIST("hBackgroundPionCount"))->GetXaxis()->SetBinLabel(1, "NotFromHypertriton"); + registry.get(HIST("hBackgroundPionCount"))->GetXaxis()->SetBinLabel(2, "TPCNcls"); + registry.get(HIST("hBackgroundPionCount"))->GetXaxis()->SetBinLabel(3, "Eta"); + registry.get(HIST("hBackgroundPionCount"))->GetXaxis()->SetBinLabel(4, "Pt"); + registry.get(HIST("hBackgroundPionCount"))->GetXaxis()->SetBinLabel(5, "TPCPID"); + } + + Configurable dcapiontopv{"dcapiontopv", .05, "DCA Pion To PV"}; + Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; + Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; + Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; + Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; + Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; + Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; + + void process(aod::Collision const& collision, aod::McParticles const& mcparticles, MyTracks const& tracks) + { + + registry.fill(HIST("hTotalCollCounter"), 0.5); + + for (auto& track : tracks) { + registry.fill(HIST("hParticleCount"), 0.5); + registry.fill(HIST("hTrackITSNcls"), track.itsNCls()); + if (track.tpcNClsCrossedRows() > 70) { + registry.fill(HIST("hParticleCount2"), 0.5); + } + registry.fill(HIST("hTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); + registry.fill(HIST("hTrackNsigmaDeuteron"), track.tpcNSigmaDe()); + registry.fill(HIST("hTrackNsigmaProton"), track.tpcNSigmaPr()); + registry.fill(HIST("hTrackNsigmaPion"), track.tpcNSigmaPi()); + + if (!track.has_mcParticle()) { + continue; + } + registry.fill(HIST("hParticleCount"), 1.5); + auto mcparticle = track.mcParticle_as(); + if (track.tpcNClsCrossedRows() > 70) { + registry.fill(HIST("hParticleCount2"), 1.5); + } + registry.fill(HIST("hTPCBB"), track.p() * track.sign(), track.tpcSignal()); + + // if (TMath::Abs(mcparticle.y()) > 0.9) {continue;} + registry.fill(HIST("hParticleCount"), 2.5); + if (track.tpcNClsCrossedRows() > 70) { + registry.fill(HIST("hParticleCount2"), 2.5); + } + registry.fill(HIST("hTrackEta"), track.eta()); + registry.fill(HIST("hTrackMcRapidity"), mcparticle.y()); + + // Hypertriton + if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { + registry.fill(HIST("hParticleCount"), 3.5); + if (track.tpcNClsCrossedRows() > 70) { + registry.fill(HIST("hParticleCount2"), 3.5); + } + registry.fill(HIST("hHypertritonMcPt"), mcparticle.pt()); + registry.fill(HIST("hHypertritonEta"), track.eta()); + registry.fill(HIST("hHypertritonMcRapidity"), mcparticle.y()); + } + + // Proton + if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { + registry.fill(HIST("hParticleCount"), 4.5); + if (track.tpcNClsCrossedRows() > 70) { + registry.fill(HIST("hParticleCount2"), 4.5); + registry.fill(HIST("hProtonTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); + } + + if (mcparticle.has_mothers()) { + registry.fill(HIST("hProtonCount"), 0.5); + for (auto& particleMother : mcparticle.mothers_as()) { + if (particleMother.pdgCode() != 1010010030 && mcparticle.pdgCode() != -1010010030) { + continue; + } + bool haveProton = false, havePion = false, haveDeuteron = false; + bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; + for (auto& mcparticleDaughter : particleMother.daughters_as()) { + if (mcparticleDaughter.pdgCode() == 2212) { + haveProton = true; + } + if (mcparticleDaughter.pdgCode() == -2212) { + haveAntiProton = true; + } + if (mcparticleDaughter.pdgCode() == 211) { + havePion = true; + } + if (mcparticleDaughter.pdgCode() == -211) { + haveAntiPion = true; + } + if (mcparticleDaughter.pdgCode() == 1000010020) { + haveDeuteron = true; + } + if (mcparticleDaughter.pdgCode() == -1000010020) { + haveAntiDeuteron = true; + } + } + if (!(haveProton && haveAntiPion && haveDeuteron && particleMother.pdgCode() == 1010010030) && !(haveAntiProton && havePion && haveAntiDeuteron && particleMother.pdgCode() == -1010010030)) { + continue; + } + registry.fill(HIST("hProtonCount"), 1.5); + registry.fill(HIST("hDauProtonPt"), track.pt()); + registry.fill(HIST("hDauProtonMcPt"), mcparticle.pt()); + registry.fill(HIST("hDauProtonNsigmaProton"), track.tpcNSigmaPr()); + if (track.p() > 1.5) { + registry.fill(HIST("hDauProtonNsigmaProtonAfterMomCut"), track.tpcNSigmaPr()); + } + if (track.tpcNClsCrossedRows() < 70) { + continue; + } + registry.fill(HIST("hProtonCount"), 2.5); + if (TMath::Abs(track.eta()) > 0.9) { + continue; + } + registry.fill(HIST("hProtonCount"), 3.5); + if (track.pt() < minProtonPt || track.pt() > maxProtonPt) { + continue; + } + registry.fill(HIST("hProtonCount"), 4.5); + if (TMath::Abs(track.tpcNSigmaPr()) > 5) { + continue; + } + registry.fill(HIST("hProtonCount"), 5.5); + } + } + + registry.fill(HIST("hProtonMcPt"), mcparticle.pt()); + registry.fill(HIST("hProtonMcP"), mcparticle.p()); + registry.fill(HIST("hProtonPt"), track.pt()); + registry.fill(HIST("hProtonP"), track.p()); + + registry.fill(HIST("hProtonNsigmaProton"), track.tpcNSigmaPr()); + registry.fill(HIST("hProtonTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); + registry.fill(HIST("hProtonEta"), track.eta()); + registry.fill(HIST("hProtonMcRapidity"), mcparticle.y()); + registry.fill(HIST("hProtonTPCBB"), track.p() * track.sign(), track.tpcSignal()); + } + + // Pion + if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { + registry.fill(HIST("hParticleCount"), 5.5); + if (track.tpcNClsCrossedRows() > 70) { + registry.fill(HIST("hParticleCount2"), 5.5); + registry.fill(HIST("hPionTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); + } + + if (mcparticle.has_mothers()) { + registry.fill(HIST("hPionCount"), 0.5); + for (auto& particleMother : mcparticle.mothers_as()) { + if (particleMother.pdgCode() != 1010010030 && particleMother.pdgCode() != -1010010030) { + continue; + } + bool haveProton = false, havePion = false, haveDeuteron = false; + bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; + for (auto& mcparticleDaughter : particleMother.daughters_as()) { + if (mcparticleDaughter.pdgCode() == 2212) { + haveProton = true; + } + if (mcparticleDaughter.pdgCode() == -2212) { + haveAntiProton = true; + } + if (mcparticleDaughter.pdgCode() == 211) { + havePion = true; + } + if (mcparticleDaughter.pdgCode() == -211) { + haveAntiPion = true; + } + if (mcparticleDaughter.pdgCode() == 1000010020) { + haveDeuteron = true; + } + if (mcparticleDaughter.pdgCode() == -1000010020) { + haveAntiDeuteron = true; + } + } + if (!(haveProton && haveAntiPion && haveDeuteron && particleMother.pdgCode() == 1010010030) && !(haveAntiProton && havePion && haveAntiDeuteron && particleMother.pdgCode() == -1010010030)) { + continue; + } + registry.fill(HIST("hPionCount"), 1.5); + registry.fill(HIST("hDauPionPt"), track.pt()); + registry.fill(HIST("hDauPionMcPt"), mcparticle.pt()); + registry.fill(HIST("hDauPionNsigmaPion"), track.tpcNSigmaPi()); + if (track.p() > 0.2) { + registry.fill(HIST("hDauPionNsigmaPionAfterMomCut"), track.tpcNSigmaPi()); + } + if (track.tpcNClsCrossedRows() < 70) { + continue; + } + registry.fill(HIST("hPionCount"), 2.5); + if (TMath::Abs(track.eta()) > 0.9) { + continue; + } + registry.fill(HIST("hPionCount"), 3.5); + if (track.pt() < minPionPt || track.pt() > maxPionPt) { + continue; + } + registry.fill(HIST("hPionCount"), 4.5); + if (TMath::Abs(track.tpcNSigmaPi()) > 5) { + continue; + } + registry.fill(HIST("hPionCount"), 5.5); + if (TMath::Abs(track.dcaXY()) < dcapiontopv) { + continue; + } + registry.fill(HIST("hPionCount"), 6.5); + } + } + + bool isFromHypertriton = false; + if (mcparticle.has_mothers()) { + for (auto& particleMother : mcparticle.mothers_as()) { + if (particleMother.pdgCode() == 1010010030 || particleMother.pdgCode() == -1010010030) { + isFromHypertriton = true; + } + } + } + + while (!isFromHypertriton) { + registry.fill(HIST("hBackgroundPionCount"), 0.5); + if (track.tpcNClsCrossedRows() < 70) { + break; + } + registry.fill(HIST("hBackgroundPionCount"), 1.5); + if (TMath::Abs(track.eta()) > 0.9) { + break; + } + registry.fill(HIST("hBackgroundPionCount"), 2.5); + if (track.pt() < minPionPt || track.pt() > maxPionPt) { + break; + } + registry.fill(HIST("hBackgroundPionCount"), 3.5); + if (TMath::Abs(track.tpcNSigmaPi()) > 5) { + break; + } + registry.fill(HIST("hBackgroundPionCount"), 4.5); + break; + } + + registry.fill(HIST("hPionMcPt"), mcparticle.pt()); + registry.fill(HIST("hPionMcP"), mcparticle.p()); + registry.fill(HIST("hPionPt"), track.pt()); + registry.fill(HIST("hPionP"), track.p()); + + registry.fill(HIST("hPionNsigmaPion"), track.tpcNSigmaPi()); + registry.fill(HIST("hPionTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); + registry.fill(HIST("hPionEta"), track.eta()); + registry.fill(HIST("hPionMcRapidity"), mcparticle.y()); + registry.fill(HIST("hPionTPCBB"), track.p() * track.sign(), track.tpcSignal()); + } + + // Deuteron + if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { + registry.fill(HIST("hParticleCount"), 6.5); + if (track.tpcNClsCrossedRows() > 70) { + registry.fill(HIST("hParticleCount2"), 6.5); + registry.fill(HIST("hDeuteronTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); + } + + if (mcparticle.has_mothers()) { + registry.fill(HIST("hDeuteronCount"), 0.5); + for (auto& particleMother : mcparticle.mothers_as()) { + if (particleMother.pdgCode() != 1010010030 && particleMother.pdgCode() != -1010010030) { + continue; + } + bool haveProton = false, havePion = false, haveDeuteron = false; + bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; + for (auto& mcparticleDaughter : particleMother.daughters_as()) { + if (mcparticleDaughter.pdgCode() == 2212) { + haveProton = true; + } + if (mcparticleDaughter.pdgCode() == -2212) { + haveAntiProton = true; + } + if (mcparticleDaughter.pdgCode() == 211) { + havePion = true; + } + if (mcparticleDaughter.pdgCode() == -211) { + haveAntiPion = true; + } + if (mcparticleDaughter.pdgCode() == 1000010020) { + haveDeuteron = true; + } + if (mcparticleDaughter.pdgCode() == -1000010020) { + haveAntiDeuteron = true; + } + } + if (!(haveProton && haveAntiPion && haveDeuteron && particleMother.pdgCode() == 1010010030) && !(haveAntiProton && havePion && haveAntiDeuteron && particleMother.pdgCode() == -1010010030)) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 1.5); + registry.fill(HIST("hDauDeuteronPt"), track.pt()); + registry.fill(HIST("hDauDeuteronMcPt"), mcparticle.pt()); + registry.fill(HIST("hDauDeuteronNsigmaDeuteron"), track.tpcNSigmaDe()); + if (track.p() > 1.5) { + registry.fill(HIST("hDauDeuteronNsigmaDeuteronAfterMomCut"), track.tpcNSigmaDe()); + } + if (track.tpcNClsCrossedRows() < 70) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 2.5); + if (TMath::Abs(track.eta()) > 0.9) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 3.5); + if (track.pt() < minDeuteronPt || track.pt() > maxDeuteronPt) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 4.5); + if (TMath::Abs(track.tpcNSigmaDe()) > 5) { + continue; + } + registry.fill(HIST("hDeuteronCount"), 5.5); + } + } + + registry.fill(HIST("hDeuteronMcPt"), mcparticle.pt()); + registry.fill(HIST("hDeuteronMcP"), mcparticle.p()); + registry.fill(HIST("hDeuteronPt"), track.pt()); + registry.fill(HIST("hDeuteronP"), track.p()); + + registry.fill(HIST("hDeuteronNsigmaDeuteron"), track.tpcNSigmaDe()); + registry.fill(HIST("hDeuteronTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); + registry.fill(HIST("hDeuteronEta"), track.eta()); + registry.fill(HIST("hDeuteronMcRapidity"), mcparticle.y()); + registry.fill(HIST("hDeuteronTPCBB"), track.p() * track.sign(), track.tpcSignal()); + } + } + } +}; + +namespace o2::aod +{ +namespace mcparticleidcheck +{ +DECLARE_SOA_COLUMN(HypertritonDaughterPdgCode, hypertritonDaughterPdgCode, int); +} +DECLARE_SOA_TABLE(McHypertritonCheck, "AOD", "HypCheck", + mcparticleidcheck::HypertritonDaughterPdgCode) +} // namespace o2::aod + +// check the performance of mcparticle +struct hypertriton3bodyMcParticleCount { + // Basic checks + Produces hypertrtitonCheckTable; + HistogramRegistry registry{ + "registry", + { + {"hTotalMcCollCounter", "hTotalMcCollCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + + {"h3dMCHypertriton", "h3dMCHypertriton", {HistType::kTH3F, {{20, -1.0f, 1.0f, "Rapidity"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {50, 0.0f, 50.0f, "ct(cm)"}}}}, + {"h3dMCDecayedHypertriton", "h3dMCDecayedHypertriton", {HistType::kTH3F, {{20, -1.0f, 1.0f, "Rapidity"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {50, 0.0f, 50.0f, "ct(cm)"}}}}, + {"hMcHypertritonCheck", "hMcHypertritonCheck", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, + {"hMcPhysicalPrimaryParticleCount", "hMcPhysicalPrimaryParticleCount", {HistType::kTH1F, {{8, 0.0f, 8.0f}}}}, + + {"hMcHypertritonCount", "hMcHypertritonCount", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, + {"hMcHypertritonDecayCount", "hMcHypertritonDecayCount", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, + {"hMcHypertritonPt", "hMcHypertritonPt", {HistType::kTH1F, {{300, 0.0f, 15.0f}}}}, + {"hMcHypertritonLifeTime", "hMcHypertritonLifeTime", {HistType::kTH1F, {{500, 0.0f, 500.0f}}}}, + {"hMcProtonPt", "hMcProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hMcPionPt", "hMcPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hMcDeuteronPt", "hMcDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + + {"hMcRecoInvMass", "hMcRecoInvMass", {HistType::kTH1F, {{100, 2.95, 3.05f}}}}, + }, + }; + + void init(InitContext&) + { + registry.get(HIST("hTotalMcCollCounter"))->GetXaxis()->SetBinLabel(1, "Total Count"); + registry.get(HIST("hTotalMcCollCounter"))->GetXaxis()->SetBinLabel(2, "Recoonstructed"); + + registry.get(HIST("hMcHypertritonCheck"))->GetXaxis()->SetBinLabel(1, "PdgCode"); + registry.get(HIST("hMcHypertritonCheck"))->GetXaxis()->SetBinLabel(2, "Rapidity"); + registry.get(HIST("hMcHypertritonCheck"))->GetXaxis()->SetBinLabel(3, "Lifetime"); + registry.get(HIST("hMcHypertritonCheck"))->GetXaxis()->SetBinLabel(4, "PtCut"); + + registry.get(HIST("hMcPhysicalPrimaryParticleCount"))->GetXaxis()->SetBinLabel(1, "ReadinAfterEvtRecSelCut(off)"); + registry.get(HIST("hMcPhysicalPrimaryParticleCount"))->GetXaxis()->SetBinLabel(2, "IsPhysicalPrimary"); + registry.get(HIST("hMcPhysicalPrimaryParticleCount"))->GetXaxis()->SetBinLabel(3, "y<0.9(off)"); + registry.get(HIST("hMcPhysicalPrimaryParticleCount"))->GetXaxis()->SetBinLabel(4, "(Anti)Proton"); + registry.get(HIST("hMcPhysicalPrimaryParticleCount"))->GetXaxis()->SetBinLabel(5, "(Anti)Pion"); + registry.get(HIST("hMcPhysicalPrimaryParticleCount"))->GetXaxis()->SetBinLabel(6, "(Anti)Deuteron"); + registry.get(HIST("hMcPhysicalPrimaryParticleCount"))->GetXaxis()->SetBinLabel(7, "(Anti)Hypertriton"); + registry.get(HIST("hMcPhysicalPrimaryParticleCount"))->GetXaxis()->SetBinLabel(8, "HasDaughter"); + registry.get(HIST("hMcHypertritonCount"))->GetXaxis()->SetBinLabel(1, "Generated number"); + registry.get(HIST("hMcHypertritonCount"))->GetXaxis()->SetBinLabel(2, "primary Hypertriton mothers"); + registry.get(HIST("hMcHypertritonDecayCount"))->GetXaxis()->SetBinLabel(1, "confirm to 3-body decay"); + registry.get(HIST("hMcHypertritonDecayCount"))->GetXaxis()->SetBinLabel(2, "Hypertriton Candidates"); + registry.get(HIST("hMcHypertritonDecayCount"))->GetXaxis()->SetBinLabel(3, "AntiHypertriton Candidates"); + } + + Configurable rapidityMCcut{"rapidityMCcut", 0.9, "rapidity cut MC count"}; + Configurable eventSelectionMC{"eventSelectionMC", true, "event selection MC count"}; + + void process(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups>& collisions) + { + std::vector SelectedEvents(collisions.size()); + int nevts = 0; + for (const auto& collision : collisions) { + if (eventSelectionMC && !collision.sel8()) { + continue; + } + SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + } + SelectedEvents.resize(nevts); + + registry.fill(HIST("hTotalMcCollCounter"), 0.5); + + const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); + if (evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection + registry.fill(HIST("hTotalMcCollCounter"), 1.5); + return; + } + + for (auto& mcparticle : mcParticles) { + + if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { + registry.fill(HIST("hMcProtonPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { + registry.fill(HIST("hMcPionPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { + registry.fill(HIST("hMcDeuteronPt"), mcparticle.pt()); + } + if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { + registry.fill(HIST("hMcHypertritonCount"), 0.5); + registry.fill(HIST("hMcHypertritonCheck"), 0.5); + registry.fill(HIST("hMcHypertritonPt"), mcparticle.pt()); + + // double dauProtonPos[3] = {-999, -999, -999}; + // double dauPionPos[3] = {-999, -999, -999}; + double dauDeuteronPos[3] = {-999, -999, -999}; + double dauProtonMom[3] = {-999, -999, -999}; + double dauPionMom[3] = {-999, -999, -999}; + double dauDeuteronMom[3] = {-999, -999, -999}; + bool haveProton = false, havePion = false, haveDeuteron = false; + bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; + for (auto& mcparticleDaughter : mcparticle.daughters_as()) { + hypertrtitonCheckTable(mcparticleDaughter.pdgCode()); + if (mcparticleDaughter.pdgCode() == 2212) { + haveProton = true; + } + if (mcparticleDaughter.pdgCode() == -2212) { + haveAntiProton = true; + } + if (mcparticleDaughter.pdgCode() == 211) { + havePion = true; + } + if (mcparticleDaughter.pdgCode() == -211) { + haveAntiPion = true; + } + if (mcparticleDaughter.pdgCode() == 1000010020) { + haveDeuteron = true; + } + if (mcparticleDaughter.pdgCode() == -1000010020) { + haveAntiDeuteron = true; + } + if (std::abs(mcparticleDaughter.pdgCode()) == 2212) { + /*dauProtonPos[0] = mcparticleDaughter.vx(); + dauProtonPos[1] = mcparticleDaughter.vy(); + dauProtonPos[2] = mcparticleDaughter.vz();*/ + dauProtonMom[0] = mcparticleDaughter.px(); + dauProtonMom[1] = mcparticleDaughter.py(); + dauProtonMom[2] = mcparticleDaughter.pz(); + } + if (std::abs(mcparticleDaughter.pdgCode()) == 211) { + /*dauPionPos[0] = mcparticleDaughter.vx(); + dauPionPos[1] = mcparticleDaughter.vy(); + dauPionPos[2] = mcparticleDaughter.vz();*/ + dauPionMom[0] = mcparticleDaughter.px(); + dauPionMom[1] = mcparticleDaughter.py(); + dauPionMom[2] = mcparticleDaughter.pz(); + } + if (std::abs(mcparticleDaughter.pdgCode()) == 1000010020) { + dauDeuteronPos[0] = mcparticleDaughter.vx(); + dauDeuteronPos[1] = mcparticleDaughter.vy(); + dauDeuteronPos[2] = mcparticleDaughter.vz(); + dauDeuteronMom[0] = mcparticleDaughter.px(); + dauDeuteronMom[1] = mcparticleDaughter.py(); + dauDeuteronMom[2] = mcparticleDaughter.pz(); + } + } + if (haveProton && haveAntiPion && haveDeuteron && mcparticle.pdgCode() == 1010010030) { + registry.fill(HIST("hMcHypertritonDecayCount"), 0.5); + registry.fill(HIST("hMcHypertritonDecayCount"), 1.5); + } + if (haveAntiProton && havePion && haveAntiDeuteron && mcparticle.pdgCode() == -1010010030) { + registry.fill(HIST("hMcHypertritonDecayCount"), 0.5); + registry.fill(HIST("hMcHypertritonDecayCount"), 2.5); + } + double MClifetime = RecoDecay::sqrtSumOfSquares(dauDeuteronPos[0] - mcparticle.vx(), dauDeuteronPos[1] - mcparticle.vy(), dauDeuteronPos[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); + if ((haveProton && haveAntiPion && haveDeuteron && mcparticle.pdgCode() == 1010010030) || (haveAntiProton && havePion && haveAntiDeuteron && mcparticle.pdgCode() == -1010010030)) { + registry.fill(HIST("hMcRecoInvMass"), RecoDecay::m(array{array{dauProtonMom[0], dauProtonMom[1], dauProtonMom[2]}, array{dauPionMom[0], dauPionMom[1], dauPionMom[2]}, array{dauDeuteronMom[0], dauDeuteronMom[1], dauDeuteronMom[2]}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron})); + registry.fill(HIST("h3dMCDecayedHypertriton"), mcparticle.y(), mcparticle.pt(), MClifetime); + } + + int daughterPionCount = 0; + for (auto& mcparticleDaughter : mcparticle.daughters_as()) { + if (std::abs(mcparticleDaughter.pdgCode()) == 211) { + daughterPionCount++; + } + } + + registry.fill(HIST("hMcHypertritonLifeTime"), MClifetime); + registry.fill(HIST("h3dMCHypertriton"), mcparticle.y(), mcparticle.pt(), MClifetime); + + // Count for hypertriton N_gen + if (TMath::Abs(mcparticle.y()) < 1) { + registry.fill(HIST("hMcHypertritonCheck"), 1.5); + if (MClifetime < 40) { + registry.fill(HIST("hMcHypertritonCheck"), 2.5); + if (mcparticle.pt() > 1 && mcparticle.pt() < 10) { + registry.fill(HIST("hMcHypertritonCheck"), 3.5); + } + } + } + } + + registry.fill(HIST("hMcPhysicalPrimaryParticleCount"), 0.5); + if (!mcparticle.isPhysicalPrimary()) { + continue; + } + registry.fill(HIST("hMcPhysicalPrimaryParticleCount"), 1.5); + // if (TMath::Abs(mcparticle.y()) > rapidityMCcut) {continue;} + registry.fill(HIST("hMcPhysicalPrimaryParticleCount"), 2.5); + + if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { + registry.fill(HIST("hMcPhysicalPrimaryParticleCount"), 3.5); + } else if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { + registry.fill(HIST("hMcPhysicalPrimaryParticleCount"), 4.5); + } else if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { + registry.fill(HIST("hMcPhysicalPrimaryParticleCount"), 5.5); + } else if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { + registry.fill(HIST("hMcPhysicalPrimaryParticleCount"), 6.5); + registry.fill(HIST("hMcHypertritonCount"), 1.5); + } + + if (!mcparticle.has_daughters()) { + continue; + } + registry.fill(HIST("hMcPhysicalPrimaryParticleCount"), 7.5); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGLF/Tasks/hypertriton3bodyanalysis.cxx b/PWGLF/Tasks/hypertriton3bodyanalysis.cxx new file mode 100644 index 00000000000..030007f43f3 --- /dev/null +++ b/PWGLF/Tasks/hypertriton3bodyanalysis.cxx @@ -0,0 +1,292 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// Example StoredVtx3BodyDatas analysis task +// ======================== +// +// This code loops over a StoredVtx3BodyDatas table and produces some +// standard analysis output. It requires either +// the hypertriton3bodybuilder or hypertriton3bodyfinder (not recommaended) tasks +// to have been executed in the workflow (before). +// +// author: yuanzhe.wang@cern.ch +// + +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/Vtx3BodyTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "CommonConstants/PhysicsConstants.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +using MyTracks = soa::Join; + +struct hypertriton3bodyQa { + // Basic checks + HistogramRegistry registry{ + "registry", + { + {"hVtxRadius", "hVtxRadius", {HistType::kTH1F, {{1000, 0.0f, 100.0f, "cm"}}}}, + {"hVtxCosPA", "hVtxCosPA", {HistType::kTH1F, {{1000, 0.95f, 1.0f}}}}, + {"hDCATrack0ToPV", "hDCAPosToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, + {"hDCATrack1ToPV", "hDCANegToPV", {HistType::kTH1F, {{1000, 10.0f, 10.0f, "cm"}}}}, + {"hDCATrack2ToPV", "hDCANegToPV", {HistType::kTH1F, {{1000, 10.0f, 10.0f, "cm"}}}}, + {"hDCAVtxDau", "hDCAVtxDau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, + {"hVtxPt", "hVtxPt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, + {"hTrack0Pt", "hTrack0Pt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, + {"hTrack1Pt", "hTrack1Pt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, + {"hTrack2Pt", "hTrack2Pt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, + }, + }; + void init(InitContext const&) + { + AxisSpec massAxis = {120, 2.9f, 3.2f, "Inv. Mass (GeV/c^{2})"}; + registry.add("hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {massAxis}}); + registry.add("hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {massAxis}}); + } + void process(aod::Collision const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, MyTracks const& tracks) + { + for (auto& vtx : vtx3bodydatas) { + registry.fill(HIST("hVtxRadius"), vtx.vtxradius()); + registry.fill(HIST("hVtxCosPA"), vtx.vtxcosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("hDCATrack0ToPV"), vtx.dcatrack0topv()); + registry.fill(HIST("hDCATrack1ToPV"), vtx.dcatrack1topv()); + registry.fill(HIST("hDCATrack2ToPV"), vtx.dcatrack2topv()); + registry.fill(HIST("hDCAVtxDau"), vtx.dcaVtxdaughters()); + registry.fill(HIST("hVtxPt"), vtx.pt()); + registry.fill(HIST("hTrack0Pt"), vtx.track0pt()); + registry.fill(HIST("hTrack1Pt"), vtx.track1pt()); + registry.fill(HIST("hTrack2Pt"), vtx.track2pt()); + registry.fill(HIST("hMassHypertriton"), vtx.mHypertriton()); + registry.fill(HIST("hMassAntiHypertriton"), vtx.mAntiHypertriton()); + } + } +}; + +struct hypertriton3bodyAnalysis { + + HistogramRegistry registry{ + "registry", + { + {"hSelectedEventCounter", "hSelectedEventCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, + {"hSelectedCandidatesCounter", "hSelectedCandidatesCounter", {HistType::kTH1F, {{9, 0.0f, 9.0f}}}}, + {"hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {{100, 2.95f, 3.05f}}}}, + {"hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {{100, 2.95f, 3.05f}}}}, + {"hMassHypertritonTotal", "hMassHypertritonTotal", {HistType::kTH1F, {{300, 2.9f, 3.2f}}}}, + {"hPtProton", "hPtProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtAntiPion", "hPtAntiPion", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtDeuteron", "hPtDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtPion", "hPtPion", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, + {"h3dMassHypertriton", "h3dMassHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {100, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + {"hTPCPIDProton", "hTPCPIDProton", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hTPCPIDPion", "hTPCPIDPion", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hTPCPIDDeuteron", "hTPCPIDDeuteron", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hProtonTPCBB", "hProtonTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + {"hPionTPCBB", "hPionTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + {"hDeuteronTPCBB", "hDeuteronTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, + {"hProtonTPCVsPt", "hProtonTPCVsPt", {HistType::kTH2F, {{50, 0.0f, 5.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, + {"hPionTPCVsPt", "hPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, + {"hDeuteronTPCVsPt", "hDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, + {"h3dMassAntiHypertriton", "h3dMassAntiHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {100, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + {"h3dTotalHypertriton", "h3dTotalHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {100, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, + {"hDalitz", "hDalitz", {HistType::kTH2F, {{120, 7.85, 8.45, "M^{2}(dp) (GeV^{2}/c^{4})"}, {60, 1.1, 1.4, "M^{2}(p#pi) (GeV^{2}/c^{4})"}}}}, + }, + }; + + Configurable saveDcaHist{"saveDcaHist", 0, "saveDcaHist"}; + + ConfigurableAxis dcaBinning{"dca-binning", {200, 0.0f, 1.0f}, ""}; + ConfigurableAxis ptBinning{"pt-binning", {200, 0.0f, 10.0f}, ""}; + + void init(InitContext const&) + { + AxisSpec dcaAxis = {dcaBinning, "DCA (cm)"}; + AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/c)"}; + AxisSpec massAxisHypertriton = {40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}; + + if (saveDcaHist == 1) { + registry.add("h3dMassHypertritonDca", "h3dMassHypertritonDca", {HistType::kTH3F, {dcaAxis, ptAxis, massAxisHypertriton}}); + registry.add("h3dMassAntiHypertritonDca", "h3dMassAntiHypertritonDca", {HistType::kTH3F, {dcaAxis, ptAxis, massAxisHypertriton}}); + } + + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(1, "Readin"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(2, "VtxCosPA"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(3, "TrackEta"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(4, "MomRapidity"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(5, "Lifetime"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(6, "DcaV0Dau"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(7, "TPCPID"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(8, "PtCut"); + registry.get(HIST("hSelectedCandidatesCounter"))->GetXaxis()->SetBinLabel(9, "PionDcatoPV"); + } + + // Selection criteria + Configurable vtxcospa{"vtxcospa", 0.9, "Vtx CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; // loose cut + Configurable dcapiontopv{"dcapiontopv", .00, "DCA Pion To PV"}; + Configurable etacut{"etacut", 1, "etacut"}; + Configurable rapidity{"rapidity", 1, "rapidity"}; + Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; + Configurable eventSelection{"eventSelection", true, "event selection"}; + Configurable lifetimecut{"lifetimecut", 40., "lifetimecut"}; // ct + Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; + Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; + Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; + Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; + Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; + Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; + + // Filter dcaFilterV0 = aod::vtx.ata::dcaV0daughters < dcavtx.au; + + void process(soa::Join::iterator const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, MyTracks const& tracks) + { + registry.fill(HIST("hSelectedEventCounter"), 0.5); + if (eventSelection && !collision.sel8()) { + return; + } + registry.fill(HIST("hSelectedEventCounter"), 1.5); + + for (auto& vtx : vtx3bodydatas) { + registry.fill(HIST("hSelectedCandidatesCounter"), 0.5); + if (vtx.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()) < vtxcospa) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 1.5); + if (TMath::Abs(vtx.track0_as().eta()) > etacut || TMath::Abs(vtx.track1_as().eta()) > etacut || TMath::Abs(vtx.track2_as().eta()) > etacut) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 2.5); + if (TMath::Abs(vtx.yHypertriton()) > rapidity) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 3.5); + double ct = vtx.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassHyperTriton; + if (ct > lifetimecut) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 4.5); + if (vtx.dcaVtxdaughters() > dcavtxdau) { + continue; + } + registry.fill(HIST("hSelectedCandidatesCounter"), 5.5); + + // 3sigma region for Dalitz plot + double mcsigma = 0.0015; // from local MC + double lowerlimit = o2::constants::physics::MassHyperTriton - 3 * mcsigma; + double upperlimit = o2::constants::physics::MassHyperTriton + 3 * mcsigma; + + // Hypertriton + if (TMath::Abs(vtx.track0_as().tpcNSigmaPr()) < TpcPidNsigmaCut && TMath::Abs(vtx.track1_as().tpcNSigmaPi()) < TpcPidNsigmaCut && TMath::Abs(vtx.track2_as().tpcNSigmaDe()) < TpcPidNsigmaCut) { + + registry.fill(HIST("hSelectedCandidatesCounter"), 6.5); + + if (vtx.track0pt() > minProtonPt && vtx.track0pt() < maxProtonPt && vtx.track1pt() > minPionPt && vtx.track1pt() < maxPionPt && vtx.track2pt() > minDeuteronPt && vtx.track2pt() < maxDeuteronPt) { + registry.fill(HIST("hSelectedCandidatesCounter"), 7.5); + + if (TMath::Abs(vtx.dcatrack1topv()) > dcapiontopv) { + registry.fill(HIST("hSelectedCandidatesCounter"), 8.5); + + registry.fill(HIST("hPtProton"), vtx.track0pt()); + registry.fill(HIST("hPtAntiPion"), vtx.track1pt()); + registry.fill(HIST("hPtDeuteron"), vtx.track2pt()); + registry.fill(HIST("hTPCPIDProton"), vtx.track0_as().tpcNSigmaPr()); + registry.fill(HIST("hTPCPIDPion"), vtx.track1_as().tpcNSigmaPi()); + registry.fill(HIST("hTPCPIDDeuteron"), vtx.track2_as().tpcNSigmaDe()); + registry.fill(HIST("hProtonTPCBB"), vtx.track0_as().p(), vtx.track0_as().tpcSignal()); + registry.fill(HIST("hPionTPCBB"), -vtx.track1_as().p(), vtx.track1_as().tpcSignal()); + registry.fill(HIST("hDeuteronTPCBB"), vtx.track2_as().p(), vtx.track0_as().tpcSignal()); + registry.fill(HIST("hProtonTPCVsPt"), vtx.track0pt(), vtx.track0_as().tpcNSigmaPr()); + registry.fill(HIST("hPionTPCVsPt"), vtx.track1pt(), vtx.track1_as().tpcNSigmaPi()); + registry.fill(HIST("hDeuteronTPCVsPt"), vtx.track2pt(), vtx.track2_as().tpcNSigmaDe()); + registry.fill(HIST("hMassHypertriton"), vtx.mHypertriton()); + registry.fill(HIST("hMassHypertritonTotal"), vtx.mHypertriton()); + registry.fill(HIST("h3dMassHypertriton"), 0., vtx.pt(), vtx.mHypertriton()); // collision.centV0M() instead of 0. once available + registry.fill(HIST("h3dTotalHypertriton"), ct, vtx.pt(), vtx.mHypertriton()); + if (vtx.mHypertriton() > lowerlimit && vtx.mHypertriton() < upperlimit) { + registry.fill(HIST("hDalitz"), RecoDecay::m2(array{array{vtx.pxtrack0(), vtx.pytrack0(), vtx.pztrack0()}, array{vtx.pxtrack2(), vtx.pytrack2(), vtx.pztrack2()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), + RecoDecay::m2(array{array{vtx.pxtrack0(), vtx.pytrack0(), vtx.pztrack0()}, array{vtx.pxtrack1(), vtx.pytrack1(), vtx.pztrack1()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); + } + + if (saveDcaHist == 1) { + registry.fill(HIST("h3dMassHypertritonDca"), vtx.dcaVtxdaughters(), vtx.pt(), vtx.mHypertriton()); + } + } + } + } + + // AntiHypertriton + if (TMath::Abs(vtx.track0_as().tpcNSigmaPi()) < TpcPidNsigmaCut && TMath::Abs(vtx.track1_as().tpcNSigmaPr()) < TpcPidNsigmaCut && TMath::Abs(vtx.track2_as().tpcNSigmaDe()) < TpcPidNsigmaCut) { + + registry.fill(HIST("hSelectedCandidatesCounter"), 6.5); + + if (vtx.track0pt() > minPionPt && vtx.track0pt() < maxPionPt && vtx.track1pt() > minProtonPt && vtx.track1pt() < maxProtonPt && vtx.track2pt() > minDeuteronPt && vtx.track2pt() < maxDeuteronPt) { + registry.fill(HIST("hSelectedCandidatesCounter"), 7.5); + if (TMath::Abs(vtx.dcatrack0topv()) > dcapiontopv) { + registry.fill(HIST("hSelectedCandidatesCounter"), 8.5); + + registry.fill(HIST("hPtAntiProton"), vtx.track1pt()); + registry.fill(HIST("hPtPion"), vtx.track0pt()); + registry.fill(HIST("hPtAntiDeuteron"), vtx.track2pt()); + registry.fill(HIST("hTPCPIDProton"), vtx.track1_as().tpcNSigmaPr()); + registry.fill(HIST("hTPCPIDPion"), vtx.track0_as().tpcNSigmaPi()); + registry.fill(HIST("hTPCPIDDeuteron"), vtx.track2_as().tpcNSigmaDe()); + registry.fill(HIST("hProtonTPCBB"), -vtx.track1_as().p(), vtx.track1_as().tpcSignal()); + registry.fill(HIST("hPionTPCBB"), vtx.track0_as().p(), vtx.track0_as().tpcSignal()); + registry.fill(HIST("hDeuteronTPCBB"), -vtx.track2_as().p(), vtx.track0_as().tpcSignal()); + registry.fill(HIST("hProtonTPCVsPt"), vtx.track1pt(), vtx.track1_as().tpcNSigmaPr()); + registry.fill(HIST("hPionTPCVsPt"), vtx.track0pt(), vtx.track0_as().tpcNSigmaPi()); + registry.fill(HIST("hDeuteronTPCVsPt"), vtx.track2pt(), vtx.track2_as().tpcNSigmaDe()); + registry.fill(HIST("hMassAntiHypertriton"), vtx.mAntiHypertriton()); + registry.fill(HIST("hMassHypertritonTotal"), vtx.mAntiHypertriton()); + registry.fill(HIST("h3dMassAntiHypertriton"), 0., vtx.pt(), vtx.mAntiHypertriton()); // collision.centV0M() instead of 0. once available + registry.fill(HIST("h3dTotalHypertriton"), ct, vtx.pt(), vtx.mAntiHypertriton()); + if (vtx.mAntiHypertriton() > lowerlimit && vtx.mAntiHypertriton() < upperlimit) { + registry.fill(HIST("hDalitz"), RecoDecay::m2(array{array{vtx.pxtrack1(), vtx.pytrack1(), vtx.pztrack1()}, array{vtx.pxtrack2(), vtx.pytrack2(), vtx.pztrack2()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), + RecoDecay::m2(array{array{vtx.pxtrack1(), vtx.pytrack1(), vtx.pztrack1()}, array{vtx.pxtrack0(), vtx.pytrack0(), vtx.pztrack0()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); + } + + if (saveDcaHist == 1) { + registry.fill(HIST("h3dMassAntiHypertritonDca"), vtx.dcaVtxdaughters(), vtx.pt(), vtx.mAntiHypertriton()); + } + } + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGLF/Tasks/k1analysis.cxx b/PWGLF/Tasks/k1analysis.cxx index c1e199eb355..6b2354ad9ac 100644 --- a/PWGLF/Tasks/k1analysis.cxx +++ b/PWGLF/Tasks/k1analysis.cxx @@ -32,27 +32,6 @@ using namespace o2::framework::expressions; using namespace o2::soa; struct k1analysis { - enum k1Type { kMatterPos = 1, - kMatterNeg, - kAntiPos, - kAntiNeg, - kMatterPos_Mix, - kMatterNeg_Mix, - kAntiPos_Mix, - kAntiNeg_Mix, - kNk1Type }; - enum k892Type { - kK892Matter = 1, - kK892Anti, - kK892Matter_Mix, - kK892Anti_Mix, - kNk892Type - }; - enum kMCType { - kInput = 1, - kRecon, // signal loss can be added. - kNkMCType - }; SliceCache cache; Preslice perRCol = aod::resodaughter::resoCollisionId; Preslice perCollision = aod::track::collisionId; @@ -67,20 +46,24 @@ struct k1analysis { Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; /// DCA Selections // DCAr to PV - Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.1, "Track DCAr cut to PV Maximum"}; // DCAz to PV - Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 0.1, "Track DCAz cut to PV Maximum"}; Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; /// PID Selections - Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 2.0, "TPC nSigma cut for Pion"}; // TPC - Configurable cMaxTPCnSigmaPion_bach{"cMaxTPCnSigmaPion_bach", 2.0, "TPC nSigma cut for bachelor Pion"}; // TPC - Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 2.0, "TOF nSigma cut for Pion"}; // TOF - Configurable cMaxTOFnSigmaPion_bach{"cMaxTOFnSigmaPion_bach", 2.0, "TOF nSigma cut for Bachelor Pion"}; // TOF + Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF + Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined + Configurable cUseOnlyTOFTrackPi{"cUseOnlyTOFTrackPi", false, "Use only TOF track for PID selection"}; // Use only TOF track for Pion PID selection + Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection // Kaon - Configurable> kaonTPCPIDpTintv{"kaonTPCPIDpTintv", {999.}, "pT intervals for Kaon TPC PID cuts"}; - Configurable> kaonTPCPIDcuts{"kaonTPCPIDcuts", {2}, "nSigma list for Kaon TPC PID cuts"}; - Configurable> kaonTOFPIDpTintv{"kaonTOFPIDpTintv", {999.}, "pT intervals for Kaon TOF PID cuts"}; - Configurable> kaonTOFPIDcuts{"kaonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; + Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC + Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 3.0, "TOF nSigma cut for Kaon"}; // TOF + Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", -999, "Combined nSigma cut for Kaon"}; // Combined + // Track selections + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor // bachelor pion TOF PID? Configurable cDoTOFPID{"cDoTOFPID", 1, "Do TOF PID"}; @@ -89,6 +72,12 @@ struct k1analysis { Configurable cK892masswindow{"cK892masswindow", 0.1, "K(892)0 inv mass selection window"}; Configurable cPiPiMin{"cPiPiMin", 0, "Pion pair inv mass selection minimum"}; Configurable cPiPiMax{"cPiPiMax", 999, "Pion pair inv mass selection maximum"}; + Configurable cPiKaMin{"cPiKaMin", 0, "bPion-Kaon pair inv mass selection minimum"}; + Configurable cPiKaMax{"cPiKaMax", 999, "bPion-Kaon pair inv mass selection maximum"}; + Configurable cMinAngle{"cMinAngle", 0, "Minimum angle between K(892)0 and bachelor pion"}; + Configurable cMaxAngle{"cMaxAngle", 4, "Maximum angle between K(892)0 and bachelor pion"}; + Configurable cMinPairAsym{"cMinPairAsym", -1, "Minimum pair asymmetry"}; + Configurable cMaxPairAsym{"cMaxPairAsym", 1, "Maximum pair asymmetry"}; // K1 selection Configurable cK1MaxRap{"cK1MaxRap", 0.5, "K1 maximum rapidity"}; @@ -96,67 +85,91 @@ struct k1analysis { void init(o2::framework::InitContext&) { - std::vector centBinning = {0., 1., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 80., 90., 100.}; - AxisSpec centAxis = {centBinning, "V0M (%)"}; - AxisSpec multAxis = {0, 0, 100, "V0M (%)"}; // for future - AxisSpec ptAxis = {200, 0, 20, "#it{p}_{T} (GeV/#it{c})"}; + std::vector centBinning = {0., 1., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 80., 90., 100., 200.}; + AxisSpec centAxis = {centBinning, "T0M (%)"}; + AxisSpec ptAxis = {150, 0, 15, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec dcaxyAxis = {300, 0, 3, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {500, 0, 5, "DCA_{#it{xy}} (cm)"}; AxisSpec invMassAxis = {900, 0.6, 1.5, "Invariant Mass (GeV/#it{c}^2)"}; // K(892)0 AxisSpec invMassAxisReso = {1600, 0.9f, 2.5f, "Invariant Mass (GeV/#it{c}^2)"}; // K1 AxisSpec invMassAxisScan = {250, 0, 2.5, "Invariant Mass (GeV/#it{c}^2)"}; // For selection AxisSpec pidQAAxis = {130, -6.5, 6.5}; AxisSpec dataTypeAxis = {9, 0, 9, "Histogram types"}; AxisSpec mcTypeAxis = {4, 0, 4, "Histogram types"}; - AxisSpec tempmultAxis = {3000, 0, 3000, "Raw Multiplicity"}; // Mass QA (quick check) histos.add("k892invmass", "Invariant mass of K(892)0", HistType::kTH1F, {invMassAxis}); histos.add("k1invmass", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_LS", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_Mix", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); + if (doprocessMC) { + histos.add("k1invmass_MC", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); + } + // DCA QA + histos.add("QA/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkDCAxy_pi_bach", "DCAxy distribution of bachelor pion track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QA/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QA/trkDCAz_pi_bach", "DCAz distribution of bachelor pion track candidates", HistType::kTH1F, {dcazAxis}); // pT QA - histos.add("QAbefore/trkpT_pi", "pT distribution of pion track candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAbefore/trkpT_ka", "pT distribution of kaon track candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAbefore/trkpT_pi_bach", "pT distribution of bachelor pion track candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAafter/trkpT_pi", "pT distribution of pion track candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAafter/trkpT_ka", "pT distribution of kaon track candidates", HistType::kTH1F, {ptAxis}); - histos.add("QAafter/trkpT_pi_bach", "pT distribution of bachelor pion track candidates", HistType::kTH1F, {ptAxis}); - // PID QA before cuts - histos.add("QAbefore/TOF_TPC_Map_pi", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAbefore/TOF_Nsigma_pi", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAbefore/TPC_Nsigma_pi", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAbefore/TOF_TPC_Map_ka", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAbefore/TOF_Nsigma_ka", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAbefore/TPC_Nsigmaka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAbefore/TOF_TPC_Map_pi_bach", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAbefore/TOF_Nsigma_pi_bach", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAbefore/TPC_Nsigma_pi_bach", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); + histos.add("QA/trkpT_pi", "pT distribution of pion track candidates", HistType::kTH1F, {ptAxis}); + histos.add("QA/trkpT_ka", "pT distribution of kaon track candidates", HistType::kTH1F, {ptAxis}); + histos.add("QA/trkpT_pi_bach", "pT distribution of bachelor pion track candidates", HistType::kTH1F, {ptAxis}); // PID QA after cuts - histos.add("QAafter/TOF_TPC_Map_pi", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAafter/TOF_Nsigma_pi", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAafter/TPC_Nsigma_pi", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAafter/TOF_TPC_Map_ka", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAafter/TOF_Nsigma_ka", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAafter/TPC_Nsigmaka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAafter/TOF_TPC_Map_pi_bach", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); - histos.add("QAafter/TOF_Nsigma_pi_bach", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - histos.add("QAafter/TPC_Nsigma_pi_bach", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); - - histos.add("QAMCbefore/InvMass_piK_pipi", "Invariant mass of pion + kaon and pion+pion;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); - - // THnSparse for Invariant mass - histos.add("THnK892invmass", "Invariant mass of K(892)0", HistType::kTHnSparseD, {dataTypeAxis, tempmultAxis, ptAxis, invMassAxis}); // TODO: multiplicity bin has to be updatde. - histos.add("THnK1invmass", "Invariant mass of K(892)0 + pion", HistType::kTHnSparseD, {dataTypeAxis, tempmultAxis, ptAxis, invMassAxisReso}); // TODO: multiplicity bin has to be updatde. - - if (doprocessMC || doprocessMCLight) { - // MC QA - histos.add("THnK1invmassMC", "Invariant mass of MC K(892)0 + pion", HistType::kTHnSparseD, {dataTypeAxis, tempmultAxis, ptAxis, invMassAxisReso}); // TODO: multiplicity bin has to be updatde. - /* - histos.add("hTrueK892pt", "pT distribution of True MC K(892)0", HistType::kTH1F, {ptAxis}); - */ + histos.add("QA/TOF_TPC_Map_pi", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QA/TOF_Nsigma_pi", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); + histos.add("QA/TPC_Nsigma_pi", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); + histos.add("QA/TOF_TPC_Map_ka", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QA/TOF_Nsigma_ka", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); + histos.add("QA/TPC_Nsigmaka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); + histos.add("QA/TOF_TPC_Map_pi_bach", "TOF + TPC Combined PID for Pion;#sigma_{TOF}^{Pion};#sigma_{TPC}^{Pion}", {HistType::kTH2F, {pidQAAxis, pidQAAxis}}); + histos.add("QA/TOF_Nsigma_pi_bach", "TOF NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); + histos.add("QA/TPC_Nsigma_pi_bach", "TPC NSigma for Pion;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Pion};", {HistType::kTH2F, {ptAxis, pidQAAxis}}); + histos.add("QA/InvMass_piK_pipi", "Invariant mass of pion + kaon and pion+pion;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); + histos.add("QA/InvMass_piK_pika", "Invariant mass of pion + kaon and pion+kaon;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); + histos.add("QA/K1OA", "Opening angle of K1(1270)pm", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle of K1(1270)pm"}}); + histos.add("QA/K1PairAsymm", "Pair asymmetry of K1(1270)pm", HistType::kTH1F, {AxisSpec{100, -1, 1, "Pair asymmetry of K1(1270)pm"}}); + + // Invariant mass histograms + histos.add("hK892invmass_PP", "Invariant mass of K(892)0 (Matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("hK892invmass_NP", "Invariant mass of K(892)0 (Matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("hK892invmass_PN", "Invariant mass of K(892)0 (Anti-matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("hK892invmass_NN", "Invariant mass of K(892)0 (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("hK1invmass_NPP", "Invariant mass of K(892)0 + pion (Matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_NPN", "Invariant mass of K(892)0 + pion (Matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_PNP", "Invariant mass of K(892)0 + pion (Anti-matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_PNN", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + // K892-LS bkg + histos.add("hK1invmass_PPP", "Invariant mass of K(892)0 + pion (Matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_PPN", "Invariant mass of K(892)0 + pion (Anti-matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_NNP", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_NNN", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + // Mixed event + histos.add("hK1invmass_NPP_Mix", "Invariant mass of K(892)0 + pion (Matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_NPN_Mix", "Invariant mass of K(892)0 + pion (Matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_PNP_Mix", "Invariant mass of K(892)0 + pion (Anti-matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_PNN_Mix", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + + if (doprocessMC) { + histos.add("QAMC/InvMass_piK_pipi", "Invariant mass of pion + kaon and pion+pion;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); + histos.add("QAMC/InvMass_piK_pika", "Invariant mass of pion + kaon and pion+kaon;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); + histos.add("QAMC/K1OA", "Opening angle of K1(1270)pm", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle of K1(1270)pm"}}); + histos.add("QAMC/K1PairAsymm", "Pair asymmetry of K1(1270)pm", HistType::kTH1F, {AxisSpec{100, 0, 1, "Pair asymmetry of K1(1270)pm"}}); + + histos.add("hK1invmass_NPP_MC", "Invariant mass of K(892)0 + pion (Matter + Matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hK1invmass_PNN_MC", "Invariant mass of K(892)0 + pion (Anti-matter + Anti-matter)", HistType::kTH3F, {centAxis, ptAxis, invMassAxisReso}); + histos.add("hReconK892pt", "pT distribution of Reconstructed MC K(892)0", HistType::kTH1F, {ptAxis}); histos.add("hTrueK1pt", "pT distribution of True MC K1", HistType::kTH1F, {ptAxis}); histos.add("hReconK1pt", "pT distribution of Reconstructed MC K1", HistType::kTH1F, {ptAxis}); - histos.add("QAMCafter/InvMass_piK_pipi", "Invariant mass of pion + kaon and pion+pion;Invariant Mass (GeV/#it{c}^{2});Invariant Mass (GeV/#it{c}^{2});", {HistType::kTH2F, {invMassAxisScan, invMassAxisScan}}); + + histos.add("k1invmass_noK1", "Invariant mass of K1(1270)pm", HistType::kTH1F, {invMassAxisReso}); } + // Print output histograms statistics + LOG(info) << "Size of the histograms in spectraTOF"; + histos.print(); } double massKa = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); @@ -173,121 +186,148 @@ struct k1analysis { return false; if (track.dcaZ() < cMinDCAzToPVcut || track.dcaZ() > cMaxDCAzToPVcut) return false; + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; + return true; + } + + // PID selection tools + template + bool selectionPIDPion(const T& candidate) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { + tpcPIDPassed = true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < cMaxTOFnSigmaPion) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedPion > 0) && (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < nsigmaCutCombinedPion * nsigmaCutCombinedPion)) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + return false; + } + template + bool selectionPIDKaon(const T& candidate) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { + tpcPIDPassed = true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cMaxTOFnSigmaKaon) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedKaon > 0) && (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa() < nsigmaCutCombinedKaon * nsigmaCutCombinedKaon)) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + return false; + } + + template + bool isTrueK1(const T& trk1, const T& trk2, const T2& bTrack) + { + if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) + return false; + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (abs(trk1.motherPDG()) != 313) + return false; + if (abs(bTrack.pdgCode()) != kPiPlus) + return false; + if (abs(bTrack.motherPDG()) != 10323) + return false; + auto siblings = bTrack.siblingIds(); + if (siblings[0] != mother1 && siblings[1] != mother1) + return false; return true; } + template + bool isTrueK892(const T& trk1, const T& trk2) + { + if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) + return false; + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (abs(trk1.motherPDG()) != 313) + return false; + return true; + } + template void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) { TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonanceK892, lDecayDaughter_bach, lResonanceK1; - bool isTrk1Selected{true}, isTrk2Selected{true}, isbTrkSelected{true}, isTrk1hasTOF{false}, isTrk2hasTOF{false}, isbTrkhasTOF{false}, isK892Anti{false}; - auto vKaonTPCPIDpTintv = static_cast>(kaonTPCPIDpTintv); - auto vKaonTPCPIDcuts = static_cast>(kaonTPCPIDcuts); - auto vKaonTOFPIDpTintv = static_cast>(kaonTOFPIDpTintv); - auto vKaonTOFPIDcuts = static_cast>(kaonTOFPIDcuts); - auto lengthOfkaonTPCPIDpTintv = static_cast(vKaonTPCPIDpTintv.size()); for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks2, dTracks2))) { // Full index policy is needed to consider all possible combinations if (trk1.index() == trk2.index()) - continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. - if (trk1.sign() * trk2.sign() > 0) // always choose opposite sign pairs - continue; - isK892Anti = false; - //// Initialize variables + continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. // Trk1: Pion, Trk2: Kaon - isTrk1Selected = true; - isTrk2Selected = true; - isTrk1hasTOF = false; - isTrk2hasTOF = false; + // apply the track cut + if (!trackCut(trk1) || !trackCut(trk2)) + continue; + + auto isTrk1hasTOF = trk1.hasTOF(); + auto isTrk2hasTOF = trk2.hasTOF(); auto trk1ptPi = trk1.pt(); auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); - auto trk1NSigmaPiTOF = -999.; + auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; auto trk2ptKa = trk2.pt(); auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); - auto trk2NSigmaKaTOF = -999.; + auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.; - // apply the track cut - if (!trackCut(trk1)) + //// PID selections + if (cUseOnlyTOFTrackPi && !isTrk1hasTOF) continue; - if (!trackCut(trk2)) + if (cUseOnlyTOFTrackKa && !isTrk2hasTOF) continue; - - // hasTOF? - if ((trk1.tofPIDselectionFlag() & aod::resodaughter::kHasTOF) == aod::resodaughter::kHasTOF) { - isTrk1hasTOF = true; - } - if ((trk2.tofPIDselectionFlag() & aod::resodaughter::kHasTOF) == aod::resodaughter::kHasTOF) { - isTrk2hasTOF = true; - } - //// PID selections - // For Pion candidate, we don't need to apply pT-dependent PID cuts - if (std::abs(trk1NSigmaPiTPC) > cMaxTPCnSigmaPion) - isTrk1Selected = false; - if (isTrk1hasTOF) { - trk1NSigmaPiTOF = trk1.tofNSigmaPi(); - if (std::abs(trk1NSigmaPiTOF) > cMaxTOFnSigmaPion) - isTrk1Selected = false; - } - // For Kaon candidate, we need to apply pT-dependent PID cuts - if (lengthOfkaonTPCPIDpTintv > 0) { - for (int i = 0; i < lengthOfkaonTPCPIDpTintv; i++) { - if (trk2ptKa < vKaonTPCPIDpTintv[i]) { - if (std::abs(trk2NSigmaKaTPC) > vKaonTPCPIDcuts[i]) - isTrk2Selected = false; - } - } - } - if (isTrk2hasTOF) { - trk2NSigmaKaTOF = trk2.tofNSigmaKa(); - if (lengthOfkaonTPCPIDpTintv > 0) { - for (int i = 0; i < lengthOfkaonTPCPIDpTintv; i++) { - if (trk2ptKa < vKaonTOFPIDpTintv[i]) { - if (std::abs(trk2NSigmaKaTOF) > vKaonTOFPIDcuts[i]) - isTrk2Selected = false; - } - } - } - } - - //// QA plots before the selection - // --- PID QA Pion - if constexpr (!IsMix) { - histos.fill(HIST("QAbefore/TPC_Nsigma_pi"), trk1ptPi, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAbefore/TOF_Nsigma_pi"), trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAbefore/TOF_TPC_Map_pi"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); - } - // --- PID QA Kaon - histos.fill(HIST("QAbefore/TPC_Nsigmaka"), trk2ptKa, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAbefore/TOF_Nsigma_ka"), trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QAbefore/TOF_TPC_Map_ka"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); - } - histos.fill(HIST("QAbefore/trkpT_pi"), trk1ptPi); - histos.fill(HIST("QAbefore/trkpT_ka"), trk2ptKa); - } - - //// Apply the selection - if (!isTrk1Selected || !isTrk2Selected) + if (!selectionPIDPion(trk1) || !selectionPIDKaon(trk2)) continue; //// QA plots after the selection // --- PID QA Pion if constexpr (!IsMix) { - histos.fill(HIST("QAafter/TPC_Nsigma_pi"), trk1ptPi, trk1NSigmaPiTPC); + histos.fill(HIST("QA/TPC_Nsigma_pi"), trk1ptPi, trk1NSigmaPiTPC); if (isTrk1hasTOF) { - histos.fill(HIST("QAafter/TOF_Nsigma_pi"), trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAafter/TOF_TPC_Map_pi"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + histos.fill(HIST("QA/TOF_Nsigma_pi"), trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QA/TOF_TPC_Map_pi"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); } // --- PID QA Kaon - histos.fill(HIST("QAafter/TPC_Nsigmaka"), trk2ptKa, trk2NSigmaKaTPC); + histos.fill(HIST("QA/TPC_Nsigmaka"), trk2ptKa, trk2NSigmaKaTPC); if (isTrk1hasTOF) { - histos.fill(HIST("QAafter/TOF_Nsigma_ka"), trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QAafter/TOF_TPC_Map_ka"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + histos.fill(HIST("QA/TOF_Nsigma_ka"), trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QA/TOF_TPC_Map_ka"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); } - histos.fill(HIST("QAafter/trkpT_pi"), trk1ptPi); - histos.fill(HIST("QAafter/trkpT_ka"), trk2ptKa); + histos.fill(HIST("QA/trkpT_pi"), trk1ptPi); + histos.fill(HIST("QA/trkpT_ka"), trk2ptKa); + + histos.fill(HIST("QA/trkDCAxy_pi"), trk1.dcaXY()); + histos.fill(HIST("QA/trkDCAxy_ka"), trk2.dcaXY()); + histos.fill(HIST("QA/trkDCAz_pi"), trk1.dcaZ()); + histos.fill(HIST("QA/trkDCAz_ka"), trk2.dcaZ()); } //// Resonance reconstruction @@ -295,64 +335,60 @@ struct k1analysis { lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); lResonanceK892 = lDecayDaughter1 + lDecayDaughter2; - if (trk2.sign() > 0) - isK892Anti = true; if constexpr (!IsMix) { histos.fill(HIST("k892invmass"), lResonanceK892.M()); // quick check - histos.fill(HIST("THnK892invmass"), (isK892Anti) ? kK892Anti : kK892Matter, collision.multV0M(), lResonanceK892.Pt(), lResonanceK892.M()); + if (trk1.sign() > 0) { // Positive pion + if (trk2.sign() > 0) // Positive kaon + histos.fill(HIST("hK892invmass_PP"), collision.multV0M(), lResonanceK892.Pt(), lResonanceK892.M()); + else // Negative kaon + histos.fill(HIST("hK892invmass_PN"), collision.multV0M(), lResonanceK892.Pt(), lResonanceK892.M()); // Anti-K(892)0 + } else { // Negative pion + if (trk2.sign() > 0) // Positive kaon + histos.fill(HIST("hK892invmass_NP"), collision.multV0M(), lResonanceK892.Pt(), lResonanceK892.M()); // K(892)0 + else // Negative kaon + histos.fill(HIST("hK892invmass_NN"), collision.multV0M(), lResonanceK892.Pt(), lResonanceK892.M()); + } } + // Like-sign rejection for K(892)0 - disabled for further LS bkg study + // if (trk1.sign() * trk2.sign() > 0) + // continue; + + if constexpr (IsMC) { // MC Check of K(892)0 + if (isTrueK892(trk1, trk2)) + histos.fill(HIST("hReconK892pt"), lResonanceK892.Pt()); + } + // Mass window cut if (std::abs(lResonanceK892.M() - massK892) > cK892masswindow) continue; // Add one more track loop for K1 reconstruction for (auto bTrack : dTracks1) { - // ID cut if (bTrack.index() == trk1.index() || bTrack.index() == trk2.index()) continue; - // Track cut if (!trackCut(bTrack)) continue; - isbTrkSelected = true; auto bTrkPt = bTrack.pt(); auto bTrkTPCnSigmaPi = bTrack.tpcNSigmaPi(); - auto bTrack_TOFnSigma = -99.0; - isbTrkhasTOF = false; - if ((bTrack.tofPIDselectionFlag() & aod::resodaughter::kHasTOF) == aod::resodaughter::kHasTOF) { - isbTrkhasTOF = true; - } + auto isbTrkhasTOF = bTrack.hasTOF(); + auto bTrack_TOFnSigma = (isbTrkhasTOF) ? bTrack.tofNSigmaPi() : -999.; // PID selection - if (std::abs(bTrkTPCnSigmaPi) > cMaxTPCnSigmaPion_bach) - isbTrkSelected = false; - if (cDoTOFPID && isbTrkhasTOF) { - bTrack_TOFnSigma = bTrack.tofNSigmaPi(); - if (std::abs(bTrack_TOFnSigma) > cMaxTOFnSigmaPion_bach) - isbTrkSelected = false; - } - if constexpr (!IsMix) { - histos.fill(HIST("QAbefore/trkpT_pi_bach"), bTrkPt); - // --- PID QA Pion - histos.fill(HIST("QAbefore/TPC_Nsigma_pi_bach"), bTrkPt, bTrkTPCnSigmaPi); - if (isTrk1hasTOF) { - histos.fill(HIST("QAbefore/TOF_Nsigma_pi_bach"), bTrkPt, bTrack_TOFnSigma); - histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_bach"), bTrack_TOFnSigma, bTrkTPCnSigmaPi); - } - } - - if (!isbTrkSelected) // bachelor track selection + if (!selectionPIDPion(bTrack)) continue; if constexpr (!IsMix) { - histos.fill(HIST("QAafter/trkpT_pi_bach"), bTrkPt); + histos.fill(HIST("QA/trkpT_pi_bach"), bTrkPt); // --- PID QA Pion - histos.fill(HIST("QAafter/TPC_Nsigma_pi_bach"), bTrkPt, bTrkTPCnSigmaPi); - if (isTrk1hasTOF) { - histos.fill(HIST("QAafter/TOF_Nsigma_pi_bach"), bTrkPt, bTrack_TOFnSigma); - histos.fill(HIST("QAafter/TOF_TPC_Map_pi_bach"), bTrack_TOFnSigma, bTrkTPCnSigmaPi); + histos.fill(HIST("QA/TPC_Nsigma_pi_bach"), bTrkPt, bTrkTPCnSigmaPi); + if (isbTrkhasTOF) { + histos.fill(HIST("QA/TOF_Nsigma_pi_bach"), bTrkPt, bTrack_TOFnSigma); + histos.fill(HIST("QA/TOF_TPC_Map_pi_bach"), bTrack_TOFnSigma, bTrkTPCnSigmaPi); } + histos.fill(HIST("QA/trkDCAxy_pi_bach"), bTrack.dcaXY()); + histos.fill(HIST("QA/trkDCAz_pi_bach"), bTrack.dcaZ()); } // K1 reconstruction @@ -362,67 +398,100 @@ struct k1analysis { // Rapidity cut if (lResonanceK1.Rapidity() > cK1MaxRap || lResonanceK1.Rapidity() < cK1MinRap) continue; - + // Opening angle cut + auto lK1Angle = lResonanceK892.Angle(lDecayDaughter_bach.Vect()); + // Pair asymmetry cut + auto lPairAsym = (lResonanceK892.E() - lDecayDaughter_bach.E()) / (lResonanceK892.E() + lDecayDaughter_bach.E()); + // PiPi, PiKa mass range cut TLorentzVector tempPiPi = lDecayDaughter1 + lDecayDaughter_bach; + TLorentzVector tempPiKa = lDecayDaughter2 + lDecayDaughter_bach; if constexpr (!IsMix) { - histos.fill(HIST("QAMCbefore/InvMass_piK_pipi"), lResonanceK892.M(), tempPiPi.M()); + histos.fill(HIST("QA/InvMass_piK_pipi"), lResonanceK892.M(), tempPiPi.M()); + histos.fill(HIST("QA/InvMass_piK_pika"), lResonanceK892.M(), tempPiKa.M()); + histos.fill(HIST("QA/K1OA"), lK1Angle); + histos.fill(HIST("QA/K1PairAsymm"), lPairAsym); } if (tempPiPi.M() < cPiPiMin || tempPiPi.M() > cPiPiMax) continue; + if (tempPiKa.M() < cPiKaMin || tempPiKa.M() > cPiKaMax) + continue; + if (lK1Angle < cMinAngle || lK1Angle > cMaxAngle) + continue; + if (lPairAsym < cMinPairAsym || lPairAsym > cMaxPairAsym) + continue; - if constexpr (!IsMix) { - if (bTrack.sign() > 0) { - // bachelor pi+ - if (!isK892Anti) { - histos.fill(HIST("k1invmass"), lResonanceK1.M()); // quick check - histos.fill(HIST("THnK1invmass"), kMatterPos, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); - } else { - histos.fill(HIST("THnK1invmass"), kAntiPos, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + if constexpr (!IsMix) { // Same event pair + if (trk1.sign() * trk2.sign() < 0) { // K892 + if (bTrack.sign() > 0) { // bachelor pi+ + if (trk2.sign() > 0) { // kaon + means K(892)0 is matter. + histos.fill(HIST("k1invmass"), lResonanceK1.M()); // quick check + histos.fill(HIST("hK1invmass_NPP"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } else { + histos.fill(HIST("k1invmass_LS"), lResonanceK1.M()); // quick check + histos.fill(HIST("hK1invmass_PNP"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } + } else { // bachelor pi- + if (trk2.sign() > 0) { // kaon + means K(892)0 is matter. + histos.fill(HIST("k1invmass_LS"), lResonanceK1.M()); // quick check + histos.fill(HIST("hK1invmass_NPN"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } else { + histos.fill(HIST("k1invmass"), lResonanceK1.M()); // quick check + histos.fill(HIST("hK1invmass_PNN"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } } - } else { - // bachelor pi- - if (!isK892Anti) { - histos.fill(HIST("THnK1invmass"), kMatterNeg, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); - } else { - histos.fill(HIST("k1invmass"), lResonanceK1.M()); // quick check - histos.fill(HIST("THnK1invmass"), kAntiNeg, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } else { // K892-LS (false) + if (bTrack.sign() > 0) { // bachelor pi+ + if (trk2.sign() > 0) { // Kaon+ + histos.fill(HIST("hK1invmass_PPP"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } else { + histos.fill(HIST("hK1invmass_PPN"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } + } else { // bachelor pi- + if (trk2.sign() > 0) { // Kaon_ + histos.fill(HIST("hK1invmass_NNN"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } else { + histos.fill(HIST("hK1invmass_NNP"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } } } - } else { - if (bTrack.sign() > 0) { - // bachelor pi+ - if (!isK892Anti) { - histos.fill(HIST("k1invmass"), lResonanceK1.M()); // quick check - histos.fill(HIST("THnK1invmass"), kMatterPos_Mix, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); - } else { - histos.fill(HIST("THnK1invmass"), kAntiPos_Mix, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); - } - } else { - // bachelor pi- - if (!isK892Anti) { - histos.fill(HIST("THnK1invmass"), kMatterNeg_Mix, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + + if constexpr (IsMC) { + if (isTrueK1(trk1, trk2, bTrack)) { + histos.fill(HIST("hReconK1pt"), lResonanceK1.Pt()); + histos.fill(HIST("QAMC/InvMass_piK_pipi"), lResonanceK892.M(), tempPiPi.M()); + histos.fill(HIST("QAMC/InvMass_piK_pika"), lResonanceK892.M(), tempPiKa.M()); + histos.fill(HIST("QAMC/K1OA"), lK1Angle); + histos.fill(HIST("QAMC/K1PairAsymm"), lPairAsym); + + if ((bTrack.sign() > 0) && (trk2.sign() > 0)) { // Matter + histos.fill(HIST("hK1invmass_NPP_MC"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("k1invmass_MC"), lResonanceK1.M()); // quick check + } + if ((bTrack.sign() < 0) && (trk2.sign() < 0)) { // Anti-matter + histos.fill(HIST("hK1invmass_PNN_MC"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("k1invmass_MC"), lResonanceK1.M()); // quick check + } + histos.fill(HIST("hTrueK1pt"), lResonanceK1.Pt()); } else { - histos.fill(HIST("k1invmass"), lResonanceK1.M()); // quick check - histos.fill(HIST("THnK1invmass"), kAntiNeg_Mix, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + if (((bTrack.sign() > 0) && (trk2.sign() > 0)) || ((bTrack.sign() < 0) && (trk2.sign() < 0))) + histos.fill(HIST("k1invmass_noK1"), lResonanceK1.M()); // quick check } } - } - // MC - if constexpr (IsMC) { - if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) - continue; - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 == mother2) { // Same mother - if (abs(trk1.motherPDG()) == 313) { // k892(0) - histos.fill(HIST("hReconK892pt"), lResonanceK892.Pt()); - if (abs(bTrack.pdgCode()) != kPiPlus) - continue; - // TODO: check if the 313 and bTrack have the same mother - if (abs(bTrack.motherPDG()) == 10323) { - histos.fill(HIST("hReconK1pt"), lResonanceK1.Pt()); - histos.fill(HIST("THnK1invmassMC"), kRecon, collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); // TODO: multV0M has to be updatde. - histos.fill(HIST("QAMCafter/InvMass_piK_pipi"), lResonanceK892.M(), tempPiPi.M()); + } else { // Mixed event pair + if (trk1.sign() * trk2.sign() < 0) { // K892 + if (bTrack.sign() > 0) { // bachelor pi+ + if (trk2.sign() > 0) { // kaon + means K(892)0 is matter. + histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); // quick check + histos.fill(HIST("hK1invmass_NPP_Mix"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } else { + histos.fill(HIST("hK1invmass_PNP_Mix"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } + } else { // bachelor pi- + if (trk2.sign() > 0) { // kaon + means K(892)0 is matter. + histos.fill(HIST("hK1invmass_NPN_Mix"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); + } else { + histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); // quick check + histos.fill(HIST("hK1invmass_PNN_Mix"), collision.multV0M(), lResonanceK1.Pt(), lResonanceK1.M()); } } } @@ -431,115 +500,56 @@ struct k1analysis { } } - void processData(aod::ResoCollisions& collisions, + void processData(aod::ResoCollision& collision, aod::ResoTracks const& resotracks) - { - LOGF(debug, "[DATA] Processing %d collisions", collisions.size()); - for (auto& collision : collisions) { - Partition selectedTracks = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks.bindTable(resotracks); - auto colTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colTracks, colTracks); - } - } - PROCESS_SWITCH(k1analysis, processData, "Process Event for data", false); - - void processDataLight(aod::ResoCollision& collision, - aod::ResoTracks const& resotracks) { fillHistograms(collision, resotracks, resotracks); } - PROCESS_SWITCH(k1analysis, processDataLight, "Process Event for data without Partitioning", true); + PROCESS_SWITCH(k1analysis, processData, "Process Event for data without Partitioning", true); - void processMC(aod::ResoCollisions& collisions, + void processMC(aod::ResoCollision& collision, soa::Join const& resotracks, aod::McParticles const& mcParticles) - { - LOGF(debug, "[MC] MC events: %d", collisions.size()); - for (auto& collision : collisions) { - Partition> selectedTracks = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks.bindTable(resotracks); - auto colTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colTracks, colTracks); - } - - // Not related to the real collisions - for (auto& part : mcParticles) { // loop over all MC particles - if (abs(part.pdgCode()) == 10323) { // K1 - if (part.y() > 0.5 || part.y() < -0.5) { // rapidity cut - continue; - } - bool pass1 = false; - bool pass2 = false; - for (auto& dau : part.daughters_as()) { - if (abs(dau.pdgCode()) == 313) { // At least one decay to K892(0) - pass2 = true; - } - if (abs(dau.pdgCode()) == kPiPlus) { // At least one decay to Pion - pass1 = true; - } - } - if (!pass1 || !pass2) // If we have both decay products - continue; - histos.fill(HIST("hTrueK1pt"), part.pt()); - } - } - } - PROCESS_SWITCH(k1analysis, processMC, "Process Event for MC", false); - - void processMCLight(aod::ResoCollision& collision, - soa::Join const& resotracks, aod::McParticles const& mcParticles) { fillHistograms(collision, resotracks, resotracks); } - PROCESS_SWITCH(k1analysis, processMCLight, "Process Event for MC", false); + PROCESS_SWITCH(k1analysis, processMC, "Process Event for MC", false); - void processMCTrue(aod::ResoCollisions& collisions, aod::McParticles const& mcParticles) + void processMCTrue(aod::ResoMCParents& resoParents) { - // Not related to the real collisions - for (auto& part : mcParticles) { // loop over all MC particles - if (abs(part.pdgCode()) == 10323) { // K1 - if (part.y() > 0.5 || part.y() < -0.5) { // rapidity cut - continue; - } - bool pass1 = false; - bool pass2 = false; - for (auto& dau : part.daughters_as()) { - if (abs(dau.pdgCode()) == 313) { // At least one decay to K892(0) - pass2 = true; - } - if (abs(dau.pdgCode()) == kPiPlus) { // At least one decay to Pion - pass1 = true; - } - } - if (!pass1 || !pass2) // If we have both decay products - continue; - histos.fill(HIST("hTrueK1pt"), part.pt()); - // histos.fill(HIST("THnK1invmassMC"), kInput, collision.multV0M(), part.pt(), part.weight()); // TODO: multV0M has to be updatde. + for (auto& part : resoParents) { // loop over all pre-filtered MC particles + if (abs(part.pdgCode()) != 10323) // K892(0) + continue; + if (abs(part.y()) > 0.5) { // rapidity cut + continue; } + bool pass1 = false; + bool pass2 = false; + if (abs(part.daughterPDG1()) == 313 || abs(part.daughterPDG2()) == 313) { // At least one decay to Kaon + pass2 = true; + } + if (abs(part.daughterPDG1()) == kPiPlus || abs(part.daughterPDG2()) == kPiPlus) { // At least one decay to Pion + pass1 = true; + } + if (!pass1 || !pass2) // If we have both decay products + continue; + histos.fill(HIST("hTrueK1pt"), part.pt()); } } - PROCESS_SWITCH(k1analysis, processMCTrue, "Process Event for MC True", false); + PROCESS_SWITCH(k1analysis, processMCTrue, "Process Event for MC", false); // Processing Event Mixing - using BinningTypeVetZTPCtemp = ColumnBinningPolicy; // TODO: MultTPCtemp has to be updatde. - BinningTypeVetZTPCtemp colBinning{{CfgVtxBins, CfgMultBins}, true}; + using BinningTypeVtxZT0M = ColumnBinningPolicy; void processME(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) { - LOGF(debug, "Event Mixing Started"); auto tracksTuple = std::make_tuple(resotracks); - SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; + SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { - Partition selectedTracks1 = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks1.bindTable(tracks1); - Partition selectedTracks2 = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks2.bindTable(tracks2); - - fillHistograms(collision1, selectedTracks1, selectedTracks2); + fillHistograms(collision1, tracks1, tracks2); } }; - PROCESS_SWITCH(k1analysis, processME, "Process EventMixing", false); + PROCESS_SWITCH(k1analysis, processME, "Process EventMixing light without partition", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/k892analysis.cxx b/PWGLF/Tasks/k892analysis.cxx index 0c5b6ef0b78..689d4a8234e 100644 --- a/PWGLF/Tasks/k892analysis.cxx +++ b/PWGLF/Tasks/k892analysis.cxx @@ -13,7 +13,7 @@ /// \brief Reconstruction of track-track decay resonance candidates /// /// -/// \author Bong-Hwi Lim +/// \author Bong-Hwi Lim , Sawan Sawan #include @@ -38,14 +38,20 @@ struct k892analysis { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; ///// Configurables - /// Figures + /// Histograms ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9, 13.0, 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7, 13.8, 13.9, 14.0, 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7, 14.8, 14.9, 15.0}, "Binning of the pT axis"}; ConfigurableAxis binsPtQA{"binsPtQA", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2, 6.4, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8, 8.0, 8.2, 8.4, 8.6, 8.8, 9.0, 9.2, 9.4, 9.6, 9.8, 10.0}, "Binning of the pT axis"}; - ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 1., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., 55., 60., 65., 70., 80., 90., 100.}, "Binning of the centrality axis"}; + ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Binning of the centrality axis"}; + Configurable cInvMassStart{"cInvMassStart", 0.6, "Invariant mass start"}; + Configurable cInvMassEnd{"cInvMassEnd", 1.5, "Invariant mass end"}; + Configurable cInvMassBins{"cInvMassBins", 900, "Invariant mass binning"}; + Configurable cPIDBins{"cPIDBins", 65, "PID binning"}; + Configurable cPIDQALimit{"cPIDQALimit", 6.5, "PID QA limit"}; + Configurable cDCABins{"cDCABins", 150, "DCA binning"}; /// Event Mixing Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Mixing bins - multiplicity"}; /// Pre-selection cuts Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; /// DCA Selections @@ -55,27 +61,45 @@ struct k892analysis { Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; /// PID Selections - Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 2.0, "TPC nSigma cut for Pion"}; // TPC - Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 2.0, "TOF nSigma cut for Pion"}; // TOF + Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC + Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF + Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, "Combined nSigma cut for Pion"}; // Combined + Configurable cUseOnlyTOFTrackPi{"cUseOnlyTOFTrackPi", false, "Use only TOF track for PID selection"}; // Use only TOF track for Pion PID selection + Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for Kaon PID selection // Kaon - Configurable> kaonTPCPIDpTintv{"kaonTPCPIDpTintv", {999.}, "pT intervals for Kaon TPC PID cuts"}; - Configurable> kaonTPCPIDcuts{"kaonTPCPIDcuts", {2}, "nSigma list for Kaon TPC PID cuts"}; - Configurable> kaonTOFPIDpTintv{"kaonTOFPIDpTintv", {999.}, "pT intervals for Kaon TOF PID cuts"}; - Configurable> kaonTOFPIDcuts{"kaonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; + Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC + Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 3.0, "TOF nSigma cut for Kaon"}; // TOF + Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", -999, "Combined nSigma cut for Kaon"}; // Combined + // Track selections + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor void init(o2::framework::InitContext&) { AxisSpec centAxis = {binsCent, "V0M (%)"}; - AxisSpec multAxis = {0, 0, 100, "V0M (%)"}; // for future + AxisSpec dcaxyAxis = {cDCABins, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {cDCABins, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; AxisSpec ptAxis = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec ptAxisQA = {binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec invMassAxis = {900, 0.6, 1.5, "Invariant Mass (GeV/#it{c}^2)"}; - AxisSpec pidQAAxis = {65, -6.5, 6.5}; + AxisSpec invMassAxis = {cInvMassBins, cInvMassStart, cInvMassEnd, "Invariant Mass (GeV/#it{c}^2)"}; + AxisSpec pidQAAxis = {cPIDBins, -cPIDQALimit, cPIDQALimit}; // Mass QA (quick check) histos.add("k892invmassDS", "Invariant mass of K(892)0 differnt sign", kTH1F, {invMassAxis}); + histos.add("k892invmassDSAnti", "Invariant mass of Anti-K(892)0 differnt sign", kTH1F, {invMassAxis}); histos.add("k892invmassLS", "Invariant mass of K(892)0 like sign", kTH1F, {invMassAxis}); + histos.add("k892invmassLSAnti", "Invariant mass of Anti-K(892)0 like sign", kTH1F, {invMassAxis}); histos.add("k892invmassME", "Invariant mass of K(892)0 mixed event", kTH1F, {invMassAxis}); + // DCA QA + histos.add("QAbefore/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAbefore/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAbefore/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAbefore/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAafter/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAafter/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAafter/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAafter/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); // pT QA histos.add("QAbefore/trkpT_pi", "pT distribution of pion track candidates", kTH1F, {ptAxis}); histos.add("QAbefore/trkpT_ka", "pT distribution of kaon track candidates", kTH1F, {ptAxis}); @@ -97,16 +121,25 @@ struct k892analysis { histos.add("QAafter/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); // 3d histogram - histos.add("h3k892invmassDS", "Invariant mass of K(892)0 differnt sign", kTH3F, {{300, 0, 3000}, ptAxis, invMassAxis}); // TODO: multiplicity bin has to be updatde. - histos.add("h3k892invmassLS", "Invariant mass of K(892)0 same sign", kTH3F, {{300, 0, 3000}, ptAxis, invMassAxis}); // TODO: multiplicity bin has to be updatde. - histos.add("h3k892invmassME", "Invariant mass of K(892)0 mixed event", kTH3F, {{300, 0, 3000}, ptAxis, invMassAxis}); // TODO: multiplicity bin has to be updatde. + histos.add("h3k892invmassDS", "Invariant mass of K(892)0 differnt sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassDSAnti", "Invariant mass of Anti-K(892)0 differnt sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassLS", "Invariant mass of K(892)0 same sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassLSAnti", "Invariant mass of Anti-K(892)0 same sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3k892invmassME", "Invariant mass of K(892)0 mixed event", kTH3F, {centAxis, ptAxis, invMassAxis}); - if (doprocessMC) { + if (doprocessMCLight) { // MC QA - histos.add("h3recok892invmass", "Invariant mass of Reconstructed MC K(892)0", kTH3F, {{300, 0, 3000}, ptAxis, invMassAxis}); // TODO: multiplicity bin has to be updatde. - histos.add("truek892pt", "pT distribution of True MC K(892)0", kTH1F, {ptAxis}); - histos.add("reconk892pt", "pT distribution of Reconstructed MC K(892)0", kTH1F, {ptAxis}); - histos.add("reconk892invmass", "Inv mass distribution of Reconstructed MC Phi", kTH1F, {invMassAxis}); + histos.add("QAMCTrue/trkDCAxy_pi", "DCAxy distribution of pion track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMCTrue/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMCTrue/trkDCAz_pi", "DCAz distribution of pion track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAMCTrue/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("h3Reck892invmass", "Invariant mass of Reconstructed MC K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3Reck892invmassAnti", "Invariant mass of Reconstructed MC Anti-K(892)0", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("k892Gen", "pT distribution of True MC K(892)0", kTH1F, {ptAxis}); + histos.add("k892GenAnti", "pT distribution of True MC Anti-K(892)0", kTH1F, {ptAxis}); + histos.add("k892Rec", "pT distribution of Reconstructed MC K(892)0", kTH1F, {ptAxis}); + histos.add("k892RecAnti", "pT distribution of Reconstructed MC Anti-K(892)0", kTH1F, {ptAxis}); + histos.add("k892Recinvmass", "Inv mass distribution of Reconstructed MC Phi", kTH1F, {invMassAxis}); } // Print output histograms statistics LOG(info) << "Size of the histograms in spectraTOF"; @@ -116,202 +149,216 @@ struct k892analysis { double massKa = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); double massPi = TDatabasePDG::Instance()->GetParticle(kPiPlus)->Mass(); + template + bool trackCut(const TrackType track) + { + // basic track cuts + if (std::abs(track.pt()) < cMinPtcut) + return false; + if (std::abs(track.dcaXY()) > cMaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) + return false; + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; + + return true; + } + // PID selection tools + template + bool selectionPIDPion(const T& candidate) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { + tpcPIDPassed = true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < cMaxTOFnSigmaPion) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedPion > 0) && (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < nsigmaCutCombinedPion * nsigmaCutCombinedPion)) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + return false; + } + template + bool selectionPIDKaon(const T& candidate) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { + tpcPIDPassed = true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cMaxTOFnSigmaKaon) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedKaon > 0) && (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa() < nsigmaCutCombinedKaon * nsigmaCutCombinedKaon)) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + return false; + } + template void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) { TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - bool isTrk1Selected{true}, isTrk2Selected{true}, isTrk1hasTOF{false}, isTrk2hasTOF{false}; - auto vKaonTPCPIDpTintv = static_cast>(kaonTPCPIDpTintv); - auto vKaonTPCPIDcuts = static_cast>(kaonTPCPIDcuts); - auto vKaonTOFPIDpTintv = static_cast>(kaonTOFPIDpTintv); - auto vKaonTOFPIDcuts = static_cast>(kaonTOFPIDcuts); - auto lengthOfkaonTPCPIDpTintv = static_cast(vKaonTPCPIDpTintv.size()); for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { // Full index policy is needed to consider all possible combinations if (trk1.index() == trk2.index()) continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. - //// Initialize variables // Trk1: Pion, Trk2: Kaon - isTrk1Selected = true; - isTrk2Selected = true; - isTrk1hasTOF = false; - isTrk2hasTOF = false; + // apply the track cut + if (!trackCut(trk1) || !trackCut(trk2)) + continue; + + auto isTrk1hasTOF = trk1.hasTOF(); + auto isTrk2hasTOF = trk2.hasTOF(); auto trk1ptPi = trk1.pt(); auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); - auto trk1NSigmaPiTOF = -999.; + auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; auto trk2ptKa = trk2.pt(); auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); - auto trk2NSigmaKaTOF = -999.; + auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.; - // hasTOF? - if ((trk1.tofPIDselectionFlag() & aod::resodaughter::kHasTOF) == aod::resodaughter::kHasTOF) { - isTrk1hasTOF = true; - } - if ((trk2.tofPIDselectionFlag() & aod::resodaughter::kHasTOF) == aod::resodaughter::kHasTOF) { - isTrk2hasTOF = true; - } - //// PID selections - // For Pion candidate, we don't need to apply pT-dependent PID cuts - if (std::abs(trk1NSigmaPiTPC) > cMaxTPCnSigmaPion) - isTrk1Selected = false; - if (isTrk1hasTOF) { - trk1NSigmaPiTOF = trk1.tofNSigmaPi(); - if (std::abs(trk1NSigmaPiTOF) > cMaxTOFnSigmaPion) - isTrk1Selected = false; - } - // For Kaon candidate, we need to apply pT-dependent PID cuts - if (lengthOfkaonTPCPIDpTintv > 0) { - for (int i = 0; i < lengthOfkaonTPCPIDpTintv; i++) { - if (trk2ptKa < vKaonTPCPIDpTintv[i]) { - if (std::abs(trk2NSigmaKaTPC) > vKaonTPCPIDcuts[i]) - isTrk2Selected = false; - } + if constexpr (!IsMix) { + //// QA plots before the selection + // --- PID QA Pion + histos.fill(HIST("QAbefore/TPC_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAbefore/TOF_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); } - } - if (isTrk2hasTOF) { - trk2NSigmaKaTOF = trk2.tofNSigmaKa(); - if (lengthOfkaonTPCPIDpTintv > 0) { - for (int i = 0; i < lengthOfkaonTPCPIDpTintv; i++) { - if (trk2ptKa < vKaonTOFPIDpTintv[i]) { - if (std::abs(trk2NSigmaKaTOF) > vKaonTOFPIDcuts[i]) - isTrk2Selected = false; - } - } + // --- PID QA Kaon + histos.fill(HIST("QAbefore/TPC_Nsigmaka_all"), trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAbefore/TOF_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); } + histos.fill(HIST("QAbefore/trkpT_pi"), trk1ptPi); + histos.fill(HIST("QAbefore/trkpT_ka"), trk2ptKa); + histos.fill(HIST("QAbefore/trkDCAxy_pi"), trk1.dcaXY()); + histos.fill(HIST("QAbefore/trkDCAxy_ka"), trk2.dcaXY()); + histos.fill(HIST("QAbefore/trkDCAz_pi"), trk1.dcaZ()); + histos.fill(HIST("QAbefore/trkDCAz_ka"), trk2.dcaZ()); } - //// QA plots before the selection - // --- PID QA Pion - histos.fill(HIST("QAbefore/TPC_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAbefore/TOF_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAbefore/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); - } - // --- PID QA Kaon - histos.fill(HIST("QAbefore/TPC_Nsigmaka_all"), trk2ptKa, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAbefore/TOF_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); - } - histos.fill(HIST("QAbefore/trkpT_pi"), trk1ptPi); - histos.fill(HIST("QAbefore/trkpT_ka"), trk2ptKa); - //// Apply the selection - if (!isTrk1Selected || !isTrk2Selected) + if (cUseOnlyTOFTrackPi && !isTrk1hasTOF) + continue; + if (cUseOnlyTOFTrackKa && !isTrk2hasTOF) + continue; + if (!selectionPIDPion(trk1) || !selectionPIDKaon(trk2)) continue; - //// QA plots after the selection - // --- PID QA Pion - histos.fill(HIST("QAafter/TPC_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAafter/TOF_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTOF); - histos.fill(HIST("QAafter/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); - } - // --- PID QA Kaon - histos.fill(HIST("QAafter/TPC_Nsigmaka_all"), trk2ptKa, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QAafter/TOF_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QAafter/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + if constexpr (!IsMix) { + //// QA plots after the selection + // --- PID QA Pion + histos.fill(HIST("QAafter/TPC_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAafter/TOF_Nsigma_pi_all"), trk1ptPi, trk1NSigmaPiTOF); + histos.fill(HIST("QAafter/TOF_TPC_Map_pi_all"), trk1NSigmaPiTOF, trk1NSigmaPiTPC); + } + // --- PID QA Kaon + histos.fill(HIST("QAafter/TPC_Nsigmaka_all"), trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAafter/TOF_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QAafter/TOF_TPC_Mapka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + histos.fill(HIST("QAafter/trkpT_pi"), trk1ptPi); + histos.fill(HIST("QAafter/trkpT_ka"), trk2ptKa); + histos.fill(HIST("QAafter/trkDCAxy_pi"), trk1.dcaXY()); + histos.fill(HIST("QAafter/trkDCAxy_ka"), trk2.dcaXY()); + histos.fill(HIST("QAafter/trkDCAz_pi"), trk1.dcaZ()); + histos.fill(HIST("QAafter/trkDCAz_ka"), trk2.dcaZ()); } - histos.fill(HIST("QAafter/trkpT_pi"), trk1ptPi); - histos.fill(HIST("QAafter/trkpT_ka"), trk2ptKa); //// Resonance reconstruction lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); lResonance = lDecayDaughter1 + lDecayDaughter2; // Rapidity cut - if (lResonance.Rapidity() > 0.5 || lResonance.Rapidity() < -0.5) + if (abs(lResonance.Rapidity()) > 0.5) continue; //// Un-like sign pair only if (trk1.sign() * trk2.sign() < 0) { if constexpr (!IsMix) { - histos.fill(HIST("k892invmassDS"), lResonance.M()); - histos.fill(HIST("h3k892invmassDS"), collision.multV0M(), lResonance.Pt(), lResonance.M()); // TODO: multV0M has to be updatde. + if (trk1.sign() > 0) { + histos.fill(HIST("k892invmassDS"), lResonance.M()); + histos.fill(HIST("h3k892invmassDS"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else { + histos.fill(HIST("k892invmassDSAnti"), lResonance.M()); + histos.fill(HIST("h3k892invmassDSAnti"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } } else { histos.fill(HIST("k892invmassME"), lResonance.M()); - histos.fill(HIST("h3k892invmassME"), collision.multV0M(), lResonance.Pt(), lResonance.M()); // TODO: multV0M has to be updatde. + histos.fill(HIST("h3k892invmassME"), collision.multV0M(), lResonance.Pt(), lResonance.M()); } // MC if constexpr (IsMC) { if (abs(trk1.pdgCode()) != kPiPlus || abs(trk2.pdgCode()) != kKPlus) continue; - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 == mother2) { // Same mother - if (abs(trk1.motherPDG()) == 313) { // k892(0) - histos.fill(HIST("reconk892pt"), lResonance.Pt()); - histos.fill(HIST("reconk892invmass"), lResonance.M()); - histos.fill(HIST("h3recok892invmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); // TODO: multV0M has to be updatde. - } + if (trk1.motherId() != trk2.motherId()) // Same mother + continue; + if (abs(trk1.motherPDG()) != 313) + continue; + + // Track selection check. + histos.fill(HIST("QAMCTrue/trkDCAxy_pi"), trk1.dcaXY()); + histos.fill(HIST("QAMCTrue/trkDCAxy_ka"), trk2.dcaXY()); + histos.fill(HIST("QAMCTrue/trkDCAz_pi"), trk1.dcaZ()); + histos.fill(HIST("QAMCTrue/trkDCAz_ka"), trk2.dcaZ()); + + // MC histograms + if (trk1.motherPDG() > 0) { + histos.fill(HIST("k892Rec"), lResonance.Pt()); + histos.fill(HIST("k892Recinvmass"), lResonance.M()); + histos.fill(HIST("h3Reck892invmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else { + histos.fill(HIST("k892RecAnti"), lResonance.Pt()); + histos.fill(HIST("k892Recinvmass"), lResonance.M()); + histos.fill(HIST("h3Reck892invmassAnti"), collision.multV0M(), lResonance.Pt(), lResonance.M()); } } } else { - if constexpr (!IsMix) { + if constexpr (!IsMix) + continue; + if (trk1.sign() > 0) { histos.fill(HIST("k892invmassLS"), lResonance.M()); - histos.fill(HIST("h3k892invmassLS"), collision.multV0M(), lResonance.Pt(), lResonance.M()); // TODO: multV0M has to be updatde. + histos.fill(HIST("h3k892invmassLS"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else { + histos.fill(HIST("k892invmassLSAnti"), lResonance.M()); + histos.fill(HIST("h3k892invmassLSAnti"), collision.multV0M(), lResonance.Pt(), lResonance.M()); } } } } - void processData(aod::ResoCollisions& collisions, - aod::ResoTracks const& resotracks) - { - LOGF(debug, "[DATA] Processing %d collisions", collisions.size()); - for (auto& collision : collisions) { - Partition selectedTracks = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks.bindTable(resotracks); - auto colTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colTracks, colTracks); - } - } - PROCESS_SWITCH(k892analysis, processData, "Process Event for data", true); - void processDataLight(aod::ResoCollision& collision, aod::ResoTracks const& resotracks) { + // LOG(info) << "new collision, zvtx: " << collision.posZ(); fillHistograms(collision, resotracks, resotracks); } PROCESS_SWITCH(k892analysis, processDataLight, "Process Event for data", false); - void processMC(aod::ResoCollisions& collisions, - soa::Join const& resotracks, aod::McParticles const& mcParticles) - { - LOGF(debug, "[MC] MC events: %d", collisions.size()); - for (auto& collision : collisions) { - Partition> selectedTracks = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks.bindTable(resotracks); - auto colTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colTracks, colTracks); - } - - // Not related to the real collisions - for (auto& part : mcParticles) { // loop over all MC particles - if (abs(part.pdgCode()) == 313) { // K892(0) - if (part.y() > 0.5 || part.y() < -0.5) { // rapidity cut - continue; - } - bool pass1 = false; - bool pass2 = false; - for (auto& dau : part.daughters_as()) { - if (abs(dau.pdgCode()) == kKPlus) { // At least one decay to Kaon - pass2 = true; - } - if (abs(dau.pdgCode()) == kPiPlus) { // At least one decay to Pion - pass1 = true; - } - } - if (!pass1 || !pass2) // If we have both decay products - continue; - histos.fill(HIST("truek892pt"), part.pt()); - } - } - } - PROCESS_SWITCH(k892analysis, processMC, "Process Event for MC", false); - void processMCLight(aod::ResoCollision& collision, soa::Join const& resotracks, aod::McParticles const& mcParticles) { @@ -319,52 +366,45 @@ struct k892analysis { } PROCESS_SWITCH(k892analysis, processMCLight, "Process Event for MC", false); - void processMCTrue(aod::ResoCollisions& collisions, aod::McParticles const& mcParticles) + void processMCTrue(aod::ResoMCParents& resoParents) { - // Not related to the real collisions - for (auto& part : mcParticles) { // loop over all MC particles - if (abs(part.pdgCode()) == 313) { // K892(0) - if (part.y() > 0.5 || part.y() < -0.5) { // rapidity cut - continue; - } - bool pass1 = false; - bool pass2 = false; - for (auto& dau : part.daughters_as()) { - if (abs(dau.pdgCode()) == kKPlus) { // At least one decay to Kaon - pass2 = true; - } - if (abs(dau.pdgCode()) == kPiPlus) { // At least one decay to Pion - pass1 = true; - } - } - if (!pass1 || !pass2) // If we have both decay products - continue; - histos.fill(HIST("truek892pt"), part.pt()); + for (auto& part : resoParents) { // loop over all pre-filtered MC particles + if (abs(part.pdgCode()) != 313) // K892(0) + continue; + if (abs(part.y()) > 0.5) { // rapidity cut + continue; + } + bool pass1 = false; + bool pass2 = false; + if (abs(part.daughterPDG1()) == kKPlus || abs(part.daughterPDG2()) == kKPlus) { // At least one decay to Kaon + pass2 = true; } + if (abs(part.daughterPDG1()) == kPiPlus || abs(part.daughterPDG2()) == kPiPlus) { // At least one decay to Pion + pass1 = true; + } + if (!pass1 || !pass2) // If we have both decay products + continue; + if (part.pdgCode() > 0) + histos.fill(HIST("k892Gen"), part.pt()); + else + histos.fill(HIST("k892GenAnti"), part.pt()); } } PROCESS_SWITCH(k892analysis, processMCTrue, "Process Event for MC", false); // Processing Event Mixing - using BinningTypeVetZTPCtemp = ColumnBinningPolicy; // TODO: MultTPCtemp has to be updatde. - BinningTypeVetZTPCtemp colBinning{{CfgVtxBins, CfgMultBins}, true}; - void processME(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) + using BinningTypeVtxZT0M = ColumnBinningPolicy; + void processMELight(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) { - LOGF(debug, "Event Mixing Started"); auto tracksTuple = std::make_tuple(resotracks); - SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; + SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { - Partition selectedTracks1 = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks1.bindTable(tracks1); - Partition selectedTracks2 = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks2.bindTable(tracks2); - - fillHistograms(collision1, selectedTracks1, selectedTracks2); + fillHistograms(collision1, tracks1, tracks2); } }; - PROCESS_SWITCH(k892analysis, processME, "Process EventMixing", false); + PROCESS_SWITCH(k892analysis, processMELight, "Process EventMixing light without partition", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/kinkAnalysis.cxx b/PWGLF/Tasks/kinkAnalysis.cxx new file mode 100644 index 00000000000..f103b385777 --- /dev/null +++ b/PWGLF/Tasks/kinkAnalysis.cxx @@ -0,0 +1,851 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief kinkAnalysis: Analysis task for kink topology, to be converted later in a table producer for common usage by other tasks +/// \author everyone + +#include + +#include "Math/Vector4D.h" +#include "Common/Core/CollisionAssociation.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Common/Core/trackUtilities.h" +#include "Framework/DataTypes.h" +#include "DCAFitter/DCAFitterN.h" +#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/RecoDecay.h" +#include "CommonConstants/LHCConstants.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/PIDResponse.h" + +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "DetectorsVertexing/SVertexer.h" +#include "DetectorsVertexing/SVertexerParams.h" +#include "TPCReconstruction/TPCFastTransformHelperO2.h" +#include "DataFormatsTPC/VDriftCorrFact.h" +#include "DataFormatsCalibration/MeanVertexObject.h" + +#include "ReconstructionDataFormats/Track.h" + +#include +using namespace std; + +using namespace o2; +using namespace vertexing; + +using namespace o2::dataformats; +using namespace o2::aod; + +using namespace o2::framework; +using namespace o2::framework::expressions; +using VBracket = o2::math_utils::Bracket; + +static constexpr int POS = 0, NEG = 1; + +namespace kink +{ +constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; +} + +struct KinkCandidates { + int chargeMother; + int globalIndexMother; + int globalIndexDaughter; + int mcParticleIdxMother; + int mcParticleIdxDaughter; + float prx, pry, prz; + float decayvtxX, decayvtxY, decayvtxZ; + float mthinnerpx, mthinnerpy, mthinnerpz; + float mthouterpx, mthouterpy, mthouterpz; + float dghtpx, dghtpy, dghtpz; + unsigned int flags = 0u; +}; + +struct kinkAnalysis { + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Service ccdb; + + enum strParticleAdDecay { SigmaMinus, + SigmaPlusToPi, + SigmaPlusToProton, + Kaon, + Pion, + Xi, + OmegaToL, + OmegaToXi }; + + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable cfgBz{"cfgBz", -999, "bz field, -999 is automatic"}; + Configurable cfgGRPpath{"cfgGRPpath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable cfgGRPmagPath{"cfgGRPmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable cfgCCDBurl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable cfgLUTpath{"cfgLUTpath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable dcaKinkDtopv{"dcaKinkDtopv", .2, "DCA kink daughter To PV"}; + Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + Configurable cfgMotherCharge{"cfgMotherCharge", -1, "mother charge"}; + Configurable cfgDaughterCharge{"cfgDaughterCharge", -1, "mother charge"}; + Configurable cfgParticleSpec{"cfgParticleSpec", SigmaPlusToProton, "particle species"}; + Configurable cfgLowerHistLimit{"cfgLowerHistLimit", 1.1, "lower limit for inv mass histo"}; + Configurable cfgUpperHistLimit{"cfgUpperHistLimit", 1.4, "upper limit for inv mass histo"}; + Configurable cfgNsigmaTPCdaughter{"cfgNsigmaTPCdaughter", 3, "nSigma TPC for the daughter track"}; + Configurable qTupper{"qTupper", 0.195, "upper qT cut"}; + Configurable qTlower{"qTLower", 0.150, "upper qT cut"}; + Configurable kinkAngle{"kinkAngle", 0.5, "mother-daughter angle cutoff"}; + Configurable zDiff{"zDiff", 20., "mother-daughter z diff"}; + Configurable phiDiff{"phiDiff", 100., "mother-daughter phi diff"}; + Configurable cfgIsMC{"cfgIsMC", true, "data or MC"}; + + o2::base::MatLayerCylSet* lut = nullptr; + o2::dataformats::MeanVertexObject* mVtx = nullptr; + o2::vertexing::DCAFitterN<2> ft2; + + std::vector mKinkCandidates; + + int mRunNumber; + float mBz; + + float etaS = 0; + float phiS = 0; + float etaP = 0; + float phiP = 0; + + std::array sigmaPDC = {0, 0, 0}; + std::array pionPDC = {0, 0, 0}; + std::array sigmaPin = {0, 0, 0}; + + float pionPabsDC = 0; + float sigmaPabsDC = 0; + float sigmaPt = 0.; + + float costheta; + float theta; + float qT; + + float pionE = 0; + double neutronE = 0; + float sigmaE = 0; + float neutronPabs = 0; + float neutronM = 0; + float mass; + float radToDeg = 180. / M_PI; + int particlePdgCode; + + o2::track::TrackParCov SigmaTr; + o2::track::TrackParCov SigmaTr2; + o2::track::TrackParCov PionTr; + + float mMother, mChargedDaughter, mNeutralDaughter; + + using CompleteTracks = soa::Join; + using CompleteCollisions = soa::Join; + + struct TrackCand { + int Idxtr; + int mcParticleIdx = -1; + VBracket vBracket{}; + }; + + float angleCutFunction(int particleName, float x) + { + + float mSigmaMinus = 1.197449, mSigmaPlus = 1.189449, mKaon = 0.493677, mPion = 0.13957018, mXi = 1.321, mOmega = 1.67245; + float par1 = mSigmaMinus; /// Default value is for SigmaMinus + float par2 = 0.8; + float par3 = M_PI; + switch (particleName) { + case SigmaPlusToPi: + par1 = mSigmaPlus; + par2 = 0.8; + break; + + case SigmaPlusToProton: + par1 = mSigmaPlus; + par2 = 0.2; + break; + + case Xi: + par1 = mXi; + par2 = 0.68; + break; + + case OmegaToL: + par1 = mOmega; + par2 = 0.68; + break; + + case OmegaToXi: + par1 = mOmega; + par2 = 0.68; + break; + + case Kaon: + par1 = mKaon; + par2 = 0.9127037; + break; + + case Pion: + par1 = mPion; + par2 = 0.2731374; + break; + } + + if ((particleName == SigmaMinus) || (particleName == SigmaPlusToPi) || (particleName == SigmaPlusToProton) || (particleName == Xi) || (particleName == OmegaToXi) || (particleName == OmegaToL)) + return par1 * (par2 / (sqrt((x * x) * (1 - (par2 * par2)) - ((par1 * par1) * (par2 * par2))))) * (180. / par3) + 1; + + return ((atan(par1 * par2 * (1.0 / (sqrt((x * x) * (1.0 - (par1 * par1)) - (par1 * par1) * (par2 * par2)))))) * 180.) / par3; + } + + void init(InitContext const&) + { + ccdb->setURL(cfgCCDBurl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + int anParticleName = cfgParticleSpec; + if (cfgIsMC) { + switch (anParticleName) { + case SigmaPlusToPi: + if (cfgMotherCharge == 1) + particlePdgCode = 3222; + else + particlePdgCode = -3222; + break; + + case SigmaPlusToProton: + if (cfgMotherCharge == 1) + particlePdgCode = 3222; + else + particlePdgCode = -3222; + break; + + case Xi: + if (cfgMotherCharge == -1) + particlePdgCode = 3312; + else + particlePdgCode = -3312; + break; + + case OmegaToL: + if (cfgMotherCharge == -1) + particlePdgCode = 3334; + else + particlePdgCode = -3334; + break; + + case OmegaToXi: + if (cfgMotherCharge == -1) + particlePdgCode = 3334; + else + particlePdgCode = -3334; + break; + + case SigmaMinus: + if (cfgMotherCharge == -1) + particlePdgCode = 3112; + else + particlePdgCode = -3112; + break; + + default: + particlePdgCode = 3112; + } + } + + mRunNumber = 0; + mBz = 0.f; + + // define axes you want to use + const AxisSpec axisEta{30, -1.5, +1.5, "#eta"}; + const AxisSpec axisqT{1000, 0.0, 1.0, "q_{T}"}; + const AxisSpec axisRmother{500, 0.0, 50.0, "#it{R}_{mother} (cm)"}; + const AxisSpec axisDCAdaugh{1000, 0.0, 10.0, "#it{DCA}_{daughter} (cm)"}; + const AxisSpec axisSigmaMass{300, cfgLowerHistLimit, cfgUpperHistLimit, "#it{M}_{inv} (Gev/#it{c^{2}})"}; + const AxisSpec axisdtime{10000, 0, 50, "#delta t"}; + const AxisSpec axisPt{500, 0., 50., "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axisdphi{360, 0, 360, "#delta phi"}; + const AxisSpec axisdz{400, -20., 20, "#delta z"}; + const AxisSpec axisPdgCodes{8001, -4000.5, 4000.5, "mother pdg codes"}; + + // create histograms + histos.add("etaHistogram", "etaHistogram", kTH1F, {axisEta}); + histos.add("hqT", "hqT", kTH1F, {axisqT}); + histos.add("hRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); + histos.add("hVtxZData", "collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); + histos.add("hCollId", "collision id", HistType::kTH1F, {{1000, 0., 100000., "collision id"}}); + histos.add("hRadiusMth", "hRadiusMth", kTH1F, {axisRmother}); + histos.add("hMassMinusPt", "hMassMinusPt", kTH2F, {axisSigmaMass, axisPt}); + histos.add("hMassPlusPt", "hMassPlusPt", kTH2F, {axisSigmaMass, axisPt}); + histos.add("hBackgroundPosNegPt", "hBackgroundPosNegPt", kTH2F, {axisSigmaMass, axisPt}); + histos.add("hBackgroundNegPosPt", "hBackgroundNegPosPt", kTH2F, {axisSigmaMass, axisPt}); + histos.add("hDCAdaughterToPV", "hDCAdaughterToPV", kTH1F, {axisDCAdaugh}); + histos.add("hDCAMotherToPV", "hDCAMotherToPV", kTH1F, {axisDCAdaugh}); + histos.add("hdeltatime", "hdeltatime", kTH1F, {axisdtime}); + histos.add("hdelt_tthresh", "hdelt_tthresh", kTH2F, {axisdtime, axisdtime}); + histos.add("hdeltaphi", "hdeltaphi", kTH1F, {axisdphi}); + histos.add("hdeltaz", "hdeltaz", kTH1F, {axisdz}); + histos.add("generatedPt", "generatedPt", kTH1F, {axisPt}); + histos.add("hPtMinusRecMcTrth", "hPtMinusRecMcTrth", kTH2F, {axisSigmaMass, axisPt}); + histos.add("hPtPlusRecMcTrth", "hPtPlusRecMcTrth", kTH2F, {axisSigmaMass, axisPt}); + histos.add("hcodes", "hcodes", kTH2F, {axisPdgCodes, axisPdgCodes}); + histos.add("hptMtrue", "hptMtrue", kTH2F, {axisPt, axisPt}); + histos.add("hptMDtrue", "hptMDtrue", kTH2F, {axisPt, axisPt}); + histos.add("hptMDelse", "hptMDelse", kTH2F, {axisPt, axisPt}); + histos.add("hPtMinusRecMcTrthM", "hPtMinusRecMcTrthM", kTH2F, {axisSigmaMass, axisPt}); + histos.add("hPtMinusRecMcTrthelse", "hPtMinusRecMcTrthelse", kTH2F, {axisSigmaMass, axisPt}); + + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(cfgLUTpath)); + ft2.setMaxChi2(5); + ft2.setUseAbsDCA(true); + + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + ft2.setMatCorrType(matCorr); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (cfgBz > -990) { + mBz = cfgBz; + ft2.setBz(mBz); + o2::parameters::GRPMagField grpmag; + if (fabs(mBz) > 1e-5) { + grpmag.setL3Current(30000.f / (mBz / 5.0f)); + } + o2::base::Propagator::initFieldFromGRP(&grpmag); + mVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + mRunNumber = bc.runNumber(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(cfgGRPpath, run3grp_timestamp); + o2::parameters::GRPMagField* grpmag = 0x0; + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + // Fetch magnetic field from ccdb for current collision + mBz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << mBz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(cfgGRPmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << cfgGRPmagPath << " of object GRPMagField and " << cfgGRPpath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + mBz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << mBz << " kZG"; + } + mVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + mRunNumber = bc.runNumber(); + + ft2.setBz(mBz); + + o2::base::Propagator::Instance()->setMatLUT(lut); + } + + std::array, 4> makeTracksPool(CompleteCollisions const& collisions, CompleteTracks const& tracks, o2::aod::AmbiguousTracks const& ambiTracks, aod::BCsWithTimestamps const&) + { + mKinkCandidates.clear(); + std::unordered_map> tmap; + TrackCand trForpool; + + std::array, 4> pools; // pools of positive and negative seeds sorted in min VtxID + + std::vector selected(tracks.size(), 0u); + std::vector globalBCvector; + + int index{0}; + for (const auto& track : tracks) { + if (track.has_collision()) { + if (track.collision_as().has_bc()) { + globalBCvector.push_back(track.collision_as().bc_as().globalBC()); + } + } else { + for (const auto& ambTrack : ambiTracks) { + if (ambTrack.trackId() == track.globalIndex()) { + globalBCvector.push_back(ambTrack.bc().begin().globalBC()); + break; + } + } + } + if (std::abs(track.eta()) < 0.8) { + if (track.hasITS() && !track.hasTPC() && !track.hasTOF() && track.itsNCls() < 6 && track.itsNClsInnerBarrel() == 3 && track.itsChi2NCl() < 4) { + selected[index] = 1; + } else if (track.hasITS() && track.hasTPC() && track.itsNClsInnerBarrel() == 0 && track.itsNCls() < 4 && track.tpcNClsCrossedRows() >= 70 && track.itsChi2NCl() < 36.f && track.tpcChi2NCl() < 4.f && track.tpcNClsCrossedRows() > 0.8 * track.tpcNClsFindable()) { + selected[index] = 2; + } + } + index++; + } + + constexpr auto bOffsetMax = 241; // 6 mus (ITS) + + for (const auto& collision : collisions) { + if (!collision.sel8()) + continue; + if (std::abs(collision.posZ()) > 10.) + continue; + + const float collTime = collision.collisionTime(); + const float collTimeRes2 = collision.collisionTimeRes() * collision.collisionTimeRes(); + uint64_t collBC = collision.bc_as().globalBC(); + const auto collIdx = collision.globalIndex(); + + histos.fill(HIST("hVtxZData"), collision.posZ()); + index = -1; + for (const auto& track : tracks) { + index++; + if (!selected[index] || !track.has_collision()) + continue; + const int64_t bcOffset = (int64_t)globalBCvector[track.filteredIndex()] - (int64_t)collBC; + if (std::abs(bcOffset) > bOffsetMax) { + continue; + } + + float trackTime{0.}; + float trackTimeRes{0.}; + if (track.isPVContributor()) { + trackTime = track.collision_as().collisionTime(); // if PV contributor, we assume the time to be the one of the collision + trackTimeRes = constants::lhc::LHCBunchSpacingNS; // 1 BC + } else { + trackTime = track.trackTime(); + trackTimeRes = track.trackTimeRes(); + } + + const float deltaTime = trackTime - collTime + bcOffset * constants::lhc::LHCBunchSpacingNS; + float sigmaTimeRes2 = collTimeRes2 + trackTimeRes * trackTimeRes; + + float thresholdTime = 0.; + if (track.isPVContributor()) { + thresholdTime = trackTimeRes; + } else if (TESTBIT(track.flags(), o2::aod::track::TrackTimeResIsRange)) { + thresholdTime = std::sqrt(sigmaTimeRes2); // + timeMargin; + } else { + // thresholdTime = nSigmaForTimeCompat * std::sqrt(sigmaTimeRes2); // + timeMargin; + thresholdTime = 4. * std::sqrt(sigmaTimeRes2); // + timeMargin; + } + + histos.fill(HIST("hdeltatime"), deltaTime); + histos.fill(HIST("hdelt_tthresh"), deltaTime, thresholdTime); + + if (std::abs(deltaTime) < thresholdTime) { + + const auto& tref = tmap.find(track.globalIndex()); + if (tref != tmap.end()) { + pools[tref->second.second][tref->second.first].vBracket.setMax(static_cast(collIdx)); // this track was already processed with other vertex, account the latter + continue; + } + } + + int poolIndex = (selected[index] - 1) * 2 + (track.sign() < 0); /// first the two mothers then the two daughters (mom pos 0, mom neg 1, dau pos 2, dau neg 3) + trForpool.Idxtr = track.globalIndex(); + trForpool.vBracket = {static_cast(collIdx), static_cast(collIdx)}; + pools[poolIndex].emplace_back(trForpool); + if (std::abs(deltaTime) < thresholdTime) { // track attached to >1 vertex, remember that it was already processed + tmap[track.globalIndex()] = {pools[poolIndex].size() - 1, poolIndex}; + } + + } // track Mother loop + } // collision loop + + return pools; + } + + void calculateInvMass(CompleteCollisions const& collisions, CompleteTracks const& tracks, o2::aod::AmbiguousTracks const& ambiTracks, aod::BCsWithTimestamps const& bcWtmp, gsl::span> trackPoolM, gsl::span> trackPoolD, int chargeM, int chargeD, int particleName, const aod::McParticles* partTable = nullptr) + { + + int ntrInner = chargeM < 0 ? trackPoolM[NEG].size() : trackPoolM[POS].size(); + int ntrOuter = chargeD < 0 ? trackPoolD[NEG].size() : trackPoolD[POS].size(); + + const int poolCh1 = chargeM < 0 ? 1 : 0; + const int poolCh2 = chargeD < 0 ? 1 : 0; + int motherPdg = 999; + int daughterPdg = 777; + + switch (particleName) { + case SigmaMinus: + mMother = 1.197449; + mChargedDaughter = 0.13957039; + mNeutralDaughter = 0.9395654205; + break; + + case SigmaPlusToPi: + mMother = 1.18937; + mChargedDaughter = 0.13957039; + mNeutralDaughter = 0.9395654205; + break; + + case SigmaPlusToProton: + mMother = 1.18937; + mChargedDaughter = 0.93827208816; + mNeutralDaughter = 0.1349768; + break; + + case Kaon: + mMother = 0.493677; + mChargedDaughter = 0.1056583755; + mNeutralDaughter = 0.; + break; + + case Xi: + mMother = 1.32171; + mChargedDaughter = 0.13957039; + mNeutralDaughter = 1.115683; + break; + + case OmegaToL: + mMother = 1.67245; + mChargedDaughter = 0.493677; + mNeutralDaughter = 1.115683; + break; + + case OmegaToXi: + mMother = 1.67245; + mChargedDaughter = 0.13957039; + mNeutralDaughter = 1.31486; + break; + } + + o2::dataformats::VertexBase primaryVertex; + + std::array, 2> mVtxSecondTrack{}; // 1st pos. and neg. track of the pools for each vertex + + for (int i = 0; i < 2; i++) { + mVtxSecondTrack[i].clear(); + mVtxSecondTrack[i].resize(collisions.size(), -1); + } + + for (int pn = 0; pn < 2; pn++) { + auto& vtxFirstT = mVtxSecondTrack[pn]; + const auto& tracksPool = trackPoolD[pn]; + for (unsigned i = 0; i < tracksPool.size(); i++) { + const auto& t = tracksPool[i]; + for (int j{t.vBracket.getMin()}; j <= t.vBracket.getMax(); ++j) { + if (vtxFirstT[j] == -1) { + vtxFirstT[j] = i; + } + } + } + } + + for (int itp = 0; itp < ntrInner; itp++) { // HERE change neg->pos to get the other charge!!! + auto& seedM = trackPoolM[poolCh1][itp]; + int firstD = mVtxSecondTrack[poolCh2][seedM.vBracket.getMin()]; + if (firstD < 0) { + LOG(debug) << "No partner is found for pos.track " << itp << " out of " << ntrInner; + continue; + } + + const auto& trackM = tracks.iteratorAt(seedM.Idxtr); + if ((seedM.mcParticleIdx != -1) && partTable) { + auto mcParticle = partTable->rawIteratorAt(seedM.mcParticleIdx); + motherPdg = mcParticle.pdgCode(); + } + + if (trackM.has_collision()) { + auto const& collision = trackM.collision_as(); + primaryVertex.setPos({collision.posX(), collision.posY(), collision.posZ()}); + primaryVertex.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + histos.fill(HIST("hRecVtxZData"), primaryVertex.getZ()); + } else { + primaryVertex.setPos({mVtx->getX(), mVtx->getY(), mVtx->getZ()}); + histos.fill(HIST("hRecVtxZData"), primaryVertex.getZ()); + } + + SigmaTr = getTrackParCov(trackM); + o2::base::Propagator::Instance()->PropagateToXBxByBz(SigmaTr, kink::LayerRadii[trackM.itsNCls() - 1]); + + SigmaTr2 = getTrackParCov(trackM); + + gpu::gpustd::array dcaInfoM; + o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, SigmaTr2, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoM); + auto motherdcaXY = abs(dcaInfoM[0]); + histos.fill(HIST("hDCAMotherToPV"), motherdcaXY); + + if (motherdcaXY > 0.03) + continue; + + for (int itn = firstD; itn < ntrOuter; itn++) { + auto& seedD = trackPoolD[poolCh2][itn]; + if (seedD.vBracket.isOutside(seedM.vBracket)) { + LOG(debug) << "Brackets do not match"; + continue; + } + + const auto& trackDgh = tracks.iteratorAt(static_cast(seedD.Idxtr)); + + if ((seedD.mcParticleIdx != -1) && partTable) { + auto mcParticle = partTable->rawIteratorAt(seedD.mcParticleIdx); + daughterPdg = mcParticle.pdgCode(); + } + PionTr = getTrackParCov(trackDgh); + + SigmaTr2.getPxPyPzGlo(sigmaPin); + + if ((particleName == SigmaMinus) || (particleName == SigmaPlusToPi) || (particleName == Xi) || (particleName == OmegaToXi)) { + if (trackDgh.tpcNSigmaPi() > cfgNsigmaTPCdaughter) + continue; + } + if (particleName == SigmaPlusToProton) { + if (trackDgh.tpcNSigmaPr() > cfgNsigmaTPCdaughter) + continue; + } + if (particleName == OmegaToL) { + if (trackDgh.tpcNSigmaKa() > cfgNsigmaTPCdaughter) + continue; + } + + gpu::gpustd::array dcaInfo; + o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, PionTr, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfo); + auto kinkdcaXY = abs(dcaInfo[0]); + histos.fill(HIST("hDCAdaughterToPV"), kinkdcaXY); + + if (kinkdcaXY < dcaKinkDtopv) + continue; + + // check how much the tracks are close in space + if ((cfgIsMC) && (motherPdg == particlePdgCode)) { + histos.fill(HIST("hdeltaphi"), (SigmaTr.getPhi() - PionTr.getPhi()) * radToDeg); + histos.fill(HIST("hdeltaz"), SigmaTr.getZ() - PionTr.getZ()); + } + + if (std::abs(SigmaTr.getZ() - PionTr.getZ()) > zDiff) + continue; + if ((std::abs(SigmaTr.getPhi() - PionTr.getPhi()) * radToDeg) > phiDiff) + continue; + + { + try { + ft2.process(PionTr, SigmaTr); + ft2.propagateTracksToVertex(); + if (ft2.isPropagateTracksToVertexDone() == true) { + auto SigmaTrDCA = ft2.getTrack(1); + auto PionTrDCA = ft2.getTrack(0); + SigmaTrDCA.getPxPyPzGlo(sigmaPDC); + sigmaPabsDC = SigmaTrDCA.getP(); + sigmaPt = SigmaTr.getPt(); + etaS = SigmaTr.getEta(); + phiS = SigmaTr.getPhi(); + + PionTrDCA.getPxPyPzGlo(pionPDC); + pionPabsDC = PionTrDCA.getP(); + etaP = PionTr.getEta(); + phiP = PionTr.getPhi(); + + pionE = 0; + neutronE = 0; + + if (ft2.getChi2AtPCACandidate() < 0) + continue; + std::array R = ft2.getPCACandidatePos(); + + pionE = sqrt(mChargedDaughter * mChargedDaughter + pionPabsDC * pionPabsDC); + + costheta = (sigmaPDC[0] * pionPDC[0] + sigmaPDC[1] * pionPDC[1] + sigmaPDC[2] * pionPDC[2]) / (sigmaPabsDC * pionPabsDC); + theta = std::acos(costheta); + + qT = pionPabsDC * std::sin(theta); + + histos.fill(HIST("hqT"), qT); + + sigmaE = sqrt(mMother * mMother + sigmaPabsDC * sigmaPabsDC); + neutronPabs = sqrt(pow((sigmaPDC[2] - pionPDC[2]), 2) + pow((sigmaPDC[1] - pionPDC[1]), 2) + pow((sigmaPDC[0] - pionPDC[0]), 2)); + neutronM = sqrt((sigmaE - pionE) * (sigmaE - pionE) - neutronPabs * neutronPabs); + + if ((particleName == SigmaMinus) || (particleName == SigmaPlusToPi)) { + if ((theta * radToDeg > (angleCutFunction(particleName, sigmaPabsDC))) && (sigmaPabsDC > 1.6)) + continue; + } + if (particleName == SigmaPlusToProton) { + if ((theta * radToDeg > (angleCutFunction(particleName, sigmaPabsDC))) && (sigmaPabsDC > 0.3)) + continue; + } + if (particleName == Kaon) { + Double_t maxDecAngKmu = angleCutFunction(particleName, sigmaPabsDC); + Double_t maxDecAngpimu = angleCutFunction(Pion, sigmaPabsDC); + + if ((theta * radToDeg < maxDecAngpimu * 1.2)) + continue; + if ((theta * radToDeg > maxDecAngKmu * .98) && (sigmaPabsDC > 1.2)) + continue; + } + if (particleName == Xi) { + if (sigmaPabsDC < 2.) + if (theta * radToDeg < 2.5) + continue; + if (sigmaPabsDC > 1.2) + if (theta * radToDeg > angleCutFunction(particleName, sigmaPabsDC)) + continue; + } + if ((particleName == OmegaToL) || (particleName == OmegaToXi)) { + if (sigmaPabsDC < 5.5) + if (theta * radToDeg < 4.) + continue; + if (sigmaPabsDC > 0.6) + if (theta * radToDeg > angleCutFunction(particleName, sigmaPabsDC)) + continue; + } + + if (!cfgIsMC) + if (sigmaPt < 1.6) + continue; + + if (theta * radToDeg < 0.5) + continue; + + if ((qT < qTlower) || (qT > qTupper)) + continue; + + if (sqrt(R[0] * R[0] + R[1] * R[1]) < 18.) + continue; + + if (chargeM == chargeD) + mKinkCandidates.emplace_back(KinkCandidates{chargeM, seedM.Idxtr, seedD.Idxtr, seedM.mcParticleIdx, seedD.mcParticleIdx, primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), R[0], R[1], R[2], sigmaPin[0], sigmaPin[1], sigmaPin[2], sigmaPDC[0], sigmaPDC[1], sigmaPDC[2], pionPDC[0], pionPDC[1], pionPDC[2]}); + + neutronE = sqrt(mNeutralDaughter * mNeutralDaughter + pow((sigmaPDC[2] - pionPDC[2]), 2) + pow((sigmaPDC[1] - pionPDC[1]), 2) + pow((sigmaPDC[0] - pionPDC[0]), 2)); + + mass = sqrt((neutronE + pionE) * (neutronE + pionE) - sigmaPabsDC * sigmaPabsDC); + + if ((chargeM == -1) && (chargeD == -1)) { + if (cfgIsMC) { + histos.fill(HIST("hcodes"), motherPdg, daughterPdg); + if ((motherPdg == particlePdgCode || motherPdg == -3222) && (daughterPdg == -211)) { + histos.fill(HIST("hPtMinusRecMcTrth"), mass, sigmaPt); + histos.fill(HIST("hptMDtrue"), sigmaPt, PionTr.getPt()); + } else if ((motherPdg == particlePdgCode || motherPdg == -3222) && (daughterPdg != -211)) { + histos.fill(HIST("hptMtrue"), sigmaPt, PionTr.getPt()); + histos.fill(HIST("hPtMinusRecMcTrthM"), mass, sigmaPt); + } else { // if ((motherPdg != particlePdgCode)&&(daughterPdg!=-211)) { + histos.fill(HIST("hptMDelse"), sigmaPt, PionTr.getPt()); + histos.fill(HIST("hPtMinusRecMcTrthelse"), mass, sigmaPt); + } + } + histos.fill(HIST("hMassMinusPt"), mass, sigmaPt); + } + if ((chargeM == 1) && (chargeD == 1)) { + if (cfgIsMC) { + if (motherPdg == particlePdgCode) + histos.fill(HIST("hPtPlusRecMcTrth"), mass, sigmaPt); + } + histos.fill(HIST("hMassPlusPt"), mass, sigmaPt); + } + + if ((chargeM == -1) && (chargeD == 1)) { + histos.fill(HIST("hBackgroundNegPosPt"), mass, sigmaPt); + } + if ((chargeM == 1) && (chargeD == -1)) { + histos.fill(HIST("hBackgroundPosNegPt"), mass, sigmaPt); + } + } // true + } catch (std::runtime_error& e) { + continue; + } + //} //dca fitter option + + } // try + + } // inner track loop + } // outer track loop + } + + void processReco(CompleteCollisions const& collisions, CompleteTracks const& tracks, o2::aod::AmbiguousTracks const& ambiTracks, aod::BCsWithTimestamps const& bcWtmp) + { + auto firstcollision = collisions.begin(); + auto bc1 = firstcollision.bc_as(); + initCCDB(bc1); + + auto trackPools = makeTracksPool(collisions, tracks, ambiTracks, bcWtmp); + + LOG(info) << "Collected for mother " << trackPools[POS].size() << " positive and " << trackPools[NEG].size() << " negative seeds"; + + LOG(info) << "Collected for daughter " << trackPools[2 + POS].size() << " positive and " << trackPools[2 + NEG].size() << " negative seeds"; + + gsl::span> trackPoolsMth{trackPools.data(), 2}; + gsl::span> trackPoolsDhgt{trackPools.data() + 2, 2}; + + calculateInvMass(collisions, tracks, ambiTracks, bcWtmp, trackPoolsMth, trackPoolsDhgt, cfgMotherCharge, cfgDaughterCharge, cfgParticleSpec); + calculateInvMass(collisions, tracks, ambiTracks, bcWtmp, trackPoolsMth, trackPoolsDhgt, -1, +1, cfgParticleSpec); + calculateInvMass(collisions, tracks, ambiTracks, bcWtmp, trackPoolsMth, trackPoolsDhgt, +1, -1, cfgParticleSpec); + + } // process + + PROCESS_SWITCH(kinkAnalysis, processReco, "process reconstructed information", true); + + void processSim(CompleteCollisions const& collisions, CompleteTracks const& tracks, o2::aod::AmbiguousTracks const& ambiTracks, aod::BCsWithTimestamps const& bcWtmp, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC) + { + auto firstcollision = collisions.begin(); + auto bc1 = firstcollision.bc_as(); + initCCDB(bc1); + + for (const auto& mcParticle : particlesMC) { + if (mcParticle.pdgCode() != particlePdgCode) + continue; + histos.fill(HIST("generatedPt"), mcParticle.pt()); + } + + auto trackPools = makeTracksPool(collisions, tracks, ambiTracks, bcWtmp); + + for (auto& pool : trackPools) { + for (auto& track : pool) { + auto label = trackLabelsMC.iteratorAt(track.Idxtr); + if (label.mcParticleId() < -1 || label.mcParticleId() >= particlesMC.size()) { + continue; + } + track.mcParticleIdx = label.mcParticleId(); + } + } + + LOG(info) << "Collected for mother " << trackPools[POS].size() << " positive and " << trackPools[NEG].size() << " negative seeds"; + + LOG(info) << "Collected for daughter " << trackPools[2 + POS].size() << " positive and " << trackPools[2 + NEG].size() << " negative seeds"; + + gsl::span> trackPoolsMth{trackPools.data(), 2}; + gsl::span> trackPoolsDhgt{trackPools.data() + 2, 2}; + + calculateInvMass(collisions, tracks, ambiTracks, bcWtmp, trackPoolsMth, trackPoolsDhgt, cfgMotherCharge, cfgDaughterCharge, cfgParticleSpec, &particlesMC); + + // for (auto& candidates : mKinkCandidates) { + + // } + + calculateInvMass(collisions, tracks, ambiTracks, bcWtmp, trackPoolsMth, trackPoolsDhgt, -1, +1, cfgParticleSpec, &particlesMC); + calculateInvMass(collisions, tracks, ambiTracks, bcWtmp, trackPoolsMth, trackPoolsDhgt, +1, -1, cfgParticleSpec, &particlesMC); + } // process + + PROCESS_SWITCH(kinkAnalysis, processSim, "process sim information", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/lambda1520SpherocityAnalysis.cxx b/PWGLF/Tasks/lambda1520SpherocityAnalysis.cxx new file mode 100644 index 00000000000..d7232e71cc0 --- /dev/null +++ b/PWGLF/Tasks/lambda1520SpherocityAnalysis.cxx @@ -0,0 +1,478 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file lambda1520_spherocity_analysis.cxx +/// \brief Produce Spherocity table. +/// Invariant Mass Reconstruction of Lambda(1520) Resonance. +/// +/// \author Yash Patley + +#include +#include + +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +// PDG p -> 2212, K -> 321 +const float massProton = TDatabasePDG::Instance()->GetParticle(2212)->Mass(); +const float massKaon = TDatabasePDG::Instance()->GetParticle(321)->Mass(); + +struct lambdaAnalysis { + + // Configurables. + Configurable nBinsPt{"nBinsPt", 200, "N bins in pT histogram"}; + Configurable nBinsInvM{"nBinsInvM", 400, "N bins in InvMass histograms"}; + Configurable doRotate{"doRotate", true, "rotated inv mass spectra"}; + + // Tracks + Configurable cfgPtMin{"ptMin", 0.15, "Minimum Track pT"}; + Configurable cfgPtMax{"ptMax", 36., "Maximum Track pT"}; + Configurable cfgEtaCut{"etaCut", 0.8, "Pseudorapidity cut"}; + Configurable cfgDcaz{"dcazMin", 1., "Minimum DCAz"}; + Configurable cfgDcaxy{"dcaxyMin", 0.1, "Minimum DCAxy"}; + Configurable cfgPIDprecut{"cfgPIDprecut", 6, "Preselection PID TPC TOF cut"}; + Configurable cfgGlobalTrackWoDCA{"cfgGlobalTrackWoDCA", true, "Global Track Selection"}; + Configurable cfgPVContributor{"cfgPVContributor", true, "PV Contributor Track Selection"}; + + // TPC TOF Protons + Configurable tpcProtonMaxPt{"tpcProtonMaxPt", 1.0, "max pT for tpc protons"}; + Configurable tpcNSigmaProton{"tpcNSigmaProton", 3, "nsigma tpc for Proton when Tof signal is present"}; + Configurable> protonTPCPIDpt{"protonTPCPIDpt", {0, 0.5, 0.7, 0.8, 1.0}, "pT dependent TPC cuts protons"}; + Configurable> protonTPCPIDcut{"protonTPCPIDcut", {5., 3.5, 2.5, 1.5}, "TPC cuts protons"}; + Configurable> protonTOFPIDpt{"protonTOFPIDpt", {36.}, "pT dependent TOF cuts protons"}; + Configurable> protonTOFPIDcut{"protonTOFPIDCut", {3}, "TOF cuts protons"}; + + // TPC TOF Kaons + Configurable tpcKaonMaxPt{"tpcKaonMaxPt", 0.5, "max pT for tpc kaons"}; + Configurable tpcNSigmaKaon{"tpcNSigmaKaon", 3, "nsigma tpc for Kaon when Tof signal is present"}; + Configurable> kaonTPCPIDpt{"kaonTPCPIDpt", {0, 0.2, 0.3, 0.4, 0.50}, "pT dependent TPC cuts kaons"}; + Configurable> kaonTPCPIDcut{"kaonTPCPIDcut", {5, 3.5, 2., 1.5}, "TPC cuts kaons"}; + Configurable> kaonTOFPIDpt{"kaonTOFPIDpt", {36.}, "pT dependent TOF cuts kaons"}; + Configurable> kaonTOFPIDcut{"kaonTOFPIDcut", {3}, "TOF cuts kaons"}; + + // Event Mixing. + Configurable doSphMix{"doSphMix", true, "Include Sph Bins to be mixed"}; + Configurable nMix{"nMix", 10, "Number of Events to be mixed"}; + ConfigurableAxis cfgVtxBins{"cfgVtxBins", {VARIABLE_WIDTH, -10.0f, -9.f, -8.f, -7.f, -6.f, -5.f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis cfgMultBins{"cfgMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f, 200.0f}, "Mixing bins - multiplicity"}; + ConfigurableAxis cfgSphBins{"cfgSphBins", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f}, "Mixing bins - spherocity"}; + + // Histogram Registry. + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + + // Define Axis. + const AxisSpec axisSp(1000, 0., 1., "S_{0}"); + const AxisSpec axisCent(105, 0, 105, "FT0M (%)"); + const AxisSpec axisPtQA(200, 0., 2., "p_{T} (GeV/c)"); + const AxisSpec axisPt(nBinsPt, 0., 10., "p_{T} (GeV/c)"); + const AxisSpec axisEta(200, -1, 1, "#eta"); + const AxisSpec axisDCAz(500, -0.5, 0.5, {"DCA_{z} (cm)"}); + const AxisSpec axisDCAxy(240, -0.12, 0.12, {"DCA_{xy} (cm)"}); + const AxisSpec axisTPCNCls(200, 0, 200, {"TPCNCls"}); + const AxisSpec axisTPCNsigma(140, -10, 10, {"n#sigma^{TPC}"}); + const AxisSpec axisTOFNsigma(140, -10, 10, {"n#sigma^{TOF}"}); + const AxisSpec axisInvM(nBinsInvM, 1.4, 3.4, {"M_{inv} (GeV/c^{2})"}); + + // Create Histograms. + // Event + histos.add("Event/hCent", "FT0M (%)", kTH1F, {axisCent}); + histos.add("Event/hSph", "Event Spherocity", kTH1F, {axisSp}); + histos.add("Event/hSpCent", "Spherocity vs FT0M(%)", kTH2F, {axisCent, axisSp}); + + // QA Before + histos.add("QAbefore/Proton/hTPCNsigma", "n#sigma^{TPC} Protons", kTH2F, {axisPtQA, axisTPCNsigma}); + histos.add("QAbefore/Proton/hTOFNsigma", "n#sigma^{TOF} Protons", kTH2F, {axisPtQA, axisTOFNsigma}); + histos.add("QAbefore/Proton/hTpcTofNsigma", "n#sigma^{TPC} vs n#sigma^{TOF} Protons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); + histos.add("QAbefore/Kaon/hTPCNsigma", "n#sigma^{TPC} Kaons", kTH2F, {axisPtQA, axisTPCNsigma}); + histos.add("QAbefore/Kaon/hTOFNsigma", "n#sigma^{TOF} Kaons", kTH2F, {axisPtQA, axisTOFNsigma}); + histos.add("QAbefore/Kaon/hTpcTofNsigma", "n#sigma^{TPC} vs n#sigma^{TOF} Kaons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); + + // QA After + histos.add("QAafter/Proton/hDcaZ", "dca_{z} Protons", kTH2F, {axisPtQA, axisDCAz}); + histos.add("QAafter/Proton/hDcaXY", "dca_{xy} Protons", kTH2F, {axisPtQA, axisDCAxy}); + histos.add("QAafter/Proton/hTPCNsigma", "n#sigma^{TPC} Protons", kTH2F, {axisPtQA, axisTPCNsigma}); + histos.add("QAafter/Proton/hTOFNsigma", "n#sigma^{TOF} Protons", kTH2F, {axisPtQA, axisTOFNsigma}); + histos.add("QAafter/Proton/hTpcTofNsigma", "n#sigma^{TPC} vs n#sigma^{TOF} Protons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); + histos.add("QAafter/Kaon/hDcaZ", "dca_{z} Kaons", kTH2F, {axisPtQA, axisDCAz}); + histos.add("QAafter/Kaon/hDcaXY", "dca_{xy} Kaons", kTH2F, {axisPtQA, axisDCAxy}); + histos.add("QAafter/Kaon/hTPCNsigma", "n#sigma^{TPC} Kaons", kTH2F, {axisPtQA, axisTPCNsigma}); + histos.add("QAafter/Kaon/hTOFNsigma", "n#sigma^{TOF} Kaons", kTH2F, {axisPtQA, axisTOFNsigma}); + histos.add("QAafter/Kaon/hTpcTofNsigma", "n#sigma^{TPC} vs n#sigma^{TOF} Kaons", kTH2F, {axisTPCNsigma, axisTOFNsigma}); + + // Analysis + // Proton Kaon + histos.add("Analysis/hPtProton", "Protons p_{T}", kTH1F, {axisPt}); + histos.add("Analysis/hEtaProton", "Protons #eta", kTH1F, {axisEta}); + histos.add("Analysis/hPtKaon", "Kaons p_{T}", kTH1F, {axisPt}); + histos.add("Analysis/hEtaKaon", "Kaons #eta", kTH1F, {axisEta}); + + // Lambda Invariant Mass + histos.add("Analysis/hInvMass", "#Lambda(1520) M_{inv}", kTH1D, {axisInvM}); + histos.add("Analysis/hInvMassLS1", "Like Signs M_{inv} p K^{+}", kTH1D, {axisInvM}); + histos.add("Analysis/hInvMassLS2", "Like Signs M_{inv} #bar{p} K^{-}", kTH1D, {axisInvM}); + histos.add("Analysis/hInvMassR", "Rotated Spectra", kTH1D, {axisInvM}); + histos.add("Analysis/hInvMassMix", "Mixed Events M_{inv}", kTH1D, {axisInvM}); + histos.add("Analysis/h4InvMass", "THn #Lambda(1520)", kTHnSparseD, {axisInvM, axisPt, axisSp, axisCent}); + histos.add("Analysis/h4InvMassLS1", "THn Like Signs p K^{+}", kTHnSparseD, {axisInvM, axisPt, axisSp, axisCent}); + histos.add("Analysis/h4InvMassLS2", "THn Like Signs #bar{p} K^{-}", kTHnSparseD, {axisInvM, axisPt, axisSp, axisCent}); + histos.add("Analysis/h4InvMassR", "THn Rotated", kTHnSparseD, {axisInvM, axisPt, axisSp, axisCent}); + histos.add("Analysis/h4InvMassMix", "THn Mixed Events", kTHnSparseD, {axisInvM, axisPt, axisSp, axisCent}); + + // MC + if (doprocessMC) { + histos.add("Event/hSphRec", "Reconstructed S_{0}", kTH1F, {axisSp}); + histos.add("Event/hSpCentRec", "Reconstructed S_{0} vs FT0M(%)", kTH2F, {axisCent, axisSp}); + histos.add("QAMCTrue/DcaZ_pr", "dca_{z}^{MC} Protons", kTH2F, {axisPtQA, axisDCAz}); + histos.add("QAMCTrue/DcaZ_ka", "dca_{z}^{MC} Kaons", kTH2F, {axisPtQA, axisDCAz}); + histos.add("QAMCTrue/DcaXY_pr", "dca_{xy}^{MC} Protons", kTH2F, {axisPtQA, axisDCAxy}); + histos.add("QAMCTrue/DcaXY_ka", "dca_{xy}^{MC} Kaons", kTH2F, {axisPtQA, axisDCAxy}); + histos.add("Analysis/hLambdaGen", "Generated #Lambda(1520) p_{T}", kTH1D, {axisPt}); + histos.add("Analysis/hLambdaGenAnti", "Generated #bar{#Lambda}(1520) p_{T}", kTH1D, {axisPt}); + histos.add("Analysis/hLambdaRec", "Reconstructed #Lambda(1520) p_{T}", kTH1D, {axisPt}); + histos.add("Analysis/hLambdaRecAnti", "Reconstructed #bar{#Lambda}(1520) p_{T}", kTH1D, {axisPt}); + histos.add("Analysis/hInvMassLambdaRec", "Recostructed #Lambda(1520)", kTH1D, {axisInvM}); + histos.add("Analysis/hInvMassLambdaRecAnti", "Recostructed #bar{#Lambda}(1520)", kTH1D, {axisInvM}); + histos.add("Analysis/h4InvMassLambdaRec", "Recostructed #Lambda(1520)", kTHnSparseD, {axisInvM, axisPt, axisSp, axisCent}); + histos.add("Analysis/h4InvMassLambdaRecAnti", "Recostructed #bar{#Lambda}(1520)", kTHnSparseD, {axisInvM, axisPt, axisSp, axisCent}); + } + } + + template + bool selTracks(T const& track) + { + + if (track.pt() < cfgPtMin || track.pt() > cfgPtMax) + return false; + + if (std::abs(track.dcaZ()) > cfgDcaz) + return false; + + if (std::abs(track.dcaXY()) > cfgDcaxy) + return false; + + if (cfgGlobalTrackWoDCA && !track.isGlobalTrackWoDCA()) + return false; + + if (cfgPVContributor && !track.isPVContributor()) + return false; + + return true; + } + + template + void fillDataHistos(trackType const& trk1, trackType const& trk2, float const& sph, float const& mult) + { + + bool isTrk1Proton{true}, isTrk2Kaon{true}, trk1HasTOF{false}, trk2HasTOF{false}, selTrk1{true}, selTrk2{true}; + + auto prTpcPIDpt = static_cast>(protonTPCPIDpt); + auto prTpcPIDcut = static_cast>(protonTPCPIDcut); + auto prTofPIDpt = static_cast>(protonTOFPIDpt); + auto prTofPIDcut = static_cast>(protonTOFPIDcut); + auto kaTpcPIDpt = static_cast>(kaonTPCPIDpt); + auto kaTpcPIDcut = static_cast>(kaonTPCPIDcut); + auto kaTofPIDpt = static_cast>(kaonTOFPIDpt); + auto kaTofPIDcut = static_cast>(kaonTOFPIDcut); + + TLorentzVector p1, p2, p; + TRandom* rn = new TRandom(); + + for (auto const& [trkPr, trkKa] : soa::combinations(soa::CombinationsFullIndexPolicy(trk1, trk2))) { + // Do not analyse same index tracks. + if (trkPr.index() == trkKa.index()) + continue; + + selTrk1 = true; + selTrk2 = true; + isTrk1Proton = true; + isTrk2Kaon = true; + trk1HasTOF = false; + trk2HasTOF = false; + + // pT, DCA, Global Tracks and PVcontrib selection. + selTrk1 = selTracks(trkPr); + selTrk2 = selTracks(trkKa); + + if (!selTrk1 || !selTrk2) + continue; + + // Protons. + if (trkPr.pt() < tpcProtonMaxPt) { + // TPC only + for (int i = 1; i < static_cast(prTpcPIDpt.size()); ++i) { + if (trkPr.pt() >= prTpcPIDpt[i - 1] && trkPr.pt() < prTpcPIDpt[i]) { + if (std::abs(trkPr.tpcNSigmaPr()) >= prTpcPIDcut[i - 1]) { + isTrk1Proton = false; + } + } + } + } else { + // TPC + TOF + if (trkPr.hasTOF()) { + trk1HasTOF = true; + for (int i = 0; i < static_cast(prTofPIDpt.size()); ++i) { + if (trkPr.pt() < prTofPIDpt[i]) { + if (std::abs(trkPr.tofNSigmaPr()) >= prTofPIDcut[i] || std::abs(trkPr.tpcNSigmaPr()) >= tpcNSigmaProton) { + isTrk1Proton = false; + trk1HasTOF = false; + } + } + } + } else { + isTrk1Proton = false; + } + } + + // Kaons + if (trkKa.pt() < tpcKaonMaxPt) { + // TPC only + for (int i = 1; i < static_cast(kaTpcPIDpt.size()); ++i) { + if (trkKa.pt() >= kaTpcPIDpt[i - 1] && trkKa.pt() < kaTpcPIDpt[i]) { + if (std::abs(trkKa.tpcNSigmaKa()) >= kaTpcPIDcut[i - 1]) { + isTrk2Kaon = false; + } + } + } + } else { + // TPC + TOF + if (trkKa.hasTOF()) { + trk2HasTOF = true; + for (int i = 0; i < static_cast(kaTofPIDpt.size()); ++i) { + if (trkKa.pt() < kaTofPIDpt[i]) { + if (std::abs(trkKa.tofNSigmaKa()) >= kaTofPIDcut[i] || std::abs(trkKa.tpcNSigmaKa()) >= tpcNSigmaKaon) { + isTrk2Kaon = false; + trk2HasTOF = false; + } + } + } + } else { + isTrk2Kaon = false; + } + } + + // Fill QA before track selection. + if (!mix & !mc) { + if (std::abs(trkPr.tpcNSigmaPr()) < cfgPIDprecut) { + histos.fill(HIST("QAbefore/Proton/hTPCNsigma"), trkPr.pt(), trkPr.tpcNSigmaPr()); + if (std::abs(trkPr.tofNSigmaPr()) < cfgPIDprecut) { + histos.fill(HIST("QAbefore/Proton/hTOFNsigma"), trkPr.pt(), trkPr.tofNSigmaPr()); + histos.fill(HIST("QAbefore/Proton/hTpcTofNsigma"), trkPr.tpcNSigmaPr(), trkPr.tofNSigmaPr()); + } + } + if (std::abs(trkKa.tpcNSigmaKa()) < cfgPIDprecut) { + histos.fill(HIST("QAbefore/Kaon/hTPCNsigma"), trkKa.pt(), trkKa.tpcNSigmaKa()); + if (std::abs(trkKa.tofNSigmaKa()) < cfgPIDprecut) { + histos.fill(HIST("QAbefore/Kaon/hTOFNsigma"), trkKa.pt(), trkKa.tofNSigmaKa()); + histos.fill(HIST("QAbefore/Kaon/hTpcTofNsigma"), trkKa.tpcNSigmaKa(), trkKa.tofNSigmaKa()); + } + } + } + + // Apply PID Selection. + if (!isTrk1Proton || !isTrk2Kaon) + continue; + + // Fill QA after track selection. + if (!mix && !mc) { + histos.fill(HIST("QAafter/Proton/hDcaZ"), trkPr.pt(), trkPr.dcaZ()); + histos.fill(HIST("QAafter/Proton/hDcaXY"), trkPr.pt(), trkPr.dcaXY()); + histos.fill(HIST("QAafter/Proton/hTPCNsigma"), trkPr.pt(), trkPr.tpcNSigmaPr()); + if (trk1HasTOF) { + histos.fill(HIST("QAafter/Proton/hTOFNsigma"), trkPr.pt(), trkPr.tofNSigmaPr()); + histos.fill(HIST("QAafter/Proton/hTpcTofNsigma"), trkPr.tpcNSigmaPr(), trkPr.tofNSigmaPr()); + } + histos.fill(HIST("QAafter/Kaon/hDcaZ"), trkKa.pt(), trkKa.dcaZ()); + histos.fill(HIST("QAafter/Kaon/hDcaXY"), trkKa.pt(), trkKa.dcaXY()); + histos.fill(HIST("QAafter/Kaon/hTPCNsigma"), trkKa.pt(), trkKa.tpcNSigmaKa()); + if (trk2HasTOF) { + histos.fill(HIST("QAafter/Kaon/hTOFNsigma"), trkKa.pt(), trkKa.tofNSigmaKa()); + histos.fill(HIST("QAafter/Kaon/hTpcTofNsigma"), trkKa.tpcNSigmaKa(), trkKa.tofNSigmaKa()); + } + } + + // Invariant mass reconstruction. + p1.SetXYZM(trkPr.px(), trkPr.py(), trkPr.pz(), massProton); + p2.SetXYZM(trkKa.px(), trkKa.py(), trkKa.pz(), massKaon); + p = p1 + p2; + + if (std::abs(p.Rapidity()) > 0.5) + continue; + + // Fill Invariant Mass Histograms. + if constexpr (!mix && !mc) { + + // Protons and Kaons pT spectra and Pseudorapidity distribution. + histos.fill(HIST("Analysis/hPtProton"), trkPr.pt()); + histos.fill(HIST("Analysis/hEtaProton"), trkPr.eta()); + histos.fill(HIST("Analysis/hPtKaon"), trkKa.pt()); + histos.fill(HIST("Analysis/hEtaKaon"), trkKa.eta()); + + if (trkPr.sign() * trkKa.sign() < 0) { + histos.fill(HIST("Analysis/hInvMass"), p.M()); + histos.fill(HIST("Analysis/h4InvMass"), p.M(), p.Pt(), sph, mult); + if (doRotate) { + float theta = rn->Uniform(2.0, 2.5); + p1.RotateZ(theta); + p = p1 + p2; + if (std::abs(p.Rapidity()) < 0.5) { + histos.fill(HIST("Analysis/hInvMassR"), p.M()); + histos.fill(HIST("Analysis/h4InvMassR"), p.M(), p.Pt(), sph, mult); + } + } + } else { + if (trkPr.sign() == 1) { + histos.fill(HIST("Analysis/hInvMassLS1"), p.M()); + histos.fill(HIST("Analysis/h4InvMassLS1"), p.M(), p.Pt(), sph, mult); + } else { + histos.fill(HIST("Analysis/hInvMassLS2"), p.M()); + histos.fill(HIST("Analysis/h4InvMassLS2"), p.M(), p.Pt(), sph, mult); + } + } + } + + if constexpr (mc) { + if (abs(trkPr.pdgCode()) != 2212 || abs(trkKa.pdgCode()) != 321) + continue; + + if (trkPr.motherId() != trkKa.motherId()) + continue; + + if (abs(trkPr.motherPDG()) != 3124) + continue; + + // Track selection check. + histos.fill(HIST("QAMCTrue/DcaXY_pr"), trkPr.pt(), trkPr.dcaXY()); + histos.fill(HIST("QAMCTrue/DcaXY_ka"), trkKa.pt(), trkKa.dcaXY()); + histos.fill(HIST("QAMCTrue/DcaZ_pr"), trkPr.pt(), trkPr.dcaZ()); + histos.fill(HIST("QAMCTrue/DcaZ_ka"), trkKa.pt(), trkKa.dcaZ()); + + // MC histograms + if (trkPr.motherPDG() > 0) { + histos.fill(HIST("Analysis/hLambdaRec"), p.Pt()); + histos.fill(HIST("Analysis/hInvMassLambdaRec"), p.M()); + histos.fill(HIST("Analysis/h4InvMassLambdaRec"), p.M(), p.Pt(), sph, mult); + } else { + histos.fill(HIST("Analysis/hLambdaRecAnti"), p.Pt()); + histos.fill(HIST("Analysis/hInvMassLambdaRecAnti"), p.M()); + histos.fill(HIST("Analysis/h4InvMassLambdaRecAnti"), p.M(), p.Pt(), sph, mult); + } + } + + if constexpr (mix) { + if (trkPr.sign() * trkKa.sign() < 0) { + histos.fill(HIST("Analysis/hInvMassMix"), p.M()); + histos.fill(HIST("Analysis/h4InvMassMix"), p.M(), p.Pt(), sph, mult); + } + } + } + } + + using resoCols = aod::ResoCollisions; + using resoTracks = aod::ResoTracks; + + void processData(resoCols::iterator const& collision, resoTracks const& tracks) + { + + histos.fill(HIST("Event/hCent"), collision.multV0M()); + histos.fill(HIST("Event/hSph"), collision.spherocity()); + histos.fill(HIST("Event/hSpCent"), collision.multV0M(), collision.spherocity()); + + fillDataHistos(tracks, tracks, collision.spherocity(), collision.multV0M()); + } + + PROCESS_SWITCH(lambdaAnalysis, processData, "Process for Same Event Data", true); + + void processMC(resoCols::iterator const& collision, + soa::Join const& tracks, aod::McParticles const& mcParticles) + { + + histos.fill(HIST("Event/hSphRec"), collision.spherocity()); + histos.fill(HIST("Event/hSpCentRec"), collision.multV0M(), collision.spherocity()); + fillDataHistos(tracks, tracks, collision.spherocity(), collision.multV0M()); + } + PROCESS_SWITCH(lambdaAnalysis, processMC, "Process Event for MC", false); + + void processMCTrue(aod::ResoMCParents const& resoParents) + { + + for (auto const& part : resoParents) { + + if (abs(part.pdgCode()) != 3124) // #Lambda(1520) PDGCode = 3124 + continue; + if (abs(part.y()) > 0.5) { // rapidity cut + continue; + } + + bool pass1 = false; + bool pass2 = false; + + if (abs(part.daughterPDG1()) == 2212 || abs(part.daughterPDG2()) == 2212) { // At least one decay to Proton + pass1 = true; + } + if (abs(part.daughterPDG1()) == 321 || abs(part.daughterPDG2()) == 321) { // At least one decay to Kaon + pass2 = true; + } + + if (!pass1 || !pass2) // If we have both decay products + continue; + + if (part.pdgCode() > 0) + histos.fill(HIST("Analysis/hLambdaGen"), part.pt()); + else + histos.fill(HIST("Analysis/hLambdaGenAnti"), part.pt()); + } + } + PROCESS_SWITCH(lambdaAnalysis, processMCTrue, "Process Event for MC", false); + + // Processing Event Mixing + SliceCache cache; + + using BinningType1 = ColumnBinningPolicy; + using BinningType2 = ColumnBinningPolicy; + void processMix(resoCols& collisions, resoTracks const& tracks) + { + + LOGF(debug, "Event Mixing Started"); + BinningType1 binningPositions1{{cfgVtxBins, cfgMultBins, cfgSphBins}, true}; + BinningType2 binningPositions2{{cfgVtxBins, cfgMultBins}, true}; + auto tracksTuple = std::make_tuple(tracks); + if (doSphMix) { + SameKindPair pairs{binningPositions1, nMix, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto& [c1, t1, c2, t2] : pairs) { + fillDataHistos(t1, t2, c1.spherocity(), c1.multV0M()); + } + } else { + SameKindPair pairs{binningPositions2, nMix, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + for (auto& [c1, t1, c2, t2] : pairs) { + fillDataHistos(t1, t2, c1.spherocity(), c1.multV0M()); + } + } + } + + PROCESS_SWITCH(lambdaAnalysis, processMix, "Process for Mixed Events", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/lambda1520analysis.cxx b/PWGLF/Tasks/lambda1520analysis.cxx index b9aa3387ff7..3d57aced314 100644 --- a/PWGLF/Tasks/lambda1520analysis.cxx +++ b/PWGLF/Tasks/lambda1520analysis.cxx @@ -31,111 +31,174 @@ struct lambda1520analysis { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Configurables + // Eta-asymmetry switch + Configurable isEtaAssym{"isEtaAssym", false, "Turn on/off EtaAssym calculation"}; + // Configurable isFillQA{"isFillQA", false, "Turn on/off QA plots"}; + Configurable IsAddlTrackcut{"IsAddlTrackcut", false, "Switch to turn on/off Additional track cut"}; + Configurable IsOldPIDcut{"IsOldPIDcut", true, "Switch to turn on/off old PID cut to apply pt dependent cut"}; + // Pre-selection Track cuts - Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; - Configurable cMinPtcut{"cMinPtcut", 0.2f, "Minimal pT for tracks"}; - Configurable cMaxPtcut{"cMaxPtcut", 10.0f, "Maximal pT for tracks"}; - Configurable cMinTPCncr{"cMinTPCncr", 70, "Minimum number of TPC crossed rows"}; + Configurable cMinPtcut{"cMinPtcut", 0.15f, "Minimal pT for tracks"}; + Configurable cMinTPCncr{"cMinTPCncr", 70, "Minimum number of TPC X rows"}; + Configurable cMinRtpccut{"cMinRtpccut", 0.8f, "minimum ratio of number of Xrows to findable clusters in TPC"}; + Configurable cMaxChi2ITScut{"cMaxChi2ITScut", 36.0f, "Maximal pT for Chi2/cluster for ITS"}; + Configurable cMaxChi2TPCcut{"cMaxChi2TPCcut", 4.0f, "Maximal pT for Chi2/cluster for TPC"}; + // DCA Selections // DCAr to PV + Configurable IsDCAr7SigCut{"IsDCAr7SigCut", false, "Track DCAr 7 Sigma cut to PV Maximum"}; Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.12f, "Track DCAr cut to PV Maximum"}; // DCAz to PV Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0f, "Track DCAz cut to PV Maximum"}; - Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0f, "Track DCAz cut to PV Minimum"}; + + // Track selections + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor /// PID Selections - Configurable cMaxTPCnSigmaProton{"cMaxTPCnSigmaProton", 2.0, "TPC nSigma cut for Proton"}; // TPC - Configurable cMaxTOFnSigmaProton{"cMaxTOFnSigmaProton", 2.0, "TOF nSigma cut for Proton"}; // TOF - Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 2.0, "TPC nSigma cut for Kaon"}; // TPC - Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 2.0, "TOF nSigma cut for Kaon"}; // TOF // Kaon - Configurable IsptIndependentKaonCut{"IsptIndependentKaonCut", true, "Flag to proceed with pT dependent Kaon pid cuts"}; Configurable> kaonTPCPIDpTintv{"kaonTPCPIDpTintv", {999.}, "pT intervals for Kaon TPC PID cuts"}; Configurable> kaonTPCPIDcuts{"kaonTPCPIDcuts", {2}, "nSigma list for Kaon TPC PID cuts"}; Configurable> kaonTOFPIDpTintv{"kaonTOFPIDpTintv", {999.}, "pT intervals for Kaon TOF PID cuts"}; Configurable> kaonTOFPIDcuts{"kaonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; + Configurable cMaxTPCnSigmaKaonVETO{"cMaxTPCnSigmaKaonVETO", 3.0, "TPC nSigma VETO cut for Kaon"}; // TPC + + Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC + Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", 3.0, "Combined nSigma cut for Kaon"}; // Combined + // Proton - Configurable IsptIndependentProtonCut{"IsptIndependentProtonCut", true, "Flag to proceed with pT dependent Proton pid cuts"}; Configurable> protonTPCPIDpTintv{"protonTPCPIDpTintv", {999.}, "pT intervals for Kaon TPC PID cuts"}; Configurable> protonTPCPIDcuts{"protonTPCPIDcuts", {2}, "nSigma list for Kaon TPC PID cuts"}; Configurable> protonTOFPIDpTintv{"protonTOFPIDpTintv", {999.}, "pT intervals for Kaon TOF PID cuts"}; Configurable> protonTOFPIDcuts{"protonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; + Configurable cMaxTPCnSigmaProtonVETO{"cMaxTPCnSigmaProtonVETO", 3.0, "TPC nSigma VETO cut for Proton"}; // TPC + + Configurable cMaxTPCnSigmaProton{"cMaxTPCnSigmaProton", 3.0, "TPC nSigma cut for Proton"}; // TPC + Configurable nsigmaCutCombinedProton{"nsigmaCutCombinedProton", 3.0, "Combined nSigma cut for Proton"}; // Combined /// Event Mixing Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; - ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 80.0f, 100.0f}, "Mixing bins - multiplicity"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -9.f, -8.f, -7.f, -6.f, -5.f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f, 100.0f}, "Mixing bins - multiplicity"}; /// Figures ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9, 13.0, 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7, 13.8, 13.9, 14.0, 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7, 14.8, 14.9, 15.0}, "Binning of the pT axis"}; - ConfigurableAxis binsPtQA{"binsPtQA", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2, 6.4, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8, 8.0, 8.2, 8.4, 8.6, 8.8, 9.0, 9.2, 9.4, 9.6, 9.8, 10.0}, "Binning of the pT axis"}; - Configurable nBinsNSigma{"nBinsNSigma", 130, "Number of nSigma bins"}; - Configurable nBinsMult{"nBinsMult", 500, "Number of mass bins (Safe limit <= 800)"}; + ConfigurableAxis binsEta{"binsEta", {100, -1, 1}, ""}; + ConfigurableAxis binsMass{"binsMass", {1700, 1.3, 3.0}, "Invariant Mass (GeV/#it{c}^2)"}; + ConfigurableAxis binsMult{"binsMult", {150, 0.0, 150.0}, "mult_{FT0M}"}; + ConfigurableAxis binsDCAz{"binsDCAz", {600, -3, 3}, ""}; + ConfigurableAxis binsDCAxy{"binsDCAxy", {300, -1.5, 1.5}, ""}; + ConfigurableAxis binsTPCXrows{"binsTPCXrows", {200, 0, 200}, ""}; + ConfigurableAxis binsnSigma{"binsnSigma", {130, -6.5, 6.5}, ""}; + ConfigurableAxis binsnTPCSignal{"binsnTPCSignal", {1000, 0, 1000}, ""}; void init(o2::framework::InitContext&) { // axes AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec axisMassLambda1520{500, 1.3, 3.0, "Invariant Mass (GeV/#it{c}^2)"}; - AxisSpec axisMult{nBinsMult, 0.0f, 500.0f, "mult_{V0M}"}; - AxisSpec axisDCA{1000, -5, 5}; - AxisSpec axisTPCcrossedrow{200, 0, 200}; - AxisSpec ptAxisQA = {binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec pidQAAxis = {nBinsNSigma, -6.5, 6.5}; - - // PID QA before cuts - // --- Kaon - histos.add("QA/QAbefore/Kaon/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {pidQAAxis, pidQAAxis}}); - histos.add("QA/QAbefore/Kaon/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); - histos.add("QA/QAbefore/Kaon/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); - histos.add("QA/QAbefore/Kaon/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {ptAxisQA, axisDCA}); - histos.add("QA/QAbefore/Kaon/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {ptAxisQA, axisDCA}); - histos.add("QA/QAbefore/Kaon/TPC_CR", "# TPC Crossedrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC Crossed rows", HistType::kTH2F, {ptAxisQA, axisTPCcrossedrow}); - histos.add("QA/QAbefore/Kaon/pT", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); - // --- Proton - histos.add("QA/QAbefore/Proton/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;#sigma_{TOF}^{Proton};#sigma_{TPC}^{Proton}", {HistType::kTH2D, {pidQAAxis, pidQAAxis}}); - histos.add("QA/QAbefore/Proton/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); - histos.add("QA/QAbefore/Proton/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); - histos.add("QA/QAbefore/Proton/dcaZ", "DCA_{Z} distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTH2F, {axisPt, axisDCA}); - histos.add("QA/QAbefore/Proton/dcaXY", "DCA_{XY} momentum distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCA}); - histos.add("QA/QAbefore/Proton/TPC_CR", "# TPC Crossedrows distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); TPC Crossed rows", HistType::kTH2F, {axisPt, axisTPCcrossedrow}); - histos.add("QA/QAbefore/Proton/pT", "pT distribution of Protons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + AxisSpec axisEta{binsEta, ""}; + AxisSpec axisMassLambda1520{binsMass, "Invariant Mass (GeV/#it{c}^2)"}; + AxisSpec axisMult{binsMult, "mult_{V0M}"}; + AxisSpec axisDCAz{binsDCAz, ""}; + AxisSpec axisDCAxy{binsDCAxy, ""}; + AxisSpec axisTPCXrow{binsTPCXrows, ""}; + AxisSpec pidQAAxis = {binsnSigma, ""}; + AxisSpec axisTPCSignal = {binsnTPCSignal, ""}; + + // Track QA before cuts + // --- Track + histos.add("QA/QAbefore/Track/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {pidQAAxis, pidQAAxis}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_ka_only", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAbefore/Track/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;#sigma_{TOF}^{Proton};#sigma_{TPC}^{Proton}", {HistType::kTH2D, {pidQAAxis, pidQAAxis}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_pr_only", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAbefore/Track/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAbefore/Track/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAbefore/Track/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAbefore/Track/pT", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAbefore/Track/eta", "#eta distribution of Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); // PID QA after cuts // --- Kaon histos.add("QA/QAafter/Kaon/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {pidQAAxis, pidQAAxis}}); - histos.add("QA/QAafter/Kaon/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); - histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); - histos.add("QA/QAafter/Kaon/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCA}); - histos.add("QA/QAafter/Kaon/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCA}); - histos.add("QA/QAafter/Kaon/TPC_CR", "# TPC Crossedrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC Crossed rows", HistType::kTH2F, {axisPt, axisTPCcrossedrow}); + histos.add("QA/QAafter/Kaon/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAafter/Kaon/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Kaon/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Kaon/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); histos.add("QA/QAafter/Kaon/pT", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAafter/Kaon/eta", "#eta distribution of Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + histos.add("QA/QAafter/Kaon/TPC_Signal_ka_all", "TPC Signal for Kaon;#it{p}_{T} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2D, {axisPt, axisTPCSignal}}); + // --- Proton histos.add("QA/QAafter/Proton/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;#sigma_{TOF}^{Proton};#sigma_{TPC}^{Proton}", {HistType::kTH2D, {pidQAAxis, pidQAAxis}}); - histos.add("QA/QAafter/Proton/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); - histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); - histos.add("QA/QAafter/Proton/dcaZ", "DCA_{Z} distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTH2F, {axisPt, axisDCA}); - histos.add("QA/QAafter/Proton/dcaXY", "DCA_{XY} momentum distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCA}); - histos.add("QA/QAafter/Proton/TPC_CR", "# TPC Crossedrows distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); TPC Crossed rows", HistType::kTH2F, {axisPt, axisTPCcrossedrow}); + histos.add("QA/QAafter/Proton/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_TPConly", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTH2D, {axisPt, pidQAAxis}}); + histos.add("QA/QAafter/Proton/dcaZ", "DCA_{Z} distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Proton/dcaXY", "DCA_{XY} momentum distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Proton/TPC_CR", "# TPC Xrows distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); histos.add("QA/QAafter/Proton/pT", "pT distribution of Protons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAafter/Proton/eta", "#eta distribution of Protons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + histos.add("QA/QAafter/Proton/TPC_Signal_pr_all", "TPC Signal for Proton;#it{p}_{T} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2D, {axisPt, axisTPCSignal}}); + + if (!doprocessMC || !doprocessMCTrue) { + // Mass QA 1D for quick check + histos.add("Result/Data/lambda1520invmass", "Invariant mass of #Lambda(1520) K^{#pm}p^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/lambda1520invmassLSPP", "Invariant mass of #Lambda(1520) Like Sign Method K^{#plus}p^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K+ + Pr + histos.add("Result/Data/lambda1520invmassLSMM", "Invariant mass of #Lambda(1520) Like Sign Method K^{#minus}p^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K- + anti-Pr + + // 3d histogram + histos.add("Result/Data/h3lambda1520invmass", "Invariant mass of #Lambda(1520) K^{#pm}p^{#mp}", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3lambda1520invmassLSPP", "Invariant mass of #Lambda(1520) Like Sign Method K^{#plus}p^{#plus}", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); // K+ + Pr + histos.add("Result/Data/h3lambda1520invmassLSMM", "Invariant mass of #Lambda(1520) Like Sign Method K^{#minus}p^{#minus}", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); // K- + anti-Pr + + if (doprocessME) { + histos.add("Result/Data/lambda1520invmassME", "Invariant mass of #Lambda(1520) mixed event K^{#pm}p^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/h3lambda1520invmassME", "Invariant mass of #Lambda(1520) mixed event K^{#pm}p^{#mp}", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); + } - // Mass QA (quick check) - histos.add("Result/Data/lambda1520invmass", "Invariant mass of #Lambda(1520) K^{#pm}p^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); - histos.add("Result/Data/lambda1520invmassLSPP", "Invariant mass of #Lambda(1520) Like Sign Method K^{#plus}p^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K+ + Pr - histos.add("Result/Data/lambda1520invmassLSMM", "Invariant mass of #Lambda(1520) Like Sign Method K^{#minus}p^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K- + anti-Pr - histos.add("Result/Data/lambda1520invmassME", "Invariant mass of #Lambda(1520) mixed event K^{#pm}p^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); - - // 3d histogram - histos.add("Result/Data/h3lambda1520invmass", "Invariant mass of #Lambda(1520) K^{#pm}p^{#mp}", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); - histos.add("Result/Data/h3lambda1520invmassLSPP", "Invariant mass of #Lambda(1520) Like Sign Method K^{#plus}p^{#plus}", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); // K+ + Pr - histos.add("Result/Data/h3lambda1520invmassLSMM", "Invariant mass of #Lambda(1520) Like Sign Method K^{#minus}p^{#minus}", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); // K- + anti-Pr - histos.add("Result/Data/h3lambda1520invmassME", "Invariant mass of #Lambda(1520) mixed event K^{#pm}p^{#mp}", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); - + if (isEtaAssym) { + histos.add("Result/Data/hlambda1520invmassUnlikeSignAside", "Invariant mass of #Lambda(1520) Unlike Sign A side", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/hlambda1520invmassLikeSignAside", "Invariant mass of #Lambda(1520) Like Sign A side", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/hlambda1520invmassUnlikeSignCside", "Invariant mass of #Lambda(1520) Unlike Sign C side", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/hlambda1520invmassLikeSignCside", "Invariant mass of #Lambda(1520) Like Sign C side", {HistType::kTH1F, {axisMassLambda1520}}); + + histos.add("Result/Data/h3lambda1520invmassUnlikeSignAside", "Invariant mass of #Lambda(1520) Unlike Sign A side", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3lambda1520invmassLikeSignAside", "Invariant mass of #Lambda(1520) Like Sign A side", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3lambda1520invmassUnlikeSignCside", "Invariant mass of #Lambda(1520) Unlike Sign C side", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3lambda1520invmassLikeSignCside", "Invariant mass of #Lambda(1520) Like Sign C side", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); + if (doprocessME) { + histos.add("Result/Data/hlambda1520invmassMixedAside", "Invariant mass of #Lambda(1520) Mixed A side", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/hlambda1520invmassMixedCside", "Invariant mass of #Lambda(1520) Mixed C side", {HistType::kTH1F, {axisMassLambda1520}}); + + histos.add("Result/Data/h3lambda1520invmassMixedAside", "Invariant mass of #Lambda(1520) Mixed A side", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3lambda1520invmassMixedCside", "Invariant mass of #Lambda(1520) Mixed C side", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); + } + } + } + // MC QA + if (doprocessMCTrue) { + histos.add("Result/MC/Genlambda1520pt", "pT distribution of True MC #Lambda(1520)0", kTH1F, {axisPt}); + histos.add("Result/MC/Genantilambda1520pt", "pT distribution of True MC Anti-#Lambda(1520)0", kTH1F, {axisPt}); + histos.add("Result/MC/GenTruelambda1520pt", "pT distribution of True MC #Lambda(1520)0", kTH1F, {axisPt}); + } if (doprocessMC) { - histos.add("Result/MC/h3recolambda1520invmass", "Invariant mass of Reconstructed MC #Lambda(1520)", HistType::kTH3F, {axisMult, axisPt, axisMassLambda1520}); - histos.add("Result/MC/truelambda1520pt", "pT distribution of True MC #Lambda(1520); #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); - histos.add("Result/MC/recolambda1520pt", "pT distribution of Reconstructed MC #Lambda(1520); #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); - histos.add("Result/MC/recolambda1520invmass", "Inv mass distribution of Reconstructed MC #Lambda(1520); #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("QA/MC/trkDCAxy_pr", "DCAxy distribution of proton track candidates", HistType::kTH1F, {axisDCAxy}); + histos.add("QA/MC/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {axisDCAxy}); + histos.add("QA/MC/trkDCAz_pr", "DCAz distribution of proton track candidates", HistType::kTH1F, {axisDCAz}); + histos.add("QA/MC/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTH1F, {axisDCAz}); + histos.add("Result/MC/h3lambda1520Recoinvmass", "Invariant mass of Reconstructed MC #Lambda(1520)0", kTH3F, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/MC/h3antilambda1520Recoinvmass", "Invariant mass of Reconstructed MC Anti-#Lambda(1520)0", kTH3F, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/MC/lambda1520Reco", "pT distribution of Reconstructed MC #Lambda(1520)0", kTH1F, {axisPt}); + histos.add("Result/MC/antilambda1520Reco", "pT distribution of Reconstructed MC Anti-#Lambda(1520)0", kTH1F, {axisPt}); + histos.add("Result/MC/hlambda1520Recoinvmass", "Inv mass distribution of Reconstructed MC #Lambda(1520)", kTH1F, {axisMassLambda1520}); + histos.add("Result/MC/hantilambda1520Recoinvmass", "Inv mass distribution of Reconstructed MC Anti-#Lambda(1520)", kTH1F, {axisMassLambda1520}); } } @@ -146,90 +209,132 @@ struct lambda1520analysis { bool trackCut(const TrackType track) { // basic track cuts - if (track.pt() < cMinPtcut || track.pt() > cMaxPtcut) - return false; - if (fabs(track.dcaXY()) > cMaxDCArToPVcut) + if (std::abs(track.pt()) < cMinPtcut) return false; - if (fabs(track.dcaZ()) < cMinDCAzToPVcut || fabs(track.dcaZ()) > cMaxDCAzToPVcut) + if (IsDCAr7SigCut) { + if (std::abs(track.dcaXY()) > (0.004f + 0.0130f / (track.pt()))) // 7 - Sigma cut + return false; + } else { + if (std::abs(track.dcaXY()) > cMaxDCArToPVcut) + return false; + } + if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) return false; if (track.tpcNClsCrossedRows() < cMinTPCncr) return false; - if (fabs(track.eta()) > cfgCutEta) + if (IsAddlTrackcut) { + if (!track.passedITSRefit() || !track.passedTPCRefit()) + return false; + if (track.tpcCrossedRowsOverFindableCls() < cMinRtpccut) + return false; + if (track.itsChi2NCl() > cMaxChi2ITScut) + return false; + if (track.tpcChi2NCl() > cMaxChi2TPCcut) + return false; + } + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) return false; return true; } + // PID selection + template + bool selectionPIDProton(const T& candidate, bool hasTOF) + { + if (hasTOF && (candidate.tofNSigmaPr() * candidate.tofNSigmaPr() + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr()) < (2.0 * nsigmaCutCombinedProton * nsigmaCutCombinedProton)) { + return true; + } else if (std::abs(candidate.tpcNSigmaPr()) < cMaxTPCnSigmaProton) { + return true; + } + return false; + } + template + bool selectionPIDKaon(const T& candidate, bool hasTOF) + { + if (hasTOF && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (2.0 * nsigmaCutCombinedKaon * nsigmaCutCombinedKaon)) { + return true; + } else if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { + return true; + } + return false; + } + template void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) { TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - bool isTrk1Selected{true}, isTrk2Selected{true}, isTrk1hasTOF{false}, isTrk2hasTOF{false}; + auto vKaonTPCPIDpTintv = static_cast>(kaonTPCPIDpTintv); + vKaonTPCPIDpTintv.insert(vKaonTPCPIDpTintv.begin(), cMinPtcut); auto vKaonTPCPIDcuts = static_cast>(kaonTPCPIDcuts); auto vKaonTOFPIDpTintv = static_cast>(kaonTOFPIDpTintv); auto vKaonTOFPIDcuts = static_cast>(kaonTOFPIDcuts); auto lengthOfkaonTPCPIDpTintv = static_cast(vKaonTPCPIDpTintv.size()); + auto lengthOfkaonTOFPIDpTintv = static_cast(vKaonTOFPIDpTintv.size()); auto vProtonTPCPIDpTintv = static_cast>(protonTPCPIDpTintv); + vProtonTPCPIDpTintv.insert(vProtonTPCPIDpTintv.begin(), cMinPtcut); auto vProtonTPCPIDcuts = static_cast>(protonTPCPIDcuts); auto vProtonTOFPIDpTintv = static_cast>(protonTOFPIDpTintv); auto vProtonTOFPIDcuts = static_cast>(protonTOFPIDcuts); auto lengthOfprotonTPCPIDpTintv = static_cast(vProtonTPCPIDpTintv.size()); + auto lengthOfprotonTOFPIDpTintv = static_cast(vProtonTOFPIDpTintv.size()); for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { // Full index policy is needed to consider all possible combinations if (trk1.index() == trk2.index()) continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. + // apply the track cut + if (!trackCut(trk1) || !trackCut(trk2)) + continue; + //// Initialize variables // Trk1: Proton, Trk2: Kaon - isTrk1Selected = true; - isTrk2Selected = true; - isTrk1hasTOF = false; - isTrk2hasTOF = false; + bool isTrk1Selected{true}, isTrk2Selected{true}; //, isTrk1hasTOF{false}, isTrk2hasTOF{false}; + + auto isTrk1hasTOF = trk1.hasTOF(); + auto isTrk2hasTOF = trk2.hasTOF(); + auto trk1ptPr = trk1.pt(); auto trk1NSigmaPrTPC = trk1.tpcNSigmaPr(); - auto trk1NSigmaPrTOF = -999.; + auto trk1NSigmaPrTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPr() : -999.; auto trk2ptKa = trk2.pt(); auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); - auto trk2NSigmaKaTOF = -999.; - - // hasTOF? - if ((trk1.tofPIDselectionFlag() & aod::resodaughter::kHasTOF) == aod::resodaughter::kHasTOF) { - isTrk1hasTOF = true; - } - if ((trk2.tofPIDselectionFlag() & aod::resodaughter::kHasTOF) == aod::resodaughter::kHasTOF) { - isTrk2hasTOF = true; - } + auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.; //// PID selections + // we can apply pT-dependent PID cuts // For Proton candidate: - if (IsptIndependentProtonCut) { - // to apply pT-independent PID cuts - if (std::abs(trk1NSigmaPrTPC) > cMaxTPCnSigmaProton) - isTrk1Selected = false; - if (isTrk1hasTOF) { - trk1NSigmaPrTOF = trk1.tofNSigmaPr(); - if (std::abs(trk1NSigmaPrTOF) > cMaxTOFnSigmaProton) + if (isTrk1hasTOF) { + trk1NSigmaPrTOF = trk1.tofNSigmaPr(); + if (lengthOfprotonTOFPIDpTintv > 0) { + if (trk1ptPr > vProtonTOFPIDpTintv[lengthOfprotonTOFPIDpTintv - 1]) { isTrk1Selected = false; - } - } else { - // to apply pT-dependent PID cuts - if (lengthOfprotonTPCPIDpTintv > 0) { - for (int i = 0; i < lengthOfprotonTPCPIDpTintv; i++) { - if (trk1ptPr < vProtonTPCPIDpTintv[i]) { - if (std::abs(trk1NSigmaPrTPC) > vProtonTPCPIDcuts[i]) - isTrk1Selected = false; + } else { + for (int i = 0; i < lengthOfprotonTOFPIDpTintv; i++) { + if (trk1ptPr < vProtonTOFPIDpTintv[i]) { + if (std::abs(trk1NSigmaPrTOF) > vProtonTOFPIDcuts[i]) + isTrk1Selected = false; + if (std::abs(trk1NSigmaPrTPC) > cMaxTPCnSigmaProtonVETO) + isTrk1Selected = false; + } } } } - if (isTrk1hasTOF) { - trk1NSigmaPrTOF = trk1.tofNSigmaPr(); - if (lengthOfprotonTPCPIDpTintv > 0) { + } else { + if (lengthOfprotonTPCPIDpTintv > 0) { + if (trk1ptPr > vProtonTPCPIDpTintv[lengthOfprotonTPCPIDpTintv - 1]) { + isTrk1Selected = false; + } else { for (int i = 0; i < lengthOfprotonTPCPIDpTintv; i++) { - if (trk1ptPr < vProtonTOFPIDpTintv[i]) { - if (std::abs(trk1NSigmaPrTOF) > vProtonTOFPIDcuts[i]) + if (trk1ptPr > vProtonTPCPIDpTintv[i] && trk1ptPr < vProtonTPCPIDpTintv[i + 1]) { + if (std::abs(trk1NSigmaPrTPC) > vProtonTPCPIDcuts[i]) isTrk1Selected = false; } } @@ -238,31 +343,30 @@ struct lambda1520analysis { } // For Kaon candidate: - // to apply pT-independent PID cuts - if (IsptIndependentKaonCut) { - if (std::abs(trk2NSigmaKaTPC) > cMaxTPCnSigmaKaon) - isTrk2Selected = false; - if (isTrk2hasTOF) { - trk2NSigmaKaTOF = trk2.tofNSigmaKa(); - if (std::abs(trk2NSigmaKaTOF) > cMaxTOFnSigmaKaon) + if (isTrk2hasTOF) { + trk2NSigmaKaTOF = trk2.tofNSigmaKa(); + if (lengthOfkaonTOFPIDpTintv > 0) { + if (trk2ptKa > vKaonTOFPIDpTintv[lengthOfkaonTOFPIDpTintv - 1]) { isTrk2Selected = false; - } - } else { - // to apply pT-dependent PID cuts - if (lengthOfkaonTPCPIDpTintv > 0) { - for (int i = 0; i < lengthOfkaonTPCPIDpTintv; i++) { - if (trk2ptKa < vKaonTPCPIDpTintv[i]) { - if (std::abs(trk2NSigmaKaTPC) > vKaonTPCPIDcuts[i]) - isTrk2Selected = false; + } else { + for (int i = 0; i < lengthOfkaonTOFPIDpTintv; i++) { + if (trk2ptKa < vKaonTOFPIDpTintv[i]) { + if (std::abs(trk2NSigmaKaTOF) > vKaonTOFPIDcuts[i]) + isTrk2Selected = false; + if (std::abs(trk2NSigmaKaTPC) > cMaxTPCnSigmaKaonVETO) + isTrk2Selected = false; + } } } } - if (isTrk2hasTOF) { - trk2NSigmaKaTOF = trk2.tofNSigmaKa(); - if (lengthOfkaonTPCPIDpTintv > 0) { + } else { + if (lengthOfkaonTPCPIDpTintv > 0) { + if (trk2ptKa > vKaonTPCPIDpTintv[lengthOfkaonTPCPIDpTintv - 1]) { + isTrk2Selected = false; + } else { for (int i = 0; i < lengthOfkaonTPCPIDpTintv; i++) { - if (trk2ptKa < vKaonTOFPIDpTintv[i]) { - if (std::abs(trk2NSigmaKaTOF) > vKaonTOFPIDcuts[i]) + if (trk2ptKa > vKaonTPCPIDpTintv[i] && trk2ptKa < vKaonTPCPIDpTintv[i + 1]) { + if (std::abs(trk2NSigmaKaTPC) > vKaonTPCPIDcuts[i]) isTrk2Selected = false; } } @@ -271,104 +375,147 @@ struct lambda1520analysis { } //// QA plots before the selection - // --- PID QA Proton - histos.fill(HIST("QA/QAbefore/Proton/TPC_Nsigma_pr_all"), trk1ptPr, trk1NSigmaPrTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QA/QAbefore/Proton/TOF_Nsigma_pr_all"), trk1ptPr, trk1NSigmaPrTOF); - histos.fill(HIST("QA/QAbefore/Proton/TOF_TPC_Map_pr_all"), trk1NSigmaPrTOF, trk1NSigmaPrTPC); - } - histos.fill(HIST("QA/QAbefore/Proton/dcaZ"), trk1ptPr, trk1.dcaZ()); - histos.fill(HIST("QA/QAbefore/Proton/dcaXY"), trk1ptPr, trk1.dcaXY()); - histos.fill(HIST("QA/QAbefore/Proton/TPC_CR"), trk1ptPr, trk1.tpcNClsCrossedRows()); - histos.fill(HIST("QA/QAbefore/Proton/pT"), trk1ptPr); + // --- Track QA all + if constexpr (!IsMix) { + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_pr_all"), trk1ptPr, trk1NSigmaPrTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TOF_Nsigma_pr_all"), trk1ptPr, trk1NSigmaPrTOF); + histos.fill(HIST("QA/QAbefore/Track/TOF_TPC_Map_pr_all"), trk1NSigmaPrTOF, trk1NSigmaPrTPC); + } + if (!isTrk1hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_pr_only"), trk1ptPr, trk1NSigmaPrTPC); + } + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TOF_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QA/QAbefore/Track/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + if (!isTrk2hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_ka_only"), trk2ptKa, trk2NSigmaKaTPC); + } - // --- PID QA Kaon - histos.fill(HIST("QA/QAbefore/Kaon/TPC_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTPC); - if (isTrk2hasTOF) { - histos.fill(HIST("QA/QAbefore/Kaon/TOF_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QA/QAbefore/Kaon/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + histos.fill(HIST("QA/QAbefore/Track/dcaZ"), trk1ptPr, trk1.dcaZ()); + histos.fill(HIST("QA/QAbefore/Track/dcaXY"), trk1ptPr, trk1.dcaXY()); + histos.fill(HIST("QA/QAbefore/Track/TPC_CR"), trk1ptPr, trk1.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAbefore/Track/pT"), trk1ptPr); + histos.fill(HIST("QA/QAbefore/Track/eta"), trk1.eta()); } - histos.fill(HIST("QA/QAbefore/Kaon/dcaZ"), trk2ptKa, trk2.dcaZ()); - histos.fill(HIST("QA/QAbefore/Kaon/dcaXY"), trk2ptKa, trk2.dcaXY()); - histos.fill(HIST("QA/QAbefore/Kaon/TPC_CR"), trk2ptKa, trk2.tpcNClsCrossedRows()); - histos.fill(HIST("QA/QAbefore/Kaon/pT"), trk2ptKa); - - // apply the track cut - if (!trackCut(trk1)) - continue; - if (!trackCut(trk2)) - continue; //// Apply the pid selection - if (!isTrk1Selected) - continue; - if (!isTrk2Selected) - continue; - - //// QA plots after the selection - // --- PID QA Proton - histos.fill(HIST("QA/QAafter/Proton/TPC_Nsigma_pr_all"), trk1ptPr, trk1NSigmaPrTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QA/QAafter/Proton/TOF_Nsigma_pr_all"), trk1ptPr, trk1NSigmaPrTOF); - histos.fill(HIST("QA/QAafter/Proton/TOF_TPC_Map_pr_all"), trk1NSigmaPrTOF, trk1NSigmaPrTPC); + if (IsOldPIDcut) { + if (!isTrk1Selected || !isTrk2Selected) + continue; + } else { + if (!selectionPIDProton(trk1, isTrk1hasTOF) || !selectionPIDKaon(trk2, isTrk2hasTOF)) + continue; } - histos.fill(HIST("QA/QAafter/Proton/dcaZ"), trk1ptPr, trk1.dcaZ()); - histos.fill(HIST("QA/QAafter/Proton/dcaXY"), trk1ptPr, trk1.dcaXY()); - histos.fill(HIST("QA/QAafter/Proton/TPC_CR"), trk1ptPr, trk1.tpcNClsCrossedRows()); - histos.fill(HIST("QA/QAafter/Proton/pT"), trk1ptPr); - // --- PID QA Kaon - histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTPC); - if (isTrk1hasTOF) { - histos.fill(HIST("QA/QAafter/Kaon/TOF_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTOF); - histos.fill(HIST("QA/QAafter/Kaon/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + //// QA plots after the selection + if constexpr (!IsMix) { // --- PID QA Proton + histos.fill(HIST("QA/QAafter/Proton/TPC_Nsigma_pr_all"), trk1ptPr, trk1NSigmaPrTPC); + histos.fill(HIST("QA/QAafter/Proton/TPC_Signal_pr_all"), trk1ptPr, trk1.tpcSignal()); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/QAafter/Proton/TOF_Nsigma_pr_all"), trk1ptPr, trk1NSigmaPrTOF); + histos.fill(HIST("QA/QAafter/Proton/TOF_TPC_Map_pr_all"), trk1NSigmaPrTOF, trk1NSigmaPrTPC); + } + if (!isTrk1hasTOF) { + histos.fill(HIST("QA/QAafter/Proton/TPC_Nsigma_pr_TPConly"), trk1ptPr, trk1NSigmaPrTPC); + } + histos.fill(HIST("QA/QAafter/Proton/dcaZ"), trk1ptPr, trk1.dcaZ()); + histos.fill(HIST("QA/QAafter/Proton/dcaXY"), trk1ptPr, trk1.dcaXY()); + histos.fill(HIST("QA/QAafter/Proton/TPC_CR"), trk1ptPr, trk1.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAafter/Proton/pT"), trk1ptPr); + histos.fill(HIST("QA/QAafter/Proton/eta"), trk1.eta()); + + // --- PID QA Kaon + histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTPC); + histos.fill(HIST("QA/QAafter/Kaon/TPC_Signal_ka_all"), trk2ptKa, trk2.tpcSignal()); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/QAafter/Kaon/TOF_Nsigma_ka_all"), trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QA/QAafter/Kaon/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + if (!isTrk2hasTOF) { + histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly"), trk2ptKa, trk2NSigmaKaTPC); + } + histos.fill(HIST("QA/QAafter/Kaon/dcaZ"), trk2ptKa, trk2.dcaZ()); + histos.fill(HIST("QA/QAafter/Kaon/dcaXY"), trk2ptKa, trk2.dcaXY()); + histos.fill(HIST("QA/QAafter/Kaon/TPC_CR"), trk2ptKa, trk2.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAafter/Kaon/pT"), trk2ptKa); + histos.fill(HIST("QA/QAafter/Kaon/eta"), trk2.eta()); } - histos.fill(HIST("QA/QAafter/Kaon/dcaZ"), trk2ptKa, trk2.dcaZ()); - histos.fill(HIST("QA/QAafter/Kaon/dcaXY"), trk2ptKa, trk2.dcaXY()); - histos.fill(HIST("QA/QAafter/Kaon/TPC_CR"), trk2ptKa, trk2.tpcNClsCrossedRows()); - histos.fill(HIST("QA/QAafter/Kaon/pT"), trk2ptKa); - //// Resonance reconstruction lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPr); lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); lResonance = lDecayDaughter1 + lDecayDaughter2; // Rapidity cut - if (lResonance.Rapidity() > 0.5 || lResonance.Rapidity() < -0.5) + if (abs(lResonance.Rapidity()) > 0.5) continue; //// Un-like sign pair only if (trk1.sign() * trk2.sign() < 0) { if constexpr (!IsMix) { histos.fill(HIST("Result/Data/lambda1520invmass"), lResonance.M()); histos.fill(HIST("Result/Data/h3lambda1520invmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + if (isEtaAssym && trk1.eta() > 0.2 && trk1.eta() < 0.8 && trk2.eta() > 0.2 && trk2.eta() < 0.8) { // Eta-range will be updated + histos.fill(HIST("Result/Data/hlambda1520invmassUnlikeSignAside"), lResonance.M()); + histos.fill(HIST("Result/Data/h3lambda1520invmassUnlikeSignAside"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else if (isEtaAssym && trk1.eta() > -0.6 && trk1.eta() < 0.0 && trk2.eta() > -0.6 && trk2.eta() < 0.0) { // Eta-range will be updated + histos.fill(HIST("Result/Data/hlambda1520invmassUnlikeSignCside"), lResonance.M()); + histos.fill(HIST("Result/Data/h3lambda1520invmassUnlikeSignCside"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } } else { histos.fill(HIST("Result/Data/lambda1520invmassME"), lResonance.M()); histos.fill(HIST("Result/Data/h3lambda1520invmassME"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + if (isEtaAssym && trk1.eta() > 0.2 && trk1.eta() < 0.8 && trk2.eta() > 0.2 && trk2.eta() < 0.8) { // Eta-range will be updated + histos.fill(HIST("Result/Data/hlambda1520invmassMixedAside"), lResonance.M()); + histos.fill(HIST("Result/Data/h3lambda1520invmassMixedAside"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else if (isEtaAssym && trk1.eta() > -0.6 && trk1.eta() < 0.0 && trk2.eta() > -0.6 && trk2.eta() < 0.0) { // Eta-range will be updated + histos.fill(HIST("Result/Data/hlambda1520invmassMixedCside"), lResonance.M()); + histos.fill(HIST("Result/Data/h3lambda1520invmassMixedCside"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } } // MC if constexpr (IsMC) { + // LOG(info) << "trk1 pdgcode: " << trk1.pdgCode() << "trk2 pdgcode: " << trk2.pdgCode() << std::endl; + if (abs(trk1.pdgCode()) != kProton || abs(trk2.pdgCode()) != kKPlus) continue; - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 == mother2) { // Same mother - if (abs(trk1.motherPDG()) == 3124) { // lambda1520(0) - histos.fill(HIST("Result/MC/reconlambda1520pt"), lResonance.Pt()); - histos.fill(HIST("Result/MC/reconlambda1520invmass"), lResonance.M()); - histos.fill(HIST("Result/MC/h3recolambda1520invmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); - } + if (trk1.motherId() != trk2.motherId()) // Same mother + continue; + if (abs(trk1.motherPDG()) != 3124) + continue; + + // Track selection check. + histos.fill(HIST("QA/MC/trkDCAxy_pr"), trk1.dcaXY()); + histos.fill(HIST("QA/MC/trkDCAxy_ka"), trk2.dcaXY()); + histos.fill(HIST("QA/MC/trkDCAz_pr"), trk1.dcaZ()); + histos.fill(HIST("QA/MC/trkDCAz_ka"), trk2.dcaZ()); + + // MC histograms + if (trk1.motherPDG() > 0) { + histos.fill(HIST("Result/MC/lambda1520Reco"), lResonance.Pt()); + histos.fill(HIST("Result/MC/hlambda1520Recoinvmass"), lResonance.M()); + histos.fill(HIST("Result/MC/h3lambda1520Recoinvmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else { + histos.fill(HIST("Result/MC/antilambda1520Reco"), lResonance.Pt()); + histos.fill(HIST("Result/MC/hantilambda1520Recoinvmass"), lResonance.M()); + histos.fill(HIST("Result/MC/h3antilambda1520Recoinvmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); } } } else { if constexpr (!IsMix) { + if (isEtaAssym && trk1.eta() > 0.2 && trk1.eta() < 0.8 && trk2.eta() > 0.2 && trk2.eta() < 0.8) { // Eta-range will be updated + histos.fill(HIST("Result/Data/hlambda1520invmassLikeSignAside"), lResonance.M()); + histos.fill(HIST("Result/Data/h3lambda1520invmassLikeSignAside"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else if (isEtaAssym && trk1.eta() > -0.6 && trk1.eta() < 0.0 && trk2.eta() > -0.6 && trk2.eta() < 0.0) { // Eta-range will be updated + histos.fill(HIST("Result/Data/hlambda1520invmassLikeSignCside"), lResonance.M()); + histos.fill(HIST("Result/Data/h3lambda1520invmassLikeSignCside"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } // Like sign pair ++ - if (trk1.sign() > 0 && trk2.sign() > 0) { + if (trk1.sign() > 0) { histos.fill(HIST("Result/Data/lambda1520invmassLSPP"), lResonance.M()); histos.fill(HIST("Result/Data/h3lambda1520invmassLSPP"), collision.multV0M(), lResonance.Pt(), lResonance.M()); - } - - // Like sign pair -- - if (trk1.sign() < 0 && trk2.sign() < 0) { + } else { // Like sign pair -- histos.fill(HIST("Result/Data/lambda1520invmassLSMM"), lResonance.M()); histos.fill(HIST("Result/Data/h3lambda1520invmassLSMM"), collision.multV0M(), lResonance.Pt(), lResonance.M()); } @@ -377,128 +524,60 @@ struct lambda1520analysis { } } - void processData(aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) - { - LOGF(debug, "[DATA] Processing %d collisions", collisions.size()); - for (auto& collision : collisions) { - Partition selectedTracks = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::eta) < static_cast(cfgCutEta)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) <= static_cast(cMaxDCArToPVcut)) /* ((0.0105f + 0.0350f / npow(o2::aod::track::pt, 1.1f)))) */ && (aod::resodaughter::tpcNClsCrossedRows > static_cast(cMinTPCncr)); // Basic DCA cuts - selectedTracks.bindTable(resotracks); - auto colTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colTracks, colTracks); - } - } - PROCESS_SWITCH(lambda1520analysis, processData, "Process Event for data with partition", true); - - void processDataLight(aod::ResoCollision& collision, - aod::ResoTracks const& resotracks) + void processData(aod::ResoCollision& collision, + aod::ResoTracks const& resotracks) { fillHistograms(collision, resotracks, resotracks); } - PROCESS_SWITCH(lambda1520analysis, processDataLight, "Process Event for data without partition", false); - - void processMC(aod::ResoCollisions& collisions, soa::Join const& resomctracks, aod::McParticles const& mcParticles) - { - LOGF(debug, "[MC] MC events: %d", collisions.size()); - for (auto& collision : collisions) { - Partition> selectedTracks = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::eta) < static_cast(cfgCutEta)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) <= static_cast(cMaxDCArToPVcut)) && (aod::resodaughter::tpcNClsCrossedRows > static_cast(cMinTPCncr)); // Basic DCA cuts - selectedTracks.bindTable(resomctracks); - auto colMCTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colMCTracks, colMCTracks); - } - - // Not related to the real collisions - for (auto& part : mcParticles) { // loop over all MC particles - if (abs(part.pdgCode()) == 3124) { // Lambda(1520) - if (part.y() > 0.5 || part.y() < -0.5) { // rapidity cut - // LOGF(info, "[Rapidity cut] Lambda(1520): %d, y: %f", part.pdgCode(), part.y()); - continue; - } - bool pass1 = false; - bool pass2 = false; - for (auto& dau : part.daughters_as()) { - if (dau.pt() < cMinPtcut || fabs(dau.eta()) > cfgCutEta) - continue; - // LOGF(info,"daughter pt: %f, eta: %f", dau.pt(), dau.eta()); - if (abs(dau.pdgCode()) == kKPlus) { // Decay to Kaons - pass2 = true; - } - if (abs(dau.pdgCode()) == kProton) { // Decay to Protons - pass1 = true; - } - } - if (!pass1 || !pass2) - continue; - histos.fill(HIST("Result/MC/truelambda1520pt"), part.pt()); - } - } - } - PROCESS_SWITCH(lambda1520analysis, processMC, "Process Event for MC with partition", false); + PROCESS_SWITCH(lambda1520analysis, processData, "Process Event for data without partition", false); - void processMCLight(aod::ResoCollision& collision, - soa::Join const& resotracks, aod::McParticles const& mcParticles) + void processMC(aod::ResoCollision& collision, + soa::Join const& resotracks, aod::McParticles const& mcParticles) { fillHistograms(collision, resotracks, resotracks); } - PROCESS_SWITCH(lambda1520analysis, processMCLight, "Process Event for MC Light without partition", false); + PROCESS_SWITCH(lambda1520analysis, processMC, "Process Event for MC Light without partition", false); - void processMCTrue(aod::ResoCollisions& collisions, aod::McParticles const& mcParticles) + void processMCTrue(aod::ResoMCParents& resoParents) { // Not related to the real collisions - for (auto& part : mcParticles) { // loop over all MC particles - if (abs(part.pdgCode()) == 3124) { // Lambda1520(0) - if (part.y() > 0.5 || part.y() < -0.5) { // rapidity cut - continue; - } - bool pass1 = false; - bool pass2 = false; - for (auto& dau : part.daughters_as()) { - if (abs(dau.pdgCode()) == kKPlus) { // At least one decay to Kaon - pass2 = true; - } - if (abs(dau.pdgCode()) == kProton) { // At least one decay to Proton - pass1 = true; - } - } - if (!pass1 || !pass2) // If we have both decay products - continue; - histos.fill(HIST("Result/MC/truelambda1520pt"), part.pt()); + for (auto& part : resoParents) { // loop over all MC particles + if (abs(part.pdgCode()) != 3124) // Lambda1520(0) + continue; + if (abs(part.y()) > 0.5) // rapidity cut + continue; + bool pass1 = false; + bool pass2 = false; + if (abs(part.daughterPDG1()) == kKPlus || abs(part.daughterPDG2()) == kKPlus) { // At least one decay to Kaon + pass2 = true; } + if (abs(part.daughterPDG1()) == kProton || abs(part.daughterPDG2()) == kProton) { // At least one decay to Proton + pass1 = true; + } + if (!pass1 || !pass2) // If we have both decay products + continue; + histos.fill(HIST("Result/MC/GenTruelambda1520pt"), part.pt()); + if (part.pdgCode() > 0) + histos.fill(HIST("Result/MC/Genlambda1520pt"), part.pt()); + else + histos.fill(HIST("Result/MC/Genantilambda1520pt"), part.pt()); } } PROCESS_SWITCH(lambda1520analysis, processMCTrue, "Process Event for MC only", false); // Processing Event Mixing - using BinningTypeVetZTPCtemp = ColumnBinningPolicy; - BinningTypeVetZTPCtemp colBinning{{CfgVtxBins, CfgMultBins}, true}; + using BinningTypeVtxZT0M = ColumnBinningPolicy; void processME(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) - { - LOGF(debug, "Event Mixing Started"); - auto tracksTuple = std::make_tuple(resotracks); - SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - - for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { - // Kaons - Partition selectedTracks1 = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::eta) < static_cast(cfgCutEta)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)) && (aod::resodaughter::tpcNClsCrossedRows > static_cast(cMinTPCncr)); // && aod::tracktag::isKaon == true; // Basic DCA cuts - selectedTracks1.bindTable(tracks1); - // Protons - Partition selectedTracks2 = (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::eta) < static_cast(cfgCutEta)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)) && (aod::resodaughter::tpcNClsCrossedRows > static_cast(cMinTPCncr)); // && aod::tracktag::isProton == true; // Basic DCA cuts - selectedTracks2.bindTable(tracks2); - - fillHistograms(collision1, selectedTracks1, selectedTracks2); - } - }; - PROCESS_SWITCH(lambda1520analysis, processME, "Process EventMixing with partition", true); - - void processMELight(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) { auto tracksTuple = std::make_tuple(resotracks); - SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; + SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { fillHistograms(collision1, tracks1, tracks2); } }; - PROCESS_SWITCH(lambda1520analysis, processMELight, "Process EventMixing light without partition", false); + PROCESS_SWITCH(lambda1520analysis, processME, "Process EventMixing light without partition", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/nonPromptCascade.cxx b/PWGLF/Tasks/nonPromptCascade.cxx new file mode 100644 index 00000000000..c0270af8869 --- /dev/null +++ b/PWGLF/Tasks/nonPromptCascade.cxx @@ -0,0 +1,609 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Track.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "CCDB/BasicCCDBManager.h" +#include "DetectorsBase/Propagator.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +namespace +{ +static constexpr int nParticles{4}; +static constexpr int nCutsPID{2}; +static const std::vector matterOrNot{"Matter", "Antimatter"}; +static const std::vector particlesNames{"K-bachelor", "Pi-bachelor", "Pr", "Pi"}; +static const std::vector cutsNames{"TPCnSigmaMin", "TPCnSigmaMax"}; +static constexpr float cutsPID[nParticles][nCutsPID]{ + {-4.f, +4.f}, /*K bachelor*/ + {-4.f, +4.f}, /*Pi bachelor*/ + {-4.f, +4.f}, /*Pr*/ + {-4.f, +4.f}, /*Pi*/ +}; +std::shared_ptr h2TPCsignal[nParticles]; +std::shared_ptr h2TPCnSigma[nParticles]; + +std::shared_ptr invMassBCOmega; +std::shared_ptr invMassACOmega; +std::shared_ptr invMassBCXi; +std::shared_ptr invMassACXi; + +} // namespace + +struct NonPromptCascadeTask { + + using TracksExtData = soa::Join; + using TracksExtMC = soa::Join; + using CollisionCandidatesRun3 = soa::Join::iterator; + + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable bz{"bz", -50., "magnetic field"}; + Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; + Configurable cfgGRPmagPath{"cfgGRPmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable cfgGRPpath{"cfgGRPpath", "GLO/GRP/GRP", "Path of the grp file"}; + + Configurable cfgCutNclusTPC{"cfgCutNclusTPC", 70, "Minimum number of TPC clusters"}; + Configurable> cfgCutsPID{"particlesCutsPID", {cutsPID[0], nParticles, nCutsPID, particlesNames, cutsNames}, "Nuclei PID selections"}; + + Service ccdb; + int mRunNumber = 0; + float mBz = 0.f; + + HistogramRegistry registry{ + "registry", + { + {"h_dca_Omega", "DCA;DCA (cm)", {HistType::kTH1D, {{200, 0., .5}}}}, + {"h_dcaxy_Omega", "DCA xy;DCA_{xy} (cm)", {HistType::kTH1D, {{200, -.5, .5}}}}, + {"h_dcaz_Omega", "DCA z;DCA_{z} (cm)", {HistType::kTH1D, {{200, -.5, .5}}}}, + {"h_bachdcaxyM_Omega", "Bachelor DCA xy;DCA_{xy} (cm)", {HistType::kTH1D, {{200, -1., 1.}}}}, + {"h_bachdcaxyAM_Omega", "Bachelor DCA xy;DCA_{xy} (cm)", {HistType::kTH1D, {{200, -1., 1.}}}}, + {"h_bachdcazM_Omega", "Bachelor DCA z;DCA_{z} (cm)", {HistType::kTH1D, {{200, -1., 1.}}}}, + {"h_bachdcazAM_Omega", "Bachelor DCA z;DCA_{z} (cm)", {HistType::kTH1D, {{200, -1., 1.}}}}, + {"h_dcavspt_Omega", "DCA vs p_{T};DCA (cm);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{100, -0.1, 0.1}, {200, 0., 10.}}}}, + {"h_bachdcavspt_Omega", "Bachelor DCA vs p_{T};DCA (cm);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{200, -1., 1.}, {200, 0., 10.}}}}, + {"h_bachdcavsr_Omega", "Bachelor DCA vs R (cm);DCA (cm);R (cm)", {HistType::kTH2D, {{200, -1., 1.}, {200, 0., 30.}}}}, + {"h_ntrackdcavspt_Omega", "N track DCA vs p_{T};DCA (cm);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{200, -1., 1.}, {200, 0., 10.}}}}, + {"h_ptrackdcavspt_Omega", "P track DCA vs p_{T};DCA (cm);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{200, -1., 1.}, {200, 0., 10.}}}}, + {"h_dcavsr_Omega", "DCA vs R;DCA (cm);R (cm)", {HistType::kTH2D, {{200, -.5, .5}, {200, 0., 10.}}}}, + {"h_massvspt_Omega", "Mass vs p_{T};Mass (GeV/#it{c}^2);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{150, 1.660, 1.690}, {200, 0., 10.}}}}, + {"h_buildermassvspt_Omega", "Mass (from builder) vs p_{T};Mass (GeV/#it{c}^2);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{150, 1.660, 1.690}, {200, 0., 10.}}}}, + {"h_massvsmass_Omega", "Mass vs mass;Mass (GeV/#it{c}^{2});Mass (GeV/#it{c}^{2})", {HistType::kTH2D, {{150, 1.660, 1.690}, {150, 1.660, 1.690}}}}, + {"h_bachelorsign_Omega", "Bachelor sign;Sign;Counts", {HistType::kTH1D, {{10, -5., 5.}}}}, + {"h_ptmassdcaxyM_Omega", ";p_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});DCA_{xy} (cm)", {HistType::kTH3D, {{200, 0., 10.}, {150, 1.660, 1.690}, {200, -.5, .5}}}}, + {"h_ptmassdcaxyAM_Omega", ";p_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});DCA_{xy} (cm)", {HistType::kTH3D, {{200, 0., 10.}, {150, 1.660, 1.690}, {200, -.5, .5}}}}, + {"h_ptmassdcazM_Omega", ";p_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});DCA_{x} (cm)", {HistType::kTH3D, {{200, 0., 10.}, {150, 1.660, 1.690}, {200, -.5, .5}}}}, + {"h_ptmassdcazAM_Omega", ";p_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});DCA_{x} (cm)", {HistType::kTH3D, {{200, 0., 10.}, {150, 1.660, 1.690}, {200, -.5, .5}}}}, + + {"h_dca_Xi", "DCA;DCA (cm)", {HistType::kTH1D, {{200, 0., .5}}}}, + {"h_dcaxy_Xi", "DCA xy;DCA_{xy} (cm)", {HistType::kTH1D, {{200, -.5, .5}}}}, + {"h_dcaz_Xi", "DCA z;DCA_{z} (cm)", {HistType::kTH1D, {{200, -.5, .5}}}}, + {"h_bachdcaxyM_Xi", "Bachelor DCA xy;DCA_{xy} (cm)", {HistType::kTH1D, {{200, -1., 1.}}}}, + {"h_bachdcaxyAM_Xi", "Bachelor DCA xy;DCA_{xy} (cm)", {HistType::kTH1D, {{200, -1., 1.}}}}, + {"h_bachdcazM_Xi", "Bachelor DCA z;DCA_{z} (cm)", {HistType::kTH1D, {{200, -1., 1.}}}}, + {"h_bachdcazAM_Xi", "Bachelor DCA z;DCA_{z} (cm)", {HistType::kTH1D, {{200, -1., 1.}}}}, + {"h_dcavspt_Xi", "DCA vs p_{T};DCA (cm);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{100, -0.1, 0.1}, {200, 0., 10.}}}}, + {"h_bachdcavspt_Xi", "Bachelor DCA vs p_{T};DCA (cm);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{200, -1., 1.}, {200, 0., 10.}}}}, + {"h_bachdcavsr_Xi", "Bachelor DCA vs R (cm);DCA (cm);R (cm)", {HistType::kTH2D, {{200, -1., 1.}, {200, 0., 30.}}}}, + {"h_ntrackdcavspt_Xi", "N track DCA vs p_{T};DCA (cm);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{200, -1., 1.}, {200, 0., 10.}}}}, + {"h_ptrackdcavspt_Xi", "P track DCA vs p_{T};DCA (cm);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{200, -1., 1.}, {200, 0., 10.}}}}, + {"h_dcavsr_Xi", "DCA vs R;DCA (cm);R (cm)", {HistType::kTH2D, {{200, -.5, .5}, {200, 0., 10.}}}}, + {"h_massvspt_Xi", "Mass vs p_{T};Mass (GeV/#it{c}^2);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{150, 1.306, 1.336}, {200, 0., 10.}}}}, + {"h_buildermassvspt_Xi", "Mass (from builder) vs p_{T};Mass (GeV/#it{c}^2);p_{T} (GeV/#it{c})", {HistType::kTH2D, {{150, 1.306, 1.336}, {200, 0., 10.}}}}, + {"h_massvsmass_Xi", "Mass vs mass;Mass (GeV/#it{c}^{2});Mass (GeV/#it{c}^{2})", {HistType::kTH2D, {{150, 1.306, 1.336}, {150, 1.306, 1.336}}}}, + {"h_bachelorsign_Xi", "Bachelor sign;Sign;Counts", {HistType::kTH1D, {{10, -5., 5.}}}}, + {"h_ptmassdcaxyM_Xi", ";p_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});DCA_{xy} (cm)", {HistType::kTH3D, {{200, 0., 10.}, {150, 1.306, 1.336}, {200, -.5, .5}}}}, + {"h_ptmassdcaxyAM_Xi", ";p_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});DCA_{xy} (cm)", {HistType::kTH3D, {{200, 0., 10.}, {150, 1.306, 1.336}, {200, -.5, .5}}}}, + {"h_ptmassdcazM_Xi", ";p_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});DCA_{x} (cm)", {HistType::kTH3D, {{200, 0., 10.}, {150, 1.306, 1.336}, {200, -.5, .5}}}}, + {"h_ptmassdcazAM_Xi", ";p_{T} (GeV/#it{c});Mass (GeV/#it{c}^{2});DCA_{x} (cm)", {HistType::kTH3D, {{200, 0., 10.}, {150, 1.306, 1.336}, {200, -.5, .5}}}}, + + }}; + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + + if (mRunNumber == bc.runNumber()) { + return; + } + LOG(debug) << "Run number: " << mRunNumber << " bc runNumber: " << bc.runNumber(); + + auto run3grp_timestamp = bc.timestamp(); + mRunNumber = bc.runNumber(); + + if (o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(cfgGRPpath, run3grp_timestamp)) { + o2::base::Propagator::initFieldFromGRP(grpo); + LOG(debug) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << mBz << " kZG"; + } else if (o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp(cfgGRPmagPath, run3grp_timestamp)) { + o2::base::Propagator::initFieldFromGRP(grpmag); + LOG(debug) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << mBz << " kZG"; + } else { + LOG(fatal) << "Got nullptr from CCDB for path " << cfgGRPpath << " of object GRPMagField and " << cfgGRPmagPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + return; + } + + void init(InitContext const&) + { + ccdb->setURL(ccdbUrl); + ccdb->setFatalWhenNull(false); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + if (static_cast(cfgMaterialCorrection.value) == o2::base::Propagator::MatCorrType::USEMatCorrLUT) { + auto* lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + o2::base::Propagator::Instance(true)->setMatLUT(lut); + } + + std::vector ptBinning = {0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 2.8, 3.2, 3.6, 4.0, 4.4, 4.8, 5.2, 5.6, 6.0}; + AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + registry.add("fTPCsignal", "Specific energy loss", HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + registry.add("fCollZpos", "collision z position", HistType::kTH1F, {{600, -20., +20., "z position (cm)"}}); + + for (int iN{0}; iN < nParticles; ++iN) { + h2TPCsignal[iN] = registry.add(Form("fTPCsignal_%s", particlesNames[iN].data()), "Specific energy loss", HistType::kTH2F, {{1200, -6, 6., "#it{p}/Z (GeV/#it{c})"}, {1400, 0, 1400, "d#it{E} / d#it{X} (a. u.)"}}); + h2TPCnSigma[iN] = registry.add(Form("fTPCnSigma_%s", particlesNames[iN].data()), "n-sigma TPC", HistType::kTH2F, {{100, -5, 5, "#it{p} /Z (GeV/#it{c})"}, {200, -10., +10., Form("n#sigma_%s (a. u.)", particlesNames[iN].data())}}); + } + auto scalers{std::get>(registry.add("fProcessedCascades", ";;Number of filtered cascades", HistType::kTH1D, {{nParticles + 1, -0.5, nParticles + 0.5}}))}; + scalers->GetXaxis()->SetBinLabel(1, "Processed cascades"); + for (uint32_t iS{0}; iS < particlesNames.size(); ++iS) { + scalers->GetXaxis()->SetBinLabel(iS + 2, particlesNames[iS].data()); + } + + auto cutsOmega{std::get>(registry.add("h_PIDcutsOmega", ";;Invariant mass (GeV/#it{c}^{2})", HistType::kTH2D, {{6, -0.5, 5.5}, {200, 1.550, 1.750}}))}; + cutsOmega->GetXaxis()->SetBinLabel(1, "Tot #Omega"); + cutsOmega->GetXaxis()->SetBinLabel(2, "hasTof"); + cutsOmega->GetXaxis()->SetBinLabel(3, "nClusTPC"); + cutsOmega->GetXaxis()->SetBinLabel(4, "nSigmaTPCbach"); + cutsOmega->GetXaxis()->SetBinLabel(5, "nSigmaTPCprotontrack"); + cutsOmega->GetXaxis()->SetBinLabel(6, "nSigmaTPCpiontrack"); + + auto cutsXi{std::get>(registry.add("h_PIDcutsXi", ";;Invariant mass (GeV/#it{c}^{2})", HistType::kTH2D, {{6, -0.5, 5.5}, {200, 1.250, 1.450}}))}; + cutsXi->GetXaxis()->SetBinLabel(1, "Tot #Xi"); + cutsXi->GetXaxis()->SetBinLabel(2, "hasTof"); + cutsXi->GetXaxis()->SetBinLabel(3, "nClusTPC"); + cutsXi->GetXaxis()->SetBinLabel(4, "nSigmaTPCbach"); + cutsXi->GetXaxis()->SetBinLabel(5, "nSigmaTPCprotontrack"); + cutsXi->GetXaxis()->SetBinLabel(6, "nSigmaTPCpiontrack"); + + auto nClusPerTrack{std::get>(registry.add("h_nClusPerTrack", ";;# Clusters", HistType::kTH2D, {{3, -0.5, 2.5}, {210, 0., 210.}}))}; + nClusPerTrack->GetXaxis()->SetBinLabel(1, "Bachelor"); + nClusPerTrack->GetXaxis()->SetBinLabel(2, "Proton track"); + nClusPerTrack->GetXaxis()->SetBinLabel(3, "Pion track"); + + invMassBCOmega = registry.add("h_invariantmass_beforeCuts_Omega", "Invariant Mass (GeV/#it{c}^{2})", HistType::kTH1D, {{150, 1.660, 1.6905, "Invariant Mass (GeV/#it{c}^{2})"}}); + invMassACOmega = registry.add("h_invariantmass_afterCuts_Omega", "Invariant Mass (GeV/#it{c}^{2})", HistType::kTH1D, {{150, 1.660, 1.690, "Invariant Mass (GeV/#it{c}^{2})"}}); + invMassBCXi = registry.add("h_invariantmass_beforeCuts_Xi", "Invariant Mass (GeV/#it{c}^{2})", HistType::kTH1D, {{150, 1.306, 1.336, "Invariant Mass (GeV/#it{c}^{2})"}}); + invMassACXi = registry.add("h_invariantmass_afterCuts_Xi", "Invariant Mass (GeV/#it{c}^{2})", HistType::kTH1D, {{150, 1.306, 1.336, "Invariant Mass (GeV/#it{c}^{2})"}}); + } + + template + void fillQAPID(float nSigmaTPC[4], B const bachelor, PR const protonTrack, PI const pionTrack) + { + registry.fill(HIST("h_nClusPerTrack"), 0, bachelor.tpcNClsFound()); + registry.fill(HIST("h_nClusPerTrack"), 1, protonTrack.tpcNClsFound()); + registry.fill(HIST("h_nClusPerTrack"), 2, pionTrack.tpcNClsFound()); + + registry.fill(HIST("fTPCsignal"), bachelor.sign() * bachelor.tpcInnerParam(), bachelor.tpcSignal()); + registry.fill(HIST("fTPCsignal"), protonTrack.sign() * protonTrack.tpcInnerParam(), protonTrack.tpcSignal()); + registry.fill(HIST("fTPCsignal"), pionTrack.sign() * pionTrack.tpcInnerParam(), pionTrack.tpcSignal()); + + h2TPCnSigma[0]->Fill(bachelor.sign() * bachelor.tpcInnerParam(), nSigmaTPC[0]); + h2TPCnSigma[1]->Fill(bachelor.sign() * bachelor.tpcInnerParam(), nSigmaTPC[1]); + h2TPCnSigma[2]->Fill(protonTrack.sign() * protonTrack.tpcInnerParam(), nSigmaTPC[2]); + h2TPCnSigma[3]->Fill(pionTrack.sign() * pionTrack.tpcInnerParam(), nSigmaTPC[3]); + + h2TPCsignal[1]->Fill(bachelor.sign() * bachelor.tpcInnerParam(), bachelor.tpcSignal()); + h2TPCsignal[2]->Fill(protonTrack.sign() * protonTrack.tpcInnerParam(), protonTrack.tpcSignal()); + h2TPCsignal[3]->Fill(pionTrack.sign() * pionTrack.tpcInnerParam(), pionTrack.tpcSignal()); + } + + template + void fillCascadeDCA(TC const& trackedCascade, T const track, B const bachelor, PR const& protonTrack, PI const& pionTrack, o2::dataformats::VertexBase primaryVertex, bool isOmega) + { + const auto matCorr = static_cast(cfgMaterialCorrection.value); + std::array, 2> momenta; + std::array masses; + auto trackCovTrk = getTrackParCov(track); + o2::dataformats::DCA impactParameterTrk; + + if (o2::base::Propagator::Instance()->propagateToDCA(primaryVertex, trackCovTrk, mBz, 2.f, matCorr, &impactParameterTrk)) { + momenta[0] = {protonTrack.px() + pionTrack.px(), protonTrack.py() + pionTrack.py(), protonTrack.pz() + pionTrack.pz()}; + momenta[1] = {bachelor.px(), bachelor.py(), bachelor.pz()}; + masses = {constants::physics::MassLambda, constants::physics::MassKaonCharged}; + const auto massOmega = RecoDecay::m(momenta, masses); + + if (protonTrack.hasTPC() && pionTrack.hasTPC()) { + if (isOmega) { + registry.fill(HIST("h_dca_Omega"), TMath::Sqrt(impactParameterTrk.getR2())); + registry.fill(HIST("h_dcaxy_Omega"), impactParameterTrk.getY()); + registry.fill(HIST("h_dcaz_Omega"), impactParameterTrk.getZ()); + registry.fill(HIST("h_dcavspt_Omega"), impactParameterTrk.getY(), track.pt()); + registry.fill(HIST("h_dcavsr_Omega"), impactParameterTrk.getY(), std::hypot(track.x(), track.y())); + registry.fill(HIST("h_massvspt_Omega"), massOmega, track.pt()); + if (bachelor.sign() < 0) { + registry.fill(HIST("h_ptmassdcazM_Omega"), track.pt(), massOmega, impactParameterTrk.getZ()); + registry.fill(HIST("h_ptmassdcaxyM_Omega"), track.pt(), massOmega, impactParameterTrk.getY()); + } else if (bachelor.sign() > 0) { + registry.fill(HIST("h_ptmassdcazAM_Omega"), track.pt(), massOmega, impactParameterTrk.getZ()); + registry.fill(HIST("h_ptmassdcaxyAM_Omega"), track.pt(), massOmega, impactParameterTrk.getY()); + } + } + } + + masses = {constants::physics::MassLambda, constants::physics::MassPionCharged}; + const auto massXi = RecoDecay::m(momenta, masses); + + if (protonTrack.hasTPC() && pionTrack.hasTPC()) { + registry.fill(HIST("h_dca_Xi"), TMath::Sqrt(impactParameterTrk.getR2())); + registry.fill(HIST("h_dcaxy_Xi"), impactParameterTrk.getY()); + registry.fill(HIST("h_dcaz_Xi"), impactParameterTrk.getZ()); + registry.fill(HIST("h_dcavspt_Xi"), impactParameterTrk.getY(), track.pt()); + registry.fill(HIST("h_dcavsr_Xi"), impactParameterTrk.getY(), std::hypot(track.x(), track.y())); + registry.fill(HIST("h_massvspt_Xi"), massXi, track.pt()); + if (bachelor.sign() < 0) { + registry.fill(HIST("h_ptmassdcazM_Xi"), track.pt(), massXi, impactParameterTrk.getZ()); + registry.fill(HIST("h_ptmassdcaxyM_Xi"), track.pt(), massXi, impactParameterTrk.getY()); + } else if (bachelor.sign() > 0) { + registry.fill(HIST("h_ptmassdcazAM_Xi"), track.pt(), massXi, impactParameterTrk.getZ()); + registry.fill(HIST("h_ptmassdcaxyAM_Xi"), track.pt(), massXi, impactParameterTrk.getY()); + } + } + } + } + + template + void fillDauDCA(TC const& trackedCascade, B const& bachelor, PR const& protonTrack, PI const& pionTrack, o2::dataformats::VertexBase primaryVertex, bool isOmega) + { + + const auto matCorr = static_cast(cfgMaterialCorrection.value); + + auto trackCovBach = getTrackParCov(bachelor); + o2::dataformats::DCA impactParameterBach; + if (o2::base::Propagator::Instance()->propagateToDCA(primaryVertex, trackCovBach, mBz, 2.f, matCorr, &impactParameterBach)) { + if (isOmega) { + if (bachelor.sign() < 0) { + registry.fill(HIST("h_bachdcaxyM_Omega"), impactParameterBach.getY()); + registry.fill(HIST("h_bachdcazM_Omega"), impactParameterBach.getZ()); + } else if (bachelor.sign() > 0) { + registry.fill(HIST("h_bachdcaxyAM_Omega"), impactParameterBach.getY()); + registry.fill(HIST("h_bachdcazAM_Omega"), impactParameterBach.getZ()); + } + registry.fill(HIST("h_bachdcavspt_Omega"), impactParameterBach.getY(), bachelor.pt()); + registry.fill(HIST("h_bachdcavsr_Omega"), impactParameterBach.getY(), std::hypot(trackedCascade.decayX(), trackedCascade.decayY())); + registry.fill(HIST("h_bachelorsign_Omega"), bachelor.sign()); + } + if (bachelor.sign() < 0) { + registry.fill(HIST("h_bachdcaxyM_Xi"), impactParameterBach.getY()); + registry.fill(HIST("h_bachdcazM_Xi"), impactParameterBach.getZ()); + } else if (bachelor.sign() > 0) { + registry.fill(HIST("h_bachdcaxyAM_Xi"), impactParameterBach.getY()); + registry.fill(HIST("h_bachdcazAM_Xi"), impactParameterBach.getZ()); + } + registry.fill(HIST("h_bachdcavspt_Xi"), impactParameterBach.getY(), bachelor.pt()); + registry.fill(HIST("h_bachdcavsr_Xi"), impactParameterBach.getY(), std::hypot(trackedCascade.decayX(), trackedCascade.decayY())); + registry.fill(HIST("h_bachelorsign_Xi"), bachelor.sign()); + } + + auto trackCovNtrack = getTrackParCov(pionTrack); + o2::dataformats::DCA impactParameterNtrack; + if (o2::base::Propagator::Instance()->propagateToDCA(primaryVertex, trackCovNtrack, mBz, 2.f, matCorr, &impactParameterNtrack)) { + if (isOmega) { + registry.fill(HIST("h_ntrackdcavspt_Omega"), impactParameterNtrack.getY(), pionTrack.pt()); + } + registry.fill(HIST("h_ntrackdcavspt_Xi"), impactParameterNtrack.getY(), pionTrack.pt()); + } + + auto trackCovPtrack = getTrackParCov(protonTrack); + o2::dataformats::DCA impactParameterPtrack; + if (o2::base::Propagator::Instance()->propagateToDCA(primaryVertex, trackCovPtrack, mBz, 2.f, matCorr, &impactParameterPtrack)) { + if (isOmega) { + registry.fill(HIST("h_ptrackdcavspt_Omega"), impactParameterPtrack.getY(), protonTrack.pt()); + } + registry.fill(HIST("h_ptrackdcavspt_Xi"), impactParameterPtrack.getY(), protonTrack.pt()); + } + } + + void processTrackedCascadesMC(CollisionCandidatesRun3 const& collision, + aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& cascades, + aod::V0s const& v0s, TracksExtMC const& tracks, + soa::Join const& trackedcascdata, + aod::McParticles const& mcParticles, aod::BCsWithTimestamps const&) + { + bool keepEvent[nParticles]{false}; + bool isOmega{false}; + + auto bc = collision.bc_as(); + initCCDB(bc); + + registry.fill(HIST("fCollZpos"), collision.posZ()); + const auto primaryVertex = getPrimaryVertex(collision); + + for (const auto& trackedCascadeData : trackedcascdata) { + registry.fill(HIST("h_buildermassvspt_Omega"), trackedCascadeData.mOmega(), trackedCascadeData.pt()); + registry.fill(HIST("h_buildermassvspt_Xi"), trackedCascadeData.mXi(), trackedCascadeData.pt()); + } + + for (const auto& trackedCascade : trackedCascades) { + registry.fill(HIST("fProcessedCascades"), 0); + + isOmega = false; + + const auto track = trackedCascade.track_as(); + const auto& casc = trackedCascade.cascade(); + const auto& bachelor = casc.bachelor_as(); + const auto& v0 = casc.v0(); + const auto& ptrack = v0.posTrack_as(); + const auto& ntrack = v0.negTrack_as(); + const auto& protonTrack = bachelor.sign() > 0 ? ntrack : ptrack; + const auto& pionTrack = bachelor.sign() > 0 ? ptrack : ntrack; + + ////Omega hypohesis -> rejecting Xi + if (TMath::Abs(trackedCascade.xiMass() - constants::physics::MassXiMinus) > 0.005) { + isOmega = true; + invMassBCOmega->Fill(trackedCascade.omegaMass()); + } + + invMassBCXi->Fill(trackedCascade.xiMass()); + + registry.fill(HIST("h_PIDcutsOmega"), 0, trackedCascade.omegaMass()); + registry.fill(HIST("h_PIDcutsXi"), 0, trackedCascade.xiMass()); + + // if (!bachelor.hasTOF() && !ptrack.hasTOF() && !ntrack.hasTOF()) { + // LOG(debug) << "no TOF: " << bachelor.hasTOF() << "/" << ptrack.hasTOF() << "/" << ntrack.hasTOF(); + // continue; + // } + + registry.fill(HIST("h_PIDcutsOmega"), 1, trackedCascade.omegaMass()); + registry.fill(HIST("h_PIDcutsXi"), 1, trackedCascade.xiMass()); + + if (protonTrack.tpcNClsFound() < cfgCutNclusTPC || pionTrack.tpcNClsFound() < cfgCutNclusTPC) { + LOG(debug) << "no tpcNClsFound: " << bachelor.tpcNClsFound() << "/" << protonTrack.tpcNClsFound() << "/" << pionTrack.tpcNClsFound(); + continue; + } + + registry.fill(HIST("h_PIDcutsOmega"), 2, trackedCascade.omegaMass()); + registry.fill(HIST("h_PIDcutsXi"), 2, trackedCascade.xiMass()); + + // QA PID + float nSigmaTPC[nParticles]{bachelor.tpcNSigmaKa(), bachelor.tpcNSigmaPi(), protonTrack.tpcNSigmaPr(), pionTrack.tpcNSigmaPi()}; + fillQAPID(nSigmaTPC, bachelor, protonTrack, pionTrack); + + if (isOmega) { + h2TPCsignal[0]->Fill(bachelor.sign() * bachelor.tpcInnerParam(), bachelor.tpcSignal()); + if (bachelor.hasTPC()) { + LOG(debug) << "TPCSignal bachelor " << bachelor.sign() << "/" << bachelor.tpcInnerParam() << "/" << bachelor.tpcSignal(); + if (nSigmaTPC[0] < cfgCutsPID->get(0u, 0u) || nSigmaTPC[0] > cfgCutsPID->get(0u, 1u)) { + continue; + } + } + keepEvent[0] = true; + registry.fill(HIST("h_PIDcutsOmega"), 3, trackedCascade.omegaMass()); + } + + if (bachelor.hasTPC()) { + LOG(debug) << "TPCSignal bachelor " << bachelor.sign() << "/" << bachelor.tpcInnerParam() << "/" << bachelor.tpcSignal(); + if (nSigmaTPC[1] < cfgCutsPID->get(1u, 0u) || nSigmaTPC[1] > cfgCutsPID->get(1u, 1u)) { + continue; + } + } + keepEvent[1] = true; + registry.fill(HIST("h_PIDcutsXi"), 3, trackedCascade.xiMass()); + + LOG(debug) << "TPCSignal protonTrack " << protonTrack.sign() << "/" << protonTrack.tpcInnerParam() << "/" << protonTrack.tpcSignal(); + if (nSigmaTPC[2] < cfgCutsPID->get(2u, 0u) || nSigmaTPC[2] > cfgCutsPID->get(2u, 1u)) { + continue; + } + keepEvent[2] = true; + + registry.fill(HIST("h_PIDcutsOmega"), 4, trackedCascade.omegaMass()); + registry.fill(HIST("h_PIDcutsXi"), 4, trackedCascade.xiMass()); + + LOG(debug) << "TPCSignal ntrack " << pionTrack.sign() << "/" << pionTrack.tpcInnerParam() << "/" << pionTrack.tpcSignal(); + if (nSigmaTPC[3] < cfgCutsPID->get(3u, 0u) || nSigmaTPC[3] > cfgCutsPID->get(3u, 1u)) { + continue; + } + keepEvent[3] = true; + + registry.fill(HIST("h_PIDcutsXi"), 5, trackedCascade.xiMass()); + registry.fill(HIST("h_PIDcutsOmega"), 5, trackedCascade.omegaMass()); + + invMassACXi->Fill(trackedCascade.xiMass()); + invMassACOmega->Fill(trackedCascade.omegaMass()); + + for (int iDecision{0}; iDecision < 4; ++iDecision) { + if (keepEvent[iDecision]) { + registry.fill(HIST("fProcessedCascades"), iDecision + 1); + } + } + + fillCascadeDCA(trackedCascade, track, bachelor, protonTrack, pionTrack, primaryVertex, isOmega); + + LOGF(debug, "protonTrack (id: %d, pdg: %d) has mother %d", protonTrack.mcParticleId(), + protonTrack.mcParticle().pdgCode(), protonTrack.mcParticle().has_mothers() ? protonTrack.mcParticle().mothersIds()[0] : -1); + LOGF(debug, "pionTrack (id: %d, pdg: %d) has mother %d", pionTrack.mcParticleId(), + pionTrack.mcParticle().pdgCode(), pionTrack.mcParticle().has_mothers() ? pionTrack.mcParticle().mothersIds()[0] : -1); + + LOG(debug) << "bachelor with PDG code: " << bachelor.mcParticle().pdgCode() << ". Charge: " << bachelor.sign(); + if (ptrack.mcParticle().has_mothers() && pionTrack.mcParticle().has_mothers() && + protonTrack.mcParticle().mothersIds()[0] == pionTrack.mcParticle().mothersIds()[0]) { + const auto v0part = protonTrack.mcParticle().mothers_as()[0]; + LOG(debug) << "v0 with PDG code: " << v0part.pdgCode(); + if (v0part.has_mothers() && bachelor.mcParticle().has_mothers() && + v0part.mothersIds()[0] == bachelor.mcParticle().mothersIds()[0]) { + int mcid = v0part.mothersIds()[0]; + for (const auto& trackedCascadeData : trackedcascdata) { + if (trackedCascadeData.mcParticleId() == mcid) { + if (isOmega) { + registry.fill(HIST("h_massvsmass_Omega"), trackedCascade.omegaMass(), trackedCascadeData.mOmega()); + } else { + registry.fill(HIST("h_massvsmass_Xi"), trackedCascade.omegaMass(), trackedCascadeData.mOmega()); + } + break; + } + LOG(debug) << "cascade with PDG code: " << v0part.mothers_as()[0].pdgCode(); + } + } else { + LOG(debug) << "Rejecting particle."; + continue; + } + } + fillDauDCA(trackedCascade, bachelor, protonTrack, pionTrack, primaryVertex, isOmega); + } + } + PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesMC, "process cascades from strangeness tracking: MC analysis", true); + + void processTrackedCascadesData(CollisionCandidatesRun3 const& collision, + aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& cascades, + aod::V0s const& v0s, TracksExtData const& tracks, + aod::BCsWithTimestamps const&) + { + + bool keepEvent[nParticles]{false}; + + bool isOmega{false}; + + auto bc = collision.bc_as(); + initCCDB(bc); + + registry.fill(HIST("fCollZpos"), collision.posZ()); + const auto primaryVertex = getPrimaryVertex(collision); + + for (const auto& trackedCascade : trackedCascades) { + registry.fill(HIST("fProcessedCascades"), 0); + + isOmega = false; + + const auto track = trackedCascade.track_as(); + const auto& casc = trackedCascade.cascade(); + const auto& bachelor = casc.bachelor_as(); + const auto& v0 = casc.v0(); + const auto& ptrack = v0.posTrack_as(); + const auto& ntrack = v0.negTrack_as(); + const auto& protonTrack = bachelor.sign() > 0 ? ntrack : ptrack; + const auto& pionTrack = bachelor.sign() > 0 ? ptrack : ntrack; + + std::array, 2> momenta; + std::array masses; + momenta[0] = {protonTrack.px() + pionTrack.px(), protonTrack.py() + pionTrack.py(), protonTrack.pz() + pionTrack.pz()}; + momenta[1] = {bachelor.px(), bachelor.py(), bachelor.pz()}; + masses = {constants::physics::MassLambda, constants::physics::MassKaonCharged}; + const auto massOmega = RecoDecay::m(momenta, masses); + masses = {constants::physics::MassLambda, constants::physics::MassPionCharged}; + const auto massXi = RecoDecay::m(momenta, masses); + + ////Omega hypohesis -> rejecting Xi + if (TMath::Abs(massXi - constants::physics::MassXiMinus) > 0.005) { + isOmega = true; + invMassBCOmega->Fill(massOmega); + } + + invMassBCXi->Fill(massXi); + + registry.fill(HIST("h_PIDcutsXi"), 0, massXi); + registry.fill(HIST("h_PIDcutsOmega"), 0, massOmega); + + // if (!bachelor.hasTOF() && !ptrack.hasTOF() && !ntrack.hasTOF() ) { + // LOG(debug)<< "no TOF: "<Fill(bachelor.sign() * bachelor.tpcInnerParam(), bachelor.tpcSignal()); + if (bachelor.hasTPC()) { + LOG(debug) << "TPCSignal bachelor " << bachelor.sign() << "/" << bachelor.tpcInnerParam() << "/" << bachelor.tpcSignal(); + if (nSigmaTPC[0] < cfgCutsPID->get(0u, 0u) || nSigmaTPC[0] > cfgCutsPID->get(0u, 1u)) { + continue; + } + } + keepEvent[0] = true; + registry.fill(HIST("h_PIDcutsOmega"), 3, massOmega); + } + + if (bachelor.hasTPC()) { + LOG(debug) << "TPCSignal bachelor " << bachelor.sign() << "/" << bachelor.tpcInnerParam() << "/" << bachelor.tpcSignal(); + if (nSigmaTPC[1] < cfgCutsPID->get(1u, 0u) || nSigmaTPC[1] > cfgCutsPID->get(1u, 1u)) { + continue; + } + } + keepEvent[1] = true; + registry.fill(HIST("h_PIDcutsXi"), 3, massXi); + + LOG(debug) << "TPCSignal protonTrack " << protonTrack.sign() << "/" << protonTrack.tpcInnerParam() << "/" << protonTrack.tpcSignal(); + if (nSigmaTPC[2] < cfgCutsPID->get(2u, 0u) || nSigmaTPC[2] > cfgCutsPID->get(2u, 1u)) { + continue; + } + keepEvent[2] = true; + + registry.fill(HIST("h_PIDcutsXi"), 4, massXi); + registry.fill(HIST("h_PIDcutsOmega"), 4, massOmega); + + LOG(debug) << "TPCSignal ntrack " << pionTrack.sign() << "/" << pionTrack.tpcInnerParam() << "/" << pionTrack.tpcSignal(); + if (nSigmaTPC[3] < cfgCutsPID->get(3u, 0u) || nSigmaTPC[3] > cfgCutsPID->get(3u, 1u)) { + continue; + } + keepEvent[3] = true; + + registry.fill(HIST("h_PIDcutsXi"), 5, massXi); + registry.fill(HIST("h_PIDcutsOmega"), 5, massOmega); + + invMassACXi->Fill(massXi); + invMassACOmega->Fill(massOmega); + + for (int iDecision{0}; iDecision < 4; ++iDecision) { + if (keepEvent[iDecision]) { + registry.fill(HIST("fProcessedCascades"), iDecision + 1); + } + } + + fillCascadeDCA(trackedCascade, track, bachelor, protonTrack, pionTrack, primaryVertex, isOmega); + fillDauDCA(trackedCascade, bachelor, protonTrack, pionTrack, primaryVertex, isOmega); + } + } + PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesData, "process cascades from strangeness tracking: Data analysis", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/phianalysis.cxx b/PWGLF/Tasks/phianalysis.cxx index fc69ab96fef..4237b5cca0f 100644 --- a/PWGLF/Tasks/phianalysis.cxx +++ b/PWGLF/Tasks/phianalysis.cxx @@ -15,7 +15,6 @@ /// /// \author Bong-Hwi Lim -#include #include #include "Common/DataModel/PIDResponse.h" @@ -35,237 +34,287 @@ using namespace o2::soa; struct phianalysis { SliceCache cache; Preslice perRCol = aod::resodaughter::resoCollisionId; - - framework::Service ccdb; /// Accessing the CCDB - ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; - ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; - Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; - + Preslice perCollision = aod::track::collisionId; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; - // Configurables - // Pre-selection cuts - Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; - Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; + ///// Configurables + /// Histograms + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6.0, 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7.0, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 8.7, 8.8, 8.9, 9.0, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 11.0, 11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 12.1, 12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9, 13.0, 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7, 13.8, 13.9, 14.0, 14.1, 14.2, 14.3, 14.4, 14.5, 14.6, 14.7, 14.8, 14.9, 15.0}, "Binning of the pT axis"}; + ConfigurableAxis binsPtQA{"binsPtQA", {VARIABLE_WIDTH, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6.0, 6.2, 6.4, 6.6, 6.8, 7.0, 7.2, 7.4, 7.6, 7.8, 8.0, 8.2, 8.4, 8.6, 8.8, 9.0, 9.2, 9.4, 9.6, 9.8, 10.0}, "Binning of the pT axis"}; + ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Binning of the centrality axis"}; + Configurable cInvMassStart{"cInvMassStart", 0.6, "Invariant mass start"}; + Configurable cInvMassEnd{"cInvMassEnd", 1.5, "Invariant mass end"}; + Configurable cInvMassBins{"cInvMassBins", 900, "Invariant mass binning"}; + Configurable cPIDBins{"cPIDBins", 65, "PID binning"}; + Configurable cPIDQALimit{"cPIDQALimit", 6.5, "PID QA limit"}; + Configurable cDCABins{"cDCABins", 150, "DCA binning"}; + /// Event Mixing + Configurable nEvtMixing{"nEvtMixing", 5, "Number of events to mix"}; + ConfigurableAxis CfgVtxBins{"CfgVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Mixing bins - multiplicity"}; + /// Pre-selection cuts Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minium pt cut"}; - /// DCA Selections // DCAr to PV Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; // DCAz to PV Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; - - Preslice perCollision = aod::track::collisionId; + /// PID Selections + Configurable cUseOnlyTOFTrackKa{"cUseOnlyTOFTrackKa", false, "Use only TOF track for PID selection"}; // Use only TOF track for PID selection + // Kaon + Configurable cMaxTPCnSigmaKaon{"cMaxTPCnSigmaKaon", 3.0, "TPC nSigma cut for Kaon"}; // TPC + Configurable cMaxTOFnSigmaKaon{"cMaxTOFnSigmaKaon", 3.0, "TOF nSigma cut for Kaon"}; // TOF + Configurable nsigmaCutCombinedKaon{"nsigmaCutCombinedKaon", 3.0, "Combined nSigma cut for Kaon"}; // Combined + // Track selections + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; // PV Contriuibutor void init(o2::framework::InitContext&) { - ccdb->setURL("http://alice-ccdb.cern.ch"); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - uint64_t now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - ccdb->setCreatedNotAfter(now); - - AxisSpec vtxZAxis = {100, -20, 20}; - - std::vector centBinning = {0., 1., 5., 10., 20., 30., 40., 50., 70., 100.}; - AxisSpec centAxis = {centBinning, "V0M (%)"}; - std::vector ptBinning = {0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4., 5., 10., 20.}; - AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec centAxis = {binsCent, "V0M (%)"}; + AxisSpec dcaxyAxis = {cDCABins, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {cDCABins, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; + AxisSpec ptAxis = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec ptAxisQA = {binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec invMassAxis = {cInvMassBins, cInvMassStart, cInvMassEnd, "Invariant Mass (GeV/#it{c}^2)"}; + AxisSpec pidQAAxis = {cPIDBins, -cPIDQALimit, cPIDQALimit}; // Mass QA (quick check) - histos.add("phiinvmass", "Invariant mass of Phi", kTH1F, {{700, 0.8, 1.5, "Invariant Mass (GeV/#it{c}^2)"}}); - histos.add("phiinvmassME", "Invariant mass of Phi mixed event", kTH1F, {{700, 0.8, 1.5, "Invariant Mass (GeV/#it{c}^2)"}}); - histos.add("trk1pT", "pT distribution of track1", kTH1F, {{100, 0, 10, "#it{p}_{T} (GeV/#it{c})"}}); - histos.add("trk2pT", "pT distribution of track1", kTH1F, {{100, 0, 10, "#it{p}_{T} (GeV/#it{c})"}}); - histos.add("TOF_TPC_Map1", "TOF + TPC Combined PID for Kaons;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {{200, -10, 10}, {200, -10, 10}}}); - histos.add("TOF_Nsigma1", "TOF NSigma for Kaons;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2F, {{200, -10, 10}, {200, -10, 10}}}); - histos.add("TPC_Nsigma1", "TPC NSigma for Kaons;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2F, {{200, -10, 10}, {200, -10, 10}}}); - histos.add("TOF_TPC_Map2", "TOF + TPC Combined PID for Kaons;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2F, {{200, -10, 10}, {200, -10, 10}}}); - histos.add("TOF_Nsigma2", "TOF NSigma for Kaons;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2F, {{200, -10, 10}, {200, -10, 10}}}); - histos.add("TPC_Nsigma2", "TPC NSigma for Kaons;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2F, {{200, -10, 10}, {200, -10, 10}}}); + histos.add("phiinvmassDS", "Invariant mass of phi differnt sign", kTH1F, {invMassAxis}); + histos.add("phiinvmassLS", "Invariant mass of phi like sign", kTH1F, {invMassAxis}); + histos.add("phiinvmassME", "Invariant mass of phi mixed event", kTH1F, {invMassAxis}); + // DCA QA + histos.add("QAbefore/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAbefore/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("QAafter/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAafter/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); + // pT QA + histos.add("QAbefore/trkpT", "pT distribution of kaon track candidates", kTH1F, {ptAxis}); + histos.add("QAafter/trkpT", "pT distribution of kaon track candidates", kTH1F, {ptAxis}); + // PID QA before cuts + histos.add("QAbefore/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {pidQAAxis, pidQAAxis}}); + histos.add("QAbefore/TOF_Nsigma_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); + histos.add("QAbefore/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); + // PID QA after cuts + histos.add("QAafter/TOF_TPC_Mapka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTH2D, {pidQAAxis, pidQAAxis}}); + histos.add("QAafter/TOF_Nsigma_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); + histos.add("QAafter/TPC_Nsigmaka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH2D, {ptAxisQA, pidQAAxis}}); // 3d histogram - histos.add("h3phiinvmass", "Invariant mass of Phi", kTH3F, {{300, 0, 3000}, {100, 0.0f, 10.0f}, {700, 0.8, 1.5}}); - histos.add("h3phiinvmassME", "Invariant mass of Phi mixed event", kTH3F, {{300, 0, 3000}, {100, 0.0f, 10.0f}, {700, 0.8, 1.5}}); - - if (doprocessMC) { - histos.add("h3recophiinvmass", "Invariant mass of Reconstructed MC Phi", kTH3F, {{300, 0, 3000}, {100, 0.0f, 10.0f}, {700, 0.8, 1.5}}); - histos.add("truephipt", "pT distribution of True MC Phi", kTH1F, {{100, 0, 10, "#it{p}_{T} (GeV/#it{c})"}}); - histos.add("reconphipt", "pT distribution of Reconstructed MC Phi", kTH1F, {{100, 0, 10, "#it{p}_{T} (GeV/#it{c})"}}); - histos.add("reconphiinvmass", "Inv mass distribution of Reconstructed MC Phi", kTH1F, {{700, 0.8, 1.5, "Invariant Mass (GeV/#it{c}^2)"}}); + histos.add("h3phiinvmassDS", "Invariant mass of phi differnt sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3phiinvmassLS", "Invariant mass of phi same sign", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("h3phiinvmassME", "Invariant mass of phi mixed event", kTH3F, {centAxis, ptAxis, invMassAxis}); + + if (doprocessMCLight) { + // MC QA + histos.add("QAMCTrue/trkDCAxy", "DCAxy distribution of kaon track candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QAMCTrue/trkDCAz", "DCAz distribution of kaon track candidates", HistType::kTH1F, {dcazAxis}); + histos.add("h3Recphiinvmass", "Invariant mass of Reconstructed MC phi", kTH3F, {centAxis, ptAxis, invMassAxis}); + histos.add("phiGen", "pT distribution of True MC phi", kTH1F, {ptAxis}); + histos.add("phiRec", "pT distribution of Reconstructed MC phi", kTH1F, {ptAxis}); + histos.add("phiRecinvmass", "Inv mass distribution of Reconstructed MC Phi", kTH1F, {invMassAxis}); } + // Print output histograms statistics + LOG(info) << "Size of the histograms in phi analysis:"; + histos.print(); } double massKa = TDatabasePDG::Instance()->GetParticle(kKPlus)->Mass(); - template - void fillHistograms(const CollisionType& collision, const TracksType& dTracks) + template + bool trackCut(const TrackType track) + { + // basic track cuts + if (std::abs(track.pt()) < cMinPtcut) + return false; + if (std::abs(track.dcaXY()) > cMaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) + return false; + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; + + return true; + } + // PID selection tool + template + bool selectionPIDKaon(const T& candidate) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { + tpcPIDPassed = true; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cMaxTOFnSigmaKaon) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedKaon > 0) && (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa() < nsigmaCutCombinedKaon * nsigmaCutCombinedKaon)) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + return false; + } + + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) { TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - for (auto& [trk1, trk2] : combinations(CombinationsUpperIndexPolicy(dTracks, dTracks))) { - // Un-like sign pair only - if (trk1.sign() * trk2.sign() > 0) + for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { + // Full index policy is needed to consider all possible combinations + if (trk1.index() == trk2.index()) + continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. + //// Initialize variables + // Trk1: Kaon, Trk2: Kaon + // apply the track cut + if (!trackCut(trk1) || !trackCut(trk2)) continue; - // pT-dependent TPC PID cut - if ((trk1.pt() < 0.3) && (std::abs(trk1.tpcNSigmaKa()) > 6.0)) - continue; - if ((trk1.pt() >= 0.3) && (trk1.pt() < 0.4) && (std::abs(trk1.tpcNSigmaKa()) > 4.0)) - continue; - if ((trk1.pt() >= 0.4) && (std::abs(trk1.tpcNSigmaKa()) > 2.0)) - continue; + auto isTrk1hasTOF = trk1.hasTOF(); + auto isTrk2hasTOF = trk2.hasTOF(); + auto trk1ptKa = trk1.pt(); + auto trk1NSigmaKaTPC = trk1.tpcNSigmaKa(); + auto trk1NSigmaKaTOF = (isTrk1hasTOF) ? trk1.tofNSigmaKa() : -999.; + // auto trk2ptKa = trk2.pt(); + // auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); + // auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.; + + if constexpr (!IsMix) { + //// QA plots before the selection + // --- PID QA Kaon + histos.fill(HIST("QAbefore/TPC_Nsigmaka_all"), trk1ptKa, trk1NSigmaKaTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAbefore/TOF_Nsigma_all"), trk1ptKa, trk1NSigmaKaTOF); + histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all"), trk1NSigmaKaTOF, trk1NSigmaKaTPC); + } + histos.fill(HIST("QAbefore/trkpT"), trk1ptKa); + histos.fill(HIST("QAbefore/trkDCAxy"), trk1.dcaXY()); + histos.fill(HIST("QAbefore/trkDCAz"), trk1.dcaZ()); + } - if ((trk2.pt() < 0.3) && (std::abs(trk2.tpcNSigmaKa()) > 6.0)) + //// Apply the selection + if (cUseOnlyTOFTrackKa && (!isTrk1hasTOF || !isTrk2hasTOF)) continue; - if ((trk2.pt() >= 0.3) && (trk2.pt() < 0.4) && (std::abs(trk2.tpcNSigmaKa()) > 4.0)) - continue; - if ((trk2.pt() >= 0.4) && (std::abs(trk2.tpcNSigmaKa()) > 2.0)) + if (!selectionPIDKaon(trk1) || !selectionPIDKaon(trk2)) continue; - if (trk1.sign() > 0) { - // --- PID QA Kaons + - histos.fill(HIST("TOF_Nsigma1"), trk1.pt(), trk1.tofNSigmaKa()); - histos.fill(HIST("TPC_Nsigma1"), trk1.pt(), trk1.tpcNSigmaKa()); - histos.fill(HIST("TOF_TPC_Map1"), trk1.tofNSigmaKa(), trk1.tpcNSigmaKa()); - // --- PID QA Kaons - - histos.fill(HIST("TOF_Nsigma2"), trk2.pt(), trk2.tofNSigmaKa()); - histos.fill(HIST("TPC_Nsigma2"), trk2.pt(), trk2.tpcNSigmaKa()); - histos.fill(HIST("TOF_TPC_Map2"), trk2.tofNSigmaKa(), trk2.tpcNSigmaKa()); - } else { - // --- PID QA Kaons + - histos.fill(HIST("TOF_Nsigma1"), trk2.pt(), trk2.tofNSigmaKa()); - histos.fill(HIST("TPC_Nsigma1"), trk2.pt(), trk2.tpcNSigmaKa()); - histos.fill(HIST("TOF_TPC_Map1"), trk2.tofNSigmaKa(), trk2.tpcNSigmaKa()); - // --- PID QA Kaons - - histos.fill(HIST("TOF_Nsigma2"), trk1.pt(), trk1.tofNSigmaKa()); - histos.fill(HIST("TPC_Nsigma2"), trk1.pt(), trk1.tpcNSigmaKa()); - histos.fill(HIST("TOF_TPC_Map2"), trk1.tofNSigmaKa(), trk1.tpcNSigmaKa()); + if constexpr (!IsMix) { + //// QA plots after the selection + // --- PID QA Kaon + histos.fill(HIST("QAafter/TPC_Nsigmaka_all"), trk1ptKa, trk1NSigmaKaTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAafter/TOF_Nsigma_all"), trk1ptKa, trk1NSigmaKaTOF); + histos.fill(HIST("QAafter/TOF_TPC_Mapka_all"), trk1NSigmaKaTOF, trk1NSigmaKaTPC); + } + histos.fill(HIST("QAafter/trkpT"), trk1ptKa); + histos.fill(HIST("QAafter/trkDCAxy"), trk1.dcaXY()); + histos.fill(HIST("QAafter/trkDCAz"), trk1.dcaZ()); } - histos.fill(HIST("trk1pT"), trk1.pt()); - histos.fill(HIST("trk2pT"), trk2.pt()); - + //// Resonance reconstruction lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); lResonance = lDecayDaughter1 + lDecayDaughter2; - - if (lResonance.Rapidity() > 0.5 || lResonance.Rapidity() < -0.5) + // Rapidity cut + if (abs(lResonance.Rapidity()) > 0.5) continue; + //// Un-like sign pair only + if (trk1.sign() * trk2.sign() < 0) { + if constexpr (!IsMix) { + if (trk1.sign() > 0) { + histos.fill(HIST("phiinvmassDS"), lResonance.M()); + histos.fill(HIST("h3phiinvmassDS"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else { + } + } else { + histos.fill(HIST("phiinvmassME"), lResonance.M()); + histos.fill(HIST("h3phiinvmassME"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } - histos.fill(HIST("phiinvmass"), lResonance.M()); - histos.fill(HIST("h3phiinvmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); - - if constexpr (IsMC) { - if (abs(trk1.pdgCode()) != kKPlus || abs(trk2.pdgCode()) != kKPlus) // check if the tracks are kaons + // MC + if constexpr (IsMC) { + if (abs(trk1.pdgCode()) != kKPlus || abs(trk2.pdgCode()) != kKPlus) + continue; + if (trk1.motherId() != trk2.motherId()) // Same mother + continue; + if (abs(trk1.motherPDG()) != 333) + continue; + + // Track selection check. + histos.fill(HIST("QAMCTrue/trkDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QAMCTrue/trkDCAz"), trk2.dcaZ()); + + // MC histograms + histos.fill(HIST("phiRec"), lResonance.Pt()); + histos.fill(HIST("phiRecinvmass"), lResonance.M()); + histos.fill(HIST("h3Recphiinvmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } + } else { + if constexpr (!IsMix) continue; - auto mother1 = trk1.motherId(); - auto mother2 = trk2.motherId(); - if (mother1 == mother2) { // Same mother - if (trk1.motherPDG() == 333) { // Phi - histos.fill(HIST("reconphiinvmass"), lResonance.M()); - histos.fill(HIST("reconphipt"), lResonance.Pt()); - histos.fill(HIST("h3recophiinvmass"), collision.multV0M(), lResonance.Pt(), lResonance.M()); - } + if (trk1.sign() > 0) { + histos.fill(HIST("phiinvmassLS"), lResonance.M()); + histos.fill(HIST("h3phiinvmassLS"), collision.multV0M(), lResonance.Pt(), lResonance.M()); + } else { } } } } - void processData(aod::ResoCollisions& collisions, - aod::ResoTracks const& resotracks) + void processDataLight(aod::ResoCollision& collision, + aod::ResoTracks const& resotracks) { - LOGF(debug, "[DATA] Processing %d collisions", collisions.size()); - for (auto& collision : collisions) { - Partition selectedTracks = requireTOFPIDKaonCutInFilter() && (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks.bindTable(resotracks); - auto colTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colTracks); - } + // LOG(info) << "new collision, zvtx: " << collision.posZ(); + fillHistograms(collision, resotracks, resotracks); } - PROCESS_SWITCH(phianalysis, processData, "Process Event for data", true); + PROCESS_SWITCH(phianalysis, processDataLight, "Process Event for data", false); - void processMC(aod::ResoCollisions& collisions, - soa::Join const& resotracks, aod::McParticles const& mcParticles) + void processMCLight(aod::ResoCollision& collision, + soa::Join const& resotracks, aod::McParticles const& mcParticles) { - LOGF(debug, "[MC] MC events: %d", collisions.size()); - for (auto& collision : collisions) { - Partition> selectedTracks = requireTOFPIDKaonCutInFilter() && (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks.bindTable(resotracks); - auto colTracks = selectedTracks->sliceByCached(aod::resodaughter::resoCollisionId, collision.globalIndex(), cache); - fillHistograms(collision, colTracks); - } + fillHistograms(collision, resotracks, resotracks); + } + PROCESS_SWITCH(phianalysis, processMCLight, "Process Event for MC", false); - // Not related to the real collisions - for (auto& part : mcParticles) { // loop over all MC particles - if (abs(part.pdgCode()) == 333) { // Phi - if (part.y() > 0.5 || part.y() < -0.5) { // rapidity cut - continue; - } - bool isDecaytoKaons = true; - for (auto& dau : part.daughters_as()) { - if (abs(dau.pdgCode()) != kKPlus) { // Decay to Kaons - isDecaytoKaons = false; - break; - } - } - if (!isDecaytoKaons) - continue; - histos.fill(HIST("truephipt"), part.pt()); + void processMCTrue(aod::ResoMCParents& resoParents) + { + for (auto& part : resoParents) { // loop over all pre-filtered MC particles + if (abs(part.pdgCode()) != 333) // phi(0) + continue; + if (abs(part.y()) > 0.5) { // rapidity cut + continue; + } + if (abs(part.daughterPDG1()) != kKPlus || abs(part.daughterPDG2()) != kKPlus) { // At least one decay to Kaon + continue; } + histos.fill(HIST("phiGen"), part.pt()); } } - PROCESS_SWITCH(phianalysis, processMC, "Process Event for MC", false); + PROCESS_SWITCH(phianalysis, processMCTrue, "Process Event for MC", false); // Processing Event Mixing - using BinningTypeVetZTPCtemp = ColumnBinningPolicy; - BinningTypeVetZTPCtemp colBinning{{CfgVtxBins, CfgMultBins}, true}; - void processME(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) + using BinningTypeVtxZT0M = ColumnBinningPolicy; + void processMELight(o2::aod::ResoCollisions& collisions, aod::ResoTracks const& resotracks) { - LOGF(debug, "Event Mixing Started"); auto tracksTuple = std::make_tuple(resotracks); - SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + BinningTypeVtxZT0M colBinning{{CfgVtxBins, CfgMultBins}, true}; + SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; for (auto& [collision1, tracks1, collision2, tracks2] : pairs) { - Partition selectedTracks1 = requireTOFPIDKaonCutInFilter() && (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks1.bindTable(tracks1); - - Partition selectedTracks2 = requireTOFPIDKaonCutInFilter() && (o2::aod::track::pt > static_cast(cMinPtcut)) && (nabs(o2::aod::track::dcaZ) > static_cast(cMinDCAzToPVcut)) && (nabs(o2::aod::track::dcaZ) < static_cast(cMaxDCAzToPVcut)) && (nabs(o2::aod::track::dcaXY) < static_cast(cMaxDCArToPVcut)); // Basic DCA cuts - selectedTracks2.bindTable(tracks2); - - for (auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(selectedTracks1, selectedTracks2))) { - // Un-like sign pair only - if (trk1.sign() * trk2.sign() > 0) - continue; - if ((trk1.pt() < 0.3) && (std::abs(trk1.tpcNSigmaKa()) > 6.0)) - continue; - if ((trk1.pt() >= 0.3) && (trk1.pt() < 0.4) && (std::abs(trk1.tpcNSigmaKa()) > 4.0)) - continue; - if ((trk1.pt() >= 0.4) && (std::abs(trk1.tpcNSigmaKa()) > 2.0)) - continue; - - if ((trk2.pt() < 0.3) && (std::abs(trk2.tpcNSigmaKa()) > 6.0)) - continue; - if ((trk2.pt() >= 0.3) && (trk2.pt() < 0.4) && (std::abs(trk2.tpcNSigmaKa()) > 4.0)) - continue; - if ((trk2.pt() >= 0.4) && (std::abs(trk2.tpcNSigmaKa()) > 2.0)) - continue; - - lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); - lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); - lResonance = lDecayDaughter1 + lDecayDaughter2; - - if (lResonance.Rapidity() > 0.5 || lResonance.Rapidity() < -0.5) - continue; - - histos.fill(HIST("phiinvmassME"), lResonance.M()); - histos.fill(HIST("h3phiinvmassME"), collision1.multV0M(), lResonance.Pt(), lResonance.M()); - } + fillHistograms(collision1, tracks1, tracks2); } }; - PROCESS_SWITCH(phianalysis, processME, "Process EventMixing", false); + PROCESS_SWITCH(phianalysis, processMELight, "Process EventMixing light without partition", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/phianalysisrun3.cxx b/PWGLF/Tasks/phianalysisrun3.cxx index 5b321a497a6..1cdf06bf584 100644 --- a/PWGLF/Tasks/phianalysisrun3.cxx +++ b/PWGLF/Tasks/phianalysisrun3.cxx @@ -183,7 +183,7 @@ struct phianalysisrun3 { using TrackCandidates = soa::Filtered>; - using EventCandidatesMC = soa::Join; + using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Filtered>; @@ -196,13 +196,10 @@ struct phianalysisrun3 { // BinningType binningOnPositions{{axisVertex, axisMultiplicityClass}, true}; using BinningType = ColumnBinningPolicy; - BinningType binningOnPositions{{axisVertex, axisMultiplicityClass}, true}; // using BinningType = ColumnBinningPolicy; // BinningType binningOnPositions{{axisVertex, axisMultiplicity}, true}; - SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, &cache}; - void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { if (!collision.sel8()) { @@ -247,6 +244,9 @@ struct phianalysisrun3 { PROCESS_SWITCH(phianalysisrun3, processSameEvent, "Process Same event", false); void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) { + auto tracksTuple = std::make_tuple(tracks); + BinningType binningOnPositions{{axisVertex, axisMultiplicityClass}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; for (auto& [c1, tracks1, c2, tracks2] : pair) { if (!c1.sel8()) { continue; @@ -317,7 +317,10 @@ struct phianalysisrun3 { PROCESS_SWITCH(phianalysisrun3, processGen, "Process Generated", false); void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const& mcParticles, aod::McCollisions const& mcCollisions) { - if (std::abs(collision.mcCollision().posZ()) > cfgCutVertex) { + if (!collision.has_mcCollision()) { + return; + } + if (std::abs(collision.mcCollision().posZ()) > cfgCutVertex || !collision.sel8()) { return; } histos.fill(HIST("hMC"), 1.5); diff --git a/PWGLF/Tasks/rhoanalysis.cxx b/PWGLF/Tasks/rhoanalysis.cxx new file mode 100644 index 00000000000..c928826a142 --- /dev/null +++ b/PWGLF/Tasks/rhoanalysis.cxx @@ -0,0 +1,386 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file rhoanalysis.cxx +/// \brief Reconstruction of track-track decay resonance candidates +/// +/// +/// \author Nasir Mehdi Malik + +#include +#include +#include + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/DataProcessorSpec.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/RecoDecay.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "RecoDecay.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct rhoanalysis { + SliceCache cache; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + // track + Configurable cfgCutPT{"cfgCutPT", 0.2, "PT cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; + Configurable nsigmaCutTOF{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmaCutCombined{"nsigmaCutCombined", 3.0, "Value of the TOF Nsigma cut"}; + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; + Configurable cMultiplicityType{"cMultiplicityType", 1, " Set 1 For multTPC, 2 for MultFT0M, 3for MultFV0M"}; + + Configurable isUnlike{"isUnlike", false, "Use unlike charged tracks"}; + Configurable isLike{"isLike", false, "use same charge tracks"}; + Configurable isMixed{"isMixed", false, "Use mixed events"}; + Configurable isMC{"isMC", false, "Run MC"}; + + void init(o2::framework::InitContext&) + { + AxisSpec ptAxis = {100, 0., 10., "#it{p}_{T} (GeV/c)"}; + AxisSpec dcaxyAxis = {100, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; + AxisSpec dcazAxis = {100, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; + + AxisSpec multAxis = {1000, 0, 1000, "mult"}; + AxisSpec ptAxiss = {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec invmassAxis = {320, 0.2, 1.8, "{M}_{#pi #pi}} (GeV/#it{c}^2)"}; + AxisSpec rapidityAxis = {100, -1.0, 1.0, "y"}; + if (isUnlike) { + histos.add("hmultTPC", "Multipicity TPC", kTH1F, {multAxis}); + histos.add("hmultFT0M", "Multipicity FT0M", kTH1F, {multAxis}); + histos.add("hmultFV0M", "Multipicity FV0M", kTH1F, {multAxis}); + histos.add("hmultTracklets", "Multipicity tracklets", kTH1F, {multAxis}); + + histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); + histos.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{1000, 0.0f, 1000.0f}}); + histos.add("ptpi", "pi pT distribution ", kTH1F, {ptAxis}); + histos.add("dcaXY", "dcaXY ", kTH1F, {dcaxyAxis}); + histos.add("dcaZ", "dcaZ ", kTH1F, {dcazAxis}); + histos.add("hNsigmaPionTPC", "NsigmaPion TPC distribution", kTH1F, {{100, -10.0f, 10.0f}}); + + histos.add("hNsigmaPionTPCvspT_beforecut", "NsigmaPion TPC distribution before cut Vs pT", kTH2F, {ptAxis, {100, -10.0f, 10.0f}}); + histos.add("hNsigmaPionTPCvspT_aftercut", "NsigmaPion TPC distribution after cuts Vs pT", kTH2F, {ptAxis, {100, -10.0f, 10.0f}}); + histos.add("hNsigmaPionTOF", "NsigmaPion TOF distribution", kTH1F, {{100, -10.0f, 10.0f}}); + + histos.add("fTPCSignal", "TPCSignal;p_{TPC} (GeV/c);dE/dx", {HistType::kTH2F, {{1000, 0.0f, 6.0f}, {2000, -100.f, 1000.f}}}); + + histos.add("hrhosame", "Invariant mass of rho", kTHnSparseD, {invmassAxis, ptAxiss, multAxis, rapidityAxis}); + } + + if (isLike) { + histos.add("hrholike", "Invariant mass of rho", kTHnSparseD, {invmassAxis, ptAxiss, multAxis, rapidityAxis}); + } + if (isMixed) { + histos.add("hrhomassmixed", "Invariant mass of rho mixed event", kTHnSparseD, {invmassAxis, ptAxiss, multAxis, rapidityAxis}); + } + + if (isMC) { + + histos.add("hNsigmaPionTPCvspT", "NsigmaPion TPC distribution Vs pT", kTH2F, {ptAxis, {100, -10.0f, 10.0f}}); + histos.add("hrhomassMc", "Invariant mass of rho mc", kTHnSparseD, {invmassAxis, ptAxiss, multAxis, rapidityAxis}); + + histos.add("hrhoGen", "Gen mass of rho mc", kTHnSparseD, {ptAxiss, {30, 100, 130, "pdg code"}, rapidityAxis}); + } + } + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgCutVertex); + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta) && (nabs(aod::track::pt) > cfgCutPT); + Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + + using TrackPi = soa::Filtered>; + using Event = soa::Filtered>; + std::array pvec0; + std::array pvec1; + + Service Ipdg; + + double mass{0.}; + double recMass{0.}; + double pT{0.}; + double rapidity; + void processSame(Event::iterator const& events, TrackPi const& tracks) + { + + histos.fill(HIST("hmultTPC"), events.multTPC()); + histos.fill(HIST("hmultFT0M"), events.multFT0M()); + histos.fill(HIST("hmultFV0M"), events.multFV0M()); + histos.fill(HIST("hmultTracklets"), events.multTracklets()); + histos.fill(HIST("hNcontributor"), events.numContrib()); + histos.fill(HIST("hVtxZ"), events.posZ()); + float multiplicity = 0; + if (cMultiplicityType == 1) + multiplicity = events.multTPC(); + else if (cMultiplicityType == 2) + multiplicity = events.multFT0M(); + else + multiplicity = events.multFV0M(); + + float massPiplus = Ipdg->Mass(kPiPlus); + float massPiminus = Ipdg->Mass(kPiMinus); + + for (auto& track1 : tracks) { + auto _px1 = track1.px(); + auto _py1 = track1.py(); + auto _pz1 = track1.pz(); + auto _pt1 = track1.pt(); + + histos.fill(HIST("hNsigmaPionTPCvspT_beforecut"), _pt1, track1.tpcNSigmaPi()); + + if (abs(track1.tpcNSigmaPi()) > nsigmaCutCombined) + continue; + histos.fill(HIST("hNsigmaPionTPCvspT_aftercut"), _pt1, track1.tpcNSigmaPi()); + histos.fill(HIST("ptpi"), _pt1); + histos.fill(HIST("dcaXY"), track1.dcaXY()); + histos.fill(HIST("dcaZ"), track1.dcaZ()); + histos.fill(HIST("hNsigmaPionTPC"), track1.tpcNSigmaPi()); + // histos.fill(HIST("hNsigmaPionTOF"), track1.tofNSigmaPi()); + + for (auto& track2 : tracks) { + if (track1.sign() * track2.sign() > 0) + continue; + auto _px2 = track2.px(); + auto _py2 = track2.py(); + auto _pz2 = track2.pz(); + + if (abs(track2.tpcNSigmaPi()) > nsigmaCutCombined) + continue; + + pvec0 = std::array{_px1, _py1, _pz1}; + pvec1 = std::array{_px2, _py2, _pz2}; + + auto arrMom = std::array{pvec0, pvec1}; + mass = RecoDecay::m(arrMom, std::array{massPiplus, massPiminus}); + pT = RecoDecay::pt(std::array{_px1 + _px2, _py1 + _py2}); + + rapidity = RecoDecay::y(std::array{_px1 + _px2, _py1 + _py2, _pz1 + _pz2}, mass); + if (std::abs(rapidity) >= 0.5) + continue; + + histos.fill(HIST("hrhosame"), mass, pT, multiplicity, rapidity); + } + } + } + PROCESS_SWITCH(rhoanalysis, processSame, "Process Same event", isUnlike); + + void processlike(Event::iterator const& events, TrackPi const& tracks) + { + + float multiplicity = 0; + if (cMultiplicityType == 1) + multiplicity = events.multTPC(); + else if (cMultiplicityType == 2) + multiplicity = events.multFT0M(); + else + multiplicity = events.multFV0M(); + + float massPiplus = Ipdg->Mass(kPiPlus); + float massPiminus = Ipdg->Mass(kPiMinus); + + for (auto& track1 : tracks) { + auto _px1 = track1.px(); + auto _py1 = track1.py(); + auto _pz1 = track1.pz(); + + if (abs(track1.tpcNSigmaPi()) > nsigmaCutCombined) + continue; + + for (auto& track2 : tracks) { + if (track1.sign() * track2.sign() < 0) + continue; + auto _px2 = track2.px(); + auto _py2 = track2.py(); + auto _pz2 = track2.pz(); + + if (abs(track2.tpcNSigmaPi()) > nsigmaCutCombined) + continue; + + pvec0 = std::array{_px1, _py1, _pz1}; + pvec1 = std::array{_px2, _py2, _pz2}; + + auto arrMom = std::array{pvec0, pvec1}; + mass = RecoDecay::m(arrMom, std::array{massPiplus, massPiminus}); + pT = RecoDecay::pt(std::array{_px1 + _px2, _py1 + _py2}); + + rapidity = RecoDecay::y(std::array{_px1 + _px2, _py1 + _py2, _pz1 + _pz2}, mass); + if (std::abs(rapidity) >= 0.5) + continue; + + histos.fill(HIST("hrholike"), mass, pT, multiplicity, rapidity); + } + } + } + + PROCESS_SWITCH(rhoanalysis, processlike, "Process Same event", isLike); + + ConfigurableAxis axisVertex{"axisVertex", {VARIABLE_WIDTH, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12}, "vertex axis for bin"}; + + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0.0, 2.75, 5.25, 7.75, 12.75, 17.75, 22.75, 27.75, 32.75, 37.75, 42.75, 47.75, 52.75, 57.75, 62.75, 67.75, 72.75, 77.75, 82.75, 87.75, 92.75, 97.75, 102.75, 107.75, 112.75, 117.75, 122.75, 127.75, 132.75, 137.75, 142.75, 147.75, 152.75, 157.75, 162.75, 167.75, 172.75, 177.75, 182.75, 187.75, 192.75, 197.75, 202.75, 207.75, 212.75, 217.75, 222.75, 227.75, 232.75, 237.75, 242.75, 247.75, 252.75, 257.75, 262.75, 267.75, 272.75, 277.75, 282.75, 287.75, 292.75, 297.75, 302.75, 307.75, 312.75, 317.75, 322.75, 327.75, 332.75, 337.75, 342.75, 347.75, 352.75, 357.75, 362.75, 367.75, 372.75, 377.75, 382.75, 387.75, 392.75, 397.75, 402.75, 407.75, 412.75, 417.75, 422.75, 427.75, 432.75, 437.75, 442.75, 447.75, 452.75, 457.75, 462.75, 467.75, 472.75, 477.75, 482.75, 487.75, 492.75, 497.75, 502.75, 507.75, 512.75, 517.75, 522.75, 527.75, 532.75, 537.75, 542.75, 547.75, 552.75, 557.75, 562.75, 567.75, 572.75, 577.75, 582.75, 587.75, 592.75, 597.75, 602.75, 607.75, 612.75, 617.75, 622.75, 627.75, 632.75, 637.75, 642.75, 647.75, 652.75, 657.75, 662.75, 667.75, 672.75, 677.75, 682.75, 687.75, 692.75, 697.75, 702.75, 707.75, 712.75, 717.75, 722.75, 727.75, 732.75, 737.75, 742.75, 747.75, 752.75, 757.75, 762.75, 767.75, 772.75, 777.75, 782.75, 787.75, 792.75, 797.75, 802.75, 807.75, 812.75, 817.75, 822.75, 827.75, 832.75, 837.75, 842.75, 847.75, 852.75, 857.75, 862.75, 867.75, 872.75, 877.75, 882.75, 887.75, 892.75, 897.75, 902.75, 907.75, 912.75, 917.75, 922.75, 927.75, 932.75, 937.75, 942.75, 947.75, 952.75, 957.75, 962.75, 967.75, 972.75, 977.75, 982.75, 987.75, 992.75, 997.75, 1002.75, 1007.75, 1012.75, 1017.75, 1022.75, 1027.75, 1032.75, 1037.75, 1042.75, 1047.75, 1052.75}, "multiplicity axis for histograms"}; + + using BinningType = ColumnBinningPolicy; + + void processMixedEvent(Event const& events, TrackPi const& tracks) + { + BinningType binningOnPositions{{axisVertex, axisMultiplicity}, true}; // true is for 'ignore overflows' (true by default) + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, &cache}; + + for (auto& [c1, tracks1, c2, tracks2] : pair) { + + float multiplicity = 0; + if (cMultiplicityType == 1) + multiplicity = c1.multTPC(); + else if (cMultiplicityType == 2) + multiplicity = c1.multFT0M(); + else + multiplicity = c1.multFV0M(); + + for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + + if (track1.sign() * track2.sign() > 0) + continue; + + if (abs(track1.tpcNSigmaPi()) > nsigmaCutCombined) + continue; + if (abs(track2.tpcNSigmaPi()) > nsigmaCutCombined) + continue; + + auto _px1 = track1.px(); + auto _py1 = track1.py(); + auto _pz1 = track1.pz(); + + auto _px2 = track2.px(); + auto _py2 = track2.py(); + auto _pz2 = track2.pz(); + + pvec0 = std::array{_px1, _py1, _pz1}; + pvec1 = std::array{_px2, _py2, _pz2}; + float massPi = Ipdg->Mass(kPiPlus); + auto arrMom = std::array{pvec0, pvec1}; + mass = RecoDecay::m(arrMom, std::array{massPi, massPi}); + pT = RecoDecay::pt(std::array{_px1 + _px2, _py1 + _py2}); + + rapidity = RecoDecay::y(std::array{_px1 + _px2, _py1 + _py2, _pz1 + _pz2}, mass); + if (std::abs(rapidity) >= 0.5) + continue; + + histos.fill(HIST("hrhomassmixed"), mass, pT, multiplicity, rapidity); + } + } + } + PROCESS_SWITCH(rhoanalysis, processMixedEvent, "Process Mixed event", isMixed.kind); + + using EventMC = soa::Join; + using TrackMC = soa::Filtered>; + void processMC(EventMC::iterator const& events, TrackMC const& tracks, aod::McParticles const& mcParticles, aod::McCollisions const& mcCollisions) + { + float massPi = Ipdg->Mass(kPiPlus); + float multiplicity = 0; + if (cMultiplicityType == 1) + multiplicity = events.multTPC(); + else if (cMultiplicityType == 2) + multiplicity = events.multFT0M(); + else + multiplicity = events.multFV0M(); + + if (std::abs(events.mcCollision().posZ()) > cfgCutVertex) { + return; + } + for (auto track1 : tracks) { + histos.fill(HIST("hNsigmaPionTPCvspT"), track1.pt(), track1.tpcNSigmaPi()); + if (abs(track1.tpcNSigmaPi()) > nsigmaCutCombined) + continue; + for (auto track2 : tracks) { + + if (abs(track2.tpcNSigmaPi()) > nsigmaCutCombined) + continue; + + if (track1.sign() * track2.sign() > 0) { + continue; + } + const auto mctrack1 = track1.mcParticle(); + const auto mctrack2 = track2.mcParticle(); + int track1PDG = std::abs(mctrack1.pdgCode()); + int track2PDG = std::abs(mctrack2.pdgCode()); + + if (!(track1PDG == 211 && track2PDG == 211)) { + continue; + } + for (auto& mothertrack1 : mctrack1.mothers_as()) { + for (auto& mothertrack2 : mctrack2.mothers_as()) { + if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) + continue; + + if (std::abs(mothertrack1.y()) > 0.5) { + continue; + } + + if (std::abs(mothertrack1.pdgCode()) != 113) { + continue; + } // + + pvec0 = std::array{track1.px(), track1.py(), track1.pz()}; + pvec1 = std::array{track2.px(), track2.py(), track2.pz()}; + auto arrMomrec = std::array{pvec0, pvec1}; + recMass = RecoDecay::m(arrMomrec, std::array{massPi, massPi}); + histos.fill(HIST("hrhomassMc"), recMass, mothertrack1.pt(), multiplicity, mothertrack1.y()); + } + } + } + } + } + PROCESS_SWITCH(rhoanalysis, processMC, "Process mc reconstructed", isMC); + void processGen(aod::McCollision const& mcCollision, aod::McParticles& mcParticles) + { + + if (std::abs(mcCollision.posZ()) > cfgCutVertex) + return; + for (auto& mcParticle : mcParticles) { + + if (std::abs(mcParticle.y()) > 0.5) + continue; + + if (std::abs(mcParticle.pdgCode()) != 113) + continue; + + auto kDaughters = mcParticle.daughters_as(); + + if (kDaughters.size() != 2) + continue; + + for (auto kCurrentDaughter : kDaughters) { + + if (!kCurrentDaughter.isPhysicalPrimary()) + continue; + + if ((kCurrentDaughter.pdgCode() == 211 || kCurrentDaughter.pdgCode() == -211)) { + + histos.fill(HIST("hrhoGen"), mcParticle.pt(), mcParticle.pdgCode(), mcParticle.y()); + } + } + } + } + PROCESS_SWITCH(rhoanalysis, processGen, "Process Generated", isMC.kind); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"lf-rhoanalysis"})}; +} diff --git a/PWGLF/Tasks/rsnanalysisTHnSparse.cxx b/PWGLF/Tasks/rsnanalysisTHnSparse.cxx new file mode 100644 index 00000000000..327772f0f42 --- /dev/null +++ b/PWGLF/Tasks/rsnanalysisTHnSparse.cxx @@ -0,0 +1,175 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \author Veronika Barbasova (veronika.barbasova@cern.ch) +/// \since October 12, 2023 + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" + +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" + +#include +#include "ReconstructionDataFormats/PID.h" +#include "Framework/ASoAHelpers.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct rsnanalysisTHnSparse { + + SliceCache cache; + + Configurable test{"test", false, "Running in test mode."}; + Configurable refresh{"print-refresh", 0, "Freqency of print event information."}; + Configurable refresh_index{"print-refresh-index", 1, "Freqency of print event information index."}; + Configurable tpcnSigma1{"tpcnSigma1", 3.0f, "TPC NSigma cut of the first particle."}; + Configurable tpcnSigma2{"tpcnSigma2", 3.0f, "TPC NSigma cut of the second particle."}; + Configurable dauther1{"dauther1", 3, "Particle type of the first dauther according to ReconstructionDataFormats/PID.h (Default = Kaon)"}; + Configurable dauther2{"dauther", 3, "Particle type of the second dauther according to ReconstructionDataFormats/PID.h (Default = Kaon)"}; + Configurable vertexfilter{"vertex-filter", 10.0f, "Z vertex range."}; + + ConfigurableAxis invaxis{"invAxis", {200, 0.97, 1.1}, "Invariant mass axis binning."}; + ConfigurableAxis ptaxis{"ptAxis", {20, 0., 20.}, "Pt axis binning."}; + ConfigurableAxis maxis{"mAxis", {200, 0., 2000.}, "Multiplicity axis binning."}; + ConfigurableAxis nsigmaaxis{"nsigma-axis", {300, -15., 15.}, "NSigma axis binning."}; + + HistogramRegistry registry{"registry", + {{"hNsigmaPos", "hNsigmaPos", {HistType::kTH1F, {nsigmaaxis}}}, + {"hNsigmaNeg", "hNsigmaNeg", {HistType::kTH1F, {nsigmaaxis}}}}}; + + // defined in DataFormats/Reconstruction/include/ReconstructionDataFormats/PID.h + float mass1 = o2::track::PID::getMass(dauther1); + float mass2 = o2::track::PID::getMass(dauther2); + + float multiplicity; + + Filter eventFilter = (o2::aod::evsel::sel8 == true); + Filter vtxFilter = (nabs(o2::aod::collision::posZ) < vertexfilter); + + using EventCandidates = soa::Filtered>; + using EventCandidate = EventCandidates::iterator; + using TrackCandidates = soa::Join; + + Partition positive = (aod::track::signed1Pt > 0.0f) && (nabs(o2::aod::pidtpc::tpcNSigmaKa) < tpcnSigma1); + Partition negative = (aod::track::signed1Pt < 0.0f) && (nabs(o2::aod::pidtpc::tpcNSigmaKa) < tpcnSigma2); + + TLorentzVector d1, d2, mother; + + void init(o2::framework::InitContext&) + { + if (test) + LOGF(info, "Running test"); + + AxisSpec invAxis = {invaxis, "Inv. mass (GeV/c^{2})", "im"}; + AxisSpec ptAxis = {ptaxis, "p_{T} (GeV/c)", "pt"}; + AxisSpec mAxis = {maxis, "N", "m"}; + HistogramConfigSpec Hist({HistType::kTHnSparseF, {invAxis, ptAxis, mAxis}}); + registry.add("unlike", "Unlike", Hist); + registry.add("likep", "Likep", Hist); + registry.add("liken", "Liken", Hist); + } + + template + bool selectedTrack(const T& track) + { + if (!track.isPrimaryTrack()) + return false; + return true; + } + + template + bool selectedPair(TLorentzVector& mother, const T& track1, const T& track2) + { + d1.SetXYZM(track1.px(), track1.py(), track1.pz(), mass1); + d2.SetXYZM(track2.px(), track2.py(), track2.pz(), mass2); + mother = d1 + d2; + + return true; + } + + void process(EventCandidate const& collision, TrackCandidates const& tracks) + { + if (test && collision.globalIndex() != 1) + return; + + auto posDauthers = positive->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negDauthers = negative->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + + if (collision.globalIndex() == 0) { + if (test) { + LOGF(info, "BAD pos=%lld neg=%lld, Z vertex position: %f [cm], %d, mult:%f.0", posDauthers.size(), negDauthers.size(), collision.posZ(), + collision.globalIndex(), multiplicity); + } + return; + } + + multiplicity = collision.multFT0A() + collision.multFT0C(); + + if (refresh > 0 && collision.globalIndex() % refresh == refresh_index) + LOGF(info, "pos=%lld neg=%lld, Z vertex position: %f [cm], %d, mult:%f.0", posDauthers.size(), negDauthers.size(), collision.posZ(), + collision.globalIndex(), multiplicity); + + for (const auto& trk : posDauthers) { + registry.fill(HIST("hNsigmaPos"), trk.tpcNSigmaKa()); + } + + for (const auto& trk : negDauthers) { + registry.fill(HIST("hNsigmaNeg"), trk.tpcNSigmaKa()); + } + + for (auto& [track1, track2] : combinations(o2::soa::CombinationsUpperIndexPolicy(posDauthers, negDauthers))) { + + if (!selectedTrack(track1)) + continue; + if (!selectedTrack(track2)) + continue; + + if (!selectedPair(mother, track1, track2)) + continue; + registry.fill(HIST("unlike"), mother.Mag(), mother.Pt(), multiplicity); + } + + for (auto& [track1, track2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(posDauthers, posDauthers))) { + + if (!selectedTrack(track1)) + continue; + if (!selectedTrack(track2)) + continue; + + if (!selectedPair(mother, track1, track2)) + continue; + registry.fill(HIST("likep"), mother.Mag(), mother.Pt(), multiplicity); + } + + for (auto& [track1, track2] : combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(negDauthers, negDauthers))) { + + if (!selectedTrack(track1)) + continue; + if (!selectedTrack(track2)) + continue; + + if (!selectedPair(mother, track1, track2)) + continue; + registry.fill(HIST("liken"), mother.Mag(), mother.Pt(), multiplicity); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/spectraCharged.cxx b/PWGLF/Tasks/spectraCharged.cxx index 69c392c1194..23e149ed695 100644 --- a/PWGLF/Tasks/spectraCharged.cxx +++ b/PWGLF/Tasks/spectraCharged.cxx @@ -33,7 +33,7 @@ using namespace o2::framework; struct chargedSpectra { HistogramRegistry histos; - Service pdg; + Service pdg; // task settings that can be steered via hyperloop Configurable isRun3{"isRun3", true, "is Run3 dataset"}; diff --git a/PWGLF/Tasks/spectraTOF.cxx b/PWGLF/Tasks/spectraTOF.cxx index 06ed0e6a80e..e797c9bf919 100644 --- a/PWGLF/Tasks/spectraTOF.cxx +++ b/PWGLF/Tasks/spectraTOF.cxx @@ -31,7 +31,7 @@ #include "Framework/StaticFor.h" #include "Common/Core/TrackSelectionDefaults.h" #include "PWGLF/DataModel/LFParticleIdentification.h" -#include "spectraTOF.h" +#include "PWGLF/DataModel/spectraTOF.h" #include "TPDGCode.h" @@ -42,10 +42,11 @@ using namespace o2::framework::expressions; // Spectra task struct tofSpectra { - Configurable cfgNSigmaCut{"cfgNSigmaCut", 3, "Value of the Nsigma cut"}; Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; - Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable cfgCutEtaMax{"cfgCutEtaMax", 0.8f, "Max eta range for tracks"}; + Configurable cfgCutEtaMin{"cfgCutEtaMin", -0.8f, "Min eta range for tracks"}; Configurable cfgCutY{"cfgCutY", 0.5f, "Y range for tracks"}; + Configurable cfgINELCut{"cfgINELCut", 0, "INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1"}; Configurable enableDcaGoodEvents{"enableDcaGoodEvents", true, "Enables the MC plots with the correct match between data and MC"}; Configurable enableTrackCutHistograms{"enableTrackCutHistograms", true, "Enables track cut histograms, before and after the cut"}; Configurable enableDeltaHistograms{"enableDeltaHistograms", true, "Enables the delta TPC and TOF histograms"}; @@ -55,6 +56,7 @@ struct tofSpectra { Configurable requireNoTrd{"requireNoTrd", false, "Require tracks without TRD"}; Configurable selectEvTime{"selectEvTime", 0, "Select event time flags; 0: any event time, 1: isEvTimeDefined, 2: IsEvTimeTOF, 3: IsEvTimeT0AC, 4: IsEvTimeTOFT0AV, 5: NOT isEvTimeDefined"}; ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0}, "Binning of the pT axis"}; + ConfigurableAxis binsEta{"binsEta", {100, -1, 1}, "Binning of the eta axis"}; ConfigurableAxis binsnsigmaTPC{"binsnsigmaTPC", {200, -10, 10}, "Binning of the nsigmaTPC axis"}; ConfigurableAxis binsnsigmaTOF{"binsnsigmaTOF", {200, -10, 10}, "Binning of the nsigmaTOF axis"}; ConfigurableAxis binsdeltaTPC{"binsdeltaTPC", {500, -1000, 1000}, "Binning of the nsigmaTPC axis"}; @@ -62,21 +64,10 @@ struct tofSpectra { ConfigurableAxis binsDca{"binsDca", {VARIABLE_WIDTH, -3.0, -2.95, -2.9, -2.85, -2.8, -2.75, -2.7, -2.65, -2.6, -2.55, -2.5, -2.45, -2.4, -2.35, -2.3, -2.25, -2.2, -2.15, -2.1, -2.05, -2.0, -1.975, -1.95, -1.925, -1.9, -1.875, -1.85, -1.825, -1.8, -1.775, -1.75, -1.725, -1.7, -1.675, -1.65, -1.625, -1.6, -1.575, -1.55, -1.525, -1.5, -1.475, -1.45, -1.425, -1.4, -1.375, -1.35, -1.325, -1.3, -1.275, -1.25, -1.225, -1.2, -1.175, -1.15, -1.125, -1.1, -1.075, -1.05, -1.025, -1.0, -0.99, -0.98, -0.97, -0.96, -0.95, -0.94, -0.93, -0.92, -0.91, -0.9, -0.89, -0.88, -0.87, -0.86, -0.85, -0.84, -0.83, -0.82, -0.81, -0.8, -0.79, -0.78, -0.77, -0.76, -0.75, -0.74, -0.73, -0.72, -0.71, -0.7, -0.69, -0.68, -0.67, -0.66, -0.65, -0.64, -0.63, -0.62, -0.61, -0.6, -0.59, -0.58, -0.57, -0.56, -0.55, -0.54, -0.53, -0.52, -0.51, -0.5, -0.49, -0.48, -0.47, -0.46, -0.45, -0.44, -0.43, -0.42, -0.41, -0.4, -0.396, -0.392, -0.388, -0.384, -0.38, -0.376, -0.372, -0.368, -0.364, -0.36, -0.356, -0.352, -0.348, -0.344, -0.34, -0.336, -0.332, -0.328, -0.324, -0.32, -0.316, -0.312, -0.308, -0.304, -0.3, -0.296, -0.292, -0.288, -0.284, -0.28, -0.276, -0.272, -0.268, -0.264, -0.26, -0.256, -0.252, -0.248, -0.244, -0.24, -0.236, -0.232, -0.228, -0.224, -0.22, -0.216, -0.212, -0.208, -0.204, -0.2, -0.198, -0.196, -0.194, -0.192, -0.19, -0.188, -0.186, -0.184, -0.182, -0.18, -0.178, -0.176, -0.174, -0.172, -0.17, -0.168, -0.166, -0.164, -0.162, -0.16, -0.158, -0.156, -0.154, -0.152, -0.15, -0.148, -0.146, -0.144, -0.142, -0.14, -0.138, -0.136, -0.134, -0.132, -0.13, -0.128, -0.126, -0.124, -0.122, -0.12, -0.118, -0.116, -0.114, -0.112, -0.11, -0.108, -0.106, -0.104, -0.102, -0.1, -0.099, -0.098, -0.097, -0.096, -0.095, -0.094, -0.093, -0.092, -0.091, -0.09, -0.089, -0.088, -0.087, -0.086, -0.085, -0.084, -0.083, -0.082, -0.081, -0.08, -0.079, -0.078, -0.077, -0.076, -0.075, -0.074, -0.073, -0.072, -0.071, -0.07, -0.069, -0.068, -0.067, -0.066, -0.065, -0.064, -0.063, -0.062, -0.061, -0.06, -0.059, -0.058, -0.057, -0.056, -0.055, -0.054, -0.053, -0.052, -0.051, -0.05, -0.049, -0.048, -0.047, -0.046, -0.045, -0.044, -0.043, -0.042, -0.041, -0.04, -0.039, -0.038, -0.037, -0.036, -0.035, -0.034, -0.033, -0.032, -0.031, -0.03, -0.029, -0.028, -0.027, -0.026, -0.025, -0.024, -0.023, -0.022, -0.021, -0.02, -0.019, -0.018, -0.017, -0.016, -0.015, -0.014, -0.013, -0.012, -0.011, -0.01, -0.009, -0.008, -0.007, -0.006, -0.005, -0.004, -0.003, -0.002, -0.001, -0.0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.011, 0.012, 0.013, 0.014, 0.015, 0.016, 0.017, 0.018, 0.019, 0.02, 0.021, 0.022, 0.023, 0.024, 0.025, 0.026, 0.027, 0.028, 0.029, 0.03, 0.031, 0.032, 0.033, 0.034, 0.035, 0.036, 0.037, 0.038, 0.039, 0.04, 0.041, 0.042, 0.043, 0.044, 0.045, 0.046, 0.047, 0.048, 0.049, 0.05, 0.051, 0.052, 0.053, 0.054, 0.055, 0.056, 0.057, 0.058, 0.059, 0.06, 0.061, 0.062, 0.063, 0.064, 0.065, 0.066, 0.067, 0.068, 0.069, 0.07, 0.071, 0.072, 0.073, 0.074, 0.075, 0.076, 0.077, 0.078, 0.079, 0.08, 0.081, 0.082, 0.083, 0.084, 0.085, 0.086, 0.087, 0.088, 0.089, 0.09, 0.091, 0.092, 0.093, 0.094, 0.095, 0.096, 0.097, 0.098, 0.099, 0.1, 0.102, 0.104, 0.106, 0.108, 0.11, 0.112, 0.114, 0.116, 0.118, 0.12, 0.122, 0.124, 0.126, 0.128, 0.13, 0.132, 0.134, 0.136, 0.138, 0.14, 0.142, 0.144, 0.146, 0.148, 0.15, 0.152, 0.154, 0.156, 0.158, 0.16, 0.162, 0.164, 0.166, 0.168, 0.17, 0.172, 0.174, 0.176, 0.178, 0.18, 0.182, 0.184, 0.186, 0.188, 0.19, 0.192, 0.194, 0.196, 0.198, 0.2, 0.204, 0.208, 0.212, 0.216, 0.22, 0.224, 0.228, 0.232, 0.236, 0.24, 0.244, 0.248, 0.252, 0.256, 0.26, 0.264, 0.268, 0.272, 0.276, 0.28, 0.284, 0.288, 0.292, 0.296, 0.3, 0.304, 0.308, 0.312, 0.316, 0.32, 0.324, 0.328, 0.332, 0.336, 0.34, 0.344, 0.348, 0.352, 0.356, 0.36, 0.364, 0.368, 0.372, 0.376, 0.38, 0.384, 0.388, 0.392, 0.396, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.0, 1.025, 1.05, 1.075, 1.1, 1.125, 1.15, 1.175, 1.2, 1.225, 1.25, 1.275, 1.3, 1.325, 1.35, 1.375, 1.4, 1.425, 1.45, 1.475, 1.5, 1.525, 1.55, 1.575, 1.6, 1.625, 1.65, 1.675, 1.7, 1.725, 1.75, 1.775, 1.8, 1.825, 1.85, 1.875, 1.9, 1.925, 1.95, 1.975, 2.0, 2.05, 2.1, 2.15, 2.2, 2.25, 2.3, 2.35, 2.4, 2.45, 2.5, 2.55, 2.6, 2.65, 2.7, 2.75, 2.8, 2.85, 2.9, 2.95, 3.0}, "Binning of DCA xy and z axis"}; ConfigurableAxis binsMultiplicity{"binsMultiplicity", {100, 0, 100}, "Binning for multiplicity"}; ConfigurableAxis binsPercentile{"binsPercentile", {100, 0, 100}, "Binning for percentiles"}; - static constexpr int kNoMultiplicity = 0; - static constexpr int kMultFV0M = 1; - static constexpr int kMultFT0M = 2; - static constexpr int kMultFDDM = 3; - static constexpr int kMultTracklets = 4; - static constexpr int kMultTPC = 5; - static constexpr int kMultNTracksPV = 6; - static constexpr int kMultNTracksPVeta1 = 7; - static constexpr int kCentralityFT0C = 8; - static constexpr int kCentralityFT0M = 9; - static constexpr int kCentralityFV0A = 10; - static constexpr int kNMults = 10; Configurable multiplicityEstimator{"multiplicityEstimator", 0, "Flag to use a multiplicity estimator: 0 no multiplicity, 1 MultFV0M, 2 MultFT0M, 3 MultFDDM, 4 MultTracklets, 5 MultTPC, 6 MultNTracksPV, 7 MultNTracksPVeta1, 8 CentralityFT0C, 9 CentralityFT0M, 10 CentralityFV0A"}; // Custom track cuts for the cut variation study TrackSelection customTrackCuts; + Configurable ckeckKaonIsPvContrib{"ckeckKaonIsPvContrib", false, "Flag to ckeck if kaon tracks are from pv"}; Configurable useCustomTrackCuts{"useCustomTrackCuts", false, "Flag to use custom track cuts"}; Configurable itsPattern{"itsPattern", 0, "0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo"}; Configurable requireITS{"requireITS", true, "Additional cut on the ITS requirement"}; @@ -89,7 +80,8 @@ struct tofSpectra { Configurable maxDcaXYFactor{"maxDcaXYFactor", 1.f, "Additional cut on the maximum value of the DCA xy (multiplicative factor)"}; Configurable maxDcaZ{"maxDcaZ", 2.f, "Additional cut on the maximum value of the DCA z"}; Configurable minTPCNClsFound{"minTPCNClsFound", 0.f, "Additional cut on the minimum value of the number of found clusters in the TPC"}; - Configurable makeTHnSparseChoice{"makeTHnSparseChoice", true, "choose if produce thnsparse"}; // RD + Configurable makeTHnSparseChoice{"makeTHnSparseChoice", false, "choose if produce thnsparse"}; // RD + Configurable tpctofVsMult{"tpctofVsMult", false, "Produce TPC-TOF plots vs multiplicity"}; // Histograms HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -166,6 +158,7 @@ struct tofSpectra { LOG(info) << "\tmaxChi2PerClusterITS=" << maxChi2PerClusterITS.value; LOG(info) << "\tmaxDcaZ=" << maxDcaZ.value; LOG(info) << "\tmakeTHnSparseChoice=" << makeTHnSparseChoice.value; + LOG(info) << "\tckeckKaonIsPvContrib=" << ckeckKaonIsPvContrib.value; customTrackCuts = getGlobalTrackSelectionRun3ITSMatch(itsPattern.value); LOG(info) << "Customizing track cuts:"; @@ -179,23 +172,37 @@ struct tofSpectra { customTrackCuts.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); customTrackCuts.SetMaxDcaXYPtDep([](float pt) { return 10000.f; }); // No DCAxy cut will be used, this is done via the member function of the task customTrackCuts.SetMaxDcaZ(maxDcaZ.value); - // customTrackCuts.SetMakeTHnSparseChoice(makeTHnSparseChoice.value); customTrackCuts.print(); } // Histograms const AxisSpec vtxZAxis{100, -20, 20, "Vtx_{z} (cm)"}; const AxisSpec pAxis{binsPt, "#it{p} (GeV/#it{c})"}; const AxisSpec ptAxis{binsPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec etaAxis{binsEta, "#eta"}; histos.add("event/vertexz", "", HistType::kTH1D, {vtxZAxis}); auto h = histos.add("evsel", "evsel", HistType::kTH1D, {{10, 0.5, 10.5}}); h->GetXaxis()->SetBinLabel(1, "Events read"); - h->GetXaxis()->SetBinLabel(2, "Ev. sel. passed"); - h->GetXaxis()->SetBinLabel(3, "posZ passed"); + h->GetXaxis()->SetBinLabel(2, "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(3, "INEL>1 (fraction)"); + h->GetXaxis()->SetBinLabel(4, "Ev. sel. passed"); + h->GetXaxis()->SetBinLabel(5, "INEL>0 (fraction)"); + h->GetXaxis()->SetBinLabel(6, "INEL>1 (fraction)"); + h->GetXaxis()->SetBinLabel(7, "posZ passed"); + if (cfgINELCut.value == 1) { + h->GetXaxis()->SetBinLabel(8, "INEL>0"); + } else { + h->GetXaxis()->SetBinLabel(8, "INEL>0 (fraction)"); + } + if (cfgINELCut.value == 2) { + h->GetXaxis()->SetBinLabel(9, "INEL>1"); + } else { + h->GetXaxis()->SetBinLabel(9, "INEL>1 (fraction)"); + } h = histos.add("tracksel", "tracksel", HistType::kTH1D, {{10, 0.5, 10.5}}); h->GetXaxis()->SetBinLabel(1, "Tracks read"); - h->GetXaxis()->SetBinLabel(2, "Eta passed"); + h->GetXaxis()->SetBinLabel(2, Form(" %.2f < #eta < %.2f ", cfgCutEtaMin.value, cfgCutEtaMax.value)); h->GetXaxis()->SetBinLabel(3, "Quality passed"); h->GetXaxis()->SetBinLabel(4, "TOF passed (partial)"); @@ -204,12 +211,12 @@ struct tofSpectra { h->GetXaxis()->SetBinLabel(2, "EvTimeDefined"); h->GetXaxis()->SetBinLabel(3, "EvTimeTOF"); h->GetXaxis()->SetBinLabel(4, "EvTimeT0AC"); - h->GetXaxis()->SetBinLabel(5, "EvTimeTOFT0AV"); + h->GetXaxis()->SetBinLabel(5, "EvTimeTOFT0AC"); h->GetXaxis()->SetBinLabel(6, "AnyEvTime (selected)"); h->GetXaxis()->SetBinLabel(7, "EvTimeDefined (selected)"); h->GetXaxis()->SetBinLabel(8, "EvTimeTOF (selected)"); h->GetXaxis()->SetBinLabel(9, "EvTimeT0AC (selected)"); - h->GetXaxis()->SetBinLabel(10, "EvTimeTOFT0AV (selected)"); + h->GetXaxis()->SetBinLabel(10, "EvTimeTOFT0AC (selected)"); histos.add("Centrality/FV0A", "FV0A", HistType::kTH1D, {{binsPercentile, "Centrality FV0A"}}); histos.add("Centrality/FT0M", "FT0M", HistType::kTH1D, {{binsPercentile, "Centrality FT0M"}}); @@ -234,6 +241,8 @@ struct tofSpectra { if (enableTrackCutHistograms) { const AxisSpec chargeAxis{2, -2.f, 2.f, "Charge"}; + histos.add("track/pos/Eta", "Eta Positive tracks", HistType::kTH1D, {{binsEta, "#eta tracks"}}); + histos.add("track/neg/Eta", "Eta Negative tracks", HistType::kTH1D, {{binsEta, "#eta tracks"}}); // its histograms histos.add("track/ITS/itsNCls", "number of found ITS clusters;# clusters ITS", kTH2D, {{8, -0.5, 7.5}, chargeAxis}); histos.add("track/ITS/itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", kTH2D, {{100, 0, 40}, chargeAxis}); @@ -299,16 +308,26 @@ struct tofSpectra { histos.add("Data/pos/pt/its_trd", "pos ITS-TRD", kTH1D, {ptAxis}); histos.add("Data/neg/pt/its_trd", "neg ITS-TRD", kTH1D, {ptAxis}); + // 1 detectors + histos.add("Data/pos/pt/its", "pos ITS", kTH1D, {ptAxis}); + histos.add("Data/neg/pt/its", "neg ITS", kTH1D, {ptAxis}); + histos.add("Data/pos/pt/tpc", "pos TPC", kTH1D, {ptAxis}); + histos.add("Data/neg/pt/tpc", "neg TPC", kTH1D, {ptAxis}); + if (doprocessMC) { histos.add("MC/fake/pos", "Fake positive tracks", kTH1D, {ptAxis}); histos.add("MC/fake/neg", "Fake negative tracks", kTH1D, {ptAxis}); histos.add("MC/no_collision/pos", "No collision pos track", kTH1D, {ptAxis}); histos.add("MC/no_collision/neg", "No collision neg track", kTH1D, {ptAxis}); - histos.add("MC/GenRecoCollisions", "Generated and Reconstructed MC Collisions", kTH1D, {{3, 0, 3}}); + auto hh = histos.add("MC/GenRecoCollisions", "Generated and Reconstructed MC Collisions", kTH1D, {{10, 0.5, 10.5}}); + hh->GetXaxis()->SetBinLabel(1, "Collisions generated"); + hh->GetXaxis()->SetBinLabel(2, "Collisions reconstructed"); + hh->GetXaxis()->SetBinLabel(3, "INEL>0"); + hh->GetXaxis()->SetBinLabel(4, "INEL>1"); + hh->GetXaxis()->SetBinLabel(5, "hasParticleInFT0C && hasParticleInFT0A"); } for (int i = 0; i < NpCharge; i++) { - switch (i) { case 0: case Np: @@ -324,19 +343,19 @@ struct tofSpectra { break; case 2: case Np + 2: - if (doprocessFullPi == false && doprocessLfFullPi == false) { + if (doprocessFullPi == false && doprocessLfFullPi == false && doprocessDerived == false) { continue; } break; case 3: case Np + 3: - if (doprocessFullKa == false && doprocessLfFullKa == false) { + if (doprocessFullKa == false && doprocessLfFullKa == false && doprocessDerived == false) { continue; } break; case 4: case Np + 4: - if (doprocessFullPr == false && doprocessLfFullPr == false) { + if (doprocessFullPr == false && doprocessLfFullPr == false && doprocessDerived == false) { continue; } break; @@ -372,65 +391,79 @@ struct tofSpectra { const AxisSpec deltaTOFAxis{binsdeltaTOF, Form("#Delta^{TOF}(%s)", pTCharge[i])}; AxisSpec multAxis{binsMultiplicity, "Undefined multiplicity estimator"}; - if (enableTPCTOFHistograms) { - histos.add(hnsigmatpctof[i].data(), pTCharge[i], kTH3D, {ptAxis, nsigmaTPCAxis, nsigmaTOFAxis}); - } - switch (multiplicityEstimator) { - case kNoMultiplicity: // No multiplicity + case MultCodes::kNoMultiplicity: // No multiplicity break; - case kMultFV0M: // MultFV0M + case MultCodes::kMultFV0M: // MultFV0M multAxis.name = "MultFV0M"; break; - case kMultFT0M: // MultFT0M + case MultCodes::kMultFT0M: // MultFT0M multAxis.name = "MultFT0M"; break; - case kMultFDDM: // MultFDDM + case MultCodes::kMultFDDM: // MultFDDM multAxis.name = "MultFDDM"; break; - case kMultTracklets: // MultTracklets + case MultCodes::kMultTracklets: // MultTracklets multAxis.name = "MultTracklets"; break; - case kMultTPC: // MultTPC + case MultCodes::kMultTPC: // MultTPC multAxis.name = "MultTPC"; break; - case kMultNTracksPV: // MultNTracksPV + case MultCodes::kMultNTracksPV: // MultNTracksPV multAxis.name = "MultNTracksPV"; break; - case kMultNTracksPVeta1: // MultNTracksPVeta1 + case MultCodes::kMultNTracksPVeta1: // MultNTracksPVeta1 multAxis.name = "MultNTracksPVeta1"; break; - case kCentralityFT0C: // Centrality FT0C + case MultCodes::kCentralityFT0C: // Centrality FT0C multAxis = {binsPercentile, "Centrality FT0C"}; break; - case kCentralityFT0M: // Centrality FT0M + case MultCodes::kCentralityFT0M: // Centrality FT0M multAxis = {binsPercentile, "Centrality FT0M"}; break; - case kCentralityFV0A: // Centrality FV0A + case MultCodes::kCentralityFV0A: // Centrality FV0A multAxis = {binsPercentile, "Centrality FV0A"}; break; default: LOG(fatal) << "Unrecognized option for multiplicity " << multiplicityEstimator; } - if (multiplicityEstimator == kNoMultiplicity) { + if (multiplicityEstimator == MultCodes::kNoMultiplicity) { histos.add(hnsigmatof[i].data(), pTCharge[i], kTH2D, {ptAxis, nsigmaTOFAxis}); histos.add(hnsigmatpc[i].data(), pTCharge[i], kTH2D, {ptAxis, nsigmaTPCAxis}); if (enableDeltaHistograms) { histos.add(hdeltatof[i].data(), pTCharge[i], kTH2D, {ptAxis, deltaTOFAxis}); histos.add(hdeltatpc[i].data(), pTCharge[i], kTH2D, {ptAxis, deltaTPCAxis}); } - } else if (multiplicityEstimator != kNoMultiplicity && makeTHnSparseChoice) { // RD - histos.add(hnsigmatof[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, nsigmaTOFAxis, multAxis, dcaXyAxis, dcaZAxis}); // RD - histos.add(hnsigmatpc[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, nsigmaTPCAxis, multAxis, dcaXyAxis, dcaZAxis}); // RD - + if (enableTPCTOFHistograms) { + if (makeTHnSparseChoice) { // JL + histos.add(hnsigmatpctof[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, etaAxis, nsigmaTPCAxis, nsigmaTOFAxis}); // JL + } else { + histos.add(hnsigmatpctof[i].data(), pTCharge[i], kTH3D, {ptAxis, nsigmaTPCAxis, nsigmaTOFAxis}); + } + } } else { - - histos.add(hnsigmatof[i].data(), pTCharge[i], kTH3D, {ptAxis, nsigmaTOFAxis, multAxis}); - histos.add(hnsigmatpc[i].data(), pTCharge[i], kTH3D, {ptAxis, nsigmaTPCAxis, multAxis}); + if (makeTHnSparseChoice) { // RD + histos.add(hnsigmatof[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, nsigmaTOFAxis, multAxis, dcaXyAxis, dcaZAxis, etaAxis}); // RD + histos.add(hnsigmatpc[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, nsigmaTPCAxis, multAxis, dcaXyAxis, dcaZAxis, etaAxis}); // RD + } else { + histos.add(hnsigmatof[i].data(), pTCharge[i], kTH3D, {ptAxis, nsigmaTOFAxis, multAxis}); + histos.add(hnsigmatpc[i].data(), pTCharge[i], kTH3D, {ptAxis, nsigmaTPCAxis, multAxis}); + } if (enableDeltaHistograms) { histos.add(hdeltatof[i].data(), pTCharge[i], kTH3D, {ptAxis, deltaTOFAxis, multAxis}); histos.add(hdeltatpc[i].data(), pTCharge[i], kTH3D, {ptAxis, deltaTPCAxis, multAxis}); } + if (enableTPCTOFHistograms) { + if (makeTHnSparseChoice) { // JL + histos.add(hnsigmatpctof[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, etaAxis, nsigmaTPCAxis, nsigmaTOFAxis}); // JL + } else { + if (tpctofVsMult) { + histos.add(hnsigmatpctof[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, nsigmaTPCAxis, nsigmaTOFAxis, multAxis}); + } else { + histos.add(hnsigmatpctof[i].data(), pTCharge[i], kTH3D, {ptAxis, nsigmaTPCAxis, nsigmaTOFAxis}); + } + } + } } histos.add(hdcaxy[i].data(), pTCharge[i], kTH2D, {ptAxis, dcaXyAxis}); @@ -441,15 +474,17 @@ struct tofSpectra { if (makeTHnSparseChoice) { //*************************************RD********************************************** - histos.add(hpt_num_prm[i].data(), pTCharge[i], kTH3D, {ptAxis, dcaXyAxis, multAxis}); - histos.add(hpt_numtof_prm[i].data(), pTCharge[i], kTH3D, {ptAxis, dcaXyAxis, multAxis}); - histos.add(hpt_numtof_str[i].data(), pTCharge[i], kTH3D, {ptAxis, dcaXyAxis, multAxis}); - histos.add(hpt_numtof_mat[i].data(), pTCharge[i], kTH3D, {ptAxis, dcaXyAxis, multAxis}); - histos.add(hpt_num_str[i].data(), pTCharge[i], kTH3D, {ptAxis, dcaXyAxis, multAxis}); - histos.add(hpt_num_mat[i].data(), pTCharge[i], kTH3D, {ptAxis, dcaXyAxis, multAxis}); - histos.add(hpt_den_prm[i].data(), pTCharge[i], kTH2D, {ptAxis, multAxis}); - histos.add(hpt_den_str[i].data(), pTCharge[i], kTH2D, {ptAxis, multAxis}); - histos.add(hpt_den_mat[i].data(), pTCharge[i], kTH2D, {ptAxis, multAxis}); + histos.add(hpt_num_prm[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); + histos.add(hpt_num_str[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); + histos.add(hpt_num_mat[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); + + histos.add(hpt_numtof_prm[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); + histos.add(hpt_numtof_str[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); + histos.add(hpt_numtof_mat[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); + + histos.add(hpt_den_prm[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); + histos.add(hpt_den_str[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); + histos.add(hpt_den_mat[i].data(), pTCharge[i], kTHnSparseD, {ptAxis, multAxis, etaAxis}); //*************************************************************************************** } else { @@ -493,65 +528,70 @@ struct tofSpectra { if (abs(track.rapidity(PID::getMass(id))) > cfgCutY) { return; } + if constexpr (id == PID::Kaon) { + if (ckeckKaonIsPvContrib && !track.isPVContributor()) { + return; + } + } const auto& nsigmaTOF = o2::aod::pidutils::tofNSigma(track); const auto& nsigmaTPC = o2::aod::pidutils::tpcNSigma(track); // const auto id = track.sign() > 0 ? id : id + Np; float multiplicity = 0.f; switch (multiplicityEstimator) { - case kNoMultiplicity: // No multiplicity + case MultCodes::kNoMultiplicity: // No multiplicity break; - case kMultFV0M: // MultFV0M + case MultCodes::kMultFV0M: // MultFV0M // multiplicity = collision.multFV0M(); // multiplicity = collision.multZeqFV0A() + collision.multZeqFV0C(); multiplicity = collision.multZeqFV0A(); break; - case kMultFT0M: // MultFT0M + case MultCodes::kMultFT0M: // MultFT0M // multiplicity = collision.multFT0M(); multiplicity = collision.multZeqFT0A() + collision.multZeqFT0C(); break; - case kMultFDDM: // MultFDDM + case MultCodes::kMultFDDM: // MultFDDM // multiplicity = collision.multFDDM(); multiplicity = collision.multZeqFDDA() + collision.multZeqFDDC(); break; - case kMultTracklets: // MultTracklets + case MultCodes::kMultTracklets: // MultTracklets multiplicity = collision.multTracklets(); break; - case kMultTPC: // MultTPC + case MultCodes::kMultTPC: // MultTPC multiplicity = collision.multTPC(); break; - case kMultNTracksPV: // MultNTracksPV + case MultCodes::kMultNTracksPV: // MultNTracksPV // multiplicity = collision.multNTracksPV(); multiplicity = collision.multZeqNTracksPV(); break; - case kMultNTracksPVeta1: // MultNTracksPVeta1 + case MultCodes::kMultNTracksPVeta1: // MultNTracksPVeta1 multiplicity = collision.multNTracksPVeta1(); break; - case kCentralityFT0C: // Centrality FT0C + case MultCodes::kCentralityFT0C: // Centrality FT0C multiplicity = collision.centFT0C(); break; - case kCentralityFT0M: // Centrality FT0M + case MultCodes::kCentralityFT0M: // Centrality FT0M multiplicity = collision.centFT0M(); break; - case kCentralityFV0A: // Centrality FT0M + case MultCodes::kCentralityFV0A: // Centrality FT0M multiplicity = collision.centFV0A(); break; default: LOG(fatal) << "Unknown multiplicity estimator: " << multiplicityEstimator; } - if (multiplicityEstimator == kNoMultiplicity) { + if (multiplicityEstimator == MultCodes::kNoMultiplicity) { if (track.sign() > 0) { histos.fill(HIST(hnsigmatpc[id]), track.pt(), nsigmaTPC); } else { histos.fill(HIST(hnsigmatpc[id + Np]), track.pt(), nsigmaTPC); } - } else if (multiplicityEstimator != kNoMultiplicity && makeTHnSparseChoice) { // RD - if (track.sign() > 0) { // RD - histos.fill(HIST(hnsigmatpc[id]), track.pt(), nsigmaTPC, multiplicity, track.dcaXY(), track.dcaZ()); // RD - } else { // RD - histos.fill(HIST(hnsigmatpc[id + Np]), track.pt(), nsigmaTPC, multiplicity, track.dcaXY(), track.dcaZ()); // RD - } // RD + } else if (makeTHnSparseChoice) { // RD + if (track.sign() > 0) { // RD + histos.fill(HIST(hnsigmatpc[id]), track.pt(), nsigmaTPC, multiplicity, track.dcaXY(), track.dcaZ(), track.eta()); // RD + } else { // RD + histos.fill(HIST(hnsigmatpc[id + Np]), track.pt(), nsigmaTPC, multiplicity, track.dcaXY(), track.dcaZ(), track.eta()); // RD + } // RD } else { if (track.sign() > 0) { histos.fill(HIST(hnsigmatpc[id]), track.pt(), nsigmaTPC, multiplicity); @@ -563,7 +603,7 @@ struct tofSpectra { if constexpr (fillFullInfo) { if (enableDeltaHistograms) { const auto& deltaTPC = o2::aod::pidutils::tpcExpSignalDiff(track); - if (multiplicityEstimator == kNoMultiplicity) { + if (multiplicityEstimator == MultCodes::kNoMultiplicity) { if (track.sign() > 0) { histos.fill(HIST(hdeltatpc[id]), track.pt(), deltaTPC); } else { @@ -660,38 +700,56 @@ struct tofSpectra { } } - if (multiplicityEstimator == kNoMultiplicity) { + if (multiplicityEstimator == MultCodes::kNoMultiplicity) { if (track.sign() > 0) { histos.fill(HIST(hnsigmatof[id]), track.pt(), nsigmaTOF); } else { histos.fill(HIST(hnsigmatof[id + Np]), track.pt(), nsigmaTOF); } - } else if (multiplicityEstimator != kNoMultiplicity && makeTHnSparseChoice) { // RD - if (track.sign() > 0) { // RD - histos.fill(HIST(hnsigmatof[id]), track.pt(), nsigmaTOF, multiplicity, track.dcaXY(), track.dcaZ()); // RD - } else { // RD - histos.fill(HIST(hnsigmatof[id + Np]), track.pt(), nsigmaTOF, multiplicity, track.dcaXY(), track.dcaZ()); // RD - } // RD } else { - if (track.sign() > 0) { - histos.fill(HIST(hnsigmatof[id]), track.pt(), nsigmaTOF, multiplicity); + if (makeTHnSparseChoice) { // RD + if (track.sign() > 0) { // RD + histos.fill(HIST(hnsigmatof[id]), track.pt(), nsigmaTOF, multiplicity, track.dcaXY(), track.dcaZ(), track.eta()); // RD + } else { // RD + histos.fill(HIST(hnsigmatof[id + Np]), track.pt(), nsigmaTOF, multiplicity, track.dcaXY(), track.dcaZ(), track.eta()); // RD + } // RD } else { - histos.fill(HIST(hnsigmatof[id + Np]), track.pt(), nsigmaTOF, multiplicity); + if (track.sign() > 0) { + histos.fill(HIST(hnsigmatof[id]), track.pt(), nsigmaTOF, multiplicity); + } else { + histos.fill(HIST(hnsigmatof[id + Np]), track.pt(), nsigmaTOF, multiplicity); + } } } if (enableTPCTOFHistograms) { - if (track.sign() > 0) { - histos.fill(HIST(hnsigmatpctof[id]), track.pt(), nsigmaTPC, nsigmaTOF); + if (makeTHnSparseChoice) { + if (track.sign() > 0) { + histos.fill(HIST(hnsigmatpctof[id]), track.pt(), track.eta(), nsigmaTPC, nsigmaTOF); + } else { + histos.fill(HIST(hnsigmatpctof[id + Np]), track.pt(), track.eta(), nsigmaTPC, nsigmaTOF); + } } else { - histos.fill(HIST(hnsigmatpctof[id + Np]), track.pt(), nsigmaTPC, nsigmaTOF); + if (tpctofVsMult) { + if (track.sign() > 0) { + histos.fill(HIST(hnsigmatpctof[id]), track.pt(), nsigmaTPC, nsigmaTOF, multiplicity); + } else { + histos.fill(HIST(hnsigmatpctof[id + Np]), track.pt(), nsigmaTPC, nsigmaTOF, multiplicity); + } + } else { + if (track.sign() > 0) { + histos.fill(HIST(hnsigmatpctof[id]), track.pt(), nsigmaTPC, nsigmaTOF); + } else { + histos.fill(HIST(hnsigmatpctof[id + Np]), track.pt(), nsigmaTPC, nsigmaTOF); + } + } } } if constexpr (fillFullInfo) { if (enableDeltaHistograms) { const auto& deltaTOF = o2::aod::pidutils::tofExpSignalDiff(track); - if (multiplicityEstimator == kNoMultiplicity) { + if (multiplicityEstimator == MultCodes::kNoMultiplicity) { if (track.sign() > 0) { histos.fill(HIST(hdeltatof[id]), track.pt(), deltaTOF); } else { @@ -708,7 +766,11 @@ struct tofSpectra { } // Filling DCA info with the TPC+TOF PID - if (std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.f) { + bool isDCAPureSample = (std::sqrt(nsigmaTOF * nsigmaTOF + nsigmaTPC * nsigmaTPC) < 2.f); + if (track.pt() <= 0.4) { + isDCAPureSample = (nsigmaTPC < 1.f); + } + if (isDCAPureSample) { if (track.sign() > 0) { histos.fill(HIST(hdcaxy[id]), track.pt(), track.dcaXY()); } else { @@ -735,23 +797,47 @@ struct tofSpectra { } } - template - bool isEventSelected(CollisionType const& collision) + template + bool isEventSelected(CollisionType const& collision, TrackType const& tracks) { if constexpr (fillHistograms) { - histos.fill(HIST("evsel"), 1); + histos.fill(HIST("evsel"), 1.f); + } + if constexpr (fillHistograms) { + if (collision.multNTracksPVeta1() >= 1) { + histos.fill(HIST("evsel"), 2.f); + } + if (collision.multNTracksPVeta1() >= 2) { + histos.fill(HIST("evsel"), 3.f); + } } if (!collision.sel8()) { return false; } if constexpr (fillHistograms) { - histos.fill(HIST("evsel"), 2); + histos.fill(HIST("evsel"), 4.f); + if (collision.multNTracksPVeta1() >= 1) { + histos.fill(HIST("evsel"), 5.f); + } + if (collision.multNTracksPVeta1() >= 2) { + histos.fill(HIST("evsel"), 6.f); + } } if (abs(collision.posZ()) > cfgCutVertex) { return false; } if constexpr (fillHistograms) { - histos.fill(HIST("evsel"), 3); + histos.fill(HIST("evsel"), 7.f); + if (collision.multNTracksPVeta1() >= 1) { + histos.fill(HIST("evsel"), 8.f); + } else if (cfgINELCut == 1) { + return false; + } + if (collision.multNTracksPVeta1() >= 2) { + histos.fill(HIST("evsel"), 9.f); + } else if (cfgINELCut == 2) { + return false; + } histos.fill(HIST("event/vertexz"), collision.posZ()); if constexpr (fillMultiplicity) { @@ -812,18 +898,23 @@ struct tofSpectra { return track.isGlobalTrackWoDCA(); } - template + template bool isTrackSelected(TrackType const& track) { if constexpr (fillHistograms) { histos.fill(HIST("tracksel"), 1); } - if (abs(track.eta()) > cfgCutEta) { + if (track.eta() < cfgCutEtaMin || track.eta() > cfgCutEtaMax) { return false; } if constexpr (fillHistograms) { histos.fill(HIST("tracksel"), 2); if (enableTrackCutHistograms) { + if (track.sign() > 0) { + histos.fill(HIST("track/pos/Eta"), track.eta()); + } else { + histos.fill(HIST("track/neg/Eta"), track.eta()); + } if (track.hasITS() && track.hasTPC()) { histos.fill(HIST("track/ITS/itsNCls"), track.itsNCls(), track.sign()); histos.fill(HIST("track/ITS/itsChi2NCl"), track.itsChi2NCl(), track.sign()); @@ -844,6 +935,20 @@ struct tofSpectra { } } } + if (track.hasITS() && track.isQualityTrackITS() && track.isInAcceptanceTrack()) { + if (track.sign() > 0) { + histos.fill(HIST("Data/pos/pt/its"), track.pt()); + } else { + histos.fill(HIST("Data/neg/pt/its"), track.pt()); + } + } + if (track.hasTPC() && track.isQualityTrackTPC() && track.isInAcceptanceTrack()) { + if (track.sign() > 0) { + histos.fill(HIST("Data/pos/pt/tpc"), track.pt()); + } else { + histos.fill(HIST("Data/neg/pt/tpc"), track.pt()); + } + } } if (!passesCutWoDCA(track)) { @@ -955,10 +1060,10 @@ struct tofSpectra { using TrackCandidates = soa::Join; - void process(CollisionCandidate::iterator const& collision, - TrackCandidates const& tracks) + void processStandard(CollisionCandidate::iterator const& collision, + TrackCandidates const& tracks) { - if (!isEventSelected(collision)) { + if (!isEventSelected(collision, tracks)) { return; } for (const auto& track : tracks) { @@ -967,6 +1072,29 @@ struct tofSpectra { } } } // end of the process function + PROCESS_SWITCH(tofSpectra, processStandard, "Standard processor from AO2D", true); + + Preslice spPerCol = aod::spectra::collisionId; + SliceCache cacheTrk; + void processDerived(aod::SpColls const& collisions, + aod::SpTracks const& tracks) + { + for (const auto& collision : collisions) { + if (!isEventSelected(collision, tracks)) { + return; + } + const auto& tracksInCollision = tracks.sliceByCached(aod::spectra::collisionId, collision.globalIndex(), cacheTrk); + for (const auto& track : tracksInCollision) { + if (!isTrackSelected(track)) { + continue; + } + fillParticleHistos(track, collision); + fillParticleHistos(track, collision); + fillParticleHistos(track, collision); + } + } + } // end of the process function + PROCESS_SWITCH(tofSpectra, processDerived, "Derived data processor", false); #define makeProcessFunction(processorName, inputPid, particleId, isFull, tofTable, tpcTable) \ void process##processorName##inputPid(CollisionCandidate::iterator const& collision, \ @@ -974,7 +1102,7 @@ struct tofSpectra { aod::pid##tofTable##inputPid, \ aod::pid##tpcTable##inputPid> const& tracks) \ { \ - if (!isEventSelected(collision)) { \ + if (!isEventSelected(collision, tracks)) { \ return; \ } \ for (const auto& track : tracks) { \ @@ -1080,37 +1208,37 @@ struct tofSpectra { float multiplicity = 0.f; switch (multiplicityEstimator) { - case kNoMultiplicity: // No multiplicity - multiplicity = 50; // to check if its filled + case MultCodes::kNoMultiplicity: // No multiplicity + multiplicity = 50; // to check if its filled break; - case kMultFV0M: // MultFV0M + case MultCodes::kMultFV0M: // MultFV0M multiplicity = collision.multZeqFV0A(); break; - case kMultFT0M: + case MultCodes::kMultFT0M: multiplicity = collision.multZeqFT0A() + collision.multZeqFT0C(); break; - case kMultFDDM: // MultFDDM + case MultCodes::kMultFDDM: // MultFDDM multiplicity = collision.multZeqFDDA() + collision.multZeqFDDC(); break; - case kMultTracklets: // MultTracklets + case MultCodes::kMultTracklets: // MultTracklets multiplicity = collision.multTracklets(); break; - case kMultTPC: // MultTPC + case MultCodes::kMultTPC: // MultTPC multiplicity = collision.multTPC(); break; - case kMultNTracksPV: // MultNTracksPV + case MultCodes::kMultNTracksPV: // MultNTracksPV // multiplicity = collision.multNTracksPV(); multiplicity = collision.multZeqNTracksPV(); break; - case kMultNTracksPVeta1: // MultNTracksPVeta1 + case MultCodes::kMultNTracksPVeta1: // MultNTracksPVeta1 multiplicity = collision.multNTracksPVeta1(); break; - case kCentralityFT0C: // Centrality FT0C + case MultCodes::kCentralityFT0C: // Centrality FT0C multiplicity = collision.centFT0C(); break; - case kCentralityFT0M: // Centrality FT0M + case MultCodes::kCentralityFT0M: // Centrality FT0M multiplicity = collision.centFT0M(); // collision.centFT0A() break; default: @@ -1122,9 +1250,10 @@ struct tofSpectra { if (mcParticle.pdgCode() != PDGs[i]) { return; } - if (std::abs(mcParticle.eta()) > cfgCutEta) { + if (track.eta() < cfgCutEtaMin || track.eta() > cfgCutEtaMax) { return; } + if (std::abs(mcParticle.y()) > cfgCutY) { return; } @@ -1152,9 +1281,9 @@ struct tofSpectra { if (!mcParticle.isPhysicalPrimary()) { if (mcParticle.getProcess() == 4) { if (makeTHnSparseChoice) { - histos.fill(HIST(hpt_num_str[i]), track.pt(), track.dcaXY(), multiplicity); // RD + histos.fill(HIST(hpt_num_str[i]), track.pt(), multiplicity, track.eta()); // RD if (track.hasTOF()) { - histos.fill(HIST(hpt_numtof_str[i]), track.pt(), track.dcaXY(), multiplicity); // RD + histos.fill(HIST(hpt_numtof_str[i]), track.pt(), multiplicity, track.eta()); // RD } } else { histos.fill(HIST(hpt_num_str[i]), track.pt()); @@ -1164,9 +1293,9 @@ struct tofSpectra { } } else { if (makeTHnSparseChoice) { - histos.fill(HIST(hpt_num_mat[i]), track.pt(), track.dcaXY(), multiplicity); // RD + histos.fill(HIST(hpt_num_mat[i]), track.pt(), multiplicity, track.eta()); // RD if (track.hasTOF()) { - histos.fill(HIST(hpt_numtof_mat[i]), track.pt(), track.dcaXY(), multiplicity); // RD + histos.fill(HIST(hpt_numtof_mat[i]), track.pt(), multiplicity, track.eta()); // RD } } else { @@ -1178,7 +1307,7 @@ struct tofSpectra { } } else { if (makeTHnSparseChoice) { - histos.fill(HIST(hpt_num_prm[i]), track.pt(), track.dcaXY(), multiplicity); // RD + histos.fill(HIST(hpt_num_prm[i]), track.pt(), multiplicity, track.eta()); // RD } else { histos.fill(HIST(hpt_num_prm[i]), track.pt()); } @@ -1196,7 +1325,7 @@ struct tofSpectra { } if (track.hasTOF()) { if (makeTHnSparseChoice) { - histos.fill(HIST(hpt_numtof_prm[i]), track.pt(), track.dcaXY(), multiplicity); // RD + histos.fill(HIST(hpt_numtof_prm[i]), track.pt(), multiplicity, track.eta()); // RD } else { histos.fill(HIST(hpt_numtof_prm[i]), track.pt()); } @@ -1269,37 +1398,37 @@ struct tofSpectra { float multiplicity = 0.f; switch (multiplicityEstimator) { - case kNoMultiplicity: // No multiplicity - multiplicity = 50; // to check if its filled + case MultCodes::kNoMultiplicity: // No multiplicity + multiplicity = 50; // to check if its filled break; - case kMultFV0M: // MultFV0M + case MultCodes::kMultFV0M: // MultFV0M multiplicity = collision.multZeqFV0A(); break; - case kMultFT0M: + case MultCodes::kMultFT0M: multiplicity = collision.multZeqFT0A() + collision.multZeqFT0C(); break; - case kMultFDDM: // MultFDDM + case MultCodes::kMultFDDM: // MultFDDM multiplicity = collision.multZeqFDDA() + collision.multZeqFDDC(); break; - case kMultTracklets: // MultTracklets + case MultCodes::kMultTracklets: // MultTracklets multiplicity = collision.multTracklets(); break; - case kMultTPC: // MultTPC + case MultCodes::kMultTPC: // MultTPC multiplicity = collision.multTPC(); break; - case kMultNTracksPV: // MultNTracksPV + case MultCodes::kMultNTracksPV: // MultNTracksPV // multiplicity = collision.multNTracksPV(); multiplicity = collision.multZeqNTracksPV(); break; - case kMultNTracksPVeta1: // MultNTracksPVeta1 + case MultCodes::kMultNTracksPVeta1: // MultNTracksPVeta1 multiplicity = collision.multNTracksPVeta1(); break; - case kCentralityFT0C: // Centrality FT0C + case MultCodes::kCentralityFT0C: // Centrality FT0C multiplicity = collision.centFT0C(); break; - case kCentralityFT0M: // Centrality FT0M + case MultCodes::kCentralityFT0M: // Centrality FT0M multiplicity = collision.centFT0M(); // collision.centFT0A() break; default: @@ -1315,20 +1444,20 @@ struct tofSpectra { if (!mcParticle.isPhysicalPrimary()) { if (mcParticle.getProcess() == 4) { if (makeTHnSparseChoice) { - histos.fill(HIST(hpt_den_str[i]), mcParticle.pt(), multiplicity); // RD + histos.fill(HIST(hpt_den_str[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); // RD } else { histos.fill(HIST(hpt_den_str[i]), mcParticle.pt()); } } else { if (makeTHnSparseChoice) { - histos.fill(HIST(hpt_den_mat[i]), mcParticle.pt(), multiplicity); // RD + histos.fill(HIST(hpt_den_mat[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); // RD } else { histos.fill(HIST(hpt_den_mat[i]), mcParticle.pt()); } } } else { if (makeTHnSparseChoice) { - histos.fill(HIST(hpt_den_prm[i]), mcParticle.pt(), multiplicity); // RD + histos.fill(HIST(hpt_den_prm[i]), mcParticle.pt(), multiplicity, mcParticle.eta()); // RD } else { histos.fill(HIST(hpt_den_prm[i]), mcParticle.pt()); } @@ -1498,8 +1627,8 @@ struct tofSpectra { CollisionCandidateMC const& collisions) { // Fill number of generated and reconstructed collisions for normalization - histos.fill(HIST("MC/GenRecoCollisions"), 0.5, mcCollisions.size()); - histos.fill(HIST("MC/GenRecoCollisions"), 1.5, collisions.size()); + histos.fill(HIST("MC/GenRecoCollisions"), 1.f, mcCollisions.size()); + histos.fill(HIST("MC/GenRecoCollisions"), 2.f, collisions.size()); // LOGF(info, "Enter processMC!"); for (const auto& track : tracks) { if (!track.has_collision()) { @@ -1510,6 +1639,9 @@ struct tofSpectra { } continue; } + if (!track.collision_as().sel8()) { + continue; + } if (!passesCutWoDCA(track)) { continue; } @@ -1561,15 +1693,18 @@ struct tofSpectra { const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); bool hasParticleInFT0C = false; bool hasParticleInFT0A = false; + + int nInelPart = 0; for (const auto& mcParticle : particlesInCollision) { if (mcParticle.isPhysicalPrimary()) { - if (TMath::Abs(mcParticle.pdgCode()) == 211) { - if (mcParticle.eta() >= -3.4 && mcParticle.eta() <= -2.3) { // Acceptance of the FT0C - hasParticleInFT0C = true; - } - if (mcParticle.eta() >= 3.8 && mcParticle.eta() <= 5.0) { // Acceptance of the FT0A - hasParticleInFT0A = true; - } + if (mcParticle.eta() >= -3.4f && mcParticle.eta() <= -2.3f) { // Acceptance of the FT0C + hasParticleInFT0C = true; + } + if (mcParticle.eta() >= 3.8f && mcParticle.eta() <= 5.0f) { // Acceptance of the FT0A + hasParticleInFT0A = true; + } + if (std::abs(mcParticle.eta()) < 1.f) { + nInelPart++; } } @@ -1580,13 +1715,18 @@ struct tofSpectra { fillParticleHistograms_MCGenEvs(mcParticle, mcCollision); }); } + if (nInelPart >= 1) { + histos.fill(HIST("MC/GenRecoCollisions"), 3.f); + } + if (nInelPart >= 2) { + histos.fill(HIST("MC/GenRecoCollisions"), 4.f); + } if (hasParticleInFT0C && hasParticleInFT0A) { - histos.fill(HIST("MC/GenRecoCollisions"), 2.5); + histos.fill(HIST("MC/GenRecoCollisions"), 5.f); } } } PROCESS_SWITCH(tofSpectra, processMC, "Process MC", false); - }; // end of spectra task WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Tasks/spectraTOFRun2.cxx b/PWGLF/Tasks/spectraTOFRun2.cxx index f91ae9f3b46..970563aaed7 100644 --- a/PWGLF/Tasks/spectraTOFRun2.cxx +++ b/PWGLF/Tasks/spectraTOFRun2.cxx @@ -31,7 +31,7 @@ #include "Framework/StaticFor.h" #include "Common/Core/TrackSelectionDefaults.h" #include "PWGLF/DataModel/LFParticleIdentification.h" -#include "spectraTOF.h" +#include "PWGLF/DataModel/spectraTOF.h" #include "TPDGCode.h" diff --git a/PWGLF/Tasks/vzero_cascade_absorption.cxx b/PWGLF/Tasks/vzero_cascade_absorption.cxx new file mode 100644 index 00000000000..c5cd00f33c0 --- /dev/null +++ b/PWGLF/Tasks/vzero_cascade_absorption.cxx @@ -0,0 +1,556 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \author Alberto Caliva (alberto.caliva@cern.ch) +/// \since September 26, 2023 + +#include +#include +#include +#include +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "ReconstructionDataFormats/Track.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +using SelectedCollisions = soa::Join; + +using FullTracks = soa::Join; + +using MCTracks = soa::Join; + +struct vzero_cascade_absorption { + + // QC Histograms + HistogramRegistry registryQC{ + "registryQC", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + // Analysis Histograms: Data + HistogramRegistry registryData{ + "registryData", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + // Analysis Histograms: MC + HistogramRegistry registryMC{ + "registryMC", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + + // Configurable Parameters + Configurable minTPCnClsFound{"minTPCnClsFound", 80.0f, "min number of found TPC clusters"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 80.0f, "min number of found TPC crossed rows"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; + Configurable etaMin{"etaMin", -0.5f, "etaMin"}; + Configurable etaMax{"etaMax", +0.5f, "etaMax"}; + Configurable pMin_k0postrack{"pMin_k0postrack", 0.3f, "Min Momentum K0 pos track"}; + Configurable pMax_k0postrack{"pMax_k0postrack", 5.0f, "Max Momentum K0 pos track"}; + Configurable pMin_k0negtrack{"pMin_k0negtrack", 0.3f, "Min Momentum K0 neg track"}; + Configurable pMax_k0negtrack{"pMax_k0negtrack", 5.0f, "Max Momentum K0 neg track"}; + Configurable pMin_Lambda_proton{"pMin_Lambda_proton", 0.3f, "Min Momentum proton from Lambda"}; + Configurable pMax_Lambda_proton{"pMax_Lambda_proton", 5.0f, "Max Momentum proton from Lambda"}; + Configurable pMin_Lambda_pion{"pMin_Lambda_pion", 0.2f, "Min Momentum pion from Lambda"}; + Configurable pMax_Lambda_pion{"pMax_Lambda_pion", 1.0f, "Max Momentum pion from Lambda"}; + Configurable requirehitsITS{"requirehitsITS", true, "require ITS hits for daughters"}; + Configurable> hit_requirement_before_target{"hit_requirement_before_target", {0, 0, 0, 1, 1, 1, 1}, "ITS Hits before target"}; + Configurable> hit_requirement_after_target{"hit_requirement_after_target", {0, 0, 0, 0, 0, 1, 1}, "ITS Hits after target"}; + Configurable useTOF{"useTOF", true, "use TOF for PID"}; + Configurable nsigmaTPCmin{"nsigmaTPCmin", -3.0f, "Minimum nsigma TPC"}; + Configurable nsigmaTPCmax{"nsigmaTPCmax", +3.0f, "Maximum nsigma TPC"}; + Configurable nsigmaTOFmin{"nsigmaTOFmin", -3.0f, "Minimum nsigma TOF"}; + Configurable nsigmaTOFmax{"nsigmaTOFmax", +3.0f, "Maximum nsigma TOF"}; + Configurable minimumV0Radius{"minimumV0Radius", 0.5f, "Minimum V0 Radius"}; + Configurable maximumV0Radius{"maximumV0Radius", 40.0f, "Maximum V0 Radius"}; + Configurable minimumCascRadius{"minimumCascRadius", 0.5f, "Minimum Cascade Radius"}; + Configurable maximumCascRadius{"maximumCascRadius", 40.0f, "Maximum Cascade Radius"}; + Configurable dcanegtoPVmin{"dcanegtoPVmin", 0.1f, "Minimum DCA Neg To PV"}; + Configurable dcapostoPVmin{"dcapostoPVmin", 0.1f, "Minimum DCA Pos To PV"}; + Configurable dcaBachelorToPVmin{"dcaBachelorToPVmin", 0.1f, "Minimum DCA bachelor To PV"}; + Configurable dcaV0ToPVmin{"dcaV0ToPVmin", 0.1f, "Minimum DCA V0 To PV for cascades"}; + Configurable v0cospaMin{"v0cospaMin", 0.99f, "Minimum V0 CosPA"}; + Configurable casccospaMin{"casccospaMin", 0.99f, "Minimum Cascade CosPA"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, "Maximum DCA Daughters"}; + Configurable dcaCascDaughtersMax{"dcaCascDaughtersMax", 0.5f, "Maximum DCA Cascade Daughters"}; + Configurable Rmin_beforeAbs{"Rmin_beforeAbs", 10.0f, "Rmin before target"}; + Configurable Rmax_beforeAbs{"Rmax_beforeAbs", 15.0f, "Rmax before target"}; + Configurable Rmin_afterAbs{"Rmin_afterAbs", 26.0f, "Rmin after target"}; + Configurable Rmax_afterAbs{"Rmax_afterAbs", 31.0f, "Rmax after target"}; + + void init(InitContext const&) + { + // Histograms + registryQC.add("event_counter", "event counter", HistType::kTH1F, {{4, 0, 4, "number of events in data (first 2 bins) and mc (last 2 bins)"}}); + + // K0 short + registryData.add("K0_before_target_data", "K0 before target data", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {240, 0.44, 0.56, "m (GeV/c^{2})"}}); + registryData.add("K0_after_target_data", "K0 after target data", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {240, 0.44, 0.56, "m (GeV/c^{2})"}}); + registryMC.add("K0_before_target_mc", "K0 before target mc", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {240, 0.44, 0.56, "m (GeV/c^{2})"}}); + registryMC.add("K0_after_target_mc", "K0 after target mc", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {240, 0.44, 0.56, "m (GeV/c^{2})"}}); + + // Lambda and Antilambda + registryData.add("Lambda_before_target_data", "Lambda before target data", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.09, 1.14, "m (GeV/c^{2})"}}); + registryData.add("Lambda_after_target_data", "Lambda after target data", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.09, 1.14, "m (GeV/c^{2})"}}); + registryData.add("AntiLambda_before_target_data", "AntiLambda before target data", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.09, 1.14, "m (GeV/c^{2})"}}); + registryData.add("AntiLambda_after_target_data", "AntiLambda after target data", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.09, 1.14, "m (GeV/c^{2})"}}); + registryMC.add("Lambda_before_target_mc", "Lambda before target mc", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.09, 1.14, "m (GeV/c^{2})"}}); + registryMC.add("Lambda_after_target_mc", "Lambda after target mc", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.09, 1.14, "m (GeV/c^{2})"}}); + registryMC.add("AntiLambda_before_target_mc", "AntiLambda before target mc", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.09, 1.14, "m (GeV/c^{2})"}}); + registryMC.add("AntiLambda_after_target_mc", "AntiLambda after target mc", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.09, 1.14, "m (GeV/c^{2})"}}); + + // Resolution + registryMC.add("K0_Rresolution_before_target", "K0 Rresolution before target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {500, -5, 5, "#Delta R (cm)"}}); + registryMC.add("K0_Rresolution_after_target", "K0 Rresolution after target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {500, -5, 5, "#Delta R (cm)"}}); + registryMC.add("Lambda_Rresolution_before_target", "Lambda Rresolution before target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {500, -5, 5, "#Delta R (cm)"}}); + registryMC.add("Lambda_Rresolution_after_target", "Lambda Rresolution after target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {500, -5, 5, "#Delta R (cm)"}}); + registryMC.add("AntiLambda_Rresolution_before_target", "AntiLambda Rresolution before target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {500, -5, 5, "#Delta R (cm)"}}); + registryMC.add("AntiLambda_Rresolution_after_target", "AntiLambda Rresolution after target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {500, -5, 5, "#Delta R (cm)"}}); + + /* + registryData.add("Csi_before_target", "Csi_before_target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.305, 1.34, "m (GeV/c)"}}); + registryData.add("Csi_after_target", "Csi_after_target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.305, 1.34, "m (GeV/c)"}}); + registryData.add("AntiCsi_before_target", "AntiCsi_before_target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.3, 1.35, "m (GeV/c)"}}); + registryData.add("AntiCsi_after_target", "AntiCsi_after_target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.3, 1.35, "m (GeV/c)"}}); + registryData.add("Omega_before_target", "Omega_before_target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.6, 1.75, "m (GeV/c)"}}); + registryData.add("Omega_after_target", "Omega_after_target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.6, 1.75, "m (GeV/c)"}}); + registryData.add("AntiOmega_before_target", "AntiOmega_before_target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.6, 1.75, "m (GeV/c)"}}); + registryData.add("AntiOmega_after_target", "AntiOmega_after_target", HistType::kTH2F, {{200, 0.0, 10.0, "p (GeV/c)"}, {200, 1.6, 1.75, "m (GeV/c)"}});*/ + } + + bool hasHitOnITSlayer(uint8_t itsClsmap, int layer) + { + + unsigned char test_bit = 1 << layer; + return (itsClsmap & test_bit); + } + + // Single-Track Selection + template + bool passedSingleTrackSelection(const T1& track, const C& collision) + { + // Single-Track Selections + if (!track.hasITS()) + return false; + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < minTPCnClsFound) + return false; + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) + return false; + if (track.tpcChi2NCl() > maxChi2TPC) + return false; + if (track.eta() < etaMin || track.eta() > etaMax) + return false; + if (useTOF && (!track.hasTOF())) + return false; + return true; + } + + // K0s Selections + template + bool passedK0Selection(const T1& v0, const T2& ntrack, const T2& ptrack, + const C& collision) + { + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + // Momentum K0 Daughters + float p_k0postrack = TMath::Sqrt(v0.pxpos() * v0.pxpos() + v0.pypos() * v0.pypos() + v0.pzpos() * v0.pzpos()); + float p_k0negtrack = TMath::Sqrt(v0.pxneg() * v0.pxneg() + v0.pyneg() * v0.pyneg() + v0.pzneg() * v0.pzneg()); + + // Momentum Interval + if (p_k0postrack < pMin_k0postrack || p_k0postrack > pMax_k0postrack) + return false; + if (p_k0negtrack < pMin_k0negtrack || p_k0negtrack > pMax_k0negtrack) + return false; + + // V0 Selections + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < v0cospaMin) + return false; + if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + return false; + if (v0.dcaV0daughters() > dcaV0DaughtersMax) + return false; + if (v0.dcapostopv() < dcapostoPVmin) + return false; + if (v0.dcanegtopv() < dcanegtoPVmin) + return false; + + // PID Selections (TPC) + if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (useTOF) { + if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) + return false; + if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) + return false; + } + + return true; + } + + // Lambda Selections + template + bool passedLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, + const C& collision) + { + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + // Momentum Lambda Daughters + float p_Lambdapostrack = TMath::Sqrt(v0.pxpos() * v0.pxpos() + v0.pypos() * v0.pypos() + v0.pzpos() * v0.pzpos()); + float p_Lambdanegtrack = TMath::Sqrt(v0.pxneg() * v0.pxneg() + v0.pyneg() * v0.pyneg() + v0.pzneg() * v0.pzneg()); + + // Momentum Interval + if (p_Lambdapostrack < pMin_Lambda_proton || p_Lambdapostrack > pMax_Lambda_proton) + return false; + if (p_Lambdanegtrack < pMin_Lambda_pion || p_Lambdanegtrack > pMax_Lambda_pion) + return false; + + // V0 Selections + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < v0cospaMin) + return false; + if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + return false; + if (v0.dcaV0daughters() > dcaV0DaughtersMax) + return false; + if (v0.dcapostopv() < dcapostoPVmin) + return false; + if (v0.dcanegtopv() < dcanegtoPVmin) + return false; + + // PID Selections (TPC) + if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || ptrack.tpcNSigmaPr() > nsigmaTPCmax) + return false; + if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (useTOF) { + if (ptrack.tofNSigmaPr() < nsigmaTOFmin || ptrack.tofNSigmaPr() > nsigmaTOFmax) + return false; + if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) + return false; + } + + return true; + } + + // AntiLambda Selections + template + bool passedAntiLambdaSelection(const T1& v0, const T2& ntrack, const T2& ptrack, + const C& collision) + { + // Single-Track Selections + if (!passedSingleTrackSelection(ptrack, collision)) + return false; + if (!passedSingleTrackSelection(ntrack, collision)) + return false; + + // Momentum Lambda Daughters + float p_Lambdapostrack = TMath::Sqrt(v0.pxpos() * v0.pxpos() + v0.pypos() * v0.pypos() + v0.pzpos() * v0.pzpos()); + float p_Lambdanegtrack = TMath::Sqrt(v0.pxneg() * v0.pxneg() + v0.pyneg() * v0.pyneg() + v0.pzneg() * v0.pzneg()); + + // Momentum Interval + if (p_Lambdapostrack < pMin_Lambda_pion || p_Lambdapostrack > pMax_Lambda_pion) + return false; + if (p_Lambdanegtrack < pMin_Lambda_proton || p_Lambdanegtrack > pMax_Lambda_proton) + return false; + + // V0 Selections + if (v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < v0cospaMin) + return false; + if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) + return false; + if (v0.dcaV0daughters() > dcaV0DaughtersMax) + return false; + if (v0.dcapostopv() < dcapostoPVmin) + return false; + if (v0.dcanegtopv() < dcanegtoPVmin) + return false; + + // PID Selections (TPC) + if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (useTOF) { + if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) + return false; + if (ntrack.tofNSigmaPr() < nsigmaTOFmin || ntrack.tofNSigmaPr() > nsigmaTOFmax) + return false; + } + + return true; + } + + // Process Data + void processData(SelectedCollisions::iterator const& collision, aod::V0Datas const& fullV0s, FullTracks const& tracks) + { + + // Event Counter (before event sel) + registryQC.fill(HIST("event_counter"), 0.5); + + // Event Selection + if (!collision.sel8()) + return; + + // Event Counter (after event sel) + registryQC.fill(HIST("event_counter"), 1.5); + + auto hit_ITS_before_target = static_cast>(hit_requirement_before_target); + auto hit_ITS_after_target = static_cast>(hit_requirement_after_target); + + // Loop over Reconstructed V0s + for (auto& v0 : fullV0s) { + + // Positive and Negative Tracks + const auto& posTrack = v0.posTrack_as(); + const auto& negTrack = v0.negTrack_as(); + + // Require TPC Refit + if (!posTrack.passedTPCRefit()) + continue; + if (!negTrack.passedTPCRefit()) + continue; + + // ITS Requirement + bool satisfyITSreq = true; + if (requirehitsITS) { + for (int i = 0; i < 7; i++) { + if (hit_ITS_before_target[i] > 0 && !hasHitOnITSlayer(posTrack.itsClusterMap(), i)) { + satisfyITSreq = false; + break; + } + if (hit_ITS_after_target[i] > 0 && !hasHitOnITSlayer(negTrack.itsClusterMap(), i)) { + satisfyITSreq = false; + break; + } + } + } + + if (requirehitsITS && (!satisfyITSreq)) + continue; + + // K0 Short + if (passedK0Selection(v0, negTrack, posTrack, collision)) { + + // Before Target + if (v0.v0radius() > Rmin_beforeAbs && v0.v0radius() < Rmax_beforeAbs) + registryData.fill(HIST("K0_before_target_data"), v0.p(), v0.mK0Short()); + + // After Target + if (v0.v0radius() > Rmin_afterAbs && v0.v0radius() < Rmax_afterAbs) + registryData.fill(HIST("K0_after_target_data"), v0.p(), v0.mK0Short()); + } + + // Lambda + if (passedLambdaSelection(v0, negTrack, posTrack, collision)) { + + // Before Target + if (v0.v0radius() > Rmin_beforeAbs && v0.v0radius() < Rmax_beforeAbs) + registryData.fill(HIST("Lambda_before_target_data"), v0.p(), v0.mLambda()); + + // After Target + if (v0.v0radius() > Rmin_afterAbs && v0.v0radius() < Rmax_afterAbs) + registryData.fill(HIST("Lambda_after_target_data"), v0.p(), v0.mLambda()); + } + + // AntiLambda + if (passedAntiLambdaSelection(v0, negTrack, posTrack, collision)) { + + // Before Target + if (v0.v0radius() > Rmin_beforeAbs && v0.v0radius() < Rmax_beforeAbs) + registryData.fill(HIST("AntiLambda_before_target_data"), v0.p(), v0.mAntiLambda()); + + // After Target + if (v0.v0radius() > Rmin_afterAbs && v0.v0radius() < Rmax_afterAbs) + registryData.fill(HIST("AntiLambda_after_target_data"), v0.p(), v0.mAntiLambda()); + } + + } // end loop on V0s + } // end processData + PROCESS_SWITCH(vzero_cascade_absorption, processData, "Process data", true); + + // Process MC + void processMC(soa::Join::iterator const& collision, aod::V0Datas const& fullV0s, MCTracks const& tracks, aod::McParticles& mcParticles, aod::McCollisions const& mcCollisions) + { + + // Event Counter (before event sel) + registryQC.fill(HIST("event_counter"), 2.5); + + // Event Selection + if (!collision.sel8()) + return; + + // Event Counter (after event sel) + registryQC.fill(HIST("event_counter"), 3.5); + + // Loop over Reconstructed V0s + for (auto& v0 : fullV0s) { + + // Positive and Negative Tracks + const auto& posTrack = v0.posTrack_as(); + const auto& negTrack = v0.negTrack_as(); + + // Require TPC Refit + if (!posTrack.passedTPCRefit()) + continue; + if (!negTrack.passedTPCRefit()) + continue; + + auto hit_ITS_before_target = static_cast>(hit_requirement_before_target); + auto hit_ITS_after_target = static_cast>(hit_requirement_after_target); + + // ITS Requirement + bool satisfyITSreq = true; + if (requirehitsITS) { + for (int i = 0; i < 7; i++) { + if (hit_ITS_before_target[i] > 0 && !hasHitOnITSlayer(posTrack.itsClusterMap(), i)) { + satisfyITSreq = false; + break; + } + if (hit_ITS_after_target[i] > 0 && !hasHitOnITSlayer(negTrack.itsClusterMap(), i)) { + satisfyITSreq = false; + break; + } + } + } + + if (requirehitsITS && (!satisfyITSreq)) + continue; + + // MC Particles + if (!posTrack.has_mcParticle()) + continue; + if (!negTrack.has_mcParticle()) + continue; + + auto posParticle = posTrack.mcParticle_as(); + auto negParticle = negTrack.mcParticle_as(); + if (!posParticle.has_mothers() || !negParticle.has_mothers()) { + continue; + } + + bool isK0s = false; + bool isLambda = false; + bool isAntiLambda = false; + + for (auto& particleMotherOfNeg : negParticle.mothers_as()) { + for (auto& particleMotherOfPos : posParticle.mothers_as()) { + if (particleMotherOfNeg == particleMotherOfPos && particleMotherOfNeg.pdgCode() == 310) + isK0s = true; + + if (particleMotherOfNeg == particleMotherOfPos && particleMotherOfNeg.pdgCode() == +3122) + isLambda = true; + if (particleMotherOfNeg == particleMotherOfPos && particleMotherOfNeg.pdgCode() == -3122) + isAntiLambda = true; + } + } + + // Resolution in radial position + float Rgen = TMath::Sqrt(posParticle.vx() * posParticle.vx() + posParticle.vy() * posParticle.vy()); + float Rrec = v0.v0radius(); + float deltaR = Rgen - Rrec; + + // K0 Short + if (passedK0Selection(v0, negTrack, posTrack, collision) && isK0s) { + + // Before Target + if (v0.v0radius() > Rmin_beforeAbs && v0.v0radius() < Rmax_beforeAbs) { + registryMC.fill(HIST("K0_before_target_mc"), v0.p(), v0.mK0Short()); + registryMC.fill(HIST("K0_Rresolution_before_target"), v0.p(), deltaR); + } + + // After Target + if (v0.v0radius() > Rmin_afterAbs && v0.v0radius() < Rmax_afterAbs) { + registryMC.fill(HIST("K0_after_target_mc"), v0.p(), v0.mK0Short()); + registryMC.fill(HIST("K0_Rresolution_after_target"), v0.p(), deltaR); + } + } + + // Lambda + if (passedLambdaSelection(v0, negTrack, posTrack, collision) && isLambda) { + + // Before Target + if (v0.v0radius() > Rmin_beforeAbs && v0.v0radius() < Rmax_beforeAbs) { + registryMC.fill(HIST("Lambda_before_target_mc"), v0.p(), v0.mLambda()); + registryMC.fill(HIST("Lambda_Rresolution_before_target"), v0.p(), deltaR); + } + + // After Target + if (v0.v0radius() > Rmin_afterAbs && v0.v0radius() < Rmax_afterAbs) { + registryMC.fill(HIST("Lambda_after_target_mc"), v0.p(), v0.mLambda()); + registryMC.fill(HIST("Lambda_Rresolution_after_target"), v0.p(), deltaR); + } + } + + // AntiLambda + if (passedAntiLambdaSelection(v0, negTrack, posTrack, collision) && isAntiLambda) { + + // Before Target + if (v0.v0radius() > Rmin_beforeAbs && v0.v0radius() < Rmax_beforeAbs) { + registryMC.fill(HIST("AntiLambda_before_target_mc"), v0.p(), v0.mAntiLambda()); + registryMC.fill(HIST("AntiLambda_Rresolution_before_target"), v0.p(), deltaR); + } + + // After Target + if (v0.v0radius() > Rmin_afterAbs && v0.v0radius() < Rmax_afterAbs) { + registryMC.fill(HIST("AntiLambda_after_target_mc"), v0.p(), v0.mAntiLambda()); + registryMC.fill(HIST("AntiLambda_Rresolution_after_target"), v0.p(), deltaR); + } + } + + } // end loop on V0s + } // end processMC + PROCESS_SWITCH(vzero_cascade_absorption, processMC, "Process mc", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Utils/collisionCuts.h b/PWGLF/Utils/collisionCuts.h index 83847342756..db1c64cf383 100644 --- a/PWGLF/Utils/collisionCuts.h +++ b/PWGLF/Utils/collisionCuts.h @@ -20,7 +20,6 @@ #ifndef PWGLF_UTILS_COLLISIONCUTS_H_ #define PWGLF_UTILS_COLLISIONCUTS_H_ -#include "Common/CCDB/TriggerAliases.h" #include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" @@ -44,7 +43,7 @@ class CollisonCuts mCutsSet = true; mZvtxMax = zvtxMax; mCheckTrigger = checkTrigger; - mTrigger = static_cast(trig); + mTrigger = trig; mCheckOffline = checkOffline; mCheckIsRun3 = checkRun3; } @@ -57,12 +56,14 @@ class CollisonCuts LOGF(error, "Event selection not set - quitting!"); } mHistogramRegistry = registry; - mHistogramRegistry->add("Event/posZ", "; vtx_{z} (cm); Entries", kTH1F, {{300, -12.5, 12.5}}); - mHistogramRegistry->add("Event/MultFV0M", "; vMultV0M; Entries", kTH1F, {{120, 0, 120}}); - mHistogramRegistry->add("Event/MultFT0M", "; vMultT0M; Entries", kTH1F, {{120, 0, 120}}); - mHistogramRegistry->add("Event/MultFT0C", "; vMultT0C; Entries", kTH1F, {{120, 0, 120}}); - mHistogramRegistry->add("Event/MultFT0A", "; vMultT0A; Entries", kTH1F, {{120, 0, 120}}); - mHistogramRegistry->add("Event/MultTPC", "; vMultTPC; Entries", kTH1F, {{300, 0, 3000}}); + mHistogramRegistry->add("Event/posZ", "; vtx_{z} (cm); Entries", kTH1F, {{250, -12.5, 12.5}}); + mHistogramRegistry->add("Event/CentFV0A", "; vCentV0A; Entries", kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0M", "; vCentT0M; Entries", kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0C", "; vCentT0C; Entries", kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/CentFT0A", "; vCentT0A; Entries", kTH1F, {{110, 0, 110}}); + mHistogramRegistry->add("Event/MultFT0M", "; FT0M signal; Entries", kTH1F, {{100000, 0, 100000}}); + mHistogramRegistry->add("Event/MultFT0C", "; FT0C signal; Entries", kTH1F, {{100000, 0, 100000}}); + mHistogramRegistry->add("Event/MultFT0A", "; FT0A signal; Entries", kTH1F, {{100000, 0, 100000}}); } /// Print some debug information @@ -85,30 +86,30 @@ class CollisonCuts LOGF(debug, "Vertex out of range"); return false; } - if (mCheckIsRun3) { + if (mCheckIsRun3) { // Run3 case if (mCheckOffline && !col.sel8()) { LOGF(debug, "Offline selection failed (Run3)"); return false; } - } else { - if (mCheckTrigger && !col.alias_bit(mTrigger)) { - LOGF(debug, "Trigger selection failed"); - if (mInitialTriggerScan) { - LOGF(debug, "Trigger scan initialized"); - for (int i = 0; i < kNaliases; i++) { - if (col.alias_bit(i)) { - LOGF(debug, "Trigger %d fired", i); - } - } - mInitialTriggerScan = false; - } - return false; - } + } else { // Run2 case if (mCheckOffline && !col.sel7()) { LOGF(debug, "Offline selection failed (sel7)"); return false; } } + if (mCheckTrigger && !col.alias_bit(mTrigger)) { + LOGF(debug, "Trigger selection failed"); + if (mInitialTriggerScan) { // Print out the trigger bits + LOGF(debug, "Trigger scan initialized"); + for (int i = 0; i < kNaliases; i++) { + if (col.alias_bit(i)) { + LOGF(debug, "Trigger %d fired", i); + } + } + mInitialTriggerScan = false; + } + return false; + } return true; } @@ -120,29 +121,16 @@ class CollisonCuts { if (mHistogramRegistry) { mHistogramRegistry->fill(HIST("Event/posZ"), col.posZ()); - mHistogramRegistry->fill(HIST("Event/MultFV0M"), col.multFV0M()); - mHistogramRegistry->fill(HIST("Event/MultFT0M"), col.centFT0M()); - mHistogramRegistry->fill(HIST("Event/MultFT0C"), col.centFT0C()); - mHistogramRegistry->fill(HIST("Event/MultFT0A"), col.centFT0A()); - mHistogramRegistry->fill(HIST("Event/MultTPC"), col.multTPC()); + mHistogramRegistry->fill(HIST("Event/CentFV0A"), col.centFV0A()); + mHistogramRegistry->fill(HIST("Event/CentFT0M"), col.centFT0M()); + mHistogramRegistry->fill(HIST("Event/CentFT0C"), col.centFT0C()); + mHistogramRegistry->fill(HIST("Event/CentFT0A"), col.centFT0A()); + mHistogramRegistry->fill(HIST("Event/MultFT0M"), col.multFT0M()); + mHistogramRegistry->fill(HIST("Event/MultFT0C"), col.multFT0C()); + mHistogramRegistry->fill(HIST("Event/MultFT0A"), col.multFT0A()); } } - /// \todo to be implemented! - /// Compute the sphericity of an event - /// Important here is that the filter on tracks does not interfere here! - /// In Run 2 we used here global tracks within |eta| < 0.8 - /// \tparam T1 type of the collision - /// \tparam T2 type of the tracks - /// \param col Collision - /// \param tracks All tracks - /// \return value of the sphericity of the event - template - float computeSphericity(T1 const& col, T2 const& tracks) - { - return 2.f; - } - private: HistogramRegistry* mHistogramRegistry = nullptr; ///< For QA output bool mCutsSet = false; ///< Protection against running without cuts @@ -150,7 +138,7 @@ class CollisonCuts bool mCheckOffline = false; ///< Check for offline criteria (might change) bool mCheckIsRun3 = false; ///< Check if running on Pilot Beam bool mInitialTriggerScan = false; ///< Check trigger when the event is first selected - triggerAliases mTrigger = kINT7; ///< Trigger to check for + int mTrigger = kINT7; ///< Trigger to check for float mZvtxMax = 999.f; ///< Maximal deviation from nominal z-vertex (cm) }; } // namespace o2::analysis diff --git a/PWGMM/Lumi/Tasks/CMakeLists.txt b/PWGMM/Lumi/Tasks/CMakeLists.txt index cc7418c07f5..154414e30cd 100644 --- a/PWGMM/Lumi/Tasks/CMakeLists.txt +++ b/PWGMM/Lumi/Tasks/CMakeLists.txt @@ -25,3 +25,12 @@ o2physics_add_dpl_workflow(lumifddft0 O2::DetectorsCommonDataFormats O2::DetectorsVertexing COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(fitvdm + SOURCES fitLumi.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + O2::ReconstructionDataFormats + O2::DetectorsBase + O2::DetectorsCommonDataFormats + O2::DetectorsVertexing + COMPONENT_NAME Analysis) diff --git a/PWGMM/Lumi/Tasks/LumiFDDFT0.cxx b/PWGMM/Lumi/Tasks/LumiFDDFT0.cxx index 8baa57ccbfd..37f7921a064 100644 --- a/PWGMM/Lumi/Tasks/LumiFDDFT0.cxx +++ b/PWGMM/Lumi/Tasks/LumiFDDFT0.cxx @@ -46,6 +46,7 @@ #include "CCDB/CcdbApi.h" #include "DataFormatsCalibration/MeanVertexObject.h" +using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using BCsWithTimestamps = soa::Join; diff --git a/PWGMM/Lumi/Tasks/fitLumi.cxx b/PWGMM/Lumi/Tasks/fitLumi.cxx new file mode 100644 index 00000000000..b1f153c3be9 --- /dev/null +++ b/PWGMM/Lumi/Tasks/fitLumi.cxx @@ -0,0 +1,115 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// author: arvind.khuntia@cern.ch + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/EventSelection.h" +#include "DataFormatsFDD/Digit.h" +#include "DataFormatsFIT/Triggers.h" +#include "Common/DataModel/FT0Corrected.h" + +#include "CCDB/CcdbApi.h" +#include "CommonDataFormat/BunchFilling.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "TH1F.h" +#include "TH2F.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using BCPattern = std::bitset; +const int nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; + +struct fitLumi { + int nTF = 0; + HistogramRegistry registry; + int nBins, nCollBins; + int relTS; + Configurable startTimeInS{"startTime", 1668079200, "unix start time"}; + Configurable endTimeInS{"endTime", 1668098700, "unix end time"}; + Configurable> collBCArray{"collBCArray", {1022, 1062, 1102, 1142, 2015, 2055, 2161, 2201, 2241, 2281, 2321, 2361, 2401, 2441, 2481, 2521, 2561, 2601, 2641, 2681}, "Colliding BC for the VdM"}; + + void init(InitContext&) + { + nBins = uint64_t(endTimeInS - startTimeInS) / 2.; + nCollBins = collBCArray->size(); + // Hist for FT0 + registry.add("FT0/VtxTrig", "vertex trigger;ts (s); Counts", {HistType::kTH1F, {{nBins, 0., static_cast(endTimeInS - startTimeInS)}}}); + registry.add("FT0/VtxTrigPerBC", "vertex trigger per BC;ts (s); Counts", {HistType::kTH2F, {{nBins, 0., static_cast(endTimeInS - startTimeInS)}, {nCollBins - 1, 0., static_cast(nCollBins)}}}); + registry.add("FT0/TF", "TF ;ts (s); Counts (nTF)", {HistType::kTH1F, {{nBins, 0., static_cast(endTimeInS - startTimeInS)}}}); + registry.add("FT0/CollBCMap", "BC map for the colliding bcsr;BC entry; entries", {HistType::kTH1F, {{nCollBins - 1, 0., static_cast(nCollBins)}}}); + // Hist for FDD + registry.add("FDD/VtxTrig", "vertex trigger;ts (s); Counts", {HistType::kTH1F, {{nBins, 0., static_cast(endTimeInS - startTimeInS)}}}); + registry.add("FDD/VtxTrigPerBC", "vertex trigger per BC;ts (s); Counts", {HistType::kTH2F, {{nBins, 0., static_cast(endTimeInS - startTimeInS)}, {nCollBins - 1, 0., static_cast(nCollBins)}}}); + } + + using BCsWithTimestamps = soa::Join; + void process(aod::FT0s const& ft0s, aod::FDDs const& fdds, aod::BCsWithTimestamps const&) + { + if (nTF < 1) { + for (int iBin = 0; iBin < nCollBins; iBin++) { + registry.get(HIST("FT0/CollBCMap"))->SetBinContent(iBin + 1, collBCArray->at(iBin)); + LOG(debug) << "bin " << iBin << " value " << collBCArray->at(iBin); + } + } + + for (auto const& ft0 : ft0s) { + auto bc = ft0.bc_as(); + if (!bc.timestamp()) { + continue; + } + std::bitset<8> fT0Triggers = ft0.triggerMask(); + auto localBC = bc.globalBC() % nBCsPerOrbit; + auto pos = std::find(collBCArray->begin(), collBCArray->end(), localBC); + bool vertex = fT0Triggers[o2::fdd::Triggers::bitVertex]; + auto tsInSecond = ((bc.timestamp() * 1.e-3) - startTimeInS); // covert ts from ms to second + if (vertex) { + registry.get(HIST("FT0/VtxTrig"))->Fill(tsInSecond); + if (pos != collBCArray->end()) { + registry.get(HIST("FT0/VtxTrigPerBC"))->Fill(tsInSecond, std::distance(collBCArray->begin(), pos)); + } + } // vertex + } // ft0 + + for (auto const& fdd : fdds) { + auto bc = fdd.bc_as(); + if (!bc.timestamp()) { + continue; + } + std::bitset<8> fddTriggers = fdd.triggerMask(); + auto localBC = bc.globalBC() % nBCsPerOrbit; + auto pos = std::find(collBCArray->begin(), collBCArray->end(), localBC); + bool vertex = fddTriggers[o2::fdd::Triggers::bitVertex]; + auto tsInSecond = ((bc.timestamp() * 1.e-3) - startTimeInS); // covert ts from ms to second + if (vertex) { + registry.get(HIST("FDD/VtxTrig"))->Fill(tsInSecond); + if (pos != collBCArray->end()) { + registry.get(HIST("FDD/VtxTrigPerBC"))->Fill(tsInSecond, std::distance(collBCArray->begin(), pos)); + } + } // vertex + } // fdd + + auto timeFirstInTFinS = ft0s.iteratorAt(0).bc_as().timestamp() * 1.e-3; + registry.get(HIST("FT0/TF"))->Fill(timeFirstInTFinS - startTimeInS); + nTF++; + } // process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"ft0qavdm"})}; +} diff --git a/PWGMM/Lumi/Tasks/lumi.cxx b/PWGMM/Lumi/Tasks/lumi.cxx index f8450a864d1..567ee49ce64 100644 --- a/PWGMM/Lumi/Tasks/lumi.cxx +++ b/PWGMM/Lumi/Tasks/lumi.cxx @@ -77,6 +77,7 @@ DECLARE_SOA_TABLE(EventInfo, "AOD", "EventInfo", full::TimeStamp, full::VertexX, full::VertexChi2, full::NContrib); } // namespace o2::aod +using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGMM/Mult/Tasks/CMakeLists.txt b/PWGMM/Mult/Tasks/CMakeLists.txt index 79a0d56f9ec..5a73dd92729 100644 --- a/PWGMM/Mult/Tasks/CMakeLists.txt +++ b/PWGMM/Mult/Tasks/CMakeLists.txt @@ -19,6 +19,11 @@ o2physics_add_dpl_workflow(dndeta PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(puremc-dndeta + SOURCES puremc-dndeta.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(dndeta-hi SOURCES dndeta-hi.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -49,3 +54,8 @@ o2physics_add_dpl_workflow(effpt-mft SOURCES effpt-mft.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(heavy-ion-mult + SOURCES heavy-ion-mult.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGMM/Mult/Tasks/dndeta-hi.cxx b/PWGMM/Mult/Tasks/dndeta-hi.cxx index 692fdcc1481..b99b34a883b 100644 --- a/PWGMM/Mult/Tasks/dndeta-hi.cxx +++ b/PWGMM/Mult/Tasks/dndeta-hi.cxx @@ -56,34 +56,37 @@ using namespace o2::framework::expressions; using namespace o2::aod::track; using namespace o2::aod; +using namespace o2::aod::evsel; using namespace o2::analysis; -using namespace o2::aod::hf_cand_2prong; -using namespace o2::aod::hf_cand_bplus; -using namespace o2::analysis::hf_cuts_bplus_to_d0_pi; using BCsRun3 = soa::Join; using MyCollisions = soa::Join; -using MyCollisionsCent = soa::Join; +using MyCollisionsCent = soa::Join; using FullBCs = soa::Join; using DaughterTrack = soa::Join; using ExTracks = soa::Join; using FiTracks = soa::Filtered; -using Particles = soa::Filtered; -using Particle = Particles::iterator; +// using FiTracks = ExTracks; +// using Particles = soa::Filtered>; +using Particles = soa::Join; +// using Particle = Particles; using LabeledTracks = soa::Join; using LabeledTracksEx = soa::Join; +using FiLTracks = soa::Filtered; using DaughterTracks = soa::Join; +typedef std::vector Bool_1d; enum { kECbegin = 0, kDATA = 1, kINEL, + kINELg0, kECend }; enum { kTrigbegin = 0, - kMBAND = 1, - kBackground, + kSel8 = 1, + kSel8g0, kTrigend }; enum { @@ -107,25 +110,67 @@ enum { kStepend }; -AxisSpec ZAxis = {60, -30, 30, "Z (cm)", "zaxis"}; +enum { + kParTypebegin = 0, + kParDATA = 1, + kMotherStrange, + kBkg, + kNotPrimary, + kPion, + kKaon, + kProtonMy, + kOPar, + kParTypeend +}; +enum { + kPtVarbegin = 0, + kNoPtVar = 1, + kPtUp, + kPtDw, + kPtVarend +}; + +namespace +{ +template +static constexpr bool hasCent() +{ + if constexpr (!soa::is_soa_join_v) { + return false; + } else if (T::template contains()) { + return true; + } else { + return false; + } +} +} // namespace + +AxisSpec ZAxis = {{-30, -20, -15, -10, -7, -5, -3, -2, -1, 0, 1, 2, 3, 5, 7, 10, 15, 20, 30}, "Z (cm)", "zaxis"}; AxisSpec DeltaZAxis = {61, -6.1, 6.1, "", "deltaz axis"}; AxisSpec DCAAxis = {601, -3.01, 3.01, "", "DCA axis"}; AxisSpec EtaAxis = {80, -4.0, 4.0, "#eta", "eta axis"}; +AxisSpec V0EtaAxis = {20, -1.0, 1.0, "#etav0", "eta axis"}; AxisSpec PhiAxis = {629, 0, 2 * M_PI, "Rad", "phi axis"}; -AxisSpec PtAxis = {2401, -0.005, 24.005, "#it{p}_{T} (GeV/c)", "P_{T} axis"}; +AxisSpec PtVarAxis = {kPtVarend - 1, kPtVarbegin + 0.5, kPtVarend - 0.5, "", "ptvar axis"}; AxisSpec EvtClassAxis = {kECend - 1, kECbegin + 0.5, kECend - 0.5, "", "event class"}; AxisSpec TrigClassAxis = {kTrigend - 1, kTrigbegin + 0.5, kTrigend - 0.5, "", "trigger class"}; -std::vector centBinning = {0, 10., 20., 30., 40., 50., 60., 70., 80., 100}; +AxisSpec ParticleTypeAxis = {kParTypeend - 1, kParTypebegin + 0.5, kParTypeend - 0.5, "", "Particle type"}; +std::vector centBinningPbPb = {0, 1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 60, 70, 80, 100}; +std::vector centBinning = {0., 0.01, 0.1, 1.0, 5.0, 10., 15., 20., 25., 30., 35., 40., 45., 50., 70., 100.0}; AxisSpec CentAxis = {centBinning, "", "centrality"}; +AxisSpec CentAxisPbPb = {centBinningPbPb, "", "centrality"}; AxisSpec SpeciesAxis = {kSpeciesend - 1, kSpeciesbegin + 0.5, kSpeciesend - 0.5, "", "species class"}; AxisSpec MassAxis = {600, 0.3f, 1.3f, "Mass (GeV/c^{2})", "Inv. Mass (GeV/c^{2})"}; AxisSpec SignAxis = {kSignend - 1, kSignbegin + 0.5, kSignend - 0.5, "", "sign"}; AxisSpec StepAxis = {kStepend - 1, kStepbegin + 0.5, kStepend - 0.5, "", "step"}; AxisSpec testAxis = {101, -0.5, 100.5, "", "test"}; -AxisSpec particleIDAxis = {10000, 0.5, 10000.5, "", "particleID"}; +AxisSpec multAxis = {1001, -0.5, 1000.5, "", "Ntrks"}; AxisSpec StatusCodeAxis = {3, -1.5, 2.5, "", "StatusCode"}; AxisSpec ProcessCodeAxis = {45, -1.5, 44.5, "", "StatusCode"}; +auto pi = TMath::Pi(); +AxisSpec phibin = {{0, pi / 2, pi, pi * 3. / 2, 2 * pi}, "#phi", "phi bin"}; + static constexpr TrackSelectionFlags::flagtype trackSelectionITS = TrackSelectionFlags::kITSNCls | TrackSelectionFlags::kITSChi2NDF | TrackSelectionFlags::kITSHits; @@ -142,10 +187,11 @@ struct MultiplicityCounter { SliceCache cache; Preslice perMCCol = aod::mcparticle::mcCollisionId; - Service pdg; + Service pdg; Configurable estimatorEta{"estimatorEta", 2.0, "eta range for INEL>0 sample definition"}; Configurable useEvSel{"useEvSel", true, "use event selection"}; + Configurable IsPbPb{"IsPbPb", false, "Is Pb-Pb"}; Configurable dcav0dau{"dcav0dau", 1.5, "DCA V0 Daughters"}; Configurable dcanegtopv{"dcanegtopv", 0.06, "DCA Neg To PV"}; @@ -155,69 +201,99 @@ struct MultiplicityCounter { Configurable etadau{"etadau", 4, "Eta Daughters"}; Configurable rapidity{"v0rapidity", 0.5, "V0 rapidity"}; - Configurable v0analysis{"v0analysis", false, "V0 analysis switch"}; Configurable mftanalysis{"mftanalysis", false, "mft analysis switch"}; + Configurable zvtxcut{"zvtxcut", false, "z vtx cut < 10cm"}; HistogramRegistry registry{ "registry", - {{"Events/Selection", ";status;events", {HistType::kTH1F, {{7, 0.5, 7.5}}}}}}; + {{"Selection", ";status;events", {HistType::kTH1F, {{17, 0.5, 17.5}}}}}}; std::vector usedTracksIds; void init(InitContext&) { - if (doprocessCountingWithCent) { - registry.add({"Tracks/ProcessCounting/Centrality/Centrality", " ; centrality_FT0C (%) ", {HistType::kTH1F, {CentAxis}}}); - registry.add({"Tracks/ProcessCounting/Centrality/hrecdndeta", "evntclass; triggerclass; zvtex, eta", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/ProcessCounting/Centrality/hrecpt", " eventclass; pt_gen; pt_rec ", {HistType::kTHnSparseD, {EvtClassAxis, PtAxis, PtAxis, CentAxis}}}); - registry.add({"Tracks/ProcessCounting/Centrality/hreczvtx", "evntclass; triggerclass; zvtex", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/ProcessCounting/Centrality/PhiEta", "; #varphi; #eta; tracks", {HistType::kTHnSparseD, {EvtClassAxis, PhiAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/ProcessCounting/Centrality/DCAXY", " ; DCA_{XY} (cm)", {HistType::kTHnSparseD, {EvtClassAxis, DCAAxis, CentAxis}}}); - registry.add({"Tracks/ProcessCounting/Centrality/DCAZ", " ; DCA_{Z} (cm)", {HistType::kTHnSparseD, {EvtClassAxis, DCAAxis, CentAxis}}}); - - if (v0analysis) { - registry.add({"Tracks/ProcessCounting/Centrality/hV0Count", "", {HistType::kTHnSparseD, {EvtClassAxis, SpeciesAxis, StepAxis, CentAxis}}}); - registry.add({"Tracks/ProcessCounting/Centrality/hV0DauEta", "", {HistType::kTHnSparseD, {EvtClassAxis, SignAxis, SpeciesAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/ProcessCounting/Centrality/hV0Mass", "species ; evntclass; K0shortMass; LambdaMass; AntiLambdaMass", {HistType::kTHnSparseD, {EvtClassAxis, SpeciesAxis, MassAxis, CentAxis}}}); - } - } - if (doprocessCountingWithoutCent) { - registry.add({"Tracks/ProcessCounting/hrecdndeta", "evntclass; triggerclass; zvtex, eta", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis, EtaAxis}}}); - registry.add({"Tracks/ProcessCounting/hrecpt", " eventclass; pt_gen; pt_rec ", {HistType::kTHnSparseD, {EvtClassAxis, PtAxis, PtAxis}}}); - registry.add({"Tracks/ProcessCounting/hreczvtx", "evntclass; triggerclass; zvtex", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis}}}); - registry.add({"Tracks/ProcessCounting/PhiEta", "; #varphi; #eta; tracks", {HistType::kTHnSparseD, {EvtClassAxis, PhiAxis, EtaAxis}}}); - registry.add({"Tracks/ProcessCounting/DCAXY", " ; DCA_{XY} (cm)", {HistType::kTHnSparseD, {EvtClassAxis, DCAAxis}}}); - registry.add({"Tracks/ProcessCounting/DCAZ", " ; DCA_{Z} (cm)", {HistType::kTHnSparseD, {EvtClassAxis, DCAAxis}}}); - - if (v0analysis) { - registry.add({"Tracks/ProcessCounting/hV0Count", "", {HistType::kTHnSparseD, {EvtClassAxis, SpeciesAxis, StepAxis}}}); - registry.add({"Tracks/ProcessCounting/hV0DauEta", "", {HistType::kTHnSparseD, {EvtClassAxis, SignAxis, SpeciesAxis, EtaAxis}}}); - registry.add({"Tracks/ProcessCounting/hV0Mass", "species ; evntclass; K0shortMass; LambdaMass; AntiLambdaMass", {HistType::kTHnSparseD, {EvtClassAxis, SpeciesAxis, MassAxis}}}); - } - } - if (doprocessMCCounting) { - registry.add({"Tracks/ProcessMCCounting/hrecdndeta", "evntclass; triggerclass; zvtex, eta", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis, EtaAxis}}}); - registry.add({"Tracks/ProcessMCCounting/hreczvtx", "evntclass; triggerclass; zvtex", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis}}}); - registry.add({"Tracks/ProcessMCCounting/hrecpt", " eventclass; pt_gen; pt_rec ", {HistType::kTHnSparseD, {EvtClassAxis, PtAxis, PtAxis}}}); - registry.add({"Tracks/ProcessMCCounting/hgenpt", " eventclass; centrality; pt; ", {HistType::kTHnSparseD, {EvtClassAxis, PtAxis}}}); - registry.add({"Tracks/ProcessMCCounting/PhiEta", "; #varphi; #eta; tracks", {HistType::kTHnSparseD, {EvtClassAxis, PhiAxis, EtaAxis}}}); - registry.add({"Tracks/ProcessMCCounting/DCAXY", " ; DCA_{XY} (cm)", {HistType::kTHnSparseD, {EvtClassAxis, DCAAxis}}}); - registry.add({"Tracks/ProcessMCCounting/DCAZ", " ; DCA_{Z} (cm)", {HistType::kTHnSparseD, {EvtClassAxis, DCAAxis}}}); - - if (v0analysis) { - registry.add({"Tracks/ProcessMCCounting/hV0Count", "", {HistType::kTHnSparseD, {EvtClassAxis, SpeciesAxis, StepAxis}}}); - registry.add({"Tracks/ProcessMCCounting/hV0DauEta", "", {HistType::kTHnSparseD, {EvtClassAxis, SignAxis, SpeciesAxis, EtaAxis}}}); - registry.add({"Tracks/ProcessMCCounting/hV0Mass", "species ; evntclass; K0shortMass; LambdaMass; AntiLambdaMass", {HistType::kTHnSparseD, {EvtClassAxis, SpeciesAxis, MassAxis}}}); - registry.add({"Tracks/ProcessMCCounting/hMotherV0Count", "", {HistType::kTHnSparseD, {EvtClassAxis, SpeciesAxis}}}); - } - registry.add({"Tracks/ProcessMCCounting/hStatusCode", "", {HistType::kTHnSparseD, {EvtClassAxis, StepAxis, StatusCodeAxis}}}); - registry.add({"Tracks/ProcessMCCounting/hMCStatusCode", "", {HistType::kTHnSparseD, {EvtClassAxis, StepAxis, StatusCodeAxis}}}); - registry.add({"Tracks/ProcessMCCounting/hProcessCode", "", {HistType::kTHnSparseD, {EvtClassAxis, StepAxis, ProcessCodeAxis}}}); - } - if (doprocessGen) { - registry.add({"Tracks/ProcessGen/hgendndeta", "evntclass; zvtex, eta", {HistType::kTHnSparseD, {EvtClassAxis, ZAxis, EtaAxis}}}); - registry.add({"Tracks/ProcessGen/hgenzvtx", "evntclass; zvtex", {HistType::kTHnSparseD, {EvtClassAxis, ZAxis}}}); + registry.add({"hetaresponse", ";etaresponse", {HistType::kTH2D, {{80, -4, 4}, {80, -4, 4}}}}); + registry.add({"hft0multiplicity", ";multiplicity", {HistType::kTH1D, {{20000, 0, 200000}}}}); + registry.add({"hcentrality", IsPbPb ? " ; centrality_FT0C (%) " : "; centrality_FT0M", {HistType::kTH1F, {{1001, -0.05, 100.05}}}}); + registry.add({"hrecdndeta", "evntclass; triggerclass; zvtex, eta", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis, EtaAxis, IsPbPb ? CentAxisPbPb : CentAxis, ParticleTypeAxis, phibin}}}); + registry.add({"hreczvtx", "evntclass; triggerclass; zvtex", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis, IsPbPb ? CentAxisPbPb : CentAxis}}}); + registry.add({"hphieta", "; #varphi; #eta; tracks", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, PhiAxis, EtaAxis, IsPbPb ? CentAxisPbPb : CentAxis}}}); + registry.add({"hrecdndetamissing", "evntclass; triggerclass; zvtex, eta", {HistType::kTHnSparseD, {EvtClassAxis, TrigClassAxis, ZAxis, EtaAxis, IsPbPb ? CentAxisPbPb : CentAxis}}}); + registry.add({"hgendndeta", "evntclass; zvtex, eta", {HistType::kTHnSparseD, {EvtClassAxis, ZAxis, EtaAxis, IsPbPb ? CentAxisPbPb : CentAxis, ParticleTypeAxis, PtVarAxis, phibin}}}); + registry.add({"hgenzvtx", "evntclass; zvtex", {HistType::kTHnSparseD, {EvtClassAxis, ZAxis, IsPbPb ? CentAxisPbPb : CentAxis}}}); + registry.add({"hv0mass", "etaaxis; invmass", {HistType::kTHnSparseD, {IsPbPb ? CentAxisPbPb : CentAxis, SpeciesAxis, V0EtaAxis, MassAxis}}}); + + const int nbins = 50; + std::vector logbins(nbins + 1, 0); + Double_t low = 0.01; + Double_t high = 10; + Double_t logbw = (log(high) - log(low)) / nbins; + for (int ij = 0; ij <= nbins; ij++) { + logbins[ij] = low * exp(ij * logbw); } + AxisSpec ptbins2 = {logbins, "pT (GeV/c)", "pt bin"}; + + registry.add({"hrecdndpt", " pt", {HistType::kTH1D, {ptbins2}}}); + registry.add({"hdndptefficiency", " pt", {HistType::kTH1D, {ptbins2}}}); + registry.add({"hgendndpt", " pt", {HistType::kTH1D, {{ptbins2}}}}); + + auto hstat = registry.get(HIST("Selection")); + auto* x = hstat->GetXaxis(); + x->SetBinLabel(1, "All"); + x->SetBinLabel(2, "Sel8"); + x->SetBinLabel(3, "Sel8z10"); + x->SetBinLabel(4, "Generated INEL>0"); + x->SetBinLabel(5, "Good BCs"); + x->SetBinLabel(6, "BCs with collisions"); + x->SetBinLabel(7, "BCs with pile-up/splitting"); + x->SetBinLabel(8, "INEL&Sel8&mcz10"); + x->SetBinLabel(9, "INEL"); + x->SetBinLabel(10, "INELg0"); + x->SetBinLabel(11, "INELgenz10"); + x->SetBinLabel(12, "INELg0genz10"); + x->SetBinLabel(13, "INELSel8"); + x->SetBinLabel(14, "INELg0Sel8g0"); + x->SetBinLabel(15, "INELSel8recz10"); + x->SetBinLabel(16, "INELg0Sel8g0recz10"); + x->SetBinLabel(17, "K0Sz10eta05"); } + + expressions::Filter trackSelectionProper = ((aod::track::trackCutFlag & trackSelectionITS) == trackSelectionITS) && ifnode(ncheckbit(aod::track::detectorMap, (uint8_t)o2::aod::track::TPC), ncheckbit(aod::track::trackCutFlag, trackSelectionTPC), true) && ncheckbit(aod::track::trackCutFlag, trackSelectionDCA); + + // static constexpr TrackSelectionFlags::flagtype trackSelectionITS = + // TrackSelectionFlags::kITSNCls | TrackSelectionFlags::kITSChi2NDF | + // TrackSelectionFlags::kITSHits; + + // static constexpr TrackSelectionFlags::flagtype trackSelectionTPC = + // TrackSelectionFlags::kTPCNCls | + // TrackSelectionFlags::kTPCCrossedRowsOverNCls | + // TrackSelectionFlags::kTPCChi2NDF; + + // static constexpr TrackSelectionFlags::flagtype trackSelectionDCA = + // TrackSelectionFlags::kDCAz | TrackSelectionFlags::kDCAxy; + + // expressions::Filter trackSelectionProper = (aod::track::trackCutFlag & TrackSelectionFlags::kQualityTracks) == TrackSelectionFlags::kQualityTracks ; + // Filter trackSelectionProper = ncheckbit(aod::track::trackCutFlag, trackSelectionDCA); + + // expressions::Filter trackSelectionProper = requireGlobalTrackWoPtEtaInFilter(); + // expressions::Filter atrackFilter = (aod::track::bestCollisionId >= 0) && + // (nabs(aod::track::bestDCAZ) <= 2.f) && + // (nabs(aod::track::bestDCAXY) <= ((0.0105f + 0.0350f / npow(aod::track::pts, 1.1f)))); + // expressions::Filter primaries = (aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary; + expressions::Filter preFilterV0 = nabs(aod::v0data::dcapostopv) > dcapostopv&& nabs(aod::v0data::dcanegtopv) > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; + + Partition mcSample = nabs(aod::mcparticle::eta) < estimatorEta; + Partition tSample = nabs(aod::track::eta) < estimatorEta; + // Partition tSample2 = (aod::fwdtrack::eta < -2.f) && (aod::fwdtrack::eta > -4.f); + Partition tSample3 = nabs(aod::track::eta) < estimatorEta; + // Partition> lsample = nabs(aod::track::eta) < estimatorEta; + + // Preslice perCol = aod::track::collisionId; + // Preslice> mcmfttracks_slice = o2::aod::fwdtrack::collisionId; + // Preslice> mctracks_slice = aod::track::collisionId; + // Preslice mcparticle_slice = o2::aod::mcparticle::mcCollisionId; + // Preslice> tracks_slice = aod::track::collisionId; + // Preslice mfttracks_slice = o2::aod::fwdtrack::collisionId; + void processEventStat( FullBCs const& bcs, soa::Join const& collisions) @@ -226,7 +302,7 @@ struct MultiplicityCounter { for (auto& bc : bcs) { if (!useEvSel || (bc.selection_bit(kIsBBT0A) & bc.selection_bit(kIsBBT0C)) != 0) { - registry.fill(HIST("Events/Selection"), 5.); + registry.fill(HIST("Selection"), 5.); cols.clear(); for (auto& collision : collisions) { if (collision.has_foundBC()) { @@ -239,9 +315,9 @@ struct MultiplicityCounter { } LOGP(debug, "BC {} has {} collisions", bc.globalBC(), cols.size()); if (!cols.empty()) { - registry.fill(HIST("Events/Selection"), 6.); + registry.fill(HIST("Selection"), 6.); if (cols.size() > 1) { - registry.fill(HIST("Events/Selection"), 7.); + registry.fill(HIST("Selection"), 7.); } } } @@ -250,402 +326,571 @@ struct MultiplicityCounter { PROCESS_SWITCH(MultiplicityCounter, processEventStat, "Collect event sample stats", false); - expressions::Filter trackSelectionProper = ((aod::track::trackCutFlag & trackSelectionITS) == trackSelectionITS) && - ifnode((aod::track::detectorMap & (uint8_t)o2::aod::track::TPC) == (uint8_t)o2::aod::track::TPC, - (aod::track::trackCutFlag & trackSelectionTPC) == trackSelectionTPC, - true) && - ((aod::track::trackCutFlag & trackSelectionDCA) == trackSelectionDCA); - expressions::Filter atrackFilter = (aod::track::bestCollisionId >= 0) && - (nabs(aod::track::bestDCAZ) <= 2.f) && - (nabs(aod::track::bestDCAXY) <= ((0.0105f + 0.0350f / npow(aod::track::pts, 1.1f)))); - std::vector tracketas; template - void runCounting(C const& collisions, FiTracks const& tracks, soa::Filtered const& fullV0s, aod::MFTTracks const& mfttracks) + void runCounting( + C const& collisions, + FiTracks const& tracks) { + for (auto& collision : collisions) { - registry.fill(HIST("Events/Selection"), 1.); + Bool_1d btrigc(kTrigend, false); + registry.fill(HIST("Selection"), 1.); auto z = collision.posZ(); - auto permfttracks = tSample2->sliceByCached(aod::fwdtrack::collisionId, collision.globalIndex(), cache); + // auto permfttracks = tSample2->sliceByCached(aod::fwdtrack::collisionId, collision.globalIndex(), cache); auto pertracks = tSample3->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto Ntrk = 0; - if (!useEvSel || collision.sel8()) { // event selection cut - if (std::abs(z) < 10) { // z-vtx cut + if (collision.sel8()) { + btrigc[kSel8] = true; + registry.fill(HIST("Selection"), 2.); + if (std::abs(z) < 10) { + registry.fill(HIST("Selection"), 3.); + } + } + if (btrigc[kSel8] && fabs(z) < 10) + registry.fill(HIST("hft0multiplicity"), collision.multFT0C()); - float cent = 0; - if constexpr (C::template contains()) { // with centrality - cent = collision.centFT0C(); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/Centrality"), cent); + for (auto& track : pertracks) { + [[maybe_unused]] int dummy = track.globalIndex(); + if (std::abs(track.eta()) < 1) + Ntrk++; // charged track check + } + if (Ntrk > 0) { + // registry.fill(HIST("Selection"), 3.); + if (btrigc[kSel8]) + btrigc[kSel8g0] = true; + } + + float cent = -1; + if (IsPbPb) { + if constexpr (C::template contains()) + cent = collision.centFT0C(); + + } else { + if constexpr (C::template contains()) + cent = collision.centFT0M(); + } - registry.fill(HIST("Events/Selection"), 2.); + if (IsPbPb) { + if (std::abs(z) < 10 && btrigc[kSel8]) + registry.fill(HIST("hcentrality"), cent); + } else { + if (std::abs(z) < 10 && btrigc[kSel8g0]) + registry.fill(HIST("hcentrality"), cent); + } + for (auto itrigc = 1u; itrigc < kTrigend; itrigc++) { + if (btrigc[itrigc]) + registry.fill(HIST("hreczvtx"), Double_t(kDATA), Double_t(itrigc), z, cent); + } - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hreczvtx"), Double_t(kDATA), Double_t(kMBAND), z, cent); + for (auto& track : pertracks) { + if (btrigc[kSel8] && std::abs(track.eta()) < 0.8 && std::abs(z) < 10) + registry.fill(HIST("hrecdndpt"), track.pt()); + for (auto itrigc = 1u; itrigc < kTrigend; itrigc++) { + if (btrigc[itrigc]) { + // if (track.phi()>3.08 && track.phi()<3.14) { + // continue; + // } + registry.fill(HIST("hphieta"), Double_t(kDATA), Double_t(itrigc), track.phi(), track.eta(), cent); + registry.fill(HIST("hrecdndeta"), Double_t(kDATA), Double_t(itrigc), z, track.eta(), cent, Double_t(kParDATA), track.phi()); + } + } + } + } + } - usedTracksIds.clear(); - tracketas.clear(); + // template + // PresliceUnsorted perMcCol = aod::mccollisionlabel::mcCollisionId; + // PresliceUnsorted> perMcCol = o2::aod::mccollisionlabel::mcCollisionId; + PresliceUnsorted> perMcCol = o2::aod::mccollisionlabel::mcCollisionId; + Preslice perMCColparticles = aod::mcparticle::mcCollisionId; + void processMCCounting( + aod::McCollisions const& mcCollisions, soa::Join const& collisions, Particles const& mcParticles + //, soa::Filtered const& mcParticles + , + FiLTracks const& tracks + //, FiTracks const& tracks + //, DaughterTracks const& + // soa::SmallGroups const& atracks, + // soa::Join const& mfttracks + ) + { + //[[maybe_unused]] constexpr bool hasCentrality = C::template contains() || C::template contains() || hasCent(); + for (auto& mcCollision : mcCollisions) { + Bool_1d bevtc(kECend, false); + bevtc[kINEL] = true; + registry.fill(HIST("Selection"), 1.); - for (auto& track : pertracks) { - if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { - continue; - } - registry.fill(HIST("Tracks/ProcessCounting/Centrality/PhiEta"), Double_t(kDATA), track.phi(), track.eta(), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/DCAXY"), Double_t(kDATA), track.dcaXY(), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/DCAZ"), Double_t(kDATA), track.dcaZ(), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hrecpt"), Double_t(kDATA), -1, track.pt(), cent); - tracketas.push_back(track.eta()); - } + // auto z = collision.posZ(); + auto mcz = mcCollision.posZ(); + auto genz = mcz; - if (mftanalysis) { - for (auto& track : permfttracks) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hrecdndeta"), Double_t(kDATA), Double_t(kMBAND), z, track.eta(), cent); - } - } + // auto cent = -1; - for (auto& eta : tracketas) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hrecdndeta"), Double_t(kDATA), Double_t(kMBAND), z, eta, cent); + auto Ntrk_gen = 0; + auto particles = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + for (auto& particle : particles) { + if (!particle.isPhysicalPrimary()) + continue; + auto kp = pdg->GetParticle(particle.pdgCode()); + if (kp != nullptr) { + if (std::abs(kp->Charge()) >= 3) { + if (std::abs(particle.eta()) < 1) { + Ntrk_gen++; } + } + } + } + if (Ntrk_gen > 0) { + registry.fill(HIST("Selection"), 4.); + bevtc[kINELg0] = true; + } + if (bevtc[kINEL]) + registry.fill(HIST("Selection"), 9); + if (bevtc[kINEL] && fabs(mcz) < 10) + registry.fill(HIST("Selection"), 11); + if (bevtc[kINELg0]) + registry.fill(HIST("Selection"), 10); + if (bevtc[kINELg0] && fabs(mcz) < 10) + registry.fill(HIST("Selection"), 12); + for (auto& particle : particles) { + if (!particle.isPhysicalPrimary()) + continue; + auto kp = pdg->GetParticle(particle.pdgCode()); + if (kp != nullptr) { + if (std::abs(kp->Charge()) >= 3) { + // if (bevtc[kINEL] == true && btrigc[kSel8] == true && std::abs(particle.eta())<0.8 && std::abs(mcz)<10 && particle.has_tracks()) registry.fill(HIST("hdndptefficiency"), particle.pt()); + if (bevtc[kINEL] && std::abs(particle.eta()) < 0.8 && std::abs(mcz) < 10) + registry.fill(HIST("hgendndpt"), particle.pt()); + } + } + } + + auto collisionsample = collisions.sliceBy(perMcCol, mcCollision.globalIndex()); + auto cent = -1; + + if (collisionsample.size() != 1) { + cent = -1; + } else { + for (auto& collision : collisionsample) { + if (IsPbPb) { + if constexpr (MyCollisionsCent::template contains()) + cent = collision.centFT0C(); + } else { + if constexpr (MyCollisionsCent::template contains()) + cent = collision.centFT0M(); + } + } + } + for (auto ievtc = 1u; ievtc < kECend; ievtc++) { + if (bevtc[ievtc]) + registry.fill(HIST("hgenzvtx"), Double_t(ievtc), genz, cent); + } + Int_t pid = 0; + for (auto& particle : particles) { + auto p = pdg->GetParticle(particle.pdgCode()); + if (std::abs(particle.pdgCode()) == 310 && std::abs(particle.eta()) < 0.5 && std::abs(genz) < 10) + registry.fill(HIST("Selection"), 17.); + if (!particle.isPhysicalPrimary()) { + continue; + } + switch (std::abs(particle.pdgCode())) { + case 211: + pid = kPion; + break; + case 321: + pid = kKaon; + break; + case 2212: + pid = kProtonMy; + break; + default: + pid = kOPar; + break; + } - if (v0analysis) { - for (auto& v0 : fullV0s) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kK0short), Double_t(kAll), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kLambda), Double_t(kAll), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kAntilambda), Double_t(kAll), cent); - - auto pTrack = v0.template posTrack_as(); - auto nTrack = v0.template negTrack_as(); - - if (v0.v0radius() > v0radius && - v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && - abs(pTrack.eta()) < etadau && - abs(nTrack.eta()) < etadau) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kK0short), Double_t(kBasiccut), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kLambda), Double_t(kBasiccut), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kAntilambda), Double_t(kBasiccut), cent); - - if (abs(v0.yK0Short()) < rapidity) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Mass"), Double_t(kDATA), Double_t(kK0short), v0.mK0Short(), cent); - if (0.482 < v0.mK0Short() && v0.mK0Short() < 0.509) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kK0short), Double_t(kMasscut), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0DauEta"), Double_t(kDATA), Double_t(kPositive), Double_t(kK0short), pTrack.eta(), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0DauEta"), Double_t(kDATA), Double_t(kNegative), Double_t(kK0short), nTrack.eta(), cent); - } - } - - if (abs(v0.yLambda()) < rapidity) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Mass"), Double_t(kDATA), Double_t(kLambda), v0.mLambda(), cent); - if (1.11 < v0.mLambda() && v0.mLambda() < 1.12) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kLambda), Double_t(kMasscut), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0DauEta"), Double_t(kDATA), Double_t(kPositive), Double_t(kLambda), pTrack.eta(), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0DauEta"), Double_t(kDATA), Double_t(kNegative), Double_t(kLambda), nTrack.eta(), cent); - } - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Mass"), Double_t(kDATA), Double_t(kAntilambda), v0.mAntiLambda(), cent); - if (1.11 < v0.mAntiLambda() && v0.mAntiLambda() < 1.12) { - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0Count"), Double_t(kDATA), Double_t(kAntilambda), Double_t(kMasscut), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0DauEta"), Double_t(kDATA), Double_t(kPositive), Double_t(kAntilambda), pTrack.eta(), cent); - registry.fill(HIST("Tracks/ProcessCounting/Centrality/hV0DauEta"), Double_t(kDATA), Double_t(kNegative), Double_t(kAntilambda), nTrack.eta(), cent); - } - } + if (p != nullptr) { + if (std::abs(p->Charge()) >= 3) { + for (auto ievtc = 1u; ievtc < kECend; ievtc++) { + if (bevtc[ievtc]) { + // if (particle.phi()>3.08 && particle.phi()<3.14) continue; + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), cent, Double_t(pid), kNoPtVar, particle.phi()); + if (particle.pt() < 0.1) { + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), cent, Double_t(pid), kPtUp, particle.phi(), -10.0 * particle.pt() + 2); + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), cent, Double_t(pid), kPtDw, particle.phi(), 5.0 * particle.pt() + 0.5); + + } else { + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), cent, Double_t(pid), kPtUp, particle.phi()); + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), cent, Double_t(pid), kPtDw, particle.phi()); } } } - } else { - // without centrality - registry.fill(HIST("Events/Selection"), 2.); - registry.fill(HIST("Tracks/ProcessCounting/hreczvtx"), Double_t(kDATA), Double_t(kMBAND), z); + } + } + } + + // if (collisionsample.size()>=2) continue; - usedTracksIds.clear(); - tracketas.clear(); + for (auto& collision : collisionsample) { + // ncoll++; + // if (!collision.has_mcCollision()) continue; + auto cent = -1; + if (IsPbPb) { + if constexpr (MyCollisionsCent::template contains()) + cent = collision.centFT0C(); + } else { + if constexpr (MyCollisionsCent::template contains()) + cent = collision.centFT0M(); + } - for (auto& track : pertracks) { - if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { - continue; + Bool_1d btrigc(kTrigend, false); + auto z = collision.posZ(); + if (collision.sel8()) { + btrigc[kSel8] = true; + registry.fill(HIST("Selection"), 2.); + if (std::abs(z) < 10) { + registry.fill(HIST("Selection"), 3.); + } + } + if (bevtc[kINEL] && btrigc[kSel8] && fabs(z) < 10) + registry.fill(HIST("hft0multiplicity"), collision.multFT0C()); + + auto Ntrk_rec = 0; + // auto trackspart = lsample->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + // auto trackspart = mctracks_slice->sliceByCached(aod::track::collisionId, collision.globalIndex(),cache); + // auto trackspart = lsample->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto trackspart = tracks.sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + // trackspart.bindExternalIndices(&mcParticles); + // cout<trackpers->"> + for (auto& track : trackspart) { + if (std::abs(track.eta()) < 1) { + Ntrk_rec++; + } + } + + if (Ntrk_rec > 0) { + // registry.fill(HIST("Selection"), 3.); + if (btrigc[kSel8]) + btrigc[kSel8g0] = true; + } + if (IsPbPb) { + if (std::abs(z) < 10 && btrigc[kSel8]) + registry.fill(HIST("hcentrality"), cent); + } else { + if (std::abs(z) < 10 && btrigc[kSel8g0]) + registry.fill(HIST("hcentrality"), cent); + } + + if (bevtc[kINEL] && btrigc[kSel8]) + registry.fill(HIST("Selection"), 13); + if (bevtc[kINEL] && btrigc[kSel8] && fabs(z) < 10) + registry.fill(HIST("Selection"), 15); + if (bevtc[kINELg0] && btrigc[kSel8g0]) + registry.fill(HIST("Selection"), 14); + if (bevtc[kINELg0] && btrigc[kSel8g0] && fabs(z) < 10) + registry.fill(HIST("Selection"), 16); + + for (auto ievtc = 1u; ievtc < kECend; ievtc++) { + for (auto itrigc = 1u; itrigc < kTrigend; itrigc++) { + if (bevtc[ievtc] && btrigc[itrigc]) { + registry.fill(HIST("hreczvtx"), Double_t(ievtc), Double_t(itrigc), z, cent); + } + } + } + std::vector mclabels; + for (auto& track : trackspart) { + if (track.has_mcParticle()) { + Int_t pid = kBkg; + auto particle = track.template mcParticle_as(); + if (bevtc[kINEL] && btrigc[kSel8] && std::abs(track.eta()) < 0.8 && std::abs(z) < 10) + registry.fill(HIST("hdndptefficiency"), particle.pt()); + + if (particle.isPhysicalPrimary()) { + switch (std::abs(particle.pdgCode())) { + case 211: + pid = kPion; + break; + case 321: + pid = kKaon; + break; + case 2212: + pid = kProtonMy; + break; + default: + pid = kOPar; + break; } - registry.fill(HIST("Tracks/ProcessCounting/PhiEta"), Double_t(kDATA), track.phi(), track.eta()); - registry.fill(HIST("Tracks/ProcessCounting/DCAXY"), Double_t(kDATA), track.dcaXY()); - registry.fill(HIST("Tracks/ProcessCounting/DCAZ"), Double_t(kDATA), track.dcaZ()); - registry.fill(HIST("Tracks/ProcessCounting/hrecpt"), Double_t(kDATA), -1, track.pt()); - tracketas.push_back(track.eta()); + } else { + pid = kNotPrimary; } - - if (mftanalysis) { - for (auto& track : permfttracks) { - registry.fill(HIST("Tracks/ProcessCounting/hrecdndeta"), Double_t(kDATA), Double_t(kMBAND), z, track.eta()); + for (auto MotherIDs = particle.mothersIds().front(); MotherIDs <= particle.mothersIds().back(); MotherIDs++) { + auto mother = mcParticles.rawIteratorAt(MotherIDs); + auto pdg_mother = mother.pdgCode(); + if (pdg_mother == 310 || std::abs(pdg_mother) == 3122) { + pid = kMotherStrange; + // cout<< "MotherIDS : "<3.08 && track.phi()<3.14) continue; + registry.fill(HIST("hrecdndeta"), Double_t(ievtc), Double_t(itrigc), z, particle.eta(), cent, Double_t(pid), particle.phi()); + registry.fill(HIST("hphieta"), Double_t(ievtc), Double_t(itrigc), track.phi(), track.eta(), cent); + } + } } - if (v0analysis) { - for (auto& v0 : fullV0s) { - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kK0short), Double_t(kAll)); - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kLambda), Double_t(kAll)); - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kAntilambda), Double_t(kAll)); - - auto pTrack = v0.template posTrack_as(); - auto nTrack = v0.template negTrack_as(); - - if (v0.v0radius() > v0radius && - v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && - abs(pTrack.eta()) < etadau && - abs(nTrack.eta()) < etadau) { - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kK0short), Double_t(kBasiccut)); - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kLambda), Double_t(kBasiccut)); - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kAntilambda), Double_t(kBasiccut)); - - if (abs(v0.yK0Short()) < rapidity) { - registry.fill(HIST("Tracks/ProcessCounting/hV0Mass"), Double_t(kDATA), Double_t(kK0short), v0.mK0Short()); - if (0.482 < v0.mK0Short() && v0.mK0Short() < 0.509) { - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kK0short), Double_t(kMasscut)); - registry.fill(HIST("Tracks/ProcessCounting/hV0DauEta"), Double_t(kDATA), Double_t(kPositive), Double_t(kK0short), pTrack.eta()); - registry.fill(HIST("Tracks/ProcessCounting/hV0DauEta"), Double_t(kDATA), Double_t(kNegative), Double_t(kK0short), nTrack.eta()); - } - } - - if (abs(v0.yLambda()) < rapidity) { - registry.fill(HIST("Tracks/ProcessCounting/hV0Mass"), Double_t(kDATA), Double_t(kLambda), v0.mLambda()); - if (1.11 < v0.mLambda() && v0.mLambda() < 1.12) { - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kLambda), Double_t(kMasscut)); - registry.fill(HIST("Tracks/ProcessCounting/hV0DauEta"), Double_t(kDATA), Double_t(kPositive), Double_t(kLambda), pTrack.eta()); - registry.fill(HIST("Tracks/ProcessCounting/hV0DauEta"), Double_t(kDATA), Double_t(kNegative), Double_t(kLambda), nTrack.eta()); - } - registry.fill(HIST("Tracks/ProcessCounting/hV0Mass"), Double_t(kDATA), Double_t(kAntilambda), v0.mAntiLambda()); - if (1.11 < v0.mAntiLambda() && v0.mAntiLambda() < 1.12) { - registry.fill(HIST("Tracks/ProcessCounting/hV0Count"), Double_t(kDATA), Double_t(kAntilambda), Double_t(kMasscut)); - registry.fill(HIST("Tracks/ProcessCounting/hV0DauEta"), Double_t(kDATA), Double_t(kPositive), Double_t(kAntilambda), pTrack.eta()); - registry.fill(HIST("Tracks/ProcessCounting/hV0DauEta"), Double_t(kDATA), Double_t(kNegative), Double_t(kAntilambda), nTrack.eta()); - } - } + } else { + for (auto ievtc = 1u; ievtc < kECend; ievtc++) { + for (auto itrigc = 1u; itrigc < kTrigend; itrigc++) { + if (bevtc[ievtc] && btrigc[itrigc]) { + // if (track.phi()>3.08 && track.phi()<3.14) continue; + registry.fill(HIST("hrecdndeta"), Double_t(ievtc), Double_t(itrigc), z, track.eta(), cent, Double_t(kBkg), track.phi()); } } } } + + // registry.fill(HIST("Tracks/ProcessMCCounting/hStatusCode"), Double_t(kINEL), Double_t(kAll), track.template mcParticle_as().getGenStatusCode()); + // registry.fill(HIST("Tracks/ProcessMCCounting/hMCStatusCode"), Double_t(kINEL), Double_t(kAll), track.template mcParticle_as().getHepMCStatusCode()); + // registrfill(HIST("Tracks/ProcessMCCounting/hProcessCode"), Double_t(kINEL), Double_t(kAll), track.template mcParticle_as().getProcess()); + // } + // else{ + // for (auto ievtc = 1u; ievtc < kECend; ievtc++) + // { + // for (auto itrigc = 1u; itrigc < kTrigend; itrigc++) + // { + // if (bevtc[ievtc] == true && btrigc[itrigc] == true){ + // registry.fill(HIST("hrecdndeta"), Double_t(ievtc), Double_t(itrigc), z, track.eta(),cent, Double_t(kBkg), track.pt()); + // } + // } + // } + + //} } } } } - Filter preFilterV0 = nabs(aod::v0data::dcapostopv) > dcapostopv&& nabs(aod::v0data::dcanegtopv) > dcanegtopv&& aod::v0data::dcaV0daughters < dcav0dau; + PROCESS_SWITCH(MultiplicityCounter, processMCCounting, "MC Count tracks", false); - void processCountingWithCent( - MyCollisionsCent const& collisions, - FiTracks const& tracks, - soa::Filtered const& fullV0s, - aod::MFTTracks const& mfttracks) + void processTrackEfficiencyGeneral( + typename soa::Join::iterator const& collision, + aod::McCollisions const& mcCollisions, Particles const& particles, + FiLTracks const& tracks) { - runCounting(collisions, tracks, fullV0s, mfttracks); - } - PROCESS_SWITCH(MultiplicityCounter, processCountingWithCent, "Count tracks with Centrality", false); - void processCountingWithoutCent( - MyCollisions const& collisions, - FiTracks const& tracks, - soa::Filtered const& fullV0s, - aod::MFTTracks const& mfttracks) - { - runCounting(collisions, tracks, fullV0s, mfttracks); - } - PROCESS_SWITCH(MultiplicityCounter, processCountingWithoutCent, "Count tracks with No Centrality", false); + if (!collision.sel8()) { + return; + } + if (!collision.has_mcCollision()) { + return; + } - expressions::Filter primaries = (aod::mcparticle::flags & (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary) == (uint8_t)o2::aod::mcparticle::enums::PhysicalPrimary; - Partition mcSample = nabs(aod::mcparticle::eta) < estimatorEta; - Partition tSample = nabs(aod::track::eta) < estimatorEta; - Partition tSample2 = (aod::fwdtrack::eta < -2.f) && (aod::fwdtrack::eta > -4.f); - Partition tSample3 = nabs(aod::track::eta) < estimatorEta; - Partition> lsample = nabs(aod::track::eta) < estimatorEta; + auto mcCollision = collision.mcCollision(); + auto particlesPerCol = particles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + } - Preslice perCol = aod::track::collisionId; - Preslice> mcmfttracks_slice = o2::aod::fwdtrack::collisionId; - Preslice> mctracks_slice = aod::track::collisionId; - Preslice mcparticle_slice = o2::aod::mcparticle::mcCollisionId; - Preslice> tracks_slice = aod::track::collisionId; - Preslice mfttracks_slice = o2::aod::fwdtrack::collisionId; + PROCESS_SWITCH(MultiplicityCounter, processTrackEfficiencyGeneral, "MC Count tracks", false); - void processMCCounting( - soa::Join const& collisions, - aod::McCollisions const&, - soa::Filtered const& fullV0s, - Particles const& mcParticles, - soa::Filtered const&, - DaughterTracks const&, - soa::SmallGroups const& atracks, - soa::Join const& mfttracks) + void processCounting( + MyCollisionsCent const& collisions, + FiTracks const& tracks) { - for (auto& collision : collisions) { - auto z = collision.posZ(); - if (useEvSel && !collision.sel8()) { // event selection cut + // runCounting(collisions, tracks, fullV0s, mfttracks); + runCounting(collisions, tracks); + } + PROCESS_SWITCH(MultiplicityCounter, processCounting, "Count tracks with Centrality", false); + + /*void processMCCounting( + //aod::McCollisions::iterator const& mccollision + //, soa::Join const& collisions + //, Particles const& mcParticles + //, soa::Filtered const& Fitrks + //, DaughterTracks const& Dautrks + //soa::SmallGroups const& atracks, + //soa::Join const& mfttracks + //) + aod::McCollisions::iterator const& mcCollision + , o2::soa::SmallGroups> const& collisions + , Particles const& particles + //, soa::Filtered const& Fitrks + , FiTracks const& Fitrks + ) + { + // runMCCounting(collisions, MCCollisions, fullV0s, mcParticles, Fitrks, Dautrks, atracks, mfttracks); + //runMCCounting(collisions + runMCCounting(mcCollision + , collisions + , particles + , Fitrks + //, Dautrks + //, atracks + //, mfttracks + ); + + }*/ + + // void processGen( + // aod::McCollisions::iterator const& mcCollision, + // o2::soa::SmallGroups> const& collisions, + // Particles const& mcParticles, FiTracks const& tracks) + void processGen( + aod::McCollisions::iterator const& mcCollision, Particles const& mcParticles) + { + + auto genz = mcCollision.posZ(); + Bool_1d bevtc(kECend, false); + bevtc[kINEL] = true; + for (auto& particle : mcParticles) { + if (!particle.isPhysicalPrimary()) continue; + auto p = pdg->GetParticle(particle.pdgCode()); + if (p != nullptr) { + if (std::abs(p->Charge()) >= 3) { + if (std::abs(particle.eta()) < 1) + bevtc[kINELg0] = true; + } } - if (!collision.has_mcCollision()) { // check mc particle + } + // cout<<"INEL? "<0? "<GetParticle(particle.pdgCode()); + if (std::abs(particle.pdgCode()) == 310 && fabs(particle.eta()) < 0.5 && fabs(genz) < 10) + registry.fill(HIST("Selection"), 17.); + if (!particle.isPhysicalPrimary()) { continue; } - if (std::abs(z) > 10) { // z-vtx cut - continue; + switch (std::abs(particle.pdgCode())) { + case 211: + pid = kPion; + break; + case 321: + pid = kKaon; + break; + case 2212: + pid = kProtonMy; + break; + default: + pid = kOPar; + break; } - if (v0analysis) { - for (auto& v0 : fullV0s) { - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kK0short), Double_t(kAll)); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kLambda), Double_t(kAll)); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kAntilambda), Double_t(kAll)); - - auto pTrack = v0.template posTrack_as(); - auto nTrack = v0.template negTrack_as(); - - if (v0.v0radius() > v0radius && - v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && - abs(pTrack.eta()) < etadau && - abs(nTrack.eta()) < etadau) { - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kK0short), Double_t(kBasiccut)); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kLambda), Double_t(kBasiccut)); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kAntilambda), Double_t(kBasiccut)); - - if (abs(v0.yK0Short()) < rapidity) { - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Mass"), Double_t(kINEL), Double_t(kK0short), v0.mK0Short()); - if (0.482 < v0.mK0Short() && v0.mK0Short() < 0.509) { - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kK0short), Double_t(kMasscut)); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0DauEta"), Double_t(kINEL), Double_t(kPositive), Double_t(kK0short), pTrack.eta()); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0DauEta"), Double_t(kINEL), Double_t(kNegative), Double_t(kK0short), nTrack.eta()); - } - } - if (abs(v0.yLambda()) < rapidity) { - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Mass"), Double_t(kINEL), Double_t(kLambda), v0.mLambda()); - if (1.11 < v0.mLambda() && v0.mLambda() < 1.12) { - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kLambda), Double_t(kMasscut)); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0DauEta"), Double_t(kINEL), Double_t(kPositive), Double_t(kLambda), pTrack.eta()); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0DauEta"), Double_t(kINEL), Double_t(kNegative), Double_t(kLambda), nTrack.eta()); - } - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Mass"), Double_t(kINEL), Double_t(kAntilambda), v0.mAntiLambda()); - if (1.11 < v0.mAntiLambda() && v0.mAntiLambda() < 1.12 && abs(v0.yLambda()) < rapidity) { - registry.fill(HIST("Tracks/ProcessMCCounting/hV0Count"), Double_t(kINEL), Double_t(kAntilambda), Double_t(kMasscut)); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0DauEta"), Double_t(kINEL), Double_t(kPositive), Double_t(kAntilambda), pTrack.eta()); - registry.fill(HIST("Tracks/ProcessMCCounting/hV0DauEta"), Double_t(kINEL), Double_t(kNegative), Double_t(kAntilambda), nTrack.eta()); + if (p != nullptr) { + if (std::abs(p->Charge()) >= 3) { + for (auto ievtc = 1u; ievtc < kECend; ievtc++) { + if (bevtc[ievtc]) { + // if (particle.phi()>3.08 && particle.phi()<3.14) continue; + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), -1.0, Double_t(pid), kNoPtVar, particle.phi()); + if (particle.pt() < 0.1) { + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), -1.0, Double_t(pid), kPtUp, particle.phi(), 2.0); + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), -1.0, Double_t(pid), kPtDw, particle.phi(), 0.5); + + } else { + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), -1.0, Double_t(pid), kPtUp, particle.phi()); + registry.fill(HIST("hgendndeta"), Double_t(ievtc), genz, particle.eta(), -1.0, Double_t(pid), kPtDw, particle.phi()); } } } } } - registry.fill(HIST("Tracks/ProcessMCCounting/hreczvtx"), Double_t(kINEL), Double_t(kMBAND), z); - auto mcCollision = collision.mcCollision(); - auto particles = mcSample->sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); - auto tracks = lsample->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - tracks.bindExternalIndices(&mcParticles); - auto permcmfttracks = mfttracks.sliceBy(mcmfttracks_slice, collision.globalIndex()); - - usedTracksIds.clear(); - for (auto& track : atracks) { - auto ttrack = track.track_as>(); - usedTracksIds.emplace_back(ttrack.globalIndex()); - if (ttrack.has_mcParticle()) { - registry.fill(HIST("Tracks/ProcessMCCounting/hrecdndeta"), Double_t(kINEL), Double_t(kMBAND), z, ttrack.mcParticle_as().eta()); - registry.fill(HIST("Tracks/ProcessMCCounting/hrecpt"), Double_t(kINEL), ttrack.mcParticle_as().pt(), ttrack.pt()); - registry.fill(HIST("Tracks/ProcessMCCounting/PhiEta"), Double_t(kINEL), ttrack.phi(), ttrack.eta()); - registry.fill(HIST("Tracks/ProcessMCCounting/DCAXY"), Double_t(kINEL), ttrack.dcaXY()); - registry.fill(HIST("Tracks/ProcessMCCounting/DCAZ"), Double_t(kINEL), ttrack.dcaZ()); - - registry.fill(HIST("Tracks/ProcessMCCounting/hStatusCode"), Double_t(kINEL), Double_t(kAll), ttrack.mcParticle_as().getGenStatusCode()); - registry.fill(HIST("Tracks/ProcessMCCounting/hMCStatusCode"), Double_t(kINEL), Double_t(kAll), ttrack.mcParticle_as().getHepMCStatusCode()); - registry.fill(HIST("Tracks/ProcessMCCounting/hProcessCode"), Double_t(kINEL), Double_t(kAll), ttrack.mcParticle_as().getProcess()); - - if (ttrack.mcParticle_as().getProcess() != 0) { - registry.fill(HIST("Tracks/ProcessMCCounting/hrecdndeta"), Double_t(kINEL), Double_t(kBackground), z, ttrack.mcParticle_as().eta()); - } + } + } + PROCESS_SWITCH(MultiplicityCounter, processGen, "Process generator-level info", false); - if (v0analysis) { - for (auto MotherIDs = ttrack.mcParticle_as().mothersIds().front(); MotherIDs <= ttrack.mcParticle_as().mothersIds().back(); MotherIDs++) { - auto mother = mcParticles.rawIteratorAt(MotherIDs); - auto pdg_mother = mother.pdgCode(); - if (pdg_mother == 310) { - registry.fill(HIST("Tracks/ProcessMCCounting/hMotherV0Count"), Double_t(kINEL), Double_t(kK0short)); - } - if (pdg_mother == 3122) { - registry.fill(HIST("Tracks/ProcessMCCounting/hMotherV0Count"), Double_t(kINEL), Double_t(kLambda)); - } - if (pdg_mother == -3122) { - registry.fill(HIST("Tracks/ProcessMCCounting/hMotherV0Count"), Double_t(kINEL), Double_t(kAntilambda)); - } - } - } - } else { - // when secondary - } - } - for (auto& track : tracks) { - if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { - continue; - } - if (track.has_mcParticle()) { - registry.fill(HIST("Tracks/ProcessMCCounting/hrecdndeta"), Double_t(kINEL), Double_t(kMBAND), z, track.mcParticle_as().eta()); - registry.fill(HIST("Tracks/ProcessMCCounting/hrecpt"), Double_t(kINEL), track.mcParticle_as().pt(), track.pt()); - registry.fill(HIST("Tracks/ProcessMCCounting/PhiEta"), Double_t(kINEL), track.phi(), track.eta()); - registry.fill(HIST("Tracks/ProcessMCCounting/DCAXY"), Double_t(kINEL), track.dcaXY()); - registry.fill(HIST("Tracks/ProcessMCCounting/DCAZ"), Double_t(kINEL), track.dcaZ()); - - registry.fill(HIST("Tracks/ProcessMCCounting/hStatusCode"), Double_t(kINEL), Double_t(kAll), track.mcParticle_as().getGenStatusCode()); - registry.fill(HIST("Tracks/ProcessMCCounting/hMCStatusCode"), Double_t(kINEL), Double_t(kAll), track.mcParticle_as().getHepMCStatusCode()); - registry.fill(HIST("Tracks/ProcessMCCounting/hProcessCode"), Double_t(kINEL), Double_t(kAll), track.mcParticle_as().getProcess()); - - if (track.mcParticle_as().getProcess() != 0) { - registry.fill(HIST("Tracks/ProcessMCCounting/hrecdndeta"), Double_t(kINEL), Double_t(kBackground), z, track.mcParticle_as().eta()); - } + void processV0Counting( + MyCollisionsCent const& collisions, + soa::Filtered const& fullV0s, + FiTracks const& tracks) + { + for (auto& collision : collisions) { + if (!collision.sel8()) + continue; + auto z = collision.posZ(); - if (v0analysis) { - for (auto MotherIDs = track.mcParticle_as().mothersIds().front(); MotherIDs <= track.mcParticle_as().mothersIds().back(); MotherIDs++) { - auto mother = mcParticles.rawIteratorAt(MotherIDs); - auto pdg_mother = mother.pdgCode(); - if (pdg_mother == 310) { - registry.fill(HIST("Tracks/ProcessMCCounting/hMotherV0Count"), Double_t(kINEL), Double_t(kK0short)); - } - if (pdg_mother == 3122) { - registry.fill(HIST("Tracks/ProcessMCCounting/hMotherV0Count"), Double_t(kINEL), Double_t(kLambda)); - } - if (pdg_mother == -3122) { - registry.fill(HIST("Tracks/ProcessMCCounting/hMotherV0Count"), Double_t(kINEL), Double_t(kAntilambda)); - } - } - } - } else { - // when secondary - } - } - if (mftanalysis) { - for (auto& track : permcmfttracks) { - if (track.has_mcParticle()) { - registry.fill(HIST("Tracks/ProcessMCCounting/hrecdndeta"), Double_t(kINEL), Double_t(kMBAND), z, track.mcParticle_as().eta()); - } - } + auto cent = -1; + if (IsPbPb) { + if constexpr (MyCollisionsCent::template contains()) + cent = collision.centFT0C(); + } else { + if constexpr (MyCollisionsCent::template contains()) + cent = collision.centFT0M(); } - for (auto& particle : particles) { - auto p = pdg->GetParticle(particle.pdgCode()); - if (p != nullptr) { - if (std::abs(p->Charge()) >= 3) { - registry.fill(HIST("Tracks/ProcessMCCounting/hgenpt"), Double_t(kINEL), particle.pt()); - } + for (auto& v0 : fullV0s) { + + auto pTrack = v0.template posTrack_as(); + auto nTrack = v0.template negTrack_as(); + + if (v0.v0radius() > v0radius && + v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && + abs(pTrack.eta()) < etadau && + abs(nTrack.eta()) < etadau && fabs(z) < 10 && fabs(v0.eta()) < 0.5) { + + registry.fill(HIST("hv0mass"), cent, Double_t(kK0short), v0.eta(), Double_t(v0.mK0Short())); + registry.fill(HIST("hv0mass"), cent, Double_t(kLambda), v0.eta(), Double_t(v0.mLambda())); + registry.fill(HIST("hv0mass"), cent, Double_t(kAntilambda), v0.eta(), Double_t(v0.mAntiLambda())); } } } } - PROCESS_SWITCH(MultiplicityCounter, processMCCounting, "MC Count tracks", false); + PROCESS_SWITCH(MultiplicityCounter, processV0Counting, "MC V0Count tracks without Centrality", false); - void processGen( - aod::McCollisions::iterator const& mcCollision, - o2::soa::SmallGroups> const& collisions, - Particles const& mcParticles, FiTracks const& tracks) + void processMCV0Counting( + soa::Join const& collisions, + aod::McCollisions const& MCCollisions, + Particles const& mcParticles, + soa::Filtered const& fullV0s, + soa::Filtered const& tracks, + DaughterTracks const& Dautrks) { - auto perCollisionMCSample = mcSample->sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); - auto genz = mcCollision.posZ(); - registry.fill(HIST("Tracks/ProcessGen/hgenzvtx"), Double_t(kINEL), genz); - for (auto& particle : perCollisionMCSample) { - auto p = pdg->GetParticle(particle.pdgCode()); - if (p != nullptr) { - if (std::abs(p->Charge()) >= 3) { - registry.fill(HIST("Tracks/ProcessGen/hgendndeta"), Double_t(kINEL), genz, particle.eta()); + for (auto& collision : collisions) { + auto cent = -1.0; + + if (IsPbPb) { + if constexpr (MyCollisionsCent::template contains()) + cent = collision.centFT0C(); + } else { + if constexpr (MyCollisionsCent::template contains()) + cent = collision.centFT0M(); + } + + // auto mcCollision = collision.mcCollision(); + + if (useEvSel && !collision.sel8()) // event selection cut + continue; + if (!collision.has_mcCollision()) // check mc particle + continue; + + for (auto& v0 : fullV0s) { + + auto pTrack = v0.template posTrack_as(); + auto nTrack = v0.template negTrack_as(); + + if (0 && v0.v0radius() > v0radius && + v0.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) > v0cospa && + abs(pTrack.eta()) < etadau && + abs(nTrack.eta()) < etadau) { + + registry.fill(HIST("hv0mass"), cent, Double_t(kK0short), v0.eta(), Double_t(v0.mK0Short())); + registry.fill(HIST("hv0mass"), cent, Double_t(kLambda), v0.eta(), Double_t(v0.mLambda())); + registry.fill(HIST("hv0mass"), cent, Double_t(kAntilambda), v0.eta(), Double_t(v0.mAntiLambda())); } } } } - PROCESS_SWITCH(MultiplicityCounter, processGen, "Process generator-level info", false); + PROCESS_SWITCH(MultiplicityCounter, processMCV0Counting, "MC V0Count tracks without Centrality", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGMM/Mult/Tasks/dndeta-mft.cxx b/PWGMM/Mult/Tasks/dndeta-mft.cxx index a4c0312a059..71f1e8a666e 100644 --- a/PWGMM/Mult/Tasks/dndeta-mft.cxx +++ b/PWGMM/Mult/Tasks/dndeta-mft.cxx @@ -72,7 +72,7 @@ struct PseudorapidityDensityMFT { Preslice perMcCol = aod::mcparticle::mcCollisionId; Preslice perColCentral = aod::track::collisionId; - Service pdg; + Service pdg; Configurable estimatorEta{"estimatorEta", 1.0, "eta range for INEL>0 sample definition"}; @@ -196,7 +196,7 @@ struct PseudorapidityDensityMFT { std::vector::iterator> cols; for (auto& bc : bcs) { - if (!useEvSel || (useEvSel && ((bc.selection_bit(evsel::kIsBBT0A) & bc.selection_bit(evsel::kIsBBT0C)) != 0))) { + if (!useEvSel || (useEvSel && ((bc.selection_bit(aod::evsel::kIsBBT0A) & bc.selection_bit(aod::evsel::kIsBBT0C)) != 0))) { registry.fill(HIST("EventSelection"), 5.); cols.clear(); for (auto& collision : collisions) { diff --git a/PWGMM/Mult/Tasks/dndeta.cxx b/PWGMM/Mult/Tasks/dndeta.cxx index 30d64f2ddc0..8c963802c58 100644 --- a/PWGMM/Mult/Tasks/dndeta.cxx +++ b/PWGMM/Mult/Tasks/dndeta.cxx @@ -21,14 +21,15 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" #include "Index.h" -#include "TDatabasePDG.h" +#include +#include #include "bestCollisionTable.h" using namespace o2; +using namespace o2::aod::track; using namespace o2::framework; using namespace o2::framework::expressions; -using namespace o2::aod::track; AxisSpec ZAxis = {301, -30.1, 30.1}; AxisSpec DeltaZAxis = {61, -6.1, 6.1}; @@ -37,7 +38,12 @@ AxisSpec EtaAxis = {22, -2.2, 2.2}; // AxisSpec MultAxis = {301, -0.5, 300.5}; AxisSpec PhiAxis = {629, 0, 2 * M_PI}; AxisSpec PtAxis = {2401, -0.005, 24.005}; +AxisSpec PtAxisEff = {{0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, + 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}}; AxisSpec PtAxis_wide = {1041, -0.05, 104.05}; +AxisSpec FT0CAxis = {1001, -0.5, 1000.5}; +AxisSpec FT0AAxis = {3001, -0.5, 3000.5}; +AxisSpec FDDAxis = {3001, -0.5, 3000.5}; static constexpr TrackSelectionFlags::flagtype trackSelectionITS = TrackSelectionFlags::kITSNCls | TrackSelectionFlags::kITSChi2NDF | @@ -51,6 +57,9 @@ static constexpr TrackSelectionFlags::flagtype trackSelectionTPC = static constexpr TrackSelectionFlags::flagtype trackSelectionDCA = TrackSelectionFlags::kDCAz | TrackSelectionFlags::kDCAxy; +static constexpr TrackSelectionFlags::flagtype trackSelectionDCAXYonly = + TrackSelectionFlags::kDCAxy; + using LabeledTracks = soa::Join; using ReTracks = soa::Join; @@ -69,17 +78,22 @@ static constexpr bool hasCent() } } // namespace +static constexpr std::string_view species[] = {"pi", "p", "e", "K"}; +static constexpr std::array speciesIds{kPiPlus, kProton, kElectron, kKPlus}; + struct MultiplicityCounter { SliceCache cache; Preslice perCol = aod::track::collisionId; Preslice perMCCol = aod::mcparticle::mcCollisionId; PresliceUnsorted perColU = aod::track::bestCollisionId; - Service pdg; + Service pdg; Configurable estimatorEta{"estimatorEta", 1.0, "eta range for INEL>0 sample definition"}; + Configurable dcaZ{"dcaZ", 0.2f, "Custom DCA Z cut (ignored if negative)"}; Configurable useEvSel{"useEvSel", true, "use event selection"}; Configurable fillResponse{"fillResponse", false, "Fill response matrix"}; + Configurable responseStudy{"responseStudy", false, "Fill multi-estimator response"}; ConfigurableAxis multBinning{"multBinning", {301, -0.5, 300.5}, ""}; ConfigurableAxis centBinning{"centBinning", {VARIABLE_WIDTH, 0, 10, 20, 30, 40, 50, 60, 70, 80, 100}, ""}; @@ -97,7 +111,7 @@ struct MultiplicityCounter { void init(InitContext&) { - AxisSpec MultAxis = {multBinning, "N_{trk}"}; + AxisSpec MultAxis = {multBinning}; AxisSpec CentAxis = {centBinning, "centrality"}; auto hstat = registry.get(HIST("Events/BCSelection")); @@ -115,7 +129,7 @@ struct MultiplicityCounter { registry.add({"Events/Centrality/Control/TimeResolution", " ; t (ms); centrality", {HistType::kTH2F, {{1001, -0.1, 100.1}, CentAxis}}}); } - if (doprocessCounting) { + if (doprocessCounting || doprocessCountingNoAmb) { registry.add({"Events/Selection", ";status;events", {HistType::kTH1F, {{4, 0.5, 4.5}}}}); hstat = registry.get(HIST("Events/Selection")); x = hstat->GetXaxis(); @@ -131,18 +145,20 @@ struct MultiplicityCounter { registry.add({"Tracks/Control/PtEta", " ; p_{T} (GeV/c); #eta", {HistType::kTH2F, {PtAxis, EtaAxis}}}); registry.add({"Tracks/Control/DCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); registry.add({"Tracks/Control/DCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); - registry.add({"Tracks/Control/ReassignedDCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); - registry.add({"Tracks/Control/ReassignedDCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); - registry.add({"Tracks/Control/ExtraDCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); - registry.add({"Tracks/Control/ExtraDCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); - registry.add({"Tracks/Control/ExtraTracksEtaZvtx", "; #eta; Z_{vtx} (cm); tracks", {HistType::kTH2F, {EtaAxis, ZAxis}}}); - registry.add({"Tracks/Control/ExtraTracksPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"Tracks/Control/ReassignedTracksEtaZvtx", "; #eta; Z_{vtx} (cm); tracks", {HistType::kTH2F, {EtaAxis, ZAxis}}}); - registry.add({"Tracks/Control/ReassignedTracksPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"Tracks/Control/ReassignedVertexCorr", "; Z_{vtx}^{orig} (cm); Z_{vtx}^{re} (cm)", {HistType::kTH2F, {ZAxis, ZAxis}}}); + if (doprocessCounting) { + registry.add({"Tracks/Control/ReassignedDCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); + registry.add({"Tracks/Control/ReassignedDCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); + registry.add({"Tracks/Control/ExtraDCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); + registry.add({"Tracks/Control/ExtraDCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm)", {HistType::kTH2F, {PtAxis, DCAAxis}}}); + registry.add({"Tracks/Control/ExtraTracksEtaZvtx", "; #eta; Z_{vtx} (cm); tracks", {HistType::kTH2F, {EtaAxis, ZAxis}}}); + registry.add({"Tracks/Control/ExtraTracksPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); + registry.add({"Tracks/Control/ReassignedTracksEtaZvtx", "; #eta; Z_{vtx} (cm); tracks", {HistType::kTH2F, {EtaAxis, ZAxis}}}); + registry.add({"Tracks/Control/ReassignedTracksPhiEta", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); + registry.add({"Tracks/Control/ReassignedVertexCorr", "; Z_{vtx}^{orig} (cm); Z_{vtx}^{re} (cm)", {HistType::kTH2F, {ZAxis, ZAxis}}}); + } } - if (doprocessCountingCentralityFT0C || doprocessCountingCentralityFT0M) { + if (doprocessCountingCentralityFT0C || doprocessCountingCentralityFT0M || doprocessCountingCentralityFT0CNoAmb || doprocessCountingCentralityFT0MNoAmb) { registry.add({"Events/Centrality/Selection", ";status;centrality;events", {HistType::kTH2F, {{3, 0.5, 3.5}, CentAxis}}}); hstat = registry.get(HIST("Events/Centrality/Selection")); x = hstat->GetXaxis(); @@ -156,18 +172,20 @@ struct MultiplicityCounter { registry.add({"Tracks/Centrality/Control/PtEta", " ; p_{T} (GeV/c); #eta; centrality", {HistType::kTHnSparseF, {PtAxis, EtaAxis, CentAxis}}}); registry.add({"Tracks/Centrality/Control/DCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); registry.add({"Tracks/Centrality/Control/DCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedDCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedDCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ExtraDCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ExtraDCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ExtraTracksEtaZvtx", "; #eta; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {EtaAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ExtraTracksPhiEta", "; #varphi; #eta; centrality", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedTracksEtaZvtx", "; #eta; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {EtaAxis, ZAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedTracksPhiEta", "; #varphi; #eta; centrality", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/ReassignedVertexCorr", "; Z_{vtx}^{orig} (cm); Z_{vtx}^{re} (cm); centrality", {HistType::kTHnSparseF, {ZAxis, ZAxis, CentAxis}}}); + if (doprocessCountingCentralityFT0C || doprocessCountingCentralityFT0M) { + registry.add({"Tracks/Centrality/Control/ReassignedDCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); + registry.add({"Tracks/Centrality/Control/ReassignedDCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); + registry.add({"Tracks/Centrality/Control/ExtraDCAXYPt", " ; p_{T} (GeV/c) ; DCA_{XY} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); + registry.add({"Tracks/Centrality/Control/ExtraDCAZPt", " ; p_{T} (GeV/c) ; DCA_{Z} (cm); centrality", {HistType::kTHnSparseF, {PtAxis, DCAAxis, CentAxis}}}); + registry.add({"Tracks/Centrality/Control/ExtraTracksEtaZvtx", "; #eta; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {EtaAxis, ZAxis, CentAxis}}}); + registry.add({"Tracks/Centrality/Control/ExtraTracksPhiEta", "; #varphi; #eta; centrality", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); + registry.add({"Tracks/Centrality/Control/ReassignedTracksEtaZvtx", "; #eta; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {EtaAxis, ZAxis, CentAxis}}}); + registry.add({"Tracks/Centrality/Control/ReassignedTracksPhiEta", "; #varphi; #eta; centrality", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); + registry.add({"Tracks/Centrality/Control/ReassignedVertexCorr", "; Z_{vtx}^{orig} (cm); Z_{vtx}^{re} (cm); centrality", {HistType::kTHnSparseF, {ZAxis, ZAxis, CentAxis}}}); + } } - if (doprocessGen) { + if (doprocessGen || doprocessGenNoAmb) { registry.add({"Events/NtrkZvtxGen", "; N_{trk}; Z_{vtx} (cm); events", {HistType::kTH2F, {MultAxis, ZAxis}}}); registry.add({"Events/NtrkZvtxGen_t", "; N_{part}; Z_{vtx} (cm); events", {HistType::kTH2F, {MultAxis, ZAxis}}}); registry.add({"Tracks/EtaZvtxGen", "; #eta; Z_{vtx} (cm); tracks", {HistType::kTH2F, {EtaAxis, ZAxis}}}); @@ -177,8 +195,7 @@ struct MultiplicityCounter { registry.add({"Tracks/Control/PtEtaGen", " ; p_{T} (GeV/c) ; #eta", {HistType::kTH2F, {PtAxis, EtaAxis}}}); registry.add({"Tracks/PhiEtaGen", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"Tracks/Control/PhiEtaGenDuplicates", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); - registry.add({"Tracks/Control/PhiEtaDuplicates", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); + registry.add({"Events/Efficiency", "; status; events", {HistType::kTH1F, {{5, 0.5, 5.5}}}}); registry.add({"Events/NotFoundEventZvtx", " ; Z_{vtx} (cm)", {HistType::kTH1F, {ZAxis}}}); @@ -186,6 +203,9 @@ struct MultiplicityCounter { registry.add({"Events/Response", " ; N_{rec}; N_{gen}; Z_{vtx} (cm)", {HistType::kTHnSparseF, {MultAxis, MultAxis, ZAxis}}}); registry.add({"Events/EfficiencyMult", " ; N_{gen}; Z_{vtx} (cm)", {HistType::kTH2F, {MultAxis, ZAxis}}}); registry.add({"Events/SplitMult", " ; N_{gen} ; Z_{vtx} (cm)", {HistType::kTH2F, {MultAxis, ZAxis}}}); + if (responseStudy) { + registry.add({"Events/Control/MultiResponse", " ; N_{gen}; N_{rec}; N_{PV cont}; N_{FT0A}; N_{FT0C}; N_{FDA}; N_{FDC}; Z_{vtx} (cm)", {HistType::kTHnSparseF, {MultAxis, MultAxis, MultAxis, FT0AAxis, FT0CAxis, FDDAxis, FDDAxis, ZAxis}}}); + } } auto heff = registry.get(HIST("Events/Efficiency")); @@ -197,7 +217,8 @@ struct MultiplicityCounter { x->SetBinLabel(5, "Selected INEL>0"); } - if (doprocessGenFT0C || doprocessGenFT0M || doprocessGenFT0Chi || doprocessGenFT0Mhi) { + if (doprocessGenFT0C || doprocessGenFT0M || doprocessGenFT0Chi || doprocessGenFT0Mhi || + doprocessGenFT0CNoAmb || doprocessGenFT0MNoAmb || doprocessGenFT0ChiNoAmb || doprocessGenFT0MhiNoAmb) { registry.add({"Events/Centrality/NtrkZvtxGen", "; N_{trk}; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {MultAxis, ZAxis, CentAxis}}}); registry.add({"Events/Centrality/NtrkZvtxGen_t", "; N_{part}; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {MultAxis, ZAxis, CentAxis}}}); registry.add({"Tracks/Centrality/EtaZvtxGen", "; #eta; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {EtaAxis, ZAxis, CentAxis}}}); @@ -207,8 +228,8 @@ struct MultiplicityCounter { registry.add({"Tracks/Centrality/Control/PtEtaGen", " ; p_{T} (GeV/c) ; #eta; centrality", {HistType::kTHnSparseF, {PtAxis, EtaAxis, CentAxis}}}); registry.add({"Tracks/Centrality/PhiEtaGen", "; #varphi; #eta; tracks", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/PhiEtaGenDuplicates", "; #varphi; #eta; tracks", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); - registry.add({"Tracks/Centrality/Control/PhiEtaDuplicates", "; #varphi; #eta; tracks", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); + // registry.add({"Tracks/Centrality/Control/PhiEtaGenDuplicates", "; #varphi; #eta; tracks", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); + // registry.add({"Tracks/Centrality/Control/PhiEtaDuplicates", "; #varphi; #eta; tracks", {HistType::kTHnSparseF, {PhiAxis, EtaAxis, CentAxis}}}); registry.add({"Events/Centrality/Efficiency", "; status; centrality; events", {HistType::kTH2F, {{5, 0.5, 5.5}, CentAxis}}}); registry.add({"Events/Centrality/NotFoundEventZvtx", " ; Z_{vtx} (cm); centrality; events", {HistType::kTH2F, {ZAxis, CentAxis}}}); @@ -216,6 +237,9 @@ struct MultiplicityCounter { registry.add({"Events/Centrality/Response", " ; N_{rec}; N_{gen}; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {MultAxis, MultAxis, ZAxis, CentAxis}}}); registry.add({"Events/Centrality/EfficiencyMult", " ; N_{gen}; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {MultAxis, ZAxis, CentAxis}}}); registry.add({"Events/Centrality/SplitMult", " ; N_{gen} ; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {MultAxis, ZAxis, CentAxis}}}); + if (responseStudy) { + registry.add({"Events/Centrality/Control/MultiResponse", " ; N_{gen}; N_{rec}, N_{PV cont}; N_{FT0A}; N_{FT0C}; N_{FDA}; N_{FDC}; Z_{vtx} (cm); centrality", {HistType::kTHnSparseF, {MultAxis, MultAxis, MultAxis, FT0AAxis, FT0CAxis, FDDAxis, FDDAxis, ZAxis, CentAxis}}}); + } } auto heff = registry.get(HIST("Events/Centrality/Efficiency")); @@ -227,22 +251,32 @@ struct MultiplicityCounter { x->SetBinLabel(5, "Selected INEL>0"); } - if (doprocessTrackEfficiency) { - registry.add({"Tracks/Control/PtGen", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtGenNoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtEfficiency", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtEfficiencyNoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtEfficiencyFakes", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); + if (doprocessTrackEfficiency || doprocessTrackEfficiencyNoAmb) { + registry.add({"Tracks/Control/PtGen", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtGenNoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtEfficiency", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtEfficiencyNoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtEfficiencyFakes", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + for (auto i = 0u; i < speciesIds.size(); ++i) { + registry.add({(std::string("Tracks/Control/") + std::string(species[i]) + "/PtGen").c_str(), " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({(std::string("Tracks/Control/") + std::string(species[i]) + "/PtEfficiency").c_str(), " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + } } if (doprocessTrackEfficiencyIndexed) { - registry.add({"Tracks/Control/PtGenI", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtGenINoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtEfficiencyI", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtEfficiencyINoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtEfficiencyISecondaries", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); - registry.add({"Tracks/Control/PtEfficiencyISecondariesNoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis}}}); + registry.add({"Tracks/Control/PhiEtaGenDuplicates", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); + registry.add({"Tracks/Control/PhiEtaDuplicates", "; #varphi; #eta; tracks", {HistType::kTH2F, {PhiAxis, EtaAxis}}}); + registry.add({"Tracks/Control/PtGenI", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtGenINoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtEfficiencyI", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtEfficiencyINoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtEfficiencyISecondaries", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Tracks/Control/PtEfficiencyISecondariesNoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); registry.add({"Tracks/Control/Mask", " ; bit", {HistType::kTH1F, {{17, -0.5, 16.5}}}}); registry.add({"Tracks/Control/ITSClusters", " ; layer", {HistType::kTH1F, {{8, 0.5, 8.5}}}}); + for (auto i = 0u; i < speciesIds.size(); ++i) { + registry.add({(std::string("Tracks/Control/") + std::string(species[i]) + "/PtGenI").c_str(), " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({(std::string("Tracks/Control/") + std::string(species[i]) + "/PtEfficiencyI").c_str(), " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + } } } @@ -253,8 +287,8 @@ struct MultiplicityCounter { constexpr bool hasCentrality = C::template contains() || C::template contains(); std::vector::iterator> cols; for (auto& bc : bcs) { - if (!useEvSel || (bc.selection_bit(evsel::kIsBBT0A) && - bc.selection_bit(evsel::kIsBBT0C)) != 0) { + if (!useEvSel || (bc.selection_bit(aod::evsel::kIsBBT0A) && + bc.selection_bit(aod::evsel::kIsBBT0C)) != 0) { registry.fill(HIST("Events/BCSelection"), 1.); cols.clear(); for (auto& collision : collisions) { @@ -327,14 +361,24 @@ struct MultiplicityCounter { usedTracksIdsDFMCEff.clear(); } - expressions::Filter trackSelectionProper = ((aod::track::trackCutFlag & trackSelectionITS) == trackSelectionITS) && - ifnode(ncheckbit(aod::track::detectorMap, (uint8_t)o2::aod::track::TPC), - ncheckbit(aod::track::trackCutFlag, trackSelectionTPC), - true) && - ncheckbit(aod::track::trackCutFlag, trackSelectionDCA); + // require ITS+TPC tracks + // expressions::Filter trackSelectionProperGlobalOnly = ncheckbit(aod::track::detectorMap, (uint8_t)o2::aod::track::ITS) && + // ncheckbit(aod::track::detectorMap, (uint8_t)o2::aod::track::TPC) && + // ncheckbit(aod::track::trackCutFlag, trackSelectionITS) && + // ncheckbit(aod::track::trackCutFlag, trackSelectionTPC) && + // ifnode(dcaZ.node() > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, trackSelectionDCAXYonly), + // ncheckbit(aod::track::trackCutFlag, trackSelectionDCA)); + + // require a mix of ITS+TPC and ITS-only tracks + expressions::Filter trackSelectionProperMixed = ncheckbit(aod::track::detectorMap, (uint8_t)o2::aod::track::ITS) && + ncheckbit(aod::track::trackCutFlag, trackSelectionITS) && + ifnode(ncheckbit(aod::track::detectorMap, (uint8_t)o2::aod::track::TPC), + ncheckbit(aod::track::trackCutFlag, trackSelectionTPC), true) && + ifnode(dcaZ.node() > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, trackSelectionDCAXYonly), + ncheckbit(aod::track::trackCutFlag, trackSelectionDCA)); expressions::Filter atrackFilter = (aod::track::bestCollisionId >= 0) && - (nabs(aod::track::bestDCAZ) <= 2.f) && + (ifnode(dcaZ.node() > 0.f, nabs(aod::track::bestDCAZ) <= dcaZ, nabs(aod::track::bestDCAZ) <= 2.0f)) && (nabs(aod::track::bestDCAXY) <= ((0.004f + 0.013f / npow(aod::track::pts, 1.1f)))); using ExTracks = soa::Join; @@ -347,7 +391,7 @@ struct MultiplicityCounter { void processCountingGeneral( typename C::iterator const& collision, FiTracks const& tracks, - soa::SmallGroups const& atracks) + soa::SmallGroups const* atracks) { float c = -1; constexpr bool hasCentrality = C::template contains() || C::template contains(); @@ -372,60 +416,77 @@ struct MultiplicityCounter { usedTracksIds.clear(); auto Ntrks = 0; - for (auto& track : atracks) { - auto otrack = track.track_as(); - usedTracksIds.emplace_back(track.trackId()); - if (std::abs(otrack.eta()) < estimatorEta) { - ++Ntrks; - } - if constexpr (hasCentrality) { - registry.fill(HIST("Tracks/Centrality/EtaZvtx"), otrack.eta(), z, c); - registry.fill(HIST("Tracks/Centrality/PhiEta"), otrack.phi(), otrack.eta(), c); - registry.fill(HIST("Tracks/Centrality/Control/PtEta"), otrack.pt(), otrack.eta(), c); - registry.fill(HIST("Tracks/Centrality/Control/DCAXYPt"), otrack.pt(), track.bestDCAXY(), c); - registry.fill(HIST("Tracks/Centrality/Control/DCAZPt"), otrack.pt(), track.bestDCAZ(), c); - } else { - registry.fill(HIST("Tracks/EtaZvtx"), otrack.eta(), z); - registry.fill(HIST("Tracks/PhiEta"), otrack.phi(), otrack.eta()); - registry.fill(HIST("Tracks/Control/PtEta"), otrack.pt(), otrack.eta()); - registry.fill(HIST("Tracks/Control/DCAXYPt"), otrack.pt(), track.bestDCAXY()); - registry.fill(HIST("Tracks/Control/DCAZPt"), otrack.pt(), track.bestDCAZ()); - } - if (!otrack.has_collision()) { - if constexpr (hasCentrality) { - registry.fill(HIST("Tracks/Centrality/Control/ExtraTracksEtaZvtx"), otrack.eta(), z, c); - registry.fill(HIST("Tracks/Centrality/Control/ExtraTracksPhiEta"), otrack.phi(), otrack.eta(), c); - registry.fill(HIST("Tracks/Centrality/Control/ExtraDCAXYPt"), otrack.pt(), track.bestDCAXY(), c); - registry.fill(HIST("Tracks/Centrality/Control/ExtraDCAZPt"), otrack.pt(), track.bestDCAZ(), c); - } else { - registry.fill(HIST("Tracks/Control/ExtraTracksEtaZvtx"), otrack.eta(), z); - registry.fill(HIST("Tracks/Control/ExtraTracksPhiEta"), otrack.phi(), otrack.eta()); - registry.fill(HIST("Tracks/Control/ExtraDCAXYPt"), otrack.pt(), track.bestDCAXY()); - registry.fill(HIST("Tracks/Control/ExtraDCAZPt"), otrack.pt(), track.bestDCAZ()); + if (atracks != nullptr) { + for (auto& track : *atracks) { + auto otrack = track.track_as(); + // same filtering for ambiguous as for general + if (!otrack.hasITS()) { + continue; + } + if ((otrack.trackCutFlag() & trackSelectionITS) == 0) { + continue; + } + if (!otrack.hasTPC()) { + continue; + } + if ((otrack.trackCutFlag() & trackSelectionTPC) == 0) { + continue; + } + usedTracksIds.emplace_back(track.trackId()); + if (std::abs(otrack.eta()) < estimatorEta) { + ++Ntrks; } - } else if (otrack.collisionId() != track.bestCollisionId()) { - usedTracksIdsDF.emplace_back(track.trackId()); if constexpr (hasCentrality) { - registry.fill(HIST("Tracks/Centrality/Control/ReassignedTracksEtaZvtx"), otrack.eta(), z, c); - registry.fill(HIST("Tracks/Centrality/Control/ReassignedTracksPhiEta"), otrack.phi(), otrack.eta(), c); - registry.fill(HIST("Tracks/Centrality/Control/ReassignedVertexCorr"), otrack.collision_as().posZ(), z, c); - registry.fill(HIST("Tracks/Centrality/Control/ReassignedDCAXYPt"), otrack.pt(), track.bestDCAXY(), c); - registry.fill(HIST("Tracks/Centrality/Control/ReassignedDCAZPt"), otrack.pt(), track.bestDCAZ(), c); + registry.fill(HIST("Tracks/Centrality/EtaZvtx"), otrack.eta(), z, c); + registry.fill(HIST("Tracks/Centrality/PhiEta"), otrack.phi(), otrack.eta(), c); + registry.fill(HIST("Tracks/Centrality/Control/PtEta"), otrack.pt(), otrack.eta(), c); + registry.fill(HIST("Tracks/Centrality/Control/DCAXYPt"), otrack.pt(), track.bestDCAXY(), c); + registry.fill(HIST("Tracks/Centrality/Control/DCAZPt"), otrack.pt(), track.bestDCAZ(), c); } else { - registry.fill(HIST("Tracks/Control/ReassignedTracksEtaZvtx"), otrack.eta(), z); - registry.fill(HIST("Tracks/Control/ReassignedTracksPhiEta"), otrack.phi(), otrack.eta()); - registry.fill(HIST("Tracks/Control/ReassignedVertexCorr"), otrack.collision_as().posZ(), z); - registry.fill(HIST("Tracks/Control/ReassignedDCAXYPt"), otrack.pt(), track.bestDCAXY()); - registry.fill(HIST("Tracks/Control/ReassignedDCAZPt"), otrack.pt(), track.bestDCAZ()); + registry.fill(HIST("Tracks/EtaZvtx"), otrack.eta(), z); + registry.fill(HIST("Tracks/PhiEta"), otrack.phi(), otrack.eta()); + registry.fill(HIST("Tracks/Control/PtEta"), otrack.pt(), otrack.eta()); + registry.fill(HIST("Tracks/Control/DCAXYPt"), otrack.pt(), track.bestDCAXY()); + registry.fill(HIST("Tracks/Control/DCAZPt"), otrack.pt(), track.bestDCAZ()); + } + if (!otrack.has_collision()) { + if constexpr (hasCentrality) { + registry.fill(HIST("Tracks/Centrality/Control/ExtraTracksEtaZvtx"), otrack.eta(), z, c); + registry.fill(HIST("Tracks/Centrality/Control/ExtraTracksPhiEta"), otrack.phi(), otrack.eta(), c); + registry.fill(HIST("Tracks/Centrality/Control/ExtraDCAXYPt"), otrack.pt(), track.bestDCAXY(), c); + registry.fill(HIST("Tracks/Centrality/Control/ExtraDCAZPt"), otrack.pt(), track.bestDCAZ(), c); + } else { + registry.fill(HIST("Tracks/Control/ExtraTracksEtaZvtx"), otrack.eta(), z); + registry.fill(HIST("Tracks/Control/ExtraTracksPhiEta"), otrack.phi(), otrack.eta()); + registry.fill(HIST("Tracks/Control/ExtraDCAXYPt"), otrack.pt(), track.bestDCAXY()); + registry.fill(HIST("Tracks/Control/ExtraDCAZPt"), otrack.pt(), track.bestDCAZ()); + } + } else if (otrack.collisionId() != track.bestCollisionId()) { + usedTracksIdsDF.emplace_back(track.trackId()); + if constexpr (hasCentrality) { + registry.fill(HIST("Tracks/Centrality/Control/ReassignedTracksEtaZvtx"), otrack.eta(), z, c); + registry.fill(HIST("Tracks/Centrality/Control/ReassignedTracksPhiEta"), otrack.phi(), otrack.eta(), c); + registry.fill(HIST("Tracks/Centrality/Control/ReassignedVertexCorr"), otrack.collision_as().posZ(), z, c); + registry.fill(HIST("Tracks/Centrality/Control/ReassignedDCAXYPt"), otrack.pt(), track.bestDCAXY(), c); + registry.fill(HIST("Tracks/Centrality/Control/ReassignedDCAZPt"), otrack.pt(), track.bestDCAZ(), c); + } else { + registry.fill(HIST("Tracks/Control/ReassignedTracksEtaZvtx"), otrack.eta(), z); + registry.fill(HIST("Tracks/Control/ReassignedTracksPhiEta"), otrack.phi(), otrack.eta()); + registry.fill(HIST("Tracks/Control/ReassignedVertexCorr"), otrack.collision_as().posZ(), z); + registry.fill(HIST("Tracks/Control/ReassignedDCAXYPt"), otrack.pt(), track.bestDCAXY()); + registry.fill(HIST("Tracks/Control/ReassignedDCAZPt"), otrack.pt(), track.bestDCAZ()); + } } } } for (auto& track : tracks) { - if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { - continue; - } - if (std::find(usedTracksIdsDF.begin(), usedTracksIdsDF.end(), track.globalIndex()) != usedTracksIdsDF.end()) { - continue; + if (atracks != nullptr) { + if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { + continue; + } + if (std::find(usedTracksIdsDF.begin(), usedTracksIdsDF.end(), track.globalIndex()) != usedTracksIdsDF.end()) { + continue; + } } if (std::abs(track.eta()) < estimatorEta) { ++Ntrks; @@ -449,15 +510,19 @@ struct MultiplicityCounter { } else { if (Ntrks > 0) { registry.fill(HIST("Events/Selection"), 3.); - for (auto& track : atracks) { - registry.fill(HIST("Tracks/EtaZvtx_gt0"), track.track_as().eta(), z); + if (atracks != nullptr) { + for (auto& track : *atracks) { + registry.fill(HIST("Tracks/EtaZvtx_gt0"), track.track_as().eta(), z); + } } for (auto& track : tracks) { - if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { - continue; - } - if (std::find(usedTracksIdsDF.begin(), usedTracksIdsDF.end(), track.globalIndex()) != usedTracksIdsDF.end()) { - continue; + if (atracks != nullptr) { + if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { + continue; + } + if (std::find(usedTracksIdsDF.begin(), usedTracksIdsDF.end(), track.globalIndex()) != usedTracksIdsDF.end()) { + continue; + } } registry.fill(HIST("Tracks/EtaZvtx_gt0"), track.eta(), z); } @@ -478,21 +543,39 @@ struct MultiplicityCounter { FiTracks const& tracks, soa::SmallGroups const& atracks) { - processCountingGeneral(collision, tracks, atracks); + processCountingGeneral(collision, tracks, &atracks); } PROCESS_SWITCH(MultiplicityCounter, processCounting, "Count tracks", false); + void processCountingNoAmb( + ExCols::iterator const& collision, + FiTracks const& tracks) + { + processCountingGeneral(collision, tracks, nullptr); + } + + PROCESS_SWITCH(MultiplicityCounter, processCountingNoAmb, "Count tracks w/o ambiguous", false); + using ExColsCentFT0C = soa::Join; void processCountingCentralityFT0C( ExColsCentFT0C::iterator const& collision, FiTracks const& tracks, soa::SmallGroups const& atracks) { - processCountingGeneral(collision, tracks, atracks); + processCountingGeneral(collision, tracks, &atracks); } - PROCESS_SWITCH(MultiplicityCounter, processCountingCentralityFT0C, "Count tracks in centrality bins", false); + PROCESS_SWITCH(MultiplicityCounter, processCountingCentralityFT0C, "Count tracks in FT0C centrality bins", false); + + void processCountingCentralityFT0CNoAmb( + ExColsCentFT0C::iterator const& collision, + FiTracks const& tracks) + { + processCountingGeneral(collision, tracks, nullptr); + } + + PROCESS_SWITCH(MultiplicityCounter, processCountingCentralityFT0CNoAmb, "Count tracks in FT0C centrality bins w/o ambiguous", false); using ExColsCentFT0M = soa::Join; void processCountingCentralityFT0M( @@ -500,10 +583,19 @@ struct MultiplicityCounter { FiTracks const& tracks, soa::SmallGroups const& atracks) { - processCountingGeneral(collision, tracks, atracks); + processCountingGeneral(collision, tracks, &atracks); + } + + PROCESS_SWITCH(MultiplicityCounter, processCountingCentralityFT0M, "Count tracks in FT0M centrality bins", false); + + void processCountingCentralityFT0MNoAmb( + ExColsCentFT0M::iterator const& collision, + FiTracks const& tracks) + { + processCountingGeneral(collision, tracks, nullptr); } - PROCESS_SWITCH(MultiplicityCounter, processCountingCentralityFT0M, "Count tracks in centrality bins", false); + PROCESS_SWITCH(MultiplicityCounter, processCountingCentralityFT0MNoAmb, "Count tracks in FT0M centrality bins w/o ambiguous", false); using Particles = soa::Filtered; using LabeledTracksEx = soa::Join; @@ -515,7 +607,7 @@ struct MultiplicityCounter { void processTrackEfficiencyIndexedGeneral( typename soa::Join::iterator const& collision, MC const&, ParticlesI const& particles, - FiLTracks const& tracks) + FiLTracks const& /*tracks*/) { if (useEvSel && !collision.sel8()) { return; @@ -536,8 +628,18 @@ struct MultiplicityCounter { continue; } registry.fill(HIST("Tracks/Control/PtGenINoEtaCut"), particle.pt()); + if (std::abs(particle.eta()) < estimatorEta) { registry.fill(HIST("Tracks/Control/PtGenI"), particle.pt()); + if (particle.pdgCode() == speciesIds[0]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[0]) + HIST("/PtGenI"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[1]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[1]) + HIST("/PtGenI"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[2]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[2]) + HIST("/PtGenI"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[3]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[3]) + HIST("/PtGenI"), particle.pt()); + } } if (particle.has_tracks()) { auto counted = false; @@ -553,6 +655,15 @@ struct MultiplicityCounter { if (std::abs(track.eta()) < estimatorEta) { if (!counted) { registry.fill(HIST("Tracks/Control/PtEfficiencyI"), particle.pt()); + if (particle.pdgCode() == speciesIds[0]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[0]) + HIST("/PtEfficiencyI"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[1]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[1]) + HIST("/PtEfficiencyI"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[2]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[2]) + HIST("/PtEfficiencyI"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[3]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[3]) + HIST("/PtEfficiencyI"), particle.pt()); + } counted = true; } } @@ -607,7 +718,7 @@ struct MultiplicityCounter { typename soa::Join::iterator const& collision, MC const&, Particles const& particles, FiLTracks const& tracks, - soa::SmallGroups const& atracks) + soa::SmallGroups const* atracks) { constexpr bool hasCentrality = C::template contains() || C::template contains() || hasCent(); @@ -634,34 +745,56 @@ struct MultiplicityCounter { auto particlesPerCol = particles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); usedTracksIds.clear(); - for (auto const& track : atracks) { - auto otrack = track.template track_as(); - usedTracksIds.emplace_back(track.trackId()); - if (otrack.collisionId() != track.bestCollisionId()) { - usedTracksIdsDFMCEff.emplace_back(track.trackId()); - } - if (otrack.has_mcParticle()) { - auto particle = otrack.mcParticle_as(); - registry.fill(HIST("Tracks/Control/PtEfficiencyNoEtaCut"), particle.pt()); - if (std::abs(otrack.eta()) < estimatorEta) { - registry.fill(HIST("Tracks/Control/PtEfficiency"), particle.pt()); + if (atracks != nullptr) { + for (auto const& track : *atracks) { + auto otrack = track.template track_as(); + usedTracksIds.emplace_back(track.trackId()); + if (otrack.collisionId() != track.bestCollisionId()) { + usedTracksIdsDFMCEff.emplace_back(track.trackId()); + } + if (otrack.has_mcParticle()) { + auto particle = otrack.mcParticle_as(); + registry.fill(HIST("Tracks/Control/PtEfficiencyNoEtaCut"), particle.pt()); + if (std::abs(otrack.eta()) < estimatorEta) { + registry.fill(HIST("Tracks/Control/PtEfficiency"), particle.pt()); + if (particle.pdgCode() == speciesIds[0]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[0]) + HIST("/PtEfficiency"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[1]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[1]) + HIST("/PtEfficiency"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[2]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[2]) + HIST("/PtEfficiency"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[3]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[3]) + HIST("/PtEfficiency"), particle.pt()); + } + } + } else { + registry.fill(HIST("Tracks/Control/PtEfficiencyFakes"), otrack.pt()); } - } else { - registry.fill(HIST("Tracks/Control/PtEfficiencyFakes"), otrack.pt()); } } for (auto const& track : tracks) { - if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { - continue; - } - if (std::find(usedTracksIdsDFMCEff.begin(), usedTracksIdsDFMCEff.end(), track.globalIndex()) != usedTracksIdsDFMCEff.end()) { - continue; + if (atracks != nullptr) { + if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { + continue; + } + if (std::find(usedTracksIdsDFMCEff.begin(), usedTracksIdsDFMCEff.end(), track.globalIndex()) != usedTracksIdsDFMCEff.end()) { + continue; + } } if (track.has_mcParticle()) { auto particle = track.template mcParticle_as(); registry.fill(HIST("Tracks/Control/PtEfficiencyNoEtaCut"), particle.pt()); if (std::abs(track.eta()) < estimatorEta) { registry.fill(HIST("Tracks/Control/PtEfficiency"), particle.pt()); + if (particle.pdgCode() == speciesIds[0]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[0]) + HIST("/PtEfficiency"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[1]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[1]) + HIST("/PtEfficiency"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[2]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[2]) + HIST("/PtEfficiency"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[3]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[3]) + HIST("/PtEfficiency"), particle.pt()); + } } } else { registry.fill(HIST("Tracks/Control/PtEfficiencyFakes"), track.pt()); @@ -680,6 +813,15 @@ struct MultiplicityCounter { registry.fill(HIST("Tracks/Control/PtGenNoEtaCut"), particle.pt()); if (std::abs(particle.eta()) < estimatorEta) { registry.fill(HIST("Tracks/Control/PtGen"), particle.pt()); + if (particle.pdgCode() == speciesIds[0]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[0]) + HIST("/PtGen"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[1]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[1]) + HIST("/PtGen"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[2]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[2]) + HIST("/PtGen"), particle.pt()); + } else if (particle.pdgCode() == speciesIds[3]) { + registry.fill(HIST("Tracks/Control/") + HIST(species[3]) + HIST("/PtGen"), particle.pt()); + } } } } @@ -690,16 +832,26 @@ struct MultiplicityCounter { FiLTracks const& filtracks, soa::SmallGroups const& atracks) { - processTrackEfficiencyGeneral(collision, mccollisions, mcParticles, filtracks, atracks); + processTrackEfficiencyGeneral(collision, mccollisions, mcParticles, filtracks, &atracks); } PROCESS_SWITCH(MultiplicityCounter, processTrackEfficiency, "Calculate tracking efficiency vs pt", false); + void processTrackEfficiencyNoAmb( + soa::Join::iterator const& collision, + aod::McCollisions const& mccollisions, Particles const& mcParticles, + FiLTracks const& filtracks) + { + processTrackEfficiencyGeneral(collision, mccollisions, mcParticles, filtracks, nullptr); + } + + PROCESS_SWITCH(MultiplicityCounter, processTrackEfficiencyNoAmb, "Calculate tracking efficiency vs pt w/o ambiguous", false); + template void processGenGeneral( typename MC::iterator const& mcCollision, o2::soa::SmallGroups> const& collisions, - Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks) + Particles const& particles, FiTracks const& tracks, FiReTracks const* atracks) { constexpr bool hasCentrality = C::template contains() || C::template contains() || hasCent(); @@ -748,6 +900,11 @@ struct MultiplicityCounter { auto Nrec = 0; std::vector NrecPerCol; std::vector c_recPerCol; + std::vector NPVPerCol; + std::vector NFT0APerCol; + std::vector NFT0CPerCol; + std::vector NFDDAPerCol; + std::vector NFDDCPerCol; for (auto& collision : collisions) { usedTracksIds.clear(); @@ -768,30 +925,67 @@ struct MultiplicityCounter { ++moreThanOne; atLeastOne = true; - auto perCollisionSample = tracks.sliceBy(perCol, collision.globalIndex()); - auto perCollisionASample = atracks.sliceBy(perColU, collision.globalIndex()); - for (auto const& track : perCollisionASample) { - auto otrack = track.template track_as(); - usedTracksIds.emplace_back(track.trackId()); - if (otrack.collisionId() != track.bestCollisionId()) { - usedTracksIdsDFMC.emplace_back(track.trackId()); - } - if (std::abs(otrack.eta()) < estimatorEta) { - ++Nrec; + if (atracks != nullptr) { + auto perCollisionASample = atracks->sliceBy(perColU, collision.globalIndex()); + for (auto const& track : perCollisionASample) { + auto otrack = track.template track_as(); + usedTracksIds.emplace_back(track.trackId()); + if (otrack.collisionId() != track.bestCollisionId()) { + usedTracksIdsDFMC.emplace_back(track.trackId()); + } + if (std::abs(otrack.eta()) < estimatorEta) { + ++Nrec; + } } } + auto perCollisionSample = tracks.sliceBy(perCol, collision.globalIndex()); for (auto const& track : perCollisionSample) { - if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { - continue; - } - if (std::find(usedTracksIdsDFMC.begin(), usedTracksIdsDFMC.end(), track.globalIndex()) != usedTracksIdsDFMC.end()) { - continue; + if (atracks != nullptr) { + if (std::find(usedTracksIds.begin(), usedTracksIds.end(), track.globalIndex()) != usedTracksIds.end()) { + continue; + } + if (std::find(usedTracksIdsDFMC.begin(), usedTracksIdsDFMC.end(), track.globalIndex()) != usedTracksIdsDFMC.end()) { + continue; + } } if (std::abs(track.eta()) < estimatorEta) { ++Nrec; } } NrecPerCol.emplace_back(Nrec); + NPVPerCol.emplace_back(collision.numContrib()); + if (collision.has_foundFT0()) { + auto ft0 = collision.foundFT0(); + float tA = 0; + float tC = 0; + for (auto i = 0u; i < ft0.amplitudeA().size(); ++i) { + tA += ft0.amplitudeA()[i]; + } + for (auto i = 0u; i < ft0.amplitudeC().size(); ++i) { + tC += ft0.amplitudeC()[i]; + } + NFT0APerCol.emplace_back(tA); + NFT0CPerCol.emplace_back(tC); + } else { + NFT0APerCol.emplace_back(-1); + NFT0CPerCol.emplace_back(-1); + } + if (collision.has_foundFDD()) { + auto fdd = collision.foundFDD(); + float tA = 0; + float tC = 0; + for (auto i = 0u; i < 8; ++i) { + tA += fdd.chargeA()[i]; + } + for (auto i = 0u; i < 8; ++i) { + tC += fdd.chargeC()[i]; + } + NFDDAPerCol.emplace_back(tA); + NFDDCPerCol.emplace_back(tC); + } else { + NFDDAPerCol.emplace_back(-1); + NFDDCPerCol.emplace_back(-1); + } if constexpr (hasCentrality) { registry.fill(HIST("Events/Centrality/Efficiency"), 4., c_gen); @@ -821,9 +1015,15 @@ struct MultiplicityCounter { if constexpr (hasCentrality) { registry.fill(HIST("Events/Centrality/Response"), NrecPerCol[i], nCharged, mcCollision.posZ(), c_recPerCol[i]); registry.fill(HIST("Events/Centrality/EfficiencyMult"), nCharged, mcCollision.posZ(), c_recPerCol[i]); + if (responseStudy) { + registry.fill(HIST("Events/Centrality/Control/MultiResponse"), nCharged, NrecPerCol[i], NPVPerCol[i], NFT0APerCol[i], NFT0CPerCol[i], NFDDAPerCol[i], NFDDCPerCol[i], mcCollision.posZ(), c_recPerCol[i]); + } } else { registry.fill(HIST("Events/Response"), NrecPerCol[i], nCharged, mcCollision.posZ()); registry.fill(HIST("Events/EfficiencyMult"), nCharged, mcCollision.posZ()); + if (responseStudy) { + registry.fill(HIST("Events/Control/MultiResponse"), nCharged, NrecPerCol[i], NPVPerCol[i], NFT0APerCol[i], NFT0CPerCol[i], NFDDAPerCol[i], NFDDCPerCol[i], mcCollision.posZ()); + } } } if (moreThanOne > 1) { @@ -888,54 +1088,104 @@ struct MultiplicityCounter { void processGen( MC::iterator const& mcCollision, o2::soa::SmallGroups> const& collisions, - Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks) + Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks, aod::FT0s const&, aod::FDDs const&) { - processGenGeneral(mcCollision, collisions, particles, tracks, atracks); + processGenGeneral(mcCollision, collisions, particles, tracks, &atracks); } PROCESS_SWITCH(MultiplicityCounter, processGen, "Process generator-level info", false); + void processGenNoAmb( + MC::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneral(mcCollision, collisions, particles, tracks, nullptr); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenNoAmb, "Process generator-level info w/o ambiguous", false); + void processGenFT0C( MC::iterator const& mcCollision, o2::soa::SmallGroups> const& collisions, - Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks) + Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks, aod::FT0s const&, aod::FDDs const&) { - processGenGeneral(mcCollision, collisions, particles, tracks, atracks); + processGenGeneral(mcCollision, collisions, particles, tracks, &atracks); } PROCESS_SWITCH(MultiplicityCounter, processGenFT0C, "Process generator-level info (FT0C centrality)", false); + void processGenFT0CNoAmb( + MC::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneral(mcCollision, collisions, particles, tracks, nullptr); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenFT0CNoAmb, "Process generator-level info (FT0C centrality) w/o ambiguous", false); + void processGenFT0M( MC::iterator const& mcCollision, o2::soa::SmallGroups> const& collisions, - Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks) + Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks, aod::FT0s const&, aod::FDDs const&) { - processGenGeneral(mcCollision, collisions, particles, tracks, atracks); + processGenGeneral(mcCollision, collisions, particles, tracks, &atracks); } PROCESS_SWITCH(MultiplicityCounter, processGenFT0M, "Process generator-level info (FT0M centrality)", false); + void processGenFT0MNoAmb( + MC::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneral(mcCollision, collisions, particles, tracks, nullptr); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenFT0MNoAmb, "Process generator-level info (FT0M centrality) w/o ambiguous", false); + using MChi = soa::Join; void processGenFT0Chi( MChi::iterator const& mcCollision, o2::soa::SmallGroups> const& collisions, - Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks) + Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks, aod::FT0s const&, aod::FDDs const&) { - processGenGeneral(mcCollision, collisions, particles, tracks, atracks); + processGenGeneral(mcCollision, collisions, particles, tracks, &atracks); } PROCESS_SWITCH(MultiplicityCounter, processGenFT0Chi, "Process generator-level info (FT0C centrality, HI)", false); + void processGenFT0ChiNoAmb( + MChi::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneral(mcCollision, collisions, particles, tracks, nullptr); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenFT0ChiNoAmb, "Process generator-level info (FT0C centrality, HI) w/o ambiguous", false); + void processGenFT0Mhi( MChi::iterator const& mcCollision, o2::soa::SmallGroups> const& collisions, - Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks) + Particles const& particles, FiTracks const& tracks, FiReTracks const& atracks, aod::FT0s const&, aod::FDDs const&) { - processGenGeneral(mcCollision, collisions, particles, tracks, atracks); + processGenGeneral(mcCollision, collisions, particles, tracks, &atracks); } PROCESS_SWITCH(MultiplicityCounter, processGenFT0Mhi, "Process generator-level info (FT0M centrality, HI)", false); + + void processGenFT0MhiNoAmb( + MChi::iterator const& mcCollision, + o2::soa::SmallGroups> const& collisions, + Particles const& particles, FiTracks const& tracks, aod::FT0s const&, aod::FDDs const&) + { + processGenGeneral(mcCollision, collisions, particles, tracks, nullptr); + } + + PROCESS_SWITCH(MultiplicityCounter, processGenFT0MhiNoAmb, "Process generator-level info (FT0M centrality, HI) w/o ambiguous", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGMM/Mult/Tasks/effpt-mft.cxx b/PWGMM/Mult/Tasks/effpt-mft.cxx index f93d2df4cc5..2d3a9919922 100644 --- a/PWGMM/Mult/Tasks/effpt-mft.cxx +++ b/PWGMM/Mult/Tasks/effpt-mft.cxx @@ -42,7 +42,7 @@ struct EffPtMFT { SliceCache cache; Preslice perMCCol = aod::mcparticle::mcCollisionId; - Service pdg; + Service pdg; Configurable useEvSel{"useEvSel", true, "use event selection"}; ConfigurableAxis PtAxis{"PtAxis", {1001, -0.0005, 1.0005}, "pt axis for histograms"}; diff --git a/PWGMM/Mult/Tasks/heavy-ion-mult.cxx b/PWGMM/Mult/Tasks/heavy-ion-mult.cxx new file mode 100644 index 00000000000..d0598205f3b --- /dev/null +++ b/PWGMM/Mult/Tasks/heavy-ion-mult.cxx @@ -0,0 +1,252 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \brief This task is an empty skeleton that fills a simple eta histogram. +/// it is meant to be a blank page for further developments. +/// \author Abhi Modak (contact: abhi.modak@cern.ch) +/// \help: To develop this code, I took help from the following codes and O2 analysis tutorial +// 1. https://github.com/AliceO2Group/O2Physics/blob/master/PWGMM/Mult/Tasks/dndeta.cxx +// 2. https://github.com/AliceO2Group/O2Physics/blob/master/PWGMM/Mult/Tasks/dndeta-hi.cxx +// 3. https://github.com/AliceO2Group/O2Physics/blob/master/PWGMM/Mult/Tasks/puremc-dndeta.cxx +// 4. O2 analysis tutorial: https://indico.cern.ch/event/1267433/ + +#include +#include +#include +#include +#include + +#include "bestCollisionTable.h" +#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/trackUtilities.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/MathConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/Configurable.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/GlobalTrackID.h" +#include "ReconstructionDataFormats/Track.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::track; + +using CollisionDataTable = soa::Join; +using TrackDataTable = soa::Join; +using FilTrackDataTable = soa::Filtered; +using CollisionMCTrueTable = aod::McCollisions; +using TrackMCTrueTable = aod::McParticles; +using CollisionMCRecTable = soa::SmallGroups>; +using TrackMCRecTable = soa::Join; +using FilTrackMCRecTable = soa::Filtered; + +static constexpr TrackSelectionFlags::flagtype trackSelectionITS = + TrackSelectionFlags::kITSNCls | TrackSelectionFlags::kITSChi2NDF | + TrackSelectionFlags::kITSHits; +static constexpr TrackSelectionFlags::flagtype trackSelectionTPC = + TrackSelectionFlags::kTPCNCls | + TrackSelectionFlags::kTPCCrossedRowsOverNCls | + TrackSelectionFlags::kTPCChi2NDF; +static constexpr TrackSelectionFlags::flagtype trackSelectionDCA = + TrackSelectionFlags::kDCAz | TrackSelectionFlags::kDCAxy; +static constexpr TrackSelectionFlags::flagtype trackSelectionDCAXYonly = + TrackSelectionFlags::kDCAxy; + +AxisSpec axisEvent{4, -0.5, 3.5, "#Event"}; +AxisSpec axisVtxZ{800, -20, 20, "Vertex Z"}; +AxisSpec axisDCA = {601, -3.01, 3.01}; +AxisSpec axisPT = {1000, -0.05, 49.95}; +AxisSpec axisEta{200, -5, 5, "#eta"}; +AxisSpec axisPhi{629, 0, 2 * M_PI, "#phi"}; +AxisSpec axisMCEvent_ambiguity{6, -0.5, 5.5, "reco collisions per true collision"}; + +struct HeavyIonMultiplicity { + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + Service pdg; + Preslice perCollision = aod::track::collisionId; + + Configurable etaRange{"eta-range", 1.0f, "Eta range to consider"}; + Configurable VtxRange{"vertex-range", 10.0f, "Vertex Z range to consider"}; + Configurable dcaZ{"dcaZ", 0.2f, "Custom DCA Z cut (ignored if negative)"}; + ConfigurableAxis multHistBin{"MultDistBinning", {501, -0.5, 500.5}, ""}; + + void init(InitContext const&) + { + AxisSpec axisMult = {multHistBin}; + histos.add("EventHist", "EventHist", kTH1D, {axisEvent}, false); + histos.add("VtxZHist", "VtxZHist", kTH1D, {axisVtxZ}, false); + + if (doprocessData) { + histos.add("MultHist", "MultHist", kTH1D, {axisMult}, true); + histos.add("MultHist_Inelgt0", "MultHist_Inelgt0", kTH1D, {axisMult}, true); + histos.add("EtaHist", "EtaHist", kTH1D, {axisEta}, true); + histos.add("PhiHist", "PhiHist", kTH1D, {axisPhi}, true); + histos.add("EtaVsVtxZHist", "EtaVsVtxZHist", kTH2D, {axisEta, axisVtxZ}, false); + histos.add("PhiVsEtaHist", "PhiVsEtaHist", kTH2D, {axisPhi, axisEta}, false); + histos.add("DCAXYHist", "DCAXYHist", kTH1D, {axisDCA}, false); + histos.add("DCAZHist", "DCAZHist", kTH1D, {axisDCA}, false); + histos.add("pTHist", "pTHist", kTH1D, {axisPT}, true); + } + + if (doprocessMC) { + histos.add("MCEventHist_ambiguity", "MCEventHist_ambiguity", kTH1D, {axisMCEvent_ambiguity}, false); + histos.add("DCAXYMCRecHist", "DCAXYMCRecHist", kTH1D, {axisDCA}, false); + histos.add("DCAZMCRecHist", "DCAZMCRecHist", kTH1D, {axisDCA}, false); + histos.add("pTMCRecHist", "pTMCRecHist", kTH1D, {axisPT}, true); + histos.add("EtaVsVtxZMCRecHist", "EtaVsVtxZMCRecHist", kTH2D, {axisEta, axisVtxZ}, true); + histos.add("MCRecEtaHist", "MCRecEtaHist", kTH1D, {axisEta}, true); + histos.add("MCGenEtaHist", "MCGenEtaHist", kTH1D, {axisEta}, true); + histos.add("MCRecPhiHist", "MCRecPhiHist", kTH1D, {axisPhi}, true); + histos.add("MCGenPhiHist", "MCGenPhiHist", kTH1D, {axisPhi}, true); + histos.add("MCRecPhiVsEtaHist", "MCRecPhiVsEtaHist", kTH2D, {axisPhi, axisEta}, false); + histos.add("MCGenPhiVsEtaHist", "MCGenPhiVsEtaHist", kTH2D, {axisPhi, axisEta}, false); + histos.add("MCRecMultHist", "MCRecMultHist", kTH1D, {axisMult}, true); + histos.add("MCGenMultHist", "MCGenMultHist", kTH1D, {axisMult}, true); + histos.add("MCGenVsRecMultHist", "MCGenVsRecMultHist", kTH2D, {axisMult, axisMult}, true); + histos.add("MCRecMultHist_Inelgt0", "MCRecMultHist_Inelgt0", kTH1D, {axisMult}, true); + histos.add("MCGenMultHist_Inelgt0", "MCGenMultHist_Inelgt0", kTH1D, {axisMult}, true); + histos.add("MCGenVsRecMultHist_Inelgt0", "MCGenVsRecMultHist_Inelgt0", kTH2D, {axisMult, axisMult}, true); + } + } + + expressions::Filter trackSelectionProperMixed = ncheckbit(aod::track::detectorMap, (uint8_t)o2::aod::track::ITS) && + ncheckbit(aod::track::trackCutFlag, trackSelectionITS) && + ifnode(ncheckbit(aod::track::detectorMap, (uint8_t)o2::aod::track::TPC), + ncheckbit(aod::track::trackCutFlag, trackSelectionTPC), true) && + ifnode(dcaZ.node() > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, trackSelectionDCAXYonly), + ncheckbit(aod::track::trackCutFlag, trackSelectionDCA)); + + void processData(CollisionDataTable::iterator const& collision, FilTrackDataTable const& tracks) + { + auto NchTracks = 0; + bool Inelgt0 = false; + histos.fill(HIST("EventHist"), 0); + if (collision.sel8()) { + histos.fill(HIST("EventHist"), 1); + if (std::abs(collision.posZ()) < VtxRange) { + histos.fill(HIST("EventHist"), 2); + histos.fill(HIST("VtxZHist"), collision.posZ()); + for (auto& track : tracks) { + if (std::abs(track.eta()) < etaRange) { + NchTracks++; + histos.fill(HIST("EtaHist"), track.eta()); + histos.fill(HIST("PhiHist"), track.phi()); + histos.fill(HIST("PhiVsEtaHist"), track.phi(), track.eta()); + histos.fill(HIST("EtaVsVtxZHist"), track.eta(), collision.posZ()); + histos.fill(HIST("DCAXYHist"), track.dcaXY()); + histos.fill(HIST("DCAZHist"), track.dcaZ()); + histos.fill(HIST("pTHist"), track.pt()); + } + } + histos.fill(HIST("MultHist"), NchTracks); + if (NchTracks > 0) { + Inelgt0 = true; + } + if (Inelgt0) { + histos.fill(HIST("EventHist"), 3); + histos.fill(HIST("MultHist_Inelgt0"), NchTracks); + } + } + } + } + + PROCESS_SWITCH(HeavyIonMultiplicity, processData, "process data", false); + + void processMC(CollisionMCTrueTable::iterator const& TrueCollision, CollisionMCRecTable const& RecCollisions, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) + { + histos.fill(HIST("MCEventHist_ambiguity"), RecCollisions.size()); + if (RecCollisions.size() == 0 || RecCollisions.size() > 1) { + return; + } + auto NchGenTracks = 0; + bool Inelgt0Gen = false; + auto NchRecTracks = 0; + bool Inelgt0Rec = false; + for (auto& particle : GenParticles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (!particle.producedByGenerator()) { + continue; + } + auto pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle == nullptr) { + continue; + } + if (std::abs(pdgParticle->Charge()) >= 3) { + if (std::abs(particle.eta()) < etaRange) { + NchGenTracks++; + histos.fill(HIST("MCGenEtaHist"), particle.eta()); + histos.fill(HIST("MCGenPhiHist"), particle.phi()); + histos.fill(HIST("MCGenPhiVsEtaHist"), particle.phi(), particle.eta()); + } + } + } + histos.fill(HIST("MCGenMultHist"), NchGenTracks); + if (NchGenTracks > 0) { + Inelgt0Gen = true; + } + if (Inelgt0Gen) { + histos.fill(HIST("MCGenMultHist_Inelgt0"), NchGenTracks); + } + for (auto& RecCollision : RecCollisions) { + histos.fill(HIST("EventHist"), 0); + if (RecCollision.sel8()) { + histos.fill(HIST("EventHist"), 1); + if (std::abs(RecCollision.posZ()) < VtxRange) { + histos.fill(HIST("EventHist"), 2); + histos.fill(HIST("VtxZHist"), RecCollision.posZ()); + + auto Rectrackspart = RecTracks.sliceBy(perCollision, RecCollision.globalIndex()); + for (auto& Rectrack : Rectrackspart) { + if (std::abs(Rectrack.eta()) < etaRange) { + NchRecTracks++; + histos.fill(HIST("MCRecEtaHist"), Rectrack.eta()); + histos.fill(HIST("MCRecPhiHist"), Rectrack.phi()); + histos.fill(HIST("MCRecPhiVsEtaHist"), Rectrack.phi(), Rectrack.eta()); + histos.fill(HIST("EtaVsVtxZMCRecHist"), Rectrack.eta(), RecCollision.posZ()); + histos.fill(HIST("DCAXYMCRecHist"), Rectrack.dcaXY()); + histos.fill(HIST("DCAZMCRecHist"), Rectrack.dcaZ()); + histos.fill(HIST("pTMCRecHist"), Rectrack.pt()); + } + } + histos.fill(HIST("MCRecMultHist"), NchRecTracks); + histos.fill(HIST("MCGenVsRecMultHist"), NchRecTracks, NchGenTracks); + if (NchRecTracks > 0) { + Inelgt0Rec = true; + histos.fill(HIST("EventHist"), 3); + } + if (Inelgt0Rec) { + histos.fill(HIST("MCRecMultHist_Inelgt0"), NchRecTracks); + } + if (Inelgt0Gen && Inelgt0Rec) { + histos.fill(HIST("MCGenVsRecMultHist_Inelgt0"), NchRecTracks, NchGenTracks); + } + } + } + } + } + PROCESS_SWITCH(HeavyIonMultiplicity, processMC, "process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGMM/Mult/Tasks/puremc-dndeta.cxx b/PWGMM/Mult/Tasks/puremc-dndeta.cxx new file mode 100644 index 00000000000..5a94e4c87b3 --- /dev/null +++ b/PWGMM/Mult/Tasks/puremc-dndeta.cxx @@ -0,0 +1,335 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include "Framework/StaticFor.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +AxisSpec ZAxis = {301, -30.1, 30.1}; +AxisSpec DeltaZAxis = {61, -6.1, 6.1}; +AxisSpec DCAAxis = {601, -3.01, 3.01}; +AxisSpec EtaAxis = {62, -6.2, 6.2}; +AxisSpec RapidityAxis = {102, -10.2, 10.2}; +AxisSpec PhiAxis = {629, 0, 2 * M_PI}; +AxisSpec PtAxis = {2401, -0.005, 24.005}; +AxisSpec PtAxis_wide = {1041, -0.05, 104.05}; +AxisSpec PtAxisEff = {{0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, + 1.7, 1.8, 1.9, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0}}; +AxisSpec ScaleAxis = {121, -0.5, 120.5}; +AxisSpec MPIAxis = {51, -0.5, 50.5}; +AxisSpec ProcAxis = {21, 89.5, 110.5}; + +auto static constexpr mincharge = 3.f; + +static constexpr std::string_view species[] = {"pi", "p", "e", "K"}; +static constexpr std::array speciesIds{kPiPlus, kProton, kElectron, kKPlus}; + +struct PureMcMultiplicityCounter { + SliceCache cache; + Preslice perCol = aod::track::collisionId; + Preslice perMcCol = aod::mcparticle::mcCollisionId; + Service pdg; + Configurable etaRange{"eta-range", 1.0f, "Eta range to consider"}; + ConfigurableAxis multBinning{"multiplicity-binning", {301, -0.5, 300.5}, ""}; + + HistogramRegistry registry{ + "registry", + { + {"MCEvents/Vertex/X", "; X (cm); events", {HistType::kTH1F, {ZAxis}}}, + {"MCEvents/Vertex/Y", "; Y (cm); events", {HistType::kTH1F, {ZAxis}}}, + {"MCEvents/Vertex/Z", "; Z (cm); events", {HistType::kTH1F, {ZAxis}}}, + {"Particles/Primaries/Pt", " ;p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis_wide}}}, + {"Particles/Primaries/Eta", " ; #eta", {HistType::kTH1F, {EtaAxis}}}, + {"Particles/Primaries/Y", " ; y", {HistType::kTH1F, {RapidityAxis}}}, + {"Particles/Primaries/EtaZvtx", " ; #eta; Z_{vtx} (cm); particles", {HistType::kTH2F, {EtaAxis, ZAxis}}}, + {"MCEvents/Properties/ProcessID", "; process ID", {HistType::kTH1F, {ProcAxis}}}, + {"MCEvents/Properties/ScalePerProcessID", " ; scale (GeV); process ID", {HistType::kTH2F, {ScaleAxis, ProcAxis}}}, + {"MCEvents/Properties/NMPIsPerProcessID", " ; N_{MPI}; process ID", {HistType::kTH2F, {MPIAxis, ProcAxis}}}, + {"MCEvents/Properties/ScaleVsNMPIsPerProcessID", " ;scale (GeV); N_{MPI}; process ID", {HistType::kTHnSparseF, {MPIAxis, ScaleAxis, ProcAxis}}}, + } // + }; + + void init(InitContext const&) + { + for (auto i = 0u; i < speciesIds.size(); ++i) { + registry.add({(std::string("Particles/Primaries/") + std::string(species[i]) + "/Pt").c_str(), " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis_wide}}}); + registry.add({(std::string("Particles/Primaries/") + std::string(species[i]) + "/Eta").c_str(), " ; #eta", {HistType::kTH1F, {EtaAxis}}}); + registry.add({(std::string("Particles/Primaries/") + std::string(species[i]) + "/Y").c_str(), " ; y", {HistType::kTH1F, {RapidityAxis}}}); + } + + AxisSpec MultAxis = {multBinning}; + registry.add({"MCEvents/NtrkZvtx", " ; N_{trk}; Z_{vtx} (cm); events", {HistType::kTH2F, {MultAxis, ZAxis}}}); + registry.add({"MCEvents/Properties/MultiplicityPerProcessID", " ; N_{p}; process ID; events", {HistType::kTH2F, {MultAxis, ProcAxis}}}); + registry.add({"MCEvents/Properties/MultiplicityVsScalePerProcessID", " ; scale; N_{p}; process ID", {HistType::kTHnSparseF, {ScaleAxis, MultAxis, ProcAxis}}}); + registry.add({"MCEvents/Properties/MultiplicityVsMPIsPerProcessID", " ; N_{MPI}; N_{p}; process ID", {HistType::kTHnSparseF, {MPIAxis, MultAxis, ProcAxis}}}); + + if (doprocessReco) { + registry.add({"Events/Properties/Multiplicity", " ; N_{p}; events", {HistType::kTH1F, {MultAxis}}}); + registry.add({"Events/Vertex/X", "; X (cm); events", {HistType::kTH1F, {ZAxis}}}); + registry.add({"Events/Vertex/Y", "; Y (cm); events", {HistType::kTH1F, {ZAxis}}}); + registry.add({"Events/Vertex/Z", "; Z (cm); events", {HistType::kTH1F, {ZAxis}}}); + registry.add({"Tracks/Pt", " ;p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis_wide}}}); + registry.add({"Tracks/Eta", " ; #eta", {HistType::kTH1F, {EtaAxis}}}); + registry.add({"Tracks/DCAXY", "; DCA_{XY} (cm)", {HistType::kTH1F, {DCAAxis}}}); + registry.add({"Tracks/DCAZ", "; DCA_{Z} (cm)", {HistType::kTH1F, {DCAAxis}}}); + registry.add({"Tracks/EtaZvtx", " ; #eta; Z_{vtx} (cm); tracks", {HistType::kTH2F, {EtaAxis, ZAxis}}}); + registry.add({"Events/NtrkZvtx", " ; N_{trk}; Z_{vtx} (cm); events", {HistType::kTH2F, {MultAxis, ZAxis}}}); + } + if (doprocessResponse) { + registry.add({"MCEvents/VertexCorrelation", " ; Z_{vtx}^{gen} (cm); Z_{vtx}^{rec} (cm)", {HistType::kTH2F, {ZAxis, ZAxis}}}); + registry.add({"MCEvents/Efficiency", "", {HistType::kTH1F, {{6, -0.5, 5.5}}}}); + registry.add({"MCEvents/Response", " ; N_{gen}; N_{rec}", {HistType::kTH2F, {MultAxis, MultAxis}}}); + auto eff = registry.get(HIST("MCEvents/Efficiency")); + auto* x = eff->GetXaxis(); + x->SetBinLabel(1, "Generated"); + x->SetBinLabel(2, "Generate INEL>0"); + x->SetBinLabel(3, "Reconstructed"); + x->SetBinLabel(4, "Reconstructed INEL>0"); + x->SetBinLabel(5, "Selected"); + x->SetBinLabel(6, "Selected INEL>0"); + + registry.add({"MCEvents/EfficiencyMultiplicityN", " ; N_{gen}", {HistType::kTH1F, {MultAxis}}}); + registry.add({"MCEvents/EfficiencyMultiplicityNExtra", " ; N_{gen}", {HistType::kTH1F, {MultAxis}}}); + registry.add({"MCEvents/EfficiencyMultiplicityD", " ; N_{gen}", {HistType::kTH1F, {MultAxis}}}); + } + if (doprocessEfficiency) { + registry.add({"Particles/Primaries/EfficiencyN", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Particles/Primaries/EfficiencyD", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Particles/Secondaries/EfficiencyN", " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxisEff}}}); + registry.add({"Particles/Primaries/PtCorrelation", " ; p_{T}^{gen} (GeV/c); p_{T}^{rec} (GeV/c)", {HistType::kTH2F, {PtAxis_wide, PtAxis_wide}}}); + registry.add({"Particles/Primaries/EtaCorrelation", " ; #eta^{gen}; #eta^{rec}", {HistType::kTH2F, {EtaAxis, EtaAxis}}}); + registry.add({"Particles/Secondaries/PtCorrelation", " ; p_{T}^{gen} (GeV/c); p_{T}^{rec} (GeV/c)", {HistType::kTH2F, {PtAxis_wide, PtAxis_wide}}}); + registry.add({"Particles/Secondaries/EtaCorrelation", " ; #eta^{gen}; #eta^{rec}", {HistType::kTH2F, {EtaAxis, EtaAxis}}}); + + for (auto i = 0u; i < speciesIds.size(); ++i) { + registry.add({(std::string("Particles/Primaries/") + std::string(species[i]) + "/EfficiencyN").c_str(), " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis_wide}}}); + registry.add({(std::string("Particles/Primaries/") + std::string(species[i]) + "/EfficiencyD").c_str(), " ; p_{T} (GeV/c)", {HistType::kTH1F, {PtAxis_wide}}}); + } + } + } + + void process(soa::Join::iterator const& collision, aod::McParticles const& particles) + { + registry.fill(HIST("MCEvents/Vertex/X"), collision.posX()); + registry.fill(HIST("MCEvents/Vertex/Y"), collision.posY()); + registry.fill(HIST("MCEvents/Vertex/Z"), collision.posZ()); + + registry.fill(HIST("MCEvents/Properties/ProcessID"), collision.processId()); + registry.fill(HIST("MCEvents/Properties/ScalePerProcessID"), collision.ptHard(), collision.processId()); + registry.fill(HIST("MCEvents/Properties/NMPIsPerProcessID"), collision.nMPI(), collision.processId()); + registry.fill(HIST("MCEvents/Properties/ScaleVsNMPIsPerProcessID"), collision.ptHard(), collision.nMPI(), collision.processId()); + + auto Np = 0; + for (auto const& particle : particles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (!particle.producedByGenerator()) { + continue; + } + auto charge = 0.; + auto* p = pdg->GetParticle(particle.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + if (std::abs(charge) < mincharge) { + continue; + } + registry.fill(HIST("Particles/Primaries/Eta"), particle.eta()); + registry.fill(HIST("Particles/Primaries/Y"), particle.y()); + registry.fill(HIST("Particles/Primaries/EtaZvtx"), particle.eta(), collision.posZ()); + + static_for<0, 3>( + [&](auto idx) { + constexpr int i = idx.value; + if (particle.pdgCode() == speciesIds[i]) { + registry.fill(HIST("Particles/Primaries/") + HIST(species[i]) + HIST("/Eta"), particle.eta()); + registry.fill(HIST("Particles/Primaries/") + HIST(species[i]) + HIST("/Y"), particle.y()); + } + }); + + if (std::abs(particle.eta()) >= etaRange) { + continue; + } + ++Np; + registry.fill(HIST("Particles/Primaries/Pt"), particle.pt()); + static_for<0, 3>( + [&](auto idx) { + constexpr int i = idx.value; + if (particle.pdgCode() == speciesIds[i]) { + registry.fill(HIST("Particles/Primaries/") + HIST(species[i]) + HIST("/Pt"), particle.pt()); + } + }); + } + registry.fill(HIST("MCEvents/Properties/MultiplicityVsMPIsPerProcessID"), collision.nMPI(), Np, collision.processId()); + registry.fill(HIST("MCEvents/Properties/MultiplicityVsScalePerProcessID"), collision.ptHard(), Np, collision.processId()); + registry.fill(HIST("MCEvents/Properties/MultiplicityPerProcessID"), Np, collision.processId()); + registry.fill(HIST("MCEvents/NtrkZvtx"), Np, collision.posZ()); + } + + void processReco(aod::Collision const& collision, soa::Join const& tracks) + { + registry.fill(HIST("Events/Vertex/X"), collision.posX()); + registry.fill(HIST("Events/Vertex/Y"), collision.posY()); + registry.fill(HIST("Events/Vertex/Z"), collision.posZ()); + auto Ntrk = 0; + for (auto& track : tracks) { + registry.fill(HIST("Tracks/DCAXY"), track.dcaXY()); + registry.fill(HIST("Tracks/DCAZ"), track.dcaZ()); + registry.fill(HIST("Tracks/Pt"), track.pt()); + registry.fill(HIST("Tracks/Eta"), track.eta()); + registry.fill(HIST("Tracks/EtaZvtx"), track.eta(), collision.posZ()); + if (std::abs(track.eta()) < etaRange) { + ++Ntrk; + } + } + registry.fill(HIST("Events/Properties/Multiplicity"), Ntrk); + registry.fill(HIST("Events/NtrkZvtx"), Ntrk, collision.posZ()); + } + + PROCESS_SWITCH(PureMcMultiplicityCounter, processReco, "Process smeared tracks", false); + + void processResponse(aod::McCollision const& mccollision, soa::SmallGroups> const& collisions, aod::McParticles const& particles, soa::Join const& tracks) + { + registry.fill(HIST("MCEvents/Efficiency"), 0); + auto Np = 0; + for (auto const& particle : particles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (!particle.producedByGenerator()) { + continue; + } + auto charge = 0.; + auto* p = pdg->GetParticle(particle.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + if (std::abs(charge) < mincharge) { + continue; + } + if (std::abs(particle.eta()) >= etaRange) { + continue; + } + ++Np; + } + registry.fill(HIST("MCEvents/EfficiencyMultiplicityD"), Np); + if (Np > 0) { + registry.fill(HIST("MCEvents/Efficiency"), 1); + } + if (collisions.size() > 0) { + registry.fill(HIST("MCEvents/EfficiencyMultiplicityN"), Np); + } + if (collisions.size() > 1) { + for (auto i = 1; i < collisions.size(); ++i) { + registry.fill(HIST("MCEvents/EfficiencyMultiplicityNExtra"), Np); + } + } + for (auto& collision : collisions) { + auto Ntrk = 0; + registry.fill(HIST("MCEvents/Efficiency"), 2); + auto tracksample = tracks.sliceBy(perCol, collision.globalIndex()); + for (auto& track : tracksample) { + if (std::abs(track.eta()) < etaRange) { + ++Ntrk; + } + } + if (Ntrk > 0) { + registry.fill(HIST("MCEvents/Efficiency"), 3); + } + registry.fill(HIST("MCEvents/Response"), Np, Ntrk); + registry.fill(HIST("MCEvents/VertexCorrelation"), mccollision.posZ(), collision.posZ()); + } + } + + PROCESS_SWITCH(PureMcMultiplicityCounter, processResponse, "Process response", false); + + void processEfficiency(soa::Join::iterator const& collision, aod::McCollisions const&, aod::McParticles const& particles, soa::Join const& tracks) + { + if (!collision.has_mcCollision()) { + return; + } + auto psample = particles.sliceBy(perMcCol, collision.mcCollisionId()); + + for (auto& particle : psample) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (!particle.producedByGenerator()) { + continue; + } + auto charge = 0.; + auto p = pdg->GetParticle(particle.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + if (std::abs(charge) < 3.) { + continue; + } + if (std::abs(particle.eta()) >= etaRange) { + continue; + } + registry.fill(HIST("Particles/Primaries/EfficiencyD"), particle.pt()); + static_for<0, 3>( + [&](auto idx) { + constexpr int i = idx.value; + if (particle.pdgCode() == speciesIds[i]) { + registry.fill(HIST("Particles/Primaries/") + HIST(species[i]) + HIST("/EfficiencyD"), particle.pt()); + } + }); + } + + for (auto& track : tracks) { + if (std::abs(track.eta()) >= etaRange) { + continue; + } + if (track.has_mcParticle()) { + auto particle = track.mcParticle(); + if (particle.mcCollisionId() != collision.mcCollisionId()) { + continue; + } + if (particle.isPhysicalPrimary()) { + registry.fill(HIST("Particles/Primaries/EfficiencyN"), particle.pt()); + registry.fill(HIST("Particles/Primaries/PtCorrelation"), particle.pt(), track.pt()); + registry.fill(HIST("Particles/Primaries/EtaCorrelation"), particle.eta(), track.eta()); + + static_for<0, 3>( + [&](auto idx) { + constexpr int i = idx.value; + if (particle.pdgCode() == speciesIds[i]) { + registry.fill(HIST("Particles/Primaries/") + HIST(species[i]) + HIST("/EfficiencyN"), particle.pt()); + } + }); + } else { + registry.fill(HIST("Particles/Secondaries/EfficiencyN"), particle.pt()); + registry.fill(HIST("Particles/Secondaries/PtCorrelation"), particle.pt(), track.pt()); + registry.fill(HIST("Particles/Secondaries/EtaCorrelation"), particle.eta(), track.eta()); + } + } + } + } + + PROCESS_SWITCH(PureMcMultiplicityCounter, processEfficiency, "Process efficiency", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return {adaptAnalysisTask(cfgc)}; +} diff --git a/PWGMM/Mult/Tasks/run2dndeta.cxx b/PWGMM/Mult/Tasks/run2dndeta.cxx index 9c854ea7001..9db9fd291d9 100644 --- a/PWGMM/Mult/Tasks/run2dndeta.cxx +++ b/PWGMM/Mult/Tasks/run2dndeta.cxx @@ -36,7 +36,7 @@ struct PseudorapidityDensity { Preslice perCol = aod::track::collisionId; Preslice perMCCol = aod::mcparticle::mcCollisionId; - Service pdg; + Service pdg; Configurable estimatorEta{"estimatorEta", 1.0, "eta range for INEL>0 sample definition"}; Configurable useEvSel{"useEvSel", true, "use event selection"}; diff --git a/PWGMM/Tasks/multiplicityPbPb.cxx b/PWGMM/Tasks/multiplicityPbPb.cxx index a3236c1a021..0f314b026aa 100644 --- a/PWGMM/Tasks/multiplicityPbPb.cxx +++ b/PWGMM/Tasks/multiplicityPbPb.cxx @@ -49,28 +49,28 @@ struct multiplicityPbPb { { // define axes you want to use const AxisSpec axisEta{nBinsEta, -2, 2, "#eta"}; - const AxisSpec axisPt{nBinsPt, 0, 6, "pT"}; + const AxisSpec axisPt{nBinsPt, 0, 5, "p_T"}; const AxisSpec axisDeltaPt{100, -1.0, +1.0, "#Delta(p_{T})"}; const AxisSpec axisCounter{1, 0, +1, ""}; - const AxisSpec axisDCAxy{nBinsDCA, -1, 1, "DCA_{xy} (cm)"}; - const AxisSpec axisDCAz{nBinsDCA, -1, 1, "DCA_{z} (cm)"}; + const AxisSpec axisDCAxy{nBinsDCA, -0.22, 0.22, "DCA_{xy} (cm)"}; + const AxisSpec axisDCAz{nBinsDCA, -0.22, 0.22, "DCA_{z} (cm)"}; - const AxisSpec axisNtrk{nBinsMult, 0, 100, "N_{trk}"}; + const AxisSpec axisNtrk{nBinsMult, 0, 300, "N_{trk}"}; - const AxisSpec axisPhi{nBinsPhi, -10, 10, "#phi"}; + const AxisSpec axisPhi{nBinsPhi, -0.4, 6.8, "#phi"}; const AxisSpec axisZvtx{nBinsZvtx, -30, 30, "Z_{vtx} (cm)"}; - histos.add("etaHistogram", "etaHistogram", kTH1F, {axisEta}); - histos.add("ptHistogram", "ptHistogram", kTH1F, {axisPt}); + histos.add("etaHistogram", "; ", kTH1F, {axisEta}); + histos.add("ptHistogram", "; ", kTH1F, {axisPt}); // histos.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); histos.add("DCAxy", "; DCA_{xy} (cm)", kTH1F, {axisDCAxy}); histos.add("DCAz", "; DCA_{z} (cm)", kTH1F, {axisDCAz}); // do not know how: - histos.add("Multiplicity", "Multiplicity; tracks; events", kTH1F, {axisNtrk}); + histos.add("Multiplicity", "; tracks; events", kTH1F, {axisNtrk}); histos.add("Anton/PhiTracks", "; #phi; tracks", kTH1F, {axisPhi}); histos.add("Anton/ZvtxEvents", "; Z_{vtx} (cm); events", kTH1F, {axisZvtx}); diff --git a/PWGMM/UE/Tasks/ue-zdc-analysys.cxx b/PWGMM/UE/Tasks/ue-zdc-analysys.cxx index 318c2e5430f..7d668bc267a 100644 --- a/PWGMM/UE/Tasks/ue-zdc-analysys.cxx +++ b/PWGMM/UE/Tasks/ue-zdc-analysys.cxx @@ -39,8 +39,8 @@ using BCsWithRun3Matchings = soa::Join nBins1{"nBins1", 400, "Nbins 1d ZDC histos"}; - Configurable nBins2{"nBins2", 800, "Nbins 2d ZDC histos"}; + Configurable nBins1{"nBins1", 400, "Nbins1"}; + Configurable nBins2{"nBins2", 800, "Nbins2"}; // CInfigurable maximum limit Configurable MaxZN{"MaxZN", 4000, "Max ZN signal"}; Configurable MaxZP{"MaxZP", 3000, "Max ZP signal"}; @@ -60,36 +60,36 @@ struct ZDCAnalysis { registry.add("ZPCpmc", "ZPCpmc", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); registry.add("ZEM1", "ZEM1", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); registry.add("ZEM2", "ZEM2", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); - registry.add("ZNvsZEM", "ZNvsZEM", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); - registry.add("ZNAvsZNC", "ZNAvsZNC", {HistType::kTH2F, {{{nBins2, -10., MaxZN}, {nBins2, -10., MaxZN}}}}); - registry.add("ZPAvsZPC", "ZPAvsZPC", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZP}}}}); - registry.add("ZNAvsZPA", "ZNAvsZPA", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); - registry.add("ZNCvsZPC", "ZNCvsZPC", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); + registry.add("ZNvsZEM", "ZNvsZEM", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); + registry.add("ZNAvsZNC", "ZNAvsZNC", {HistType::kTH2F, {{{nBins1, -10., MaxZN}, {nBins1, -10., MaxZN}}}}); + registry.add("ZPAvsZPC", "ZPAvsZPC", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZP}}}}); + registry.add("ZNAvsZPA", "ZNAvsZPA", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); + registry.add("ZNCvsZPC", "ZNCvsZPC", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); // registry.add("ZNCcvsZNCsum", "ZNCcvsZNCsum", {HistType::kTH2F, {{{nBins1, -10., 3. * MaxZN}, {nBins1, -10., 3. * MaxZN}}}}); registry.add("ZNAcvsZNAsum", "ZNAcvsZNAsum", {HistType::kTH2F, {{{nBins1, -10., 3. * MaxZN}, {nBins1, -10., 3. * MaxZN}}}}); registry.add("ZPCcvsZPCsum", "ZPCcvsZPCsum", {HistType::kTH2F, {{{nBins1, -10., 3. * MaxZP}, {nBins1, -10., 3. * MaxZP}}}}); registry.add("ZPAcvsZPAsum", "ZPAcvsZPAsum", {HistType::kTH2F, {{{nBins1, -10., 3. * MaxZP}, {nBins1, -10., 3. * MaxZP}}}}); // - registry.add("ZNCadcvstdc", "ZNCadcvstdc", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZN}}}}); - registry.add("ZNAadcvstdc", "ZNAadcvstdc", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZN}}}}); - registry.add("ZPCadcvstdc", "ZPCadcvstdc", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZP}}}}); - registry.add("ZPAadcvstdc", "ZPAadcvstdc", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZP}}}}); - registry.add("ZEM1adcvstdc", "ZEM1adcvstdc", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZP}}}}); - registry.add("ZEM2adcvstdc", "ZEM2adcvstdc", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZP}}}}); + registry.add("ZNCadcvstdc", "ZNCadcvstdc", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZN}}}}); + registry.add("ZNAadcvstdc", "ZNAadcvstdc", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZN}}}}); + registry.add("ZPCadcvstdc", "ZPCadcvstdc", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZP}}}}); + registry.add("ZPAadcvstdc", "ZPAadcvstdc", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZP}}}}); + registry.add("ZEM1adcvstdc", "ZEM1adcvstdc", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZP}}}}); + registry.add("ZEM2adcvstdc", "ZEM2adcvstdc", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZP}}}}); } if (doprocessZdcBcAss) { // Check if the process function for ZDCBcAss is enabled registry.add("ZNAbc", "ZNAbc", {HistType::kTH1F, {{nBins1, -10., MaxZN}}}); - registry.add("ZPAbc", "ZPAbc", {HistType::kTH1F, {{nBins1, -10., MaxZN}}}); - registry.add("ZNCbc", "ZNCbc", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); + registry.add("ZNCbc", "ZNCbc", {HistType::kTH1F, {{nBins1, -10., MaxZN}}}); + registry.add("ZPAbc", "ZPAbc", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); registry.add("ZPCbc", "ZPCbc", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); registry.add("ZEM1bc", "ZEM1bc", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); registry.add("ZEM2bc", "ZEM2bc", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); - registry.add("ZNvsZEMbc", "ZNvsZEMbc", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); - registry.add("ZNAvsZNCbc", "ZNAvsZNCbc", {HistType::kTH2F, {{{nBins2, -10., MaxZN}, {nBins2, -10., MaxZN}}}}); - registry.add("ZPAvsZPCbc", "ZPAvsZPCbc", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZP}}}}); - registry.add("ZNAvsZPAbc", "ZNAvsZPAbc", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); - registry.add("ZNCvsZPCbc", "ZNCvsZPCbc", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); + registry.add("ZNvsZEMbc", "ZNvsZEMbc", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); + registry.add("ZNAvsZNCbc", "ZNAvsZNCbc", {HistType::kTH2F, {{{nBins1, -10., MaxZN}, {nBins1, -10., MaxZN}}}}); + registry.add("ZPAvsZPCbc", "ZPAvsZPCbc", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZP}}}}); + registry.add("ZNAvsZPAbc", "ZNAvsZPAbc", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); + registry.add("ZNCvsZPCbc", "ZNCvsZPCbc", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); } if (doprocessZdcCollAss) { // Check if the process function for ZDCCollAss is enabled registry.add("ZNAcoll", "ZNAcoll", {HistType::kTH1F, {{nBins1, -10., MaxZN}}}); @@ -98,18 +98,18 @@ struct ZDCAnalysis { registry.add("ZPCcoll", "ZPCcoll", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); registry.add("ZEM1coll", "ZEM1coll", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); registry.add("ZEM2coll", "ZEM2coll", {HistType::kTH1F, {{nBins1, -10., MaxZP}}}); - registry.add("ZNvsZEMcoll", "ZNvsZEMcoll", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); - registry.add("ZNAvsZNCcoll", "ZNAvsZNCcoll", {HistType::kTH2F, {{{nBins2, -10., MaxZN}, {nBins2, -10., MaxZN}}}}); - registry.add("ZPAvsZPCcoll", "ZPAvsZPCcoll", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZP}}}}); - registry.add("ZNAvsZPAcoll", "ZNAvsZPAcoll", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); - registry.add("ZNCvsZPCcoll", "ZNCvsZPCcoll", {HistType::kTH2F, {{{nBins2, -10., MaxZP}, {nBins2, -10., MaxZN}}}}); + registry.add("ZNvsZEMcoll", "ZNvsZEMcoll", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); + registry.add("ZNAvsZNCcoll", "ZNAvsZNCcoll", {HistType::kTH2F, {{{nBins1, -10., MaxZN}, {nBins1, -10., MaxZN}}}}); + registry.add("ZPAvsZPCcoll", "ZPAvsZPCcoll", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZP}}}}); + registry.add("ZNAvsZPAcoll", "ZNAvsZPAcoll", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); + registry.add("ZNCvsZPCcoll", "ZNCvsZPCcoll", {HistType::kTH2F, {{{nBins1, -10., MaxZP}, {nBins1, -10., MaxZN}}}}); // - registry.add("ZNCadcvstdccoll", "ZNCadcvstdccoll", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZN}}}}); - registry.add("ZNAadcvstdccoll", "ZNAadcvstdccoll", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZN}}}}); - registry.add("ZPCadcvstdccoll", "ZPCadcvstdccoll", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZP}}}}); - registry.add("ZPAadcvstdccoll", "ZPAadcvstdccoll", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZP}}}}); - registry.add("ZEM1adcvstdccoll", "ZEM1adcvstdccoll", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZP}}}}); - registry.add("ZEM2adcvstdccoll", "ZEM2adcvstdccoll", {HistType::kTH2F, {{{100, -25., 25.}, {nBins1, -10., MaxZP}}}}); + registry.add("ZNCadcvstdccoll", "ZNCadcvstdccoll", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZN}}}}); + registry.add("ZNAadcvstdccoll", "ZNAadcvstdccoll", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZN}}}}); + registry.add("ZPCadcvstdccoll", "ZPCadcvstdccoll", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZP}}}}); + registry.add("ZPAadcvstdccoll", "ZPAadcvstdccoll", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZP}}}}); + registry.add("ZEM1adcvstdccoll", "ZEM1adcvstdccoll", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZP}}}}); + registry.add("ZEM2adcvstdccoll", "ZEM2adcvstdccoll", {HistType::kTH2F, {{{400, -50., 50.}, {nBins1, -10., MaxZP}}}}); } if (doprocessZdcCorrela) { // Check if the process function for ZDCCollCorrela is enabled registry.add("ZNvsFV0Acorrel", "ZNvsFV0Acorrel", {HistType::kTH2F, {{{nBins2, 0., MaxMultFV0}, {nBins2, -10., MaxZN}}}}); @@ -136,10 +136,10 @@ struct ZDCAnalysis { float sumZNA = (zdc.energySectorZNA())[0] + (zdc.energySectorZNA())[1] + (zdc.energySectorZNA())[2] + (zdc.energySectorZNA())[3]; float sumZPC = (zdc.energySectorZPC())[0] + (zdc.energySectorZPC())[1] + (zdc.energySectorZPC())[2] + (zdc.energySectorZPC())[3]; float sumZPA = (zdc.energySectorZPA())[0] + (zdc.energySectorZPA())[1] + (zdc.energySectorZPA())[2] + (zdc.energySectorZPA())[3]; - registry.get(HIST("ZNCcvsZNCsum"))->Fill(zdc.energyCommonZNC(), sumZNC); - registry.get(HIST("ZNAcvsZNAsum"))->Fill(zdc.energyCommonZNA(), sumZNA); - registry.get(HIST("ZPCcvsZPCsum"))->Fill(zdc.energyCommonZPC(), sumZPC); - registry.get(HIST("ZPAcvsZPAsum"))->Fill(zdc.energyCommonZPA(), sumZPA); + registry.get(HIST("ZNCcvsZNCsum"))->Fill(sumZNC, zdc.energyCommonZNC()); + registry.get(HIST("ZNAcvsZNAsum"))->Fill(sumZNA, zdc.energyCommonZNA()); + registry.get(HIST("ZPCcvsZPCsum"))->Fill(sumZPC, zdc.energyCommonZPC()); + registry.get(HIST("ZPAcvsZPAsum"))->Fill(sumZPA, zdc.energyCommonZPA()); // registry.get(HIST("ZNCadcvstdc"))->Fill(zdc.timeZNC(), zdc.amplitudeZNC()); registry.get(HIST("ZNAadcvstdc"))->Fill(zdc.timeZNA(), zdc.amplitudeZNA()); diff --git a/PWGMM/UE/Tasks/uecharged.cxx b/PWGMM/UE/Tasks/uecharged.cxx index b0cc59afc86..7adf87bb28d 100644 --- a/PWGMM/UE/Tasks/uecharged.cxx +++ b/PWGMM/UE/Tasks/uecharged.cxx @@ -45,7 +45,7 @@ struct ueCharged { TrackSelection myTrackSelection(); - Service pdg; + Service pdg; float DeltaPhi(float phia, float phib, float rangeMin, float rangeMax); Configurable isRun3{"isRun3", true, "is Run3 dataset"}; // acceptance cuts diff --git a/PWGUD/AQC/udQC.cxx b/PWGUD/AQC/udQC.cxx index 65fc1b442f8..3e719cbb283 100644 --- a/PWGUD/AQC/udQC.cxx +++ b/PWGUD/AQC/udQC.cxx @@ -16,11 +16,13 @@ #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include "TLorentzVector.h" +#include "Framework/AnalysisDataModel.h" #include "ReconstructionDataFormats/BCRange.h" #include "CommonConstants/PhysicsConstants.h" +#include "Common/DataModel/FT0Corrected.h" #include "PWGUD/Core/UDHelpers.h" #include "Framework/StaticFor.h" +#include "TLorentzVector.h" using namespace o2; using namespace o2::framework; @@ -34,6 +36,7 @@ struct UDQC { static constexpr std::string_view hcFIT1s[5] = {"cleanFIT1FV0A", "cleanFIT1FT0A", "cleanFIT1FT0C", "cleanFIT1FDDA", "cleanFIT1FDDC"}; static constexpr std::string_view hcFIT2s[5] = {"cleanFIT2FV0A", "cleanFIT2FT0A", "cleanFIT2FT0C", "cleanFIT2FDDA", "cleanFIT2FDDC"}; + static constexpr std::string_view hcRelBCs[5] = {"BCFV0A", "BCFT0A", "BCFT0C", "BCFDDA", "BCFDDC"}; // global variables float maxdEdxTPC; @@ -59,7 +62,7 @@ struct UDQC { using CCs = soa::Join; using CC = CCs::iterator; using BCs = soa::Join; - using TCs = soa::Join; + using TCs = soa::Join; using FWs = aod::FwdTracks; using ATs = aod::AmbiguousTracks; using AFTs = aod::AmbiguousFwdTracks; @@ -73,29 +76,67 @@ struct UDQC { // add histograms for the different process functions if (context.mOptions.get("processMain")) { - registry.add("Stat", "#Stat", {HistType::kTH1F, {{20, -0.5, 19.5}}}); - registry.add("Tracks", "#Tracks", {HistType::kTH1F, {{300, 0.5, 300.5}}}); - registry.add("vtxTracks", "#vtxTracks", {HistType::kTH1F, {{300, 0.5, 300.5}}}); - registry.add("globalTracks", "#globalTracks", {HistType::kTH1F, {{300, 0.5, 300.5}}}); - registry.add("PVTracks", "#PVTracks", {HistType::kTH1F, {{300, 0.5, 300.5}}}); - registry.add("rejectedTracks", "#rejectedTracks", {HistType::kTH1F, {{17, -0.5, 16.5}}}); - registry.add("tResvsrTOFTracks", "#tResvsrTOFTracks", {HistType::kTH2F, {{1000, 0., 1.E3}, {101, -0.01, 1.01}}}); - registry.add("vtxPosxy", "#vtxPosxy", {HistType::kTH2F, {{200, -2., 2.}, {200, -2., 2.}}}); - registry.add("vtxPosz", "#vtxPosz", {HistType::kTH1F, {{1000, -100., 100.}}}); - registry.add("etapt", "#etapt", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); - registry.add("dEdxTPC", "#dEdxTPC", {HistType::kTH2F, {{120, -6., 6.}, {1000, 0., 1000.}}}); - registry.add("dEdxTPCmom", "#dEdxTPCmom", {HistType::kTH2F, {{120, 0., 5.}, {1000, 0., 1000.}}}); - registry.add("dEdxTOF", "#dEdxTOF", {HistType::kTH2F, {{100, 0., 5.0}, {1000, 0., 500000.}}}); - registry.add("vtxPosxyDG", "#vtxPosxyDG", {HistType::kTH2F, {{200, -2., 2.}, {200, -2., 2.}}}); - registry.add("vtxPoszDG", "#vtxPoszDG", {HistType::kTH1F, {{1000, -100., 100.}}}); - registry.add("etaptDG", "#etaptDG", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); - registry.add("dEdxTPCDG", "#dEdxTPCDG", {HistType::kTH2F, {{120, -6., 6.0}, {1000, 0., 1000.}}}); - registry.add("dEdxTPCDGmom", "#dEdxTPCDGmom", {HistType::kTH2F, {{120, 0., 5.0}, {1000, 0., 1000.}}}); - registry.add("dEdxTOFDG", "#dEdxTOFDG", {HistType::kTH2F, {{100, 0., 5.0}, {1000, 0., 500000.}}}); - registry.add("netChargeDG", "#netChargeDG", {HistType::kTH1F, {{21, -10.5, 10.5}}}); - registry.add("IVMptSysDG", "#IVMptSysDG", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); - registry.add("IVMptTrkDG", "#IVMptTrkDG", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); - registry.add("IVMptSysDG2trk", "#IVMptSysDG2trk", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); + + // collisions + registry.add("collisions/Stat", "Cut statistics; Selection criterion; Collisions", {HistType::kTH1F, {{20, -0.5, 19.5}}}); + registry.add("collisions/Tracks", "Number of tracks; Number of tracks; Collisions", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/vtxTracks", "Number of vertex tracks; Number of contributors; Collisions", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/globalTracks", "Number of global tracks; Number of global tracks; Collisions", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/TwoTracks", "Two tracks; Number of contributor two ; Collisions", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/PVTracks", "Number of PV tracks; Number of PV tracks; Collisions", {HistType::kTH1F, {{300, 0.5, 300.5}}}); + registry.add("collisions/posxy", "Vertex position in x and y direction; V_x; V_y; Collisions", {HistType::kTH2F, {{100, -0.5, 0.5}, {100, -0.5, 0.5}}}); + registry.add("collisions/posz", "Vertex position in z direction; V_z; Collisions", {HistType::kTH1F, {{1000, -100., 100.}}}); + registry.add("collisions/notPVTracks", "Not PV tracks; Track status bit; Not PV tracks", {HistType::kTH1F, {{17, -0.5, 16.5}}}); + registry.add("collisions/tResvsrTOFTracks", "Number of PV tracks with TOF hit versus collision time resolution; Collision time resolution [ns]; Fraction of PV tracks with TOF hit; Collisions", {HistType::kTH2F, {{1000, 0., 1.E3}, {101, -0.01, 1.01}}}); + registry.add("collisions/tResvsTOFTrkNoPV", "Number of No PV tracks with TOF hit versus collision time resolution; Collision time resolution [ns]; Fraction of No PV tracks with TOF hit; Collisions", {HistType::kTH2F, {{1000, 0., 1.E3}, {101, -0.01, 1.01}}}); + + // tracks + registry.add("tracks/Stat", "Track bits as function of pT; Track pT; Track bit; Tracks", {HistType::kTH2F, {{100, 0., 5.}, {8, 0.5, 8.5}}}); + registry.add("tracks/etapt", "eta versus pT of all tracks; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("tracks/etapt2", "eta versus pT of all quality tracks; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("tracks/etapt3", "eta versus pT of all global tracks; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("tracks/etapt4", "eta versus pT of all tracks with ITS Only; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("tracks/etapt5", "eta versus pT of all tracks with ITS; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("tracks/etapt6", "eta versus pT of all tracks with TPC; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("tracks/etapt7", "eta versus pT of all tracks with TRD; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("tracks/etapt8", "eta versus pT of all tracks with TOF; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + + registry.add("tracks/dEdxTPC", "TPC signal versus signed track momentum; Signed track momentum [GeV/c]; TPC signal; Tracks", {HistType::kTH2F, {{120, -6., 6.}, {1000, 0., 1000.}}}); + registry.add("tracks/dEdxTPCmom", "TPC signal versus track momentum;track momentum [GeV/c]; TPC signal; Tracks", {HistType::kTH2F, {{120, 0., 5.}, {1000, 0., 1000.}}}); + registry.add("tracks/dEdxTOF", "TOF signal versus signed track momentum; Signed track momentum [GeV/c]; TOF signal; Tracks", {HistType::kTH2F, {{1000, 0., 10.}, {1000, 0., 10.}}}); + + // DG + registry.add("DG/PVposxy", "DG: Vertex position in x and y direction; V_x [mm]; V_y [mm]; DG collisions", {HistType::kTH2F, {{100, -0.5, 0.5}, {100, -0.5, 0.5}}}); + registry.add("DG/PVposz", "DG: Vertex position in z direction; V_z; DG collisions", {HistType::kTH1F, {{1000, -100., 100.}}}); + registry.add("DG/netCharge", "DG: net charge; Net charge; DG collisions", {HistType::kTH1F, {{21, -10.5, 10.5}}}); + registry.add("DG/TrackStat", "Track bits as function of pT; Track pT; Track bit; Tracks", {HistType::kTH2F, {{100, 0., 5.}, {8, 0.5, 8.5}}}); + + registry.add("DG/etapt", "DG: eta versus pT of all tracks; eta of track; p_T of track [GeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("DG/etapt2", "DG: eta versus pT of all quality tracks; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("DG/etapt3", "DG: eta versus pT of all global tracks; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("DG/etapt4", "DG: eta versus pT of all TPC clusers; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("DG/etapt5", "DG: eta versus pT of frac.TPCSharedClusters; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("DG/etapt6", "DG: eta versus pT of all tracks with ITS; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("DG/etapt7", "DG: eta versus pT of all tracks with TPC; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("DG/etapt8", "DG: eta versus pT of all tracks with TRD; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + registry.add("DG/etapt9", "DG: eta versus pT of all tracks with TOF; eta of track; p_T of track [MeV/c^2]; Tracks", {HistType::kTH2F, {{80, -2., 2.}, {100, 0., 5.}}}); + + registry.add("DG/dEdxTPC", "DG: TPC signal versus signed track momentum; Signed track momentum [GeV/c]; TPC signal; Tracks", {HistType::kTH2F, {{120, -6., 6.}, {1000, 0., 1000.}}}); + registry.add("DG/dEdxTPCmom", "DG: TPC signal versus track momentum; Track momentum [GeV/c]; TPC signal; Tracks", {HistType::kTH2F, {{120, -6., 6.}, {1000, 0., 1000.}}}); + registry.add("DG/dEdxTOF", "DG: TOF signal versus signed track momentum; Signed track momentum [GeV/c]; TOF signal; Tracks", {HistType::kTH2F, {{1000, 0., 10.}, {1000, 0., 10.}}}); + registry.add("DG/IVMptSys", "DG: Invariant mass versus p_{T, system}; Invarian mass [GeV/c^2]; p_{T, system} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); + registry.add("DG/IVMptSys2PVtrk", "DG: Invariant mass versus p_{T, system}; Invarian mass [GeV/c^2]; p_{T, system} [GeV/c]; DG collisions 2 PV tracks", {HistType::kTH2F, {{1000, 0., 10.}, {350, 0., 3.5}}}); + registry.add("DG/IVMptTrk", "DG: Invariant mass versus p_{T, tracks}; Invarian mass [GeV/c^2]; p_{T, tracks} [GeV/c]; DG collisions", {HistType::kTH2F, {{1000, 0., 10.}, {350, 0., 3.5}}}); + registry.add("DG/nTPCclusters", "DG: No. of TPC clusters;PV tracks;N_{TPCcluster}", {HistType::kTH2F, {{300, 0.5, 300.5}, {200, 0., 200.}}}); + registry.add("DG/tpcNClsCrossedRows", "DG: No. of TPC tpcNClsCrossedRows;PV tracks;N_{tpcNClsCrossedRows}", {HistType::kTH2F, {{300, 0.5, 300.5}, {200, 0., 200.}}}); + registry.add("DG/tpcNClsShared", "DG: No. of shared TPC clusters;PV tracks;N_{tpcFracSharedCls}", {HistType::kTH2F, {{300, 0.5, 300.5}, {200, 0., 200.}}}); + registry.add("DG/nITSclsMap", "DG: No. of ITS cluster Map;PV tracks;Sector", {HistType::kTH2F, {{300, 0.5, 300.5}, {20, 0., 20.}}}); + registry.add("DG/trkDCAxy", "DG: Track DCA of XY;PV tracks; DCAxy", {HistType::kTH2F, {{300, 0.5, 300.5}, {100, -5., 5.}}}); + registry.add("DG/trkDCAz", "DG: Track DCA of XY; PV tracks; DCAz", {HistType::kTH2F, {{300, 0.5, 300.5}, {100, -5., 5.}}}); + + registry.add("DG/etaplus", "DG: eta of positive tracks; eta of track", {HistType::kTH1F, {{1000, -5., 5.}}}); + registry.add("DG/etaminus", "DG: eta of negative tracks; eta of track", {HistType::kTH1F, {{1000, -5., 5.}}}); + registry.add("DG/hMass", "DG: Invariant mass of pions; Invarian mass [GeV/c^2]", {HistType::kTH1F, {{1000, 0., 10.}}}); } if (context.mOptions.get("processFewProng")) { registry.add("fpStat", "#fpStat", {HistType::kTH1F, {{2, 0.5, 2.5}}}); @@ -124,18 +165,27 @@ struct UDQC { for (auto n{0}; n < 5; n++) { registry.add(hcFIT2s[n].data(), hcFIT2s[n].data(), {HistType::kTH2F, {{20, -0.5, 19.5}, {2, -0.5, 1.5}}}); + registry.add(hcRelBCs[n].data(), hcRelBCs[n].data(), {HistType::kTH1F, {{3564, -0.5, 3563.5}}}); } } if (context.mOptions.get("processFV0")) { registry.add("FV0A", "#FV0A", {HistType::kTH2F, {{48, -0.5, 47.5}, {2000, 0., 2000.}}}); + registry.add("hV0A", "Time FV0A", {HistType::kTH1F, {{500, -5.0, 5.0}}}); } if (context.mOptions.get("processFT0")) { registry.add("FT0A", "#FT0A", {HistType::kTH2F, {{96, -0.5, 95.5}, {400, 0., 400.}}}); registry.add("FT0C", "#FT0C", {HistType::kTH2F, {{112, -0.5, 111.5}, {400, 0., 400.}}}); + registry.add("hT0A", "Time FT0 A side", {HistType::kTH1F, {{500, -5.0, 5.0}}}); + registry.add("hT0C", "Time FT0 C side", {HistType::kTH1F, {{500, -5.0, 5.0}}}); + registry.add("hT0ACorr", "Corrected Time FT0 A side", {HistType::kTH1F, {{500, -5.0, 5.0}}}); + registry.add("hT0CCorr", "Corrected Time FT0 C side", {HistType::kTH1F, {{500, -5.0, 5.0}}}); + registry.add("hT0AC", "Average Time FT0", {HistType::kTH1F, {{500, -5.0, 5.0}}}); } if (context.mOptions.get("processFDD")) { registry.add("FDDA", "#FDDA", {HistType::kTH2F, {{8, -0.5, 7.5}, {100, 0., 100.}}}); registry.add("FDDC", "#FDDC", {HistType::kTH2F, {{8, -0.5, 7.5}, {100, 0., 100.}}}); + registry.add("hFDDA", " Avg Time FDD A side", {HistType::kTH1F, {{500, -5.0, 5.0}}}); + registry.add("hFDDC", " Avg Time FDD C side", {HistType::kTH1F, {{500, -5.0, 5.0}}}); } if (context.mOptions.get("processZDC")) { registry.add("ZdcEnergies", "#ZdcEnergies", {HistType::kTH2F, {{22, -0.5, 21.5}, {100, 0., 1000.}}}); @@ -153,64 +203,102 @@ struct UDQC { LOGF(debug, " Start %i", abcrs.size()); bool isDGcandidate = true; - registry.get(HIST("Stat"))->Fill(0., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(0., isDGcandidate * 1.); // update collision histograms // vertex position - registry.get(HIST("vtxPosxy"))->Fill(collision.posX(), collision.posY()); - registry.get(HIST("vtxPosz"))->Fill(collision.posZ()); - // Number of tracks - registry.get(HIST("Tracks"))->Fill(tracks.size()); + registry.get(HIST("collisions/posxy"))->Fill(collision.posX(), collision.posY()); + registry.get(HIST("collisions/posz"))->Fill(collision.posZ()); + // tracks + registry.get(HIST("collisions/Tracks"))->Fill(tracks.size()); // vertex tracks - registry.get(HIST("vtxTracks"))->Fill(collision.numContrib()); // numContrib: Number of tracks used for the vertex + registry.get(HIST("collisions/vtxTracks"))->Fill(collision.numContrib()); // global tracks Partition goodTracks = requireGlobalTrackInFilter(); goodTracks.bindTable(tracks); - registry.get(HIST("globalTracks"))->Fill(goodTracks.size()); + registry.get(HIST("collisions/globalTracks"))->Fill(goodTracks.size()); + + // PV contributors + int nPVcont = 0; + for (auto const& trk : tracks) { + if (trk.isPVContributor()) { + nPVcont++; + } + } + registry.get(HIST("collisions/PVTracks"))->Fill(nPVcont); + // Number of tracks with 2 tracks vertex if (collision.numContrib() == 2) { - registry.get(HIST("PVTracks"))->Fill(tracks.size()); + registry.get(HIST("collisions/TwoTracks"))->Fill(tracks.size()); } - // number of vertex tracks with TOF hit + // loop over all tracks float rgtrwTOF = 0.; + float norgtrwTOF = 0.; for (auto const& track : tracks) { + // update PV track stats + if (track.isPVContributor()) { + registry.get(HIST("tracks/Stat"))->Fill(track.pt(), 1., 1.); + registry.get(HIST("tracks/Stat"))->Fill(track.pt(), 2., track.isQualityTrack() * 1.); + registry.get(HIST("tracks/Stat"))->Fill(track.pt(), 3., track.isGlobalTrack() * 1.); + registry.get(HIST("tracks/Stat"))->Fill(track.pt(), 4., (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) * 1.); + registry.get(HIST("tracks/Stat"))->Fill(track.pt(), 5., track.hasITS() * 1.); + registry.get(HIST("tracks/Stat"))->Fill(track.pt(), 6., track.hasTPC() * 1.); + registry.get(HIST("tracks/Stat"))->Fill(track.pt(), 7., track.hasTRD() * 1.); + registry.get(HIST("tracks/Stat"))->Fill(track.pt(), 8., track.hasTOF() * 1.); + + // update eta vs pt histograms + registry.get(HIST("tracks/etapt"))->Fill(track.eta(), track.pt(), 1.); + registry.get(HIST("tracks/etapt2"))->Fill(track.eta(), track.pt(), track.isQualityTrack() * 1.); + registry.get(HIST("tracks/etapt3"))->Fill(track.eta(), track.pt(), track.isGlobalTrack() * 1.); + registry.get(HIST("tracks/etapt4"))->Fill(track.eta(), track.pt(), (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) * 1.); + registry.get(HIST("tracks/etapt5"))->Fill(track.eta(), track.pt(), track.hasITS() * 1.); + registry.get(HIST("tracks/etapt6"))->Fill(track.eta(), track.pt(), track.hasTPC() * 1.); + registry.get(HIST("tracks/etapt7"))->Fill(track.eta(), track.pt(), track.hasTRD() * 1.); + registry.get(HIST("tracks/etapt8"))->Fill(track.eta(), track.pt(), track.hasTOF() * 1.); + + // update dEdx histograms + registry.get(HIST("tracks/dEdxTPC"))->Fill(track.tpcInnerParam() * track.sign(), track.tpcSignal()); + registry.get(HIST("tracks/dEdxTPCmom"))->Fill(track.tpcInnerParam() / track.sign(), track.tpcSignal()); + + if (track.tpcSignal() > maxdEdxTPC) { + maxdEdxTPC = track.tpcSignal(); + LOGF(debug, " New maxdEdx TPC %f", maxdEdxTPC); + } - // update eta vs pt histogram - registry.get(HIST("etapt"))->Fill(track.eta(), track.pt()); - // update TPC dEdx histograms - registry.get(HIST("dEdxTPC"))->Fill(track.p() * track.sign(), track.tpcSignal()); - registry.get(HIST("dEdxTPCmom"))->Fill(track.p(), track.tpcSignal()); - - if (track.tpcSignal() > maxdEdxTPC) { - maxdEdxTPC = track.tpcSignal(); - LOGF(debug, " New maxdEdx TPC %f", maxdEdxTPC); - } - - // TOF hit? - if (track.hasTOF()) { - - registry.get(HIST("dEdxTOF"))->Fill(track.p(), track.tofSignal()); + // TOF hit? + if (track.hasTOF()) { + registry.get(HIST("tracks/dEdxTOF"))->Fill(track.p(), track.beta()); + if (track.tofSignal() > maxdEdxTOF) { + maxdEdxTOF = track.tofSignal(); + LOGF(debug, " New maxdEdx TOF %f", maxdEdxTOF); + } - if (track.tofSignal() > maxdEdxTOF) { - maxdEdxTOF = track.tofSignal(); - LOGF(debug, " New maxdEdx tOF %f", maxdEdxTOF); - } + // No vertex track with TOF hit? + if (!track.isPVContributor()) { + norgtrwTOF += 1.; + } - // vertex track with TOF hit? - if (track.isPVContributor()) { - rgtrwTOF += 1.; + // vertex track with TOF hit? + if (track.isPVContributor()) { + rgtrwTOF += 1.; + } } } + } // closing track loop + + // fraction of No PV tracks with TOF hit + if (collision.numContrib() > 0) { + norgtrwTOF /= collision.numContrib(); } + // fraction of PV tracks with TOF hit if (collision.numContrib() > 0) { rgtrwTOF /= collision.numContrib(); } - - // Collision time resolution vs PV track fraction with TOF hits - LOGF(debug, " Vertex tracks with TOF: %f [1]", rgtrwTOF); - registry.get(HIST("tResvsrTOFTracks"))->Fill(collision.collisionTimeRes(), rgtrwTOF); + LOGF(debug, " PV tracks with TOF: %f [1]", rgtrwTOF); + registry.get(HIST("collisions/tResvsrTOFTracks"))->Fill(collision.collisionTimeRes(), rgtrwTOF); + registry.get(HIST("collisions/tResvsTOFTrkNoPV"))->Fill(collision.collisionTimeRes(), norgtrwTOF); // is it a DG candidate? // 1. DG = no FIT signal in compatible BCs @@ -222,7 +310,6 @@ struct UDQC { // 7. & no global track which is not a vertex track // 8. & no vertex track which is not a global track // 9. & ntrMin <= number of vertex tracks <= ntrMax - isDGcandidate = true; // get BCrange to test for FIT signals @@ -231,17 +318,17 @@ struct UDQC { // 1. no FIT signal in bcSlice / collision if (doCleanFITBC) { for (auto const& bc : bcSlice) { - if (!udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits())) { + if (!udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits())) { isDGcandidate = false; break; } } } else { - if (!udhelpers::cleanFITCollision(collision, diffCuts.FITAmpLimits())) { + if (!udhelpers::cleanFITCollision(collision, diffCuts.maxFITtime(), diffCuts.FITAmpLimits())) { isDGcandidate = false; } } - registry.get(HIST("Stat"))->Fill(1., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(1., isDGcandidate * 1.); // 2. no Zdc signal in bcSlice std::vector lims(10, 0.); @@ -251,7 +338,7 @@ struct UDQC { break; } } - registry.get(HIST("Stat"))->Fill(2., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(2., isDGcandidate * 1.); // 3. no Calo signal in bcSlice for (auto const& bc : bcSlice) { @@ -260,21 +347,21 @@ struct UDQC { break; } } - registry.get(HIST("Stat"))->Fill(3., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(3., isDGcandidate * 1.); // 4. no V0s isDGcandidate &= (v0s.size() == 0); - registry.get(HIST("Stat"))->Fill(4., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(4., isDGcandidate * 1.); // 5. no Cascades isDGcandidate &= (cascades.size() == 0); - registry.get(HIST("Stat"))->Fill(5., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(5., isDGcandidate * 1.); // 6. number of forward tracks = 0 isDGcandidate &= (fwdtracks.size() == 0); - registry.get(HIST("Stat"))->Fill(6., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(6., isDGcandidate * 1.); - // 7. no global tracks which are no vtx tracks + // 7. Check for global tracks which are no vtx tracks bool globalAndVtx = isDGcandidate; bool vtxAndGlobal = isDGcandidate; for (auto const& track : tracks) { @@ -285,25 +372,9 @@ struct UDQC { vtxAndGlobal = false; } } - registry.get(HIST("Stat"))->Fill(7., globalAndVtx * 1.); - // 8. no vertex tracks which are no global tracks - isDGcandidate &= globalAndVtx; - if (diffCuts.globalTracksOnly()) { - isDGcandidate &= vtxAndGlobal; - } - registry.get(HIST("Stat"))->Fill(8., vtxAndGlobal * 1.); - - // number of vertex tracks <= n - isDGcandidate &= (collision.numContrib() >= diffCuts.minNTracks()); - registry.get(HIST("Stat"))->Fill(9., isDGcandidate * 1.); - isDGcandidate &= (collision.numContrib() <= diffCuts.maxNTracks()); - registry.get(HIST("Stat"))->Fill(10., isDGcandidate * 1.); - - // fraction of PV tracks with TOF hit - isDGcandidate &= (rgtrwTOF >= diffCuts.minRgtrwTOF()); - registry.get(HIST("Stat"))->Fill(11., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(7., globalAndVtx * 1.); - // check a given bc for possible ambiguous Tracks + // 8. check a given bc for possible ambiguous Tracks auto noAmbTracks = isDGcandidate; for (auto const& bc : bcSlice) { if (abcrs.isInRange(bc.globalIndex())) { @@ -311,10 +382,9 @@ struct UDQC { break; } } + registry.get(HIST("collisions/Stat"))->Fill(8., noAmbTracks * 1.); // noAmbTracks - registry.get(HIST("Stat"))->Fill(12., noAmbTracks * 1.); // noAmbTracks - - // check a given bc for possible ambiguous FwdTracks + // 9. check a given bc for possible ambiguous FwdTracks auto noAmbFwdTracks = isDGcandidate; for (auto const& bc : bcSlice) { if (afbcrs.isInRange(bc.globalIndex())) { @@ -322,9 +392,19 @@ struct UDQC { break; } } - registry.get(HIST("Stat"))->Fill(13., noAmbFwdTracks * 1.); // noAmbFwdTracks + registry.get(HIST("collisions/Stat"))->Fill(9., noAmbFwdTracks * 1.); // noAmbFwdTracks + + // 10. number of vertex tracks <= n + isDGcandidate &= (collision.numContrib() >= diffCuts.minNTracks()); + registry.get(HIST("collisions/Stat"))->Fill(10., isDGcandidate * 1.); + isDGcandidate &= (collision.numContrib() <= diffCuts.maxNTracks()); + registry.get(HIST("collisions/Stat"))->Fill(11., isDGcandidate * 1.); - // net charge and invariant mass + // 11. fraction of PV tracks with TOF hit + isDGcandidate &= (rgtrwTOF >= diffCuts.minRgtrwTOF()); + registry.get(HIST("collisions/Stat"))->Fill(12., isDGcandidate * 1.); + + // 12. net charge and invariant mass bool goodetas = true; bool goodpts = true; bool goodnchs = true; @@ -341,25 +421,25 @@ struct UDQC { // check also pt and eta of tracks for (auto const& track : tracks) { - // update histogram rejectedTracks + // update histogram for rejectedTracks/notPVtracks if (!track.isPVContributor()) { - registry.get(HIST("rejectedTracks"))->Fill(0., 1.); - registry.get(HIST("rejectedTracks"))->Fill(1., track.isGlobalTrackSDD() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(2., track.passedTrackType() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(3., track.passedPtRange() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(4., track.passedEtaRange() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(5., track.passedTPCNCls() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(6., track.passedTPCCrossedRows() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(7., track.passedTPCCrossedRowsOverNCls() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(8., track.passedTPCChi2NDF() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(9., track.passedTPCRefit() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(10., track.passedITSNCls() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(11., track.passedITSChi2NDF() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(12., track.passedITSRefit() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(13., track.passedITSHits() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(14., track.passedGoldenChi2() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(15., track.passedDCAxy() * 1.); - registry.get(HIST("rejectedTracks"))->Fill(16., track.passedDCAz() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(0., 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(1., track.isGlobalTrackSDD() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(2., track.passedTrackType() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(3., track.passedPtRange() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(4., track.passedEtaRange() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(5., track.passedTPCNCls() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(6., track.passedTPCCrossedRows() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(7., track.passedTPCCrossedRowsOverNCls() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(8., track.passedTPCChi2NDF() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(9., track.passedTPCRefit() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(10., track.passedITSNCls() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(11., track.passedITSChi2NDF() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(12., track.passedITSRefit() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(13., track.passedITSHits() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(14., track.passedGoldenChi2() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(15., track.passedDCAxy() * 1.); + registry.get(HIST("collisions/notPVTracks"))->Fill(16., track.passedDCAz() * 1.); continue; } @@ -376,44 +456,100 @@ struct UDQC { } } isDGcandidate &= goodpts; - registry.get(HIST("Stat"))->Fill(14., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(13., isDGcandidate * 1.); isDGcandidate &= goodetas; - registry.get(HIST("Stat"))->Fill(15., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(14., isDGcandidate * 1.); + auto netChargeValues = diffCuts.netCharges(); + // float tofval = diffCuts.minRgtrwTOF(); + // auto tpcsigpi = diffCuts.maxNSigmaTPC(); if (std::find(netChargeValues.begin(), netChargeValues.end(), netCharge) == netChargeValues.end()) { goodnchs = false; } isDGcandidate &= goodnchs; - registry.get(HIST("Stat"))->Fill(16., isDGcandidate * 1.); - registry.get(HIST("Stat"))->Fill(17., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(15., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(16., isDGcandidate * 1.); isDGcandidate &= (ivm.M() >= diffCuts.minIVM()); - registry.get(HIST("Stat"))->Fill(18., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(17., isDGcandidate * 1.); isDGcandidate &= (ivm.M() <= diffCuts.maxIVM()); - registry.get(HIST("Stat"))->Fill(19., isDGcandidate * 1.); + registry.get(HIST("collisions/Stat"))->Fill(18., isDGcandidate * 1.); + + // 8. check for vertex tracks which are no global tracks + isDGcandidate &= globalAndVtx; + if (diffCuts.globalTracksOnly()) { + isDGcandidate &= vtxAndGlobal; + } + registry.get(HIST("collisions/Stat"))->Fill(19., isDGcandidate * 1.); // update some DG histograms if (isDGcandidate) { // vertex position of DG events - registry.get(HIST("vtxPosxyDG"))->Fill(collision.posX(), collision.posY()); - registry.get(HIST("vtxPoszDG"))->Fill(collision.posZ()); - registry.get(HIST("netChargeDG"))->Fill(netCharge); + registry.get(HIST("DG/PVposxy"))->Fill(collision.posX(), collision.posY()); + registry.get(HIST("DG/PVposz"))->Fill(collision.posZ()); + registry.get(HIST("DG/netCharge"))->Fill(netCharge); + // Invariant mass with 2 PV contributors and all contributors if (collision.numContrib() == 2) { - registry.get(HIST("IVMptSysDG2trk"))->Fill(ivm.M(), ivm.Perp()); + registry.get(HIST("DG/IVMptSys2PVtrk"))->Fill(ivm.M(), ivm.Perp()); + bool ispipiCand = true; + for (auto const& track : tracks) { + if (track.isPVContributor()) { + if (std::abs(track.tpcNSigmaPi()) > diffCuts.maxNSigmaTPC()) { + ispipiCand = false; + } + } + } + if (ispipiCand) { + registry.get(HIST("DG/hMass"))->Fill(ivm.M()); + } } else { - registry.get(HIST("IVMptSysDG"))->Fill(ivm.M(), ivm.Perp()); + registry.get(HIST("DG/IVMptSys"))->Fill(ivm.M(), ivm.Perp()); } - - // fill dEdx of DG event tracks + // fill dEdx and kinematics of DG event tracks for (auto const& track : tracks) { if (track.isPVContributor()) { + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 1., 1.); + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 2., track.isQualityTrack() * 1.); + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 3., track.isGlobalTrack() * 1.); + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 4., track.tpcNClsFound() * 1.); + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 5., track.tpcFractionSharedCls() * 1.); + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 6., track.hasITS() * 1.); + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 7., track.hasTPC() * 1.); + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 8., track.hasTRD() * 1.); + registry.get(HIST("DG/TrackStat"))->Fill(track.pt(), 9., track.hasTOF() * 1.); + + registry.get(HIST("DG/etapt"))->Fill(track.eta(), track.pt(), 1.); + registry.get(HIST("DG/etapt2"))->Fill(track.eta(), track.pt(), track.isQualityTrack() * 1.); + registry.get(HIST("DG/etapt3"))->Fill(track.eta(), track.pt(), track.isGlobalTrack() * 1.); + registry.get(HIST("DG/etapt4"))->Fill(track.eta(), track.pt(), track.tpcNClsFound() * 1.); + registry.get(HIST("DG/etapt5"))->Fill(track.eta(), track.pt(), track.tpcFractionSharedCls() * 1.); + registry.get(HIST("DG/etapt6"))->Fill(track.eta(), track.pt(), track.hasITS() * 1.); + registry.get(HIST("DG/etapt7"))->Fill(track.eta(), track.pt(), track.hasTPC() * 1.); + registry.get(HIST("DG/etapt8"))->Fill(track.eta(), track.pt(), track.hasTRD() * 1.); + registry.get(HIST("DG/etapt9"))->Fill(track.eta(), track.pt(), track.hasTOF() * 1.); + // eta distribution of positive and negative charged tracks + if (track.sign() > 0) { + registry.get(HIST("DG/etaplus"))->Fill(track.eta()); + } + if (track.sign() < 0) { + registry.get(HIST("DG/etaminus"))->Fill(track.eta()); + } + LOGF(debug, "dEdx TPC %f TOF %i %f", track.tpcSignal(), track.hasTOF(), track.hasTOF() ? track.tofSignal() : 0.); - registry.get(HIST("dEdxTPCDG"))->Fill(track.p() * track.sign(), track.tpcSignal()); - registry.get(HIST("dEdxTPCDGmom"))->Fill(track.p(), track.tpcSignal()); - registry.get(HIST("etaptDG"))->Fill(track.eta(), track.pt()); - registry.get(HIST("IVMptTrkDG"))->Fill(ivm.M(), track.pt()); + if (collision.numContrib() == 2) { + registry.get(HIST("DG/dEdxTPC"))->Fill(track.p() / track.sign(), track.tpcSignal()); + registry.get(HIST("DG/dEdxTPCmom"))->Fill(track.tpcInnerParam(), track.tpcSignal()); + registry.get(HIST("DG/IVMptTrk"))->Fill(ivm.M(), track.pt()); + registry.get(HIST("DG/nTPCclusters"))->Fill(collision.numContrib(), track.tpcNClsFound()); + registry.get(HIST("DG/tpcNClsCrossedRows"))->Fill(collision.numContrib(), track.tpcNClsCrossedRows()); + registry.get(HIST("DG/tpcNClsShared"))->Fill(collision.numContrib(), track.tpcFractionSharedCls()); + registry.get(HIST("DG/nITSclsMap"))->Fill(collision.numContrib(), track.itsClusterMap()); + registry.get(HIST("DG/trkDCAxy"))->Fill(collision.numContrib(), track.dcaXY()); + registry.get(HIST("DG/trkDCAz"))->Fill(collision.numContrib(), track.dcaZ()); + } + if (track.hasTOF()) { - registry.get(HIST("dEdxTOFDG"))->Fill(track.p(), track.tofSignal()); + registry.get(HIST("DG/dEdxTOF"))->Fill(track.p(), track.beta()); } } } @@ -432,7 +568,7 @@ struct UDQC { // check FT0 to be empty auto bc = collision.foundBC_as(); - if (udhelpers::cleanFT0(bc, 0., 0.)) { + if (udhelpers::cleanFT0(bc, diffCuts.maxFITtime(), 0., 0.)) { // only collisions with empty FT0 arrive here registry.get(HIST("fpStat"))->Fill(2., 1.); @@ -459,7 +595,7 @@ struct UDQC { ampFV0A = ampFT0A = ampFT0C = ampFDDA = ampFDDC = 0.; isDGcandidate = true; for (auto const& bc : bcSlice) { - isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits()); + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits()); if (bc.has_foundFV0()) { ampFV0A += udhelpers::FV0AmplitudeA(bc.foundFV0()); @@ -487,7 +623,7 @@ struct UDQC { FITlims[n] = 0.; isDGcandidate = true; for (auto const& bc : bcSlice) { - isDGcandidate &= udhelpers::cleanFIT(bc, FITlims); + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), FITlims); } constexpr int index = n.value; registry.fill(HIST(hcFIT1s[index]), NDtcoll, isDGcandidate * 1.); @@ -503,7 +639,11 @@ struct UDQC { aod::FT0s const& ft0s, aod::FV0As const& fv0as, aod::FDDs const& fdds) { LOGF(debug, "(); + bcnum = collbc.globalBC() % o2::constants::lhc::LHCMaxBunches; + } // test influence of BCrange width using a series of nMinBC float ampFV0A, ampFT0A, ampFT0C, ampFDDA, ampFDDC; auto FITlims = std::vector(5, 1000000.); @@ -513,7 +653,7 @@ struct UDQC { ampFV0A = ampFT0A = ampFT0C = ampFDDA = ampFDDC = 0.; isDGcandidate = true; for (auto const& bc : bcSlice) { - isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits()); + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits()); if (bc.has_foundFV0()) { ampFV0A += udhelpers::FV0AmplitudeA(bc.foundFV0()); @@ -528,6 +668,7 @@ struct UDQC { } } registry.get(HIST("cleanFIT2"))->Fill(nMinBC, isDGcandidate * 1.); + if (isDGcandidate) { registry.get(HIST("cF2FV0Aamp"))->Fill(nMinBC, ampFV0A); registry.get(HIST("cF2FT0Aamp"))->Fill(nMinBC, ampFT0A); @@ -541,10 +682,11 @@ struct UDQC { FITlims[n] = 0.; isDGcandidate = true; for (auto const& bc : bcSlice) { - isDGcandidate &= udhelpers::cleanFIT(bc, FITlims); + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), FITlims); // DG } constexpr int index = n.value; registry.fill(HIST(hcFIT2s[index]), nMinBC, isDGcandidate * 1.); + registry.fill(HIST(hcRelBCs[index]), static_cast(bcnum)); FITlims[n] = 1000000.; }); } @@ -561,7 +703,7 @@ struct UDQC { } for (auto fv0 : fv0s) { - + registry.get(HIST("hV0A"))->Fill(fv0.time()); // side A for (size_t ind = 0; ind < fv0.channel().size(); ind++) { registry.get(HIST("FV0A"))->Fill((fv0.channel())[ind], (fv0.amplitude())[ind]); @@ -571,11 +713,25 @@ struct UDQC { PROCESS_SWITCH(UDQC, processFV0, "Process FV0", true); // ............................................................................................................... - void processFT0(aod::FT0s const& ft0s, BCs const&) + void processFT0(aod::FT0s const& ft0s, aod::FT0sCorrected const& ft0scorr, BCs const&) { LOGF(debug, " %d", ft0s.size()); + for (auto const& collision : ft0scorr) { + if (collision.t0ACorrectedValid()) { + registry.get(HIST("hT0ACorr"))->Fill(collision.t0ACorrected()); + } + if (collision.t0CCorrectedValid()) { + registry.get(HIST("hT0CCorr"))->Fill(collision.t0CCorrected()); + } + + if (collision.t0CCorrectedValid() && collision.t0ACorrectedValid()) { + registry.get(HIST("hT0AC"))->Fill(collision.t0AC()); + } + } for (auto ft0 : ft0s) { + registry.get(HIST("hT0A"))->Fill(ft0.timeA()); + registry.get(HIST("hT0C"))->Fill(ft0.timeC()); // side A for (size_t ind = 0; ind < ft0.channelA().size(); ind++) { @@ -597,6 +753,8 @@ struct UDQC { for (auto fdd : fdds) { + registry.get(HIST("hFDDA"))->Fill(fdd.timeA()); + registry.get(HIST("hFDDC"))->Fill(fdd.timeC()); // side A for (auto ind = 0; ind < 8; ind++) { registry.get(HIST("FDDA"))->Fill(ind, (fdd.chargeA())[ind]); diff --git a/PWGUD/Core/DGCutparHolder.cxx b/PWGUD/Core/DGCutparHolder.cxx index 501323196c6..3e6e452a278 100644 --- a/PWGUD/Core/DGCutparHolder.cxx +++ b/PWGUD/Core/DGCutparHolder.cxx @@ -20,10 +20,18 @@ void DGCutparHolder::SetMinNBCs(int nminbcs) { mMinNBCs = nminbcs; } +void DGCutparHolder::SetWithFwdTracks(bool withFwdTracks) +{ + mWithFwdTracks = withFwdTracks; +} void DGCutparHolder::SetGlobalTracksOnly(bool globalTracksOnly) { mGlobalTracksOnly = globalTracksOnly; } +void DGCutparHolder::SetITSOnlyTracks(bool ITSonlyTracks) +{ + mITSOnlyTracks = ITSonlyTracks; +} void DGCutparHolder::SetMinRgtrwTOF(float rgtrwTOF) { mMinRgtrwTOF = rgtrwTOF; @@ -70,7 +78,10 @@ void DGCutparHolder::SetMaxNSigmaTOF(float maxnSigma) { mMaxNSigmaTOF = maxnSigma; } - +void DGCutparHolder::SetMaxFITtime(float maxFITtime) +{ + mMaxFITtime = maxFITtime; +} void DGCutparHolder::SetFITAmpLimits(std::vector FITAmpLimits) { mFITAmpLimits = FITAmpLimits; @@ -79,7 +90,9 @@ void DGCutparHolder::SetFITAmpLimits(std::vector FITAmpLimits) // getter int DGCutparHolder::NDtcoll() const { return mNDtcoll; } int DGCutparHolder::minNBCs() const { return mMinNBCs; } +bool DGCutparHolder::withFwdTracks() const { return mWithFwdTracks; } bool DGCutparHolder::globalTracksOnly() const { return mGlobalTracksOnly; } +bool DGCutparHolder::ITSOnlyTracks() const { return mITSOnlyTracks; } float DGCutparHolder::minRgtrwTOF() const { return mMinRgtrwTOF; } int DGCutparHolder::minNTracks() const { return mMinNTracks; } int DGCutparHolder::maxNTracks() const { return mMaxNTracks; } @@ -95,4 +108,5 @@ float DGCutparHolder::minIVM() const { return mMinIVM; } float DGCutparHolder::maxIVM() const { return mMaxIVM; } float DGCutparHolder::maxNSigmaTPC() const { return mMaxNSigmaTPC; } float DGCutparHolder::maxNSigmaTOF() const { return mMaxNSigmaTOF; } +float DGCutparHolder::maxFITtime() const { return mMaxFITtime; } std::vector DGCutparHolder::FITAmpLimits() const { return mFITAmpLimits; } diff --git a/PWGUD/Core/DGCutparHolder.h b/PWGUD/Core/DGCutparHolder.h index f5814f2949c..64b832aa59e 100644 --- a/PWGUD/Core/DGCutparHolder.h +++ b/PWGUD/Core/DGCutparHolder.h @@ -21,7 +21,9 @@ class DGCutparHolder public: // constructor DGCutparHolder(int ndtcoll = 4, int nMinBCs = 7, + bool withFwdTracks = false, bool globalTracksOnly = false, + bool ITSonlyTracks = true, float minrgtrwTOF = 0., int MinNTracks = 0, int MaxNTracks = 10000, std::vector NetCharges = {0}, @@ -31,14 +33,17 @@ class DGCutparHolder float minEta = -1.0, float maxEta = 1.0, float minIVM = 0.0, float maxIVM = 1000., float maxNSigmaTPC = 1000., float maxNSigmaTOF = 1000., - std::vector FITAmpLimits = {0., 0., 0., 0., 0.}) : mNDtcoll{ndtcoll}, mMinNBCs{nMinBCs}, mGlobalTracksOnly{globalTracksOnly}, mMinRgtrwTOF{minrgtrwTOF}, mMinNTracks{MinNTracks}, mMaxNTracks{MaxNTracks}, mNetCharges{NetCharges}, mPidHypo{pidHypo}, mMinVertexPosz{MinPosz}, mMaxVertexPosz{MaxPosz}, mMinPt{minPt}, mMaxPt{maxPt}, mMinEta{minEta}, mMaxEta{maxEta}, mMinIVM{minIVM}, mMaxIVM{maxIVM}, mMaxNSigmaTPC{maxNSigmaTPC}, mMaxNSigmaTOF{maxNSigmaTOF}, mFITAmpLimits{FITAmpLimits} + float maxFITtime = 4, + std::vector FITAmpLimits = {0., 0., 0., 0., 0.}) : mNDtcoll{ndtcoll}, mMinNBCs{nMinBCs}, mWithFwdTracks{withFwdTracks}, mGlobalTracksOnly{globalTracksOnly}, mITSOnlyTracks{ITSonlyTracks}, mMinRgtrwTOF{minrgtrwTOF}, mMinNTracks{MinNTracks}, mMaxNTracks{MaxNTracks}, mNetCharges{NetCharges}, mPidHypo{pidHypo}, mMinVertexPosz{MinPosz}, mMaxVertexPosz{MaxPosz}, mMinPt{minPt}, mMaxPt{maxPt}, mMinEta{minEta}, mMaxEta{maxEta}, mMinIVM{minIVM}, mMaxIVM{maxIVM}, mMaxNSigmaTPC{maxNSigmaTPC}, mMaxNSigmaTOF{maxNSigmaTOF}, mMaxFITtime{maxFITtime}, mFITAmpLimits{FITAmpLimits} { } // setter void SetNDtcoll(int); void SetMinNBCs(int); + void SetWithFwdTracks(bool); void SetGlobalTracksOnly(bool); + void SetITSOnlyTracks(bool); void SetMinRgtrwTOF(float); void SetNTracks(int MinNTracks, int MaxNTracks); void SetNetCharges(std::vector netCharges); @@ -49,12 +54,15 @@ class DGCutparHolder void SetIVMRange(float minIVM, float maxIVM); void SetMaxNSigmaTPC(float maxnSigma); void SetMaxNSigmaTOF(float maxnSigma); + void SetMaxFITtime(float maxFITtime); void SetFITAmpLimits(std::vector FITAmpLimits); // getter int NDtcoll() const; int minNBCs() const; + bool withFwdTracks() const; bool globalTracksOnly() const; + bool ITSOnlyTracks() const; float minRgtrwTOF() const; int minNTracks() const; int maxNTracks() const; @@ -70,6 +78,7 @@ class DGCutparHolder float maxIVM() const; float maxNSigmaTPC() const; float maxNSigmaTOF() const; + float maxFITtime() const; std::vector FITAmpLimits() const; private: @@ -77,8 +86,12 @@ class DGCutparHolder int mNDtcoll; int mMinNBCs; + // allow forward tracks + bool mWithFwdTracks; + // require all vertex tracks to be global tracks bool mGlobalTracksOnly; + bool mITSOnlyTracks; // required minimum fraction of global tracks with TOF hit float mMinRgtrwTOF; @@ -104,6 +117,9 @@ class DGCutparHolder float mMaxNSigmaTPC; // maximum nSigma TPC float mMaxNSigmaTOF; // maximum nSigma TOF + // maximum FIT time + float mMaxFITtime; + // lower limits for FIT signals std::vector mFITAmpLimits; diff --git a/PWGUD/Core/DGPIDSelector.cxx b/PWGUD/Core/DGPIDSelector.cxx index a992d984abb..5d37ef6c8de 100644 --- a/PWGUD/Core/DGPIDSelector.cxx +++ b/PWGUD/Core/DGPIDSelector.cxx @@ -129,6 +129,12 @@ void DGAnaparHolder::Print() LOGF(info, " max dcaz: %f", mMaxDCAz); LOGF(info, " min dBC: %d", mdBCMin); LOGF(info, " max dBC: %d", mdBCMax); + LOGF(info, " FIT vetoes (FV0A, FT0A, FT0C, FDDA, FDDC)"); + LOGF(info, " %d %d %d %d %d", mFITvetoes[0], mFITvetoes[1], mFITvetoes[2], mFITvetoes[3], mFITvetoes[4]); + LOGF(info, " min NCl TPC: %d", mMinNClTPC); + LOGF(info, " max NCl TPC: %d", mMaxNClTPC); + LOGF(info, " min chi^{2} TPC %f", mMinChi2NClTPC); + LOGF(info, " max chi^{2} TPC %f", mMaxChi2NClTPC); LOGF(info, " min track pT: %f", mMinpt); LOGF(info, " max track pT: %f", mMaxpt); LOGF(info, " min eta: %f", mMineta); @@ -138,8 +144,12 @@ void DGAnaparHolder::Print() LOGF(info, " min system pT: %f", mMinptsys); LOGF(info, " max system pT: %f", mMaxptsys); LOGF(info, " nCombine: %d", mNCombine); - LOGF(info, " net charges"); - for (auto ch : mNetCharges) { + LOGF(info, " unlike charges"); + for (auto ch : mUnlikeCharges) { + LOGF(info, " %i", ch); + } + LOGF(info, " like charges"); + for (auto ch : mLikeCharges) { LOGF(info, " %i", ch); } LOGF(info, " PIDs"); @@ -300,7 +310,8 @@ DGPIDSelector::DGPIDSelector() DGPIDSelector::~DGPIDSelector() { - mIVMs.clear(); + mUnlikeIVMs.clear(); + mLikeIVMs.clear(); } // ----------------------------------------------------------------------------- @@ -313,7 +324,8 @@ void DGPIDSelector::Print() void DGPIDSelector::init(DGAnaparHolder anaPars) { mAnaPars = anaPars; - mIVMs.clear(); + mUnlikeIVMs.clear(); + mLikeIVMs.clear(); } // ----------------------------------------------------------------------------- diff --git a/PWGUD/Core/DGPIDSelector.h b/PWGUD/Core/DGPIDSelector.h index 12a1b627fa3..f0fa074eb31 100644 --- a/PWGUD/Core/DGPIDSelector.h +++ b/PWGUD/Core/DGPIDSelector.h @@ -110,14 +110,20 @@ struct DGAnaparHolder { DGAnaparHolder(int MinNTracks = 0, int MaxNTracks = 10000, float minrgtrwTOF = 0., float maxDCAxy = 100., float maxDCAz = 100, int dBCMin = 0, int dBCMax = 0, + std::vector FITvetoes = {0, 1, 1, 0, 0}, + bool ITSonlyTracks = true, + int minNClTPC = 0, int maxNClTPC = 200, + float minChi2NClTPC = 0., float maxChi2NClTPC = 100., float minpt = 0.0, float maxpt = 100.0, float mineta = -2.0, float maxeta = 2.0, float minalpha = 0.0, float maxalpha = 3.2, float minptsys = 0.0, float maxptsys = 100.0, int nCombine = 2, std::vector netCharges = {0}, + std::vector unlikeCharges = {0}, + std::vector likeCharges = {-2, 2}, std::vector DGPIDs = {211, 211}, - std::vector DGPIDCutValues = {}) : mMinNTracks{MinNTracks}, mMaxNTracks{MaxNTracks}, mMinRgtrwTOF{minrgtrwTOF}, mMaxDCAxy{maxDCAxy}, mMaxDCAz{maxDCAz}, mdBCMin{dBCMin}, mdBCMax{dBCMax}, mMinpt{minpt}, mMaxpt{maxpt}, mMineta{mineta}, mMaxeta{maxeta}, mMinAlpha{minalpha}, mMaxAlpha{maxalpha}, mMinptsys{minptsys}, mMaxptsys{maxptsys}, mNCombine{nCombine}, mNetCharges{netCharges}, mDGPIDs{DGPIDs}, mDGPIDCutValues{DGPIDCutValues} + std::vector DGPIDCutValues = {}) : mMinNTracks{MinNTracks}, mMaxNTracks{MaxNTracks}, mMinRgtrwTOF{minrgtrwTOF}, mMaxDCAxy{maxDCAxy}, mMaxDCAz{maxDCAz}, mdBCMin{dBCMin}, mdBCMax{dBCMax}, mFITvetoes{FITvetoes}, mITSOnlyTracks{ITSonlyTracks}, mMinNClTPC{minNClTPC}, mMaxNClTPC{maxNClTPC}, mMinChi2NClTPC{minChi2NClTPC}, mMaxChi2NClTPC{maxChi2NClTPC}, mMinpt{minpt}, mMaxpt{maxpt}, mMineta{mineta}, mMaxeta{maxeta}, mMinAlpha{minalpha}, mMaxAlpha{maxalpha}, mMinptsys{minptsys}, mMaxptsys{maxptsys}, mNCombine{nCombine}, mNetCharges{netCharges}, mUnlikeCharges{unlikeCharges}, mLikeCharges{likeCharges}, mDGPIDs{DGPIDs}, mDGPIDCutValues{DGPIDCutValues} { if (mdBCMin < -16) { mdBCMin = -16; @@ -144,6 +150,12 @@ struct DGAnaparHolder { float maxDCAz() const { return mMaxDCAz; } int dBCMin() const { return mdBCMin; } int dBCMax() const { return mdBCMax; } + std::vector FITvetoes() { return mFITvetoes; } + bool ITSOnlyTracks() { return mITSOnlyTracks; } + int minNClTPC() { return mMinNClTPC; } + int maxNClTPC() { return mMaxNClTPC; } + float minChi2NClTPC() { return mMinChi2NClTPC; } + float maxChi2NClTPC() { return mMaxChi2NClTPC; } float minpt() const { return mMinpt; } float maxpt() const { return mMaxpt; } float mineta() const { return mMineta; } @@ -154,6 +166,8 @@ struct DGAnaparHolder { float maxptsys() const { return mMaxptsys; } int nCombine() const { return mNCombine; } std::vector netCharges() const { return mNetCharges; } + std::vector unlikeCharges() const { return mUnlikeCharges; } + std::vector likeCharges() const { return mLikeCharges; } std::vector PIDs() const { return mDGPIDs; } DGPIDCuts PIDCuts(); std::vector uniquePermutations(); @@ -172,6 +186,12 @@ struct DGAnaparHolder { float mMaxDCAz; int mdBCMin; int mdBCMax; + std::vector mFITvetoes; + bool mITSOnlyTracks; + int mMinNClTPC; + int mMaxNClTPC; + float mMinChi2NClTPC; + float mMaxChi2NClTPC; float mMinpt; float mMaxpt; float mMineta; @@ -181,7 +201,9 @@ struct DGAnaparHolder { float mMinptsys; float mMaxptsys; int mNCombine; - std::vector mNetCharges; + std::vector mNetCharges; // all PV tracks + std::vector mUnlikeCharges; // selected PV tracks + std::vector mLikeCharges; // selected PV tracks std::vector mDGPIDs; std::vector mDGPIDCutValues; @@ -247,7 +269,7 @@ struct DGPIDSelector { // getters void Print(); template - bool isGoodCombination(std::vector comb, TTrack const& tracks) + bool isGoodCombination(std::vector comb, TTrack const& tracks, std::vector acceptedCharges) { // compute net charge of track combination int netCharge = 0.; @@ -256,8 +278,7 @@ struct DGPIDSelector { } // is this in the list of accepted net charges? - auto netCharges = mAnaPars.netCharges(); - if (std::find(netCharges.begin(), netCharges.end(), netCharge) != netCharges.end()) { + if (std::find(acceptedCharges.begin(), acceptedCharges.end(), netCharge) != acceptedCharges.end()) { return true; } return false; @@ -275,6 +296,23 @@ struct DGPIDSelector { return false; } + // check ITS only + if (!mAnaPars.ITSOnlyTracks() && !track.hasTPC()) { + return false; + } + + // check ncluster TPC + auto nTPCCL = track.tpcNClsFindable() - track.tpcNClsFindableMinusFound(); + if (nTPCCL < mAnaPars.minNClTPC() || nTPCCL > mAnaPars.maxNClTPC()) { + return false; + } + + // check chi2 per ncluster TPC + auto chi2NClTPC = track.tpcChi2NCl(); + if (chi2NClTPC < mAnaPars.minChi2NClTPC() || chi2NClTPC > mAnaPars.maxChi2NClTPC()) { + return false; + } + // check pt of track if (track.pt() < mAnaPars.minpt() || track.pt() > mAnaPars.maxpt()) { return false; @@ -361,41 +399,44 @@ struct DGPIDSelector { return true; } + template - int computeIVMs(TTrack const& tracks) + std::vector computeIVMs(TTrack const& tracks) { // reset - mIVMs.clear(); + mUnlikeIVMs.clear(); + mLikeIVMs.clear(); // create combinations including permutations auto combs = combinations(tracks.size()); // loop over unique combinations for (auto comb : combs) { - // is combination compatible with netCharge requirements? - if (!isGoodCombination(comb, tracks)) { - LOGF(info, "Not a good combination"); - continue; - } - // is tracks compatible with PID requirements? - bool isGoodComb = true; + // are tracks compatible with PID requirements? + bool isGoodTracks = true; auto cnt = -1; for (auto ind : comb) { cnt++; if (!isGoodTrack(tracks.begin() + ind, cnt)) { - isGoodComb = false; + isGoodTracks = false; break; } } - // update list of IVMs - if (isGoodComb) { + // is combination compatible with netCharge requirements? + if (isGoodTracks) { DGParticle IVM(fPDG, mAnaPars, tracks, comb); - mIVMs.push_back(IVM); + // unlike sign + if (isGoodCombination(comb, tracks, mAnaPars.unlikeCharges())) { + mUnlikeIVMs.push_back(IVM); + } + if (isGoodCombination(comb, tracks, mAnaPars.likeCharges())) { + mLikeIVMs.push_back(IVM); + } } } - return mIVMs.size(); + return std::vector{static_cast(mUnlikeIVMs.size()), static_cast(mLikeIVMs.size())}; } DGAnaparHolder getAnaPars() { return mAnaPars; } @@ -437,7 +478,8 @@ struct DGPIDSelector { return 0.; } } - std::vector IVMs() { return mIVMs; } + std::vector unlikeIVMs() { return mUnlikeIVMs; } + std::vector likeIVMs() { return mLikeIVMs; } int pid2ind(int pid); @@ -446,7 +488,8 @@ struct DGPIDSelector { DGAnaparHolder mAnaPars; // list of DGParticles - std::vector mIVMs; + std::vector mUnlikeIVMs; + std::vector mLikeIVMs; // particle properties TDatabasePDG* fPDG; diff --git a/PWGUD/Core/DGSelector.h b/PWGUD/Core/DGSelector.h index ba197b3e0ea..12a2bd038c4 100644 --- a/PWGUD/Core/DGSelector.h +++ b/PWGUD/Core/DGSelector.h @@ -45,41 +45,38 @@ class DGSelector // check that there are no FIT signals in any of the compatible BCs // Double Gap (DG) condition - auto lims = diffCuts.FITAmpLimits(); - for (auto const& bc : bcRange) { - LOGF(debug, "Amplitudes FV0A %f FT0 %f / %f FDD %i / %i", - bc.has_foundFV0() ? udhelpers::FV0AmplitudeA(bc.foundFV0()) : -1., - bc.has_foundFT0() ? udhelpers::FT0AmplitudeA(bc.foundFT0()) : -1., - bc.has_foundFT0() ? udhelpers::FT0AmplitudeC(bc.foundFT0()) : -1., - bc.has_foundFDD() ? udhelpers::FDDAmplitudeA(bc.foundFDD()) : -1, - bc.has_foundFDD() ? udhelpers::FDDAmplitudeC(bc.foundFDD()) : -1); - LOGF(debug, " clean FV0A %i FT0 %i FDD %i", udhelpers::cleanFV0(bc, lims[0]), udhelpers::cleanFT0(bc, lims[1], lims[2]), udhelpers::cleanFDD(bc, lims[3], lims[4])); - - if (!udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits())) { + if (!udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits())) { return 1; } } - // no activity in forward direction + // forward tracks LOGF(debug, "FwdTracks %i", fwdtracks.size()); - for (auto& fwdtrack : fwdtracks) { - LOGF(debug, " %i / %f / %f / %f", fwdtrack.trackType(), fwdtrack.eta(), fwdtrack.pt(), fwdtrack.p()); - } - if (fwdtracks.size() > 0) { - return 2; + if (!diffCuts.withFwdTracks()) { + // only consider tracks with MID (good timing) + for (auto& fwdtrack : fwdtracks) { + LOGF(info, " %i / %f / %f / %f / %f", fwdtrack.trackType(), fwdtrack.eta(), fwdtrack.pt(), fwdtrack.p(), fwdtrack.trackTimeRes()); + if (fwdtrack.trackType() == 0 || fwdtrack.trackType() == 3) { + return 2; + } + } } // no global tracks which are not vtx tracks // no vtx tracks which are not global tracks + // no PV tracks with ITS only auto rgtrwTOF = 0.; // fraction of PV tracks with TOF hit for (auto& track : tracks) { if (track.isGlobalTrack() && !track.isPVContributor()) { return 3; } - if (diffCuts.globalTracksOnly() && !track.isGlobalTrack() && track.isPVContributor()) { + if (diffCuts.globalTracksOnly() && track.isPVContributor() && !track.isGlobalTrack()) { return 4; } + if (!diffCuts.ITSOnlyTracks() && track.isPVContributor() && !track.hasTPC()) { + return 5; + } // update fraction of PV tracks with TOF hit if (track.isPVContributor() && track.hasTOF()) { @@ -90,12 +87,12 @@ class DGSelector rgtrwTOF /= collision.numContrib(); } if (rgtrwTOF < diffCuts.minRgtrwTOF()) { - return 5; + return 6; } // number of vertex tracks if (collision.numContrib() < diffCuts.minNTracks() || collision.numContrib() > diffCuts.maxNTracks()) { - return 6; + return 7; } // PID, pt, and eta of tracks, invariant mass, and net charge @@ -116,18 +113,18 @@ class DGSelector // PID // if (!udhelpers::hasGoodPID(diffCuts, track)) { - // return 7; + // return 8; // } // pt lvtmp.SetXYZM(track.px(), track.py(), track.pz(), mass2Use); if (lvtmp.Perp() < diffCuts.minPt() || lvtmp.Perp() > diffCuts.maxPt()) { - return 8; + return 9; } // eta if (lvtmp.Eta() < diffCuts.minEta() || lvtmp.Eta() > diffCuts.maxEta()) { - return 9; + return 10; } netCharge += track.sign(); ivm += lvtmp; @@ -137,11 +134,11 @@ class DGSelector // net charge auto netChargeValues = diffCuts.netCharges(); if (std::find(netChargeValues.begin(), netChargeValues.end(), netCharge) == netChargeValues.end()) { - return 10; + return 11; } // invariant mass if (ivm.M() < diffCuts.minIVM() || ivm.M() > diffCuts.maxIVM()) { - return 11; + return 12; } // if we arrive here then the event is good! @@ -155,7 +152,7 @@ class DGSelector // check that there are no FIT signals in bcRange // Double Gap (DG) condition for (auto const& bc : bcRange) { - if (!udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits())) { + if (!udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits())) { return 1; } } @@ -171,7 +168,7 @@ class DGSelector // number of tracks if (static_cast(tracks.size()) < diffCuts.minNTracks() || static_cast(tracks.size()) > diffCuts.maxNTracks()) { - return 6; + return 7; } // PID, pt, and eta of tracks, invariant mass, and net charge @@ -188,18 +185,18 @@ class DGSelector for (auto& track : tracks) { // PID if (!udhelpers::hasGoodPID(diffCuts, track)) { - return 7; + return 8; } // pt lvtmp.SetXYZM(track.px(), track.py(), track.pz(), mass2Use); if (lvtmp.Perp() < diffCuts.minPt() || lvtmp.Perp() > diffCuts.maxPt()) { - return 8; + return 9; } // eta if (lvtmp.Eta() < diffCuts.minEta() || lvtmp.Eta() > diffCuts.maxEta()) { - return 9; + return 10; } netCharge += track.sign(); ivm += lvtmp; @@ -208,12 +205,12 @@ class DGSelector // net charge auto netChargeValues = diffCuts.netCharges(); if (std::find(netChargeValues.begin(), netChargeValues.end(), netCharge) == netChargeValues.end()) { - return 10; + return 11; } // invariant mass if (ivm.M() < diffCuts.minIVM() || ivm.M() > diffCuts.maxIVM()) { - return 11; + return 12; } // if we arrive here then the event is good! diff --git a/PWGUD/Core/UDHelpers.h b/PWGUD/Core/UDHelpers.h index aeb1ddc8e67..fa60436f7f7 100644 --- a/PWGUD/Core/UDHelpers.h +++ b/PWGUD/Core/UDHelpers.h @@ -18,12 +18,14 @@ #include #include +#include "TLorentzVector.h" #include "Framework/Logger.h" #include "DataFormatsFT0/Digit.h" #include "CommonConstants/LHCConstants.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/PIDResponse.h" +#include "PWGUD/Core/UPCHelpers.h" #include "PWGUD/Core/DGCutparHolder.h" using namespace o2; @@ -104,65 +106,8 @@ T compatibleBCs(uint64_t meanBC, int deltaBC, T const& bcs); template T compatibleBCs(I& bcIter, uint64_t meanBC, int deltaBC, T const& bcs); -// In this variant of compatibleBCs the range of compatible BCs is calculated from the -// collision time and the time resolution dt. Typically the range is +- 4*dt. -template -T compatibleBCs(soa::Join::iterator const& collision, int ndt, T const& bcs, int nMinBCs = 7) -{ - LOGF(debug, "Collision time / resolution [ns]: %f / %f", collision.collisionTime(), collision.collisionTimeRes()); - - // return if collisions has no associated BC - if (!collision.has_foundBC()) { - return T{{bcs.asArrowTable()->Slice(0, 0)}, (uint64_t)0}; - } - - // get associated BC - auto bcIter = collision.foundBC_as(); - - // due to the filling scheme the most probable BC may not be the one estimated from the collision time - uint64_t mostProbableBC = bcIter.globalBC(); - uint64_t meanBC = mostProbableBC + std::lround(collision.collisionTime() / o2::constants::lhc::LHCBunchSpacingNS); - - // enforce minimum number for deltaBC - int deltaBC = std::ceil(collision.collisionTimeRes() / o2::constants::lhc::LHCBunchSpacingNS * ndt); - if (deltaBC < nMinBCs) { - deltaBC = nMinBCs; - } - LOGF(debug, "BC %d, deltaBC %d", bcIter.globalIndex(), deltaBC); - - return compatibleBCs(bcIter, meanBC, deltaBC, bcs); -} - -// same as above but with an other collision iterator as input -template -T compatibleBCs1(soa::Filtered>::iterator const& collision, int ndt, T const& bcs, int nMinBCs = 7) -{ - LOGF(debug, "Collision time / resolution [ns]: %f / %f", collision.collisionTime(), collision.collisionTimeRes()); - - // return if collisions has no associated BC - if (!collision.has_foundBC()) { - return T{{bcs.asArrowTable()->Slice(0, 0)}, (uint64_t)0}; - } - - // get associated BC - auto bcIter = collision.foundBC_as(); - - // due to the filling scheme the most probable BC may not be the one estimated from the collision time - uint64_t mostProbableBC = bcIter.globalBC(); - uint64_t meanBC = mostProbableBC + std::lround(collision.collisionTime() / o2::constants::lhc::LHCBunchSpacingNS); - - // enforce minimum number for deltaBC - int deltaBC = std::ceil(collision.collisionTimeRes() / o2::constants::lhc::LHCBunchSpacingNS * ndt); - if (deltaBC < nMinBCs) { - deltaBC = nMinBCs; - } - LOGF(debug, "BC %d, deltaBC %d", bcIter.globalIndex(), deltaBC); - - return compatibleBCs(bcIter, meanBC, deltaBC, bcs); -} - // In this variant of compatibleBCs the bcIter is ideally placed within -// [minBC, maxBC], but it does not need to be. The range is given by +- delatBC. +// [minBC, maxBC], but it does not need to be. The range is given by meanBC +- delatBC. template T compatibleBCs(I& bcIter, uint64_t meanBC, int deltaBC, T const& bcs) { @@ -224,6 +169,35 @@ T compatibleBCs(I& bcIter, uint64_t meanBC, int deltaBC, T const& bcs) return slice; } +// In this variant of compatibleBCs the range of compatible BCs is calculated from the +// collision time and the time resolution dt. Typically the range is +- 4*dt. +template +T compatibleBCs(C const& collision, int ndt, T const& bcs, int nMinBCs = 7) +{ + LOGF(debug, "Collision time / resolution [ns]: %f / %f", collision.collisionTime(), collision.collisionTimeRes()); + + // return if collisions has no associated BC + if (!collision.has_foundBC() || ndt < 0) { + return T{{bcs.asArrowTable()->Slice(0, 0)}, (uint64_t)0}; + } + + // get associated BC + auto bcIter = collision.template foundBC_as(); + + // due to the filling scheme the most probable BC may not be the one estimated from the collision time + uint64_t mostProbableBC = bcIter.globalBC(); + uint64_t meanBC = mostProbableBC + std::lround(collision.collisionTime() / o2::constants::lhc::LHCBunchSpacingNS); + + // enforce minimum number for deltaBC + int deltaBC = std::ceil(collision.collisionTimeRes() / o2::constants::lhc::LHCBunchSpacingNS * ndt); + if (deltaBC < nMinBCs) { + deltaBC = nMinBCs; + } + LOGF(debug, "BC %d, deltaBC %d", bcIter.globalIndex(), deltaBC); + + return compatibleBCs(bcIter, meanBC, deltaBC, bcs); +} + // In this variant of compatibleBCs the range of compatible BCs is defined by meanBC +- deltaBC. template T compatibleBCs(uint64_t meanBC, int deltaBC, T const& bcs) @@ -237,8 +211,8 @@ T compatibleBCs(uint64_t meanBC, int deltaBC, T const& bcs) // ----------------------------------------------------------------------------- // Same as above but for collisions with MC information -template -T MCcompatibleBCs(soa::Join::iterator const& collision, int ndt, T const& bcs, int nMinBCs = 7) +template +T MCcompatibleBCs(F const& collision, int ndt, T const& bcs, int nMinBCs = 7) { LOGF(debug, "Collision time / resolution [ns]: %f / %f", collision.collisionTime(), collision.collisionTimeRes()); @@ -249,7 +223,7 @@ T MCcompatibleBCs(soa::Join(); + auto bcIter = collision.template foundBC_as(); // due to the filling scheme the most probable BC may not be the one estimated from the collision time uint64_t mostProbableBC = bcIter.globalBC(); @@ -377,11 +351,12 @@ int16_t FDDAmplitudeC(aod::FDD&& fdd) // ----------------------------------------------------------------------------- template -bool cleanFV0(T& bc, float limitA) +bool cleanFV0(T& bc, float maxFITtime, float limitA) { if (bc.has_foundFV0()) { + bool ota = std::abs(bc.foundFV0().time()) <= maxFITtime; bool oma = FV0AmplitudeA(bc.foundFV0()) <= limitA; - return oma; + return ota && oma; } else { return true; } @@ -389,11 +364,13 @@ bool cleanFV0(T& bc, float limitA) // ----------------------------------------------------------------------------- template -bool cleanFT0(T& bc, float limitA, float limitC) +bool cleanFT0(T& bc, float maxFITtime, float limitA, float limitC) { if (bc.has_foundFT0()) { - // check amplitudes + // check times and amplitudes + bool ota = std::abs(bc.foundFT0().timeA()) <= maxFITtime; + bool otc = std::abs(bc.foundFT0().timeC()) <= maxFITtime; bool oma = FT0AmplitudeA(bc.foundFT0()) <= limitA; bool omc = FT0AmplitudeC(bc.foundFT0()) <= limitC; @@ -401,9 +378,9 @@ bool cleanFT0(T& bc, float limitA, float limitC) std::bitset<8> triggers = bc.foundFT0().triggerMask(); bool ora = !triggers[o2::ft0::Triggers::bitA]; bool orc = !triggers[o2::ft0::Triggers::bitC]; - LOGF(debug, "ora/FT0AmplitudeA %d/%d orc/FT0AmplitudeC %d/%d", ora, oma, orc, omc); + LOGF(debug, "ota %f otc %f ora/FT0AmplitudeA %d/%d orc/FT0AmplitudeC %d/%d", bc.foundFT0().timeA(), bc.foundFT0().timeC(), ora, oma, orc, omc); - return oma && omc; + return ota && oma && otc && omc; } else { return true; } @@ -411,12 +388,14 @@ bool cleanFT0(T& bc, float limitA, float limitC) // ----------------------------------------------------------------------------- template -bool cleanFDD(T& bc, float limitA, float limitC) +bool cleanFDD(T& bc, float maxFITtime, float limitA, float limitC) { if (bc.has_foundFDD()) { + bool ota = std::abs(bc.foundFDD().timeA()) <= maxFITtime; + bool otc = std::abs(bc.foundFDD().timeC()) <= maxFITtime; bool oma = FDDAmplitudeA(bc.foundFDD()) <= limitA; bool omc = FDDAmplitudeC(bc.foundFDD()) <= limitC; - return oma && omc; + return ota && oma && otc && omc; } else { return true; } @@ -431,27 +410,133 @@ bool cleanFDD(T& bc, float limitA, float limitC) // lims[4]: FDDC template -bool cleanFIT(T& bc, std::vector lims) +bool cleanFIT(T& bc, float maxFITtime, std::vector lims) { - return cleanFV0(bc, lims[0]) && cleanFT0(bc, lims[1], lims[2]) && cleanFDD(bc, lims[3], lims[4]); + return cleanFV0(bc, maxFITtime, lims[0]) && + cleanFT0(bc, maxFITtime, lims[1], lims[2]) && + cleanFDD(bc, maxFITtime, lims[3], lims[4]); } template -bool cleanFITCollision(T& col, std::vector lims) +bool cleanFITCollision(T& col, float maxFITtime, std::vector lims) { bool isCleanFV0 = true; if (col.has_foundFV0()) { - isCleanFV0 = (FV0AmplitudeA(col.foundFV0()) < lims[0]); + isCleanFV0 = (std::abs(col.foundFV0().time()) <= maxFITtime) && (FV0AmplitudeA(col.foundFV0()) < lims[0]); } bool isCleanFT0 = true; if (col.has_foundFT0()) { - isCleanFT0 = (FT0AmplitudeA(col.foundFT0()) < lims[1]) && (FT0AmplitudeC(col.foundFT0()) < lims[2]); + isCleanFT0 = (std::abs(col.foundFT0().timeA()) <= maxFITtime) && (FT0AmplitudeA(col.foundFT0()) < lims[1]) && + (std::abs(col.foundFT0().timeC()) <= maxFITtime) && (FT0AmplitudeC(col.foundFT0()) < lims[2]); } bool isCleanFDD = true; if (col.has_foundFDD()) { - isCleanFDD = (FDDAmplitudeA(col.foundFDD()) < lims[3]) && (FDDAmplitudeC(col.foundFDD()) < lims[4]); + isCleanFDD = (std::abs(col.foundFDD().timeA()) <= maxFITtime) && (FDDAmplitudeA(col.foundFDD()) < lims[3]) && + (std::abs(col.foundFDD().timeC()) <= maxFITtime) && (FDDAmplitudeC(col.foundFDD()) < lims[4]); } return (isCleanFV0 && isCleanFT0 && isCleanFDD); } +// ----------------------------------------------------------------------------- +// fill BB and BG information into FITInfo +template +void fillBGBBFlags(upchelpers::FITInfo& info, uint64_t const& minbc, BCR const& bcrange) +{ + for (auto const& bc2u : bcrange) { + + // 0 <= bit <= 31 + auto bit = bc2u.globalBC() - minbc; + if (!bc2u.selection_bit(o2::aod::evsel::kNoBGT0A)) + SETBIT(info.BGFT0Apf, bit); + if (!bc2u.selection_bit(o2::aod::evsel::kNoBGT0C)) + SETBIT(info.BGFT0Cpf, bit); + if (bc2u.selection_bit(o2::aod::evsel::kIsBBT0A)) + SETBIT(info.BBFT0Apf, bit); + if (bc2u.selection_bit(o2::aod::evsel::kIsBBT0C)) + SETBIT(info.BBFT0Cpf, bit); + if (!bc2u.selection_bit(o2::aod::evsel::kNoBGV0A)) + SETBIT(info.BGFV0Apf, bit); + if (bc2u.selection_bit(o2::aod::evsel::kIsBBV0A)) + SETBIT(info.BBFV0Apf, bit); + if (!bc2u.selection_bit(o2::aod::evsel::kNoBGFDA)) + SETBIT(info.BGFDDApf, bit); + if (!bc2u.selection_bit(o2::aod::evsel::kNoBGFDC)) + SETBIT(info.BGFDDCpf, bit); + if (bc2u.selection_bit(o2::aod::evsel::kIsBBFDA)) + SETBIT(info.BBFDDApf, bit); + if (bc2u.selection_bit(o2::aod::evsel::kIsBBFDC)) + SETBIT(info.BBFDDCpf, bit); + } +} + +// ----------------------------------------------------------------------------- +// extract FIT information +template +void getFITinfo(upchelpers::FITInfo info, uint64_t const& bcnum, B const& bcs, aod::FT0s const& ft0s, aod::FV0As const& fv0as, aod::FDDs const& fdds) +{ + // find bc with globalBC = bcnum + Partition selbc = aod::bc::globalBC == bcnum; + selbc.bindTable(bcs); + + // if BC exists then update FIT information for this BC + if (selbc.size() > 0) { + auto bc = selbc.begin(); + + // FT0 + if (bc.has_foundFT0()) { + auto ft0 = ft0s.iteratorAt(bc.foundFT0Id()); + info.timeFT0A = ft0.timeA(); + info.timeFT0C = ft0.timeC(); + const auto& ampsA = ft0.amplitudeA(); + const auto& ampsC = ft0.amplitudeC(); + info.ampFT0A = 0.; + for (auto amp : ampsA) { + info.ampFT0A += amp; + } + info.ampFT0C = 0.; + for (auto amp : ampsC) { + info.ampFT0C += amp; + } + info.triggerMaskFT0 = ft0.triggerMask(); + } + + // FV0A + if (bc.has_foundFV0()) { + auto fv0a = fv0as.iteratorAt(bc.foundFV0Id()); + info.timeFV0A = fv0a.time(); + const auto& amps = fv0a.amplitude(); + info.ampFV0A = 0.; + for (auto amp : amps) { + info.ampFV0A += amp; + } + info.triggerMaskFV0A = fv0a.triggerMask(); + } + + // FDD + if (bc.has_foundFDD()) { + auto fdd = fdds.iteratorAt(bc.foundFDDId()); + info.timeFDDA = fdd.timeA(); + info.timeFDDC = fdd.timeC(); + const auto& ampsA = fdd.chargeA(); + const auto& ampsC = fdd.chargeC(); + info.ampFDDA = 0.; + for (auto amp : ampsA) { + info.ampFDDA += amp; + } + info.ampFDDC = 0.; + for (auto amp : ampsC) { + info.ampFDDC += amp; + } + info.triggerMaskFDD = fdd.triggerMask(); + } + } + + // fill BG and BB flags + auto minbc = bcnum - 16; + auto maxbc = bcnum + 15; + Partition bcrange = aod::bc::globalBC >= minbc && aod::bc::globalBC <= maxbc; + bcrange.bindTable(bcs); + fillBGBBFlags(info, minbc, bcrange); +} + // ----------------------------------------------------------------------------- template bool cleanZDC(T const& bc, aod::Zdcs& zdcs, std::vector& lims, SliceCache& cache) @@ -517,6 +602,12 @@ bool isPythiaCDE(T MCparts) template bool isGraniittiCDE(T MCparts) { + + for (auto MCpart : MCparts) { + LOGF(debug, " MCpart.pdgCode() %d", MCpart.pdgCode()); + } + LOGF(debug, ""); + if (MCparts.size() < 7) { return false; } else { @@ -539,6 +630,31 @@ bool isGraniittiCDE(T MCparts) return true; } +// ----------------------------------------------------------------------------- +// Invariant mass of GRANIITTI generated event +template +TLorentzVector ivmGraniittiCDE(T MCparts) +{ + TLorentzVector ivm = TLorentzVector(0., 0., 0., 0.); + + // is this a GRANIITTI generated event? + if (isGraniittiCDE(MCparts)) { + TLorentzVector lvtmp; + + for (int ii = 7; ii < MCparts.size(); ii++) { + auto mcPart = MCparts.iteratorAt(ii); + LOGF(debug, " part %d / %d", mcPart.pdgCode(), mcPart.getGenStatusCode()); + if (mcPart.getGenStatusCode() == 0) { + lvtmp.SetXYZT(mcPart.px(), mcPart.py(), mcPart.pz(), mcPart.e()); + ivm += lvtmp; + } + } + LOGF(debug, ""); + } + + return ivm; +} + // ----------------------------------------------------------------------------- } // namespace udhelpers diff --git a/PWGUD/Core/UPCCutparHolder.h b/PWGUD/Core/UPCCutparHolder.h index 4824473063b..ded4094a86e 100644 --- a/PWGUD/Core/UPCCutparHolder.h +++ b/PWGUD/Core/UPCCutparHolder.h @@ -157,7 +157,16 @@ class UPCCutparHolder private: bool fUseFwdCuts{true}; // Use cuts for forward tracks - int fTrackType{3}; // Filter by Fwd. track type: -1 -> no filter, 0 -> MFT-MCH-MID, 2 -> MFT-MCH, 3 -> MCH-MID. See ForwardTrackTypeEnum + + // Filter by Fwd. track type: + // -1 -> no filter, + // 0 -> MFT-MCH-MID, + // 2 -> MFT-MCH, + // 3 -> MCH-MID, + // 4 -> MCH + // 5 -> MCH-MID and MCH + // See ForwardTrackTypeEnum + int fTrackType{3}; // basic float fFwdPtLow{0.5}; // Minimal Pt for forward tracks diff --git a/PWGUD/Core/UPCHelpers.h b/PWGUD/Core/UPCHelpers.h index 4648560c51e..e898a1ec341 100644 --- a/PWGUD/Core/UPCHelpers.h +++ b/PWGUD/Core/UPCHelpers.h @@ -9,8 +9,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#ifndef O2PHYSICS_UPCHELPERS_H -#define O2PHYSICS_UPCHELPERS_H +#ifndef PWGUD_CORE_UPCHELPERS_H_ +#define PWGUD_CORE_UPCHELPERS_H_ #include "Framework/AnalysisDataModel.h" #include "Common/DataModel/EventSelection.h" @@ -29,7 +29,8 @@ using ForwardTracks = o2::soa::Join; using BarrelTracks = o2::soa::Join; + o2::aod::TOFSignal, o2::aod::pidTOFbeta, + o2::aod::pidTOFFullEl, o2::aod::pidTOFFullMu, o2::aod::pidTOFFullPi, o2::aod::pidTOFFullKa, o2::aod::pidTOFFullPr>; // namespace with helpers for UPC track skimming and candidate production namespace upchelpers @@ -129,4 +130,4 @@ void applyBarrelCuts(UPCCutparHolder& upcCuts, const BarrelTracks::iterator& tra } // namespace upchelpers -#endif // O2PHYSICS_UPCHELPERS_H +#endif // PWGUD_CORE_UPCHELPERS_H_ diff --git a/PWGUD/DataModel/UDTables.h b/PWGUD/DataModel/UDTables.h index 11fb71ca982..faaa57e2547 100644 --- a/PWGUD/DataModel/UDTables.h +++ b/PWGUD/DataModel/UDTables.h @@ -26,7 +26,7 @@ namespace o2::aod namespace udmccollision { -DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); +DECLARE_SOA_COLUMN(GlobalBC, globalBC, uint64_t); //! } // namespace udmccollision DECLARE_SOA_TABLE(UDMcCollisions, "AOD", "UDMCCOLLISIONS", @@ -132,6 +132,10 @@ DECLARE_SOA_DYNAMIC_COLUMN(BBFV0A, bbFV0A, DECLARE_SOA_DYNAMIC_COLUMN(BGFV0A, bgFV0A, [](int32_t bgFV0Apf) -> bool { return TESTBIT(bgFV0Apf, 16); }); +DECLARE_SOA_INDEX_COLUMN(Collision, collision); + +DECLARE_SOA_INDEX_COLUMN(UDMcCollision, udMcCollision); + } // namespace udcollision DECLARE_SOA_TABLE(UDCollisions, "AOD", "UDCOLLISION", @@ -166,8 +170,16 @@ DECLARE_SOA_TABLE(UDCollisionsSels, "AOD", "UDCOLLISIONSEL", udcollision::BBFV0A, udcollision::BGFV0A, udcollision::BBFDDA, udcollision::BBFDDC, udcollision::BGFDDA, udcollision::BGFDDC); +DECLARE_SOA_TABLE(UDCollsLabels, "AOD", "UDCOLLSLABEL", + udcollision::CollisionId); + +DECLARE_SOA_TABLE(UDMcCollsLabels, "AOD", "UDMCCOLLSLABEL", + udcollision::UDMcCollisionId); + using UDCollision = UDCollisions::iterator; using UDCollisionsSel = UDCollisionsSels::iterator; +using UDCollsLabel = UDCollsLabels::iterator; +using UDMcCollsLabel = UDMcCollsLabels::iterator; namespace udtrack { @@ -190,6 +202,9 @@ DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! [](float px, float py) -> float { return std::sqrt(px * px + py * py); }); + +DECLARE_SOA_INDEX_COLUMN(Track, track); + } // namespace udtrack // Barrel track kinematics @@ -211,6 +226,7 @@ DECLARE_SOA_TABLE(UDTracksCov, "AOD", "UDTRACKCOV", DECLARE_SOA_TABLE(UDTracksPID, "AOD", "UDTRACKPID", pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtofbeta::Beta, pidtofbeta::BetaError, pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr); DECLARE_SOA_TABLE(UDTracksExtra, "AOD", "UDTRACKEXTRA", @@ -247,11 +263,15 @@ DECLARE_SOA_TABLE(UDTracksFlags, "AOD", "UDTRACKFLAG", udtrack::IsPVContributor, udtrack::IsAmbiguous); +DECLARE_SOA_TABLE(UDTracksLabels, "AOD", "UDTRACKLABEL", + udtrack::TrackId); + using UDTrack = UDTracks::iterator; using UDTrackCov = UDTracksCov::iterator; using UDTrackExtra = UDTracksExtra::iterator; using UDTrackDCA = UDTracksDCA::iterator; using UDTrackFlags = UDTracksFlags::iterator; +using UDTracksLabel = UDTracksLabels::iterator; namespace udmctracklabel { diff --git a/PWGUD/TableProducer/DGBCCandProducer.cxx b/PWGUD/TableProducer/DGBCCandProducer.cxx index d4e9d8d545f..fb89dfad037 100644 --- a/PWGUD/TableProducer/DGBCCandProducer.cxx +++ b/PWGUD/TableProducer/DGBCCandProducer.cxx @@ -49,10 +49,10 @@ struct tracksWGTInBCs { void init(InitContext& context) { if (context.mOptions.get("processBarrel")) { - registry.add("barrel/Tracks", "#barrelTracks", {HistType::kTH1F, {{6, -0.5, 5.5}}}); + registry.add("barrel/Tracks", "Number of barrel track types", {HistType::kTH1F, {{6, -0.5, 5.5}}}); } if (context.mOptions.get("processForward")) { - registry.add("forward/Tracks", "#forwardTracks", {HistType::kTH1F, {{5, -0.5, 4.5}}}); + registry.add("forward/Tracks", "Number of forward track types", {HistType::kTH1F, {{5, -0.5, 4.5}}}); } } @@ -87,7 +87,7 @@ struct tracksWGTInBCs { } // only consider tracks with good timing - if (track.trackTimeRes() <= o2::constants::lhc::LHCBunchSpacingNS) { + if (std::abs(track.trackTimeRes()) <= o2::constants::lhc::LHCBunchSpacingNS) { registry.get(HIST("barrel/Tracks"))->Fill(4., 1.); // get first compatible BC @@ -96,6 +96,7 @@ struct tracksWGTInBCs { // compute the BC closest in time auto firstCompatibleBC = ambTracksSlice.begin().bc().begin().globalBC(); + LOGF(debug, "Track time %f", track.trackTime()); closestBC = (uint64_t)(firstCompatibleBC + (track.trackTime() / o2::constants::lhc::LHCBunchSpacingNS)); } else { @@ -105,6 +106,7 @@ struct tracksWGTInBCs { } // update tracksInBCList + LOGF(debug, "Closest BC %d", closestBC); tracksInBCList[closestBC].emplace_back((int32_t)track.globalIndex()); } } @@ -113,6 +115,7 @@ struct tracksWGTInBCs { int indBCToStart = 0; int indBCToSave; for (auto const& tracksInBC : tracksInBCList) { + LOGF(debug, "tracksInBC.first %d", tracksInBC.first); indBCToSave = -1; // find corresponding BC for (auto ind = indBCToStart; ind < bcs.size(); ind++) { @@ -129,7 +132,7 @@ struct tracksWGTInBCs { tracksWGTInBCs(indBCToSave, rnum, tracksInBC.first, tracksInBC.second); LOGF(debug, " BC %i/%u with %i tracks with good timing", indBCToSave, tracksInBC.first, tracksInBC.second.size()); } - LOGF(info, "barrel done"); + LOGF(debug, "barrel done"); } PROCESS_SWITCH(tracksWGTInBCs, processBarrel, "Process barrel tracks", false); @@ -159,7 +162,7 @@ struct tracksWGTInBCs { // only consider tracks with trackTimeRes < LHCBunchSpacingNS LOGF(debug, "Time resolution of fwdTrack %f", fwdTrack.trackTimeRes()); - if (fwdTrack.trackTimeRes() <= o2::constants::lhc::LHCBunchSpacingNS) { + if (std::abs(fwdTrack.trackTimeRes()) <= o2::constants::lhc::LHCBunchSpacingNS) { registry.get(HIST("forward/Tracks"))->Fill(3., 1.); // get first compatible BC @@ -202,7 +205,7 @@ struct tracksWGTInBCs { fwdTracksWGTInBCs(indBCToSave, rnum, fwdTracksInBC.first, fwdTracksInBC.second); LOGF(debug, " BC %i/%u with %i forward tracks with good timing", indBCToSave, fwdTracksInBC.first, fwdTracksInBC.second.size()); } - LOGF(info, "fwd done"); + LOGF(debug, "fwd done"); } PROCESS_SWITCH(tracksWGTInBCs, processForward, "Process forward tracks", false); @@ -218,6 +221,7 @@ struct DGBCCandProducer { // data tables Produces outputCollisions; Produces outputCollisionsSels; + Produces outputCollsLabels; Produces outputZdcs; Produces outputTracks; Produces outputTracksCov; @@ -225,6 +229,7 @@ struct DGBCCandProducer { Produces outputTracksPID; Produces outputTracksExtra; Produces outputTracksFlag; + Produces outputTracksLabel; // get a DGCutparHolder DGCutparHolder diffCuts = DGCutparHolder(); @@ -245,119 +250,45 @@ struct DGBCCandProducer { using BC = BCs::iterator; using TCs = soa::Join; + aod::TOFSignal, aod::pidTOFbeta, + aod::pidTOFFullEl, aod::pidTOFFullMu, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr>; using FTCs = aod::FwdTracks; + SliceCache cache; Preslice TCperCollision = aod::track::collisionId; Preslice FWperCollision = aod::fwdtrack::collisionId; - // fill BB and BG information into FITInfo - template - void fillBGBBFlags(upchelpers::FITInfo& info, uint64_t const& minbc, BCR const& bcrange) - { - for (auto const& bc2u : bcrange) { - - // 0 <= bit <= 31 - auto bit = bc2u.globalBC() - minbc; - if (!bc2u.selection_bit(evsel::kNoBGT0A)) - SETBIT(info.BGFT0Apf, bit); - if (!bc2u.selection_bit(evsel::kNoBGT0C)) - SETBIT(info.BGFT0Cpf, bit); - if (bc2u.selection_bit(evsel::kIsBBT0A)) - SETBIT(info.BBFT0Apf, bit); - if (bc2u.selection_bit(evsel::kIsBBT0C)) - SETBIT(info.BBFT0Cpf, bit); - if (!bc2u.selection_bit(evsel::kNoBGV0A)) - SETBIT(info.BGFV0Apf, bit); - if (bc2u.selection_bit(evsel::kIsBBV0A)) - SETBIT(info.BBFV0Apf, bit); - if (!bc2u.selection_bit(evsel::kNoBGFDA)) - SETBIT(info.BGFDDApf, bit); - if (!bc2u.selection_bit(evsel::kNoBGFDC)) - SETBIT(info.BGFDDCpf, bit); - if (bc2u.selection_bit(evsel::kIsBBFDA)) - SETBIT(info.BBFDDApf, bit); - if (bc2u.selection_bit(evsel::kIsBBFDC)) - SETBIT(info.BBFDDCpf, bit); - } - } - - // extract FIT information - void getFITinfo(upchelpers::FITInfo info, uint64_t const& bcnum, BCs const& bcs, aod::FT0s const& ft0s, aod::FV0As const& fv0as, aod::FDDs const& fdds) + // update UDTables + template + void updateUDTables(bool onlyPV, int64_t colID, uint64_t bcnum, int rnum, float vx, float vy, float vz, + uint16_t const& ntrks, int8_t const& ncharge, float const& rtrwTOF, + TTracks const& tracks, upchelpers::FITInfo const& fitInfo) { - // FITinfo - uint64_t minbc = bcnum > 16 ? bcnum - 16 : 0; - - // find bc with globalBC = bcnum - Partition selbc = aod::bc::globalBC == bcnum; - selbc.bindTable(bcs); - - // if BC exists then update FIT information for this BC - if (selbc.size() > 0) { - auto bc = bcs.iteratorAt(selbc.begin().globalIndex()); - - // FT0 - if (bc.has_foundFT0()) { - auto ft0 = ft0s.iteratorAt(bc.foundFT0Id()); - info.timeFT0A = ft0.timeA(); - info.timeFT0C = ft0.timeC(); - const auto& ampsA = ft0.amplitudeA(); - const auto& ampsC = ft0.amplitudeC(); - info.ampFT0A = 0.; - for (auto amp : ampsA) { - info.ampFT0A += amp; - } - info.ampFT0C = 0.; - for (auto amp : ampsC) { - info.ampFT0C += amp; - } - info.triggerMaskFT0 = ft0.triggerMask(); - } - - // FV0A - if (bc.has_foundFV0()) { - auto fv0a = fv0as.iteratorAt(bc.foundFV0Id()); - info.timeFV0A = fv0a.time(); - const auto& amps = fv0a.amplitude(); - info.ampFV0A = 0.; - for (auto amp : amps) { - info.ampFV0A += amp; - } - info.triggerMaskFV0A = fv0a.triggerMask(); - } + outputCollisions(bcnum, rnum, vx, vy, vz, ntrks, ncharge, rtrwTOF); + outputCollisionsSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, + fitInfo.triggerMaskFT0, + fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, + fitInfo.triggerMaskFDD, + fitInfo.ampFV0A, fitInfo.timeFV0A, fitInfo.triggerMaskFV0A, + fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, + fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, + fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); + outputCollsLabels(colID); - // FDD - if (bc.has_foundFDD()) { - auto fdd = fdds.iteratorAt(bc.foundFDDId()); - info.timeFDDA = fdd.timeA(); - info.timeFDDC = fdd.timeC(); - const auto& ampsA = fdd.chargeA(); - const auto& ampsC = fdd.chargeC(); - info.ampFDDA = 0.; - for (auto amp : ampsA) { - info.ampFDDA += amp; - } - info.ampFDDC = 0.; - for (auto amp : ampsC) { - info.ampFDDC += amp; - } - info.triggerMaskFDD = fdd.triggerMask(); + // update DGTracks tables + for (auto const& track : tracks) { + if (track.isPVContributor() || !onlyPV) { + updateUDTrackTables(outputCollisions.lastIndex(), track, bcnum); } - - auto bcrange = udhelpers::compatibleBCs(bc, bcnum, 16, bcs); - fillBGBBFlags(info, minbc, bcrange); - } else { - auto bcrange = udhelpers::compatibleBCs(bcnum, 16, bcs); - fillBGBBFlags(info, minbc, bcrange); } } // function to update UDTracks, UDTracksCov, UDTracksDCA, UDTracksPID, UDTracksExtra, UDTracksFlag, // and UDTrackCollisionIDs template - void updateUDTrackTables(TTrack const& track, uint64_t const& bcnum) + void updateUDTrackTables(int64_t lastIndex, TTrack const& track, uint64_t const& bcnum) { - outputTracks(outputCollisions.lastIndex(), + outputTracks(lastIndex, track.px(), track.py(), track.pz(), track.sign(), bcnum, track.trackTime(), track.trackTimeRes()); @@ -373,6 +304,8 @@ struct DGBCCandProducer { track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), + track.betaerror(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), @@ -397,30 +330,7 @@ struct DGBCCandProducer { track.detectorMap()); outputTracksFlag(track.has_collision(), track.isPVContributor()); - } - - // update UDTables - template - void updateUDTables(bool onlyPV, uint64_t bcnum, int rnum, float vx, float vy, float vz, - uint16_t const& ntrks, int8_t const& ncharge, float const& rtrwTOF, - TTracks const& tracks, upchelpers::FITInfo const& fitInfo) - { - outputCollisions(bcnum, rnum, vx, vy, vz, ntrks, ncharge, rtrwTOF); - outputCollisionsSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, - fitInfo.triggerMaskFT0, - fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, - fitInfo.triggerMaskFDD, - fitInfo.ampFV0A, fitInfo.timeFV0A, fitInfo.triggerMaskFV0A, - fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, - fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, - fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); - - // update DGTracks tables - for (auto const& track : tracks) { - if (track.isPVContributor() || !onlyPV) { - updateUDTrackTables(track, bcnum); - } - } + outputTracksLabel(track.globalIndex()); } void init(InitContext& context) @@ -451,7 +361,7 @@ struct DGBCCandProducer { // fill FITInfo auto bcnum = tibc.bcnum(); upchelpers::FITInfo fitInfo{}; - getFITinfo(fitInfo, bcnum, bcs, ft0s, fv0as, fdds); + udhelpers::getFITinfo(fitInfo, bcnum, bcs, ft0s, fv0as, fdds); // check if DG event // distinguish between cases with and without associated BC @@ -476,9 +386,9 @@ struct DGBCCandProducer { colSlize.bindExternalIndices(&bcs); auto col = colSlize.begin(); - auto colTracks = tracks.sliceBy(TCperCollision, col.globalIndex()); - auto colFwdTracks = fwdtracks.sliceBy(FWperCollision, col.globalIndex()); - auto bcRange = udhelpers::compatibleBCs1(col, diffCuts.NDtcoll(), bcs, diffCuts.minNBCs()); + auto colTracks = tracks.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); + auto colFwdTracks = fwdtracks.sliceByCached(aod::fwdtrack::collisionId, col.globalIndex(), cache); + auto bcRange = udhelpers::compatibleBCs(col, diffCuts.NDtcoll(), bcs, diffCuts.minNBCs()); isDG = dgSelector.IsSelected(diffCuts, col, bcRange, colTracks, colFwdTracks); // update UDTables, case 1. @@ -487,7 +397,7 @@ struct DGBCCandProducer { rtrwTOF = udhelpers::rPVtrwTOF(colTracks, col.numContrib()); nCharge = udhelpers::netCharge(colTracks); - updateUDTables(false, bc.globalBC(), bc.runNumber(), col.posX(), col.posY(), col.posZ(), + updateUDTables(false, col.globalIndex(), bc.globalBC(), bc.runNumber(), col.posX(), col.posY(), col.posZ(), col.numContrib(), nCharge, rtrwTOF, colTracks, fitInfo); } } else { @@ -519,7 +429,7 @@ struct DGBCCandProducer { rtrwTOF = udhelpers::rPVtrwTOF(tracksArray, tracksArray.size()); nCharge = udhelpers::netCharge(tracksArray); - updateUDTables(false, bc.globalBC(), bc.runNumber(), -2., 2., -2, + updateUDTables(false, -1, bc.globalBC(), bc.runNumber(), -2., 2., -2, tracksArray.size(), nCharge, rtrwTOF, tracksArray, fitInfo); } } @@ -565,7 +475,7 @@ struct DGBCCandProducer { rtrwTOF = udhelpers::rPVtrwTOF(tracksArray, tracksArray.size()); nCharge = udhelpers::netCharge(tracksArray); - updateUDTables(false, bcnum, tibc.runNumber(), -3., 3., -3, + updateUDTables(false, -1, bcnum, tibc.runNumber(), -3., 3., -3, tracksArray.size(), nCharge, rtrwTOF, tracksArray, fitInfo); } } @@ -670,8 +580,8 @@ struct DGBCCandProducer { ntr1 = col.numContrib(); auto bcRange = udhelpers::compatibleBCs(bc, bcnum, diffCuts.minNBCs(), bcs); - auto colTracks = tracks.sliceBy(TCperCollision, col.globalIndex()); - auto colFwdTracks = fwdtracks.sliceBy(FWperCollision, col.globalIndex()); + auto colTracks = tracks.sliceByCached(aod::track::collisionId, col.globalIndex(), cache); + auto colFwdTracks = fwdtracks.sliceByCached(aod::fwdtrack::collisionId, col.globalIndex(), cache); isDG1 = dgSelector.IsSelected(diffCuts, col, bcRange, colTracks, colFwdTracks); LOGF(debug, " isDG1 %d with %d tracks", isDG1, ntr1); if (isDG1 == 0) { @@ -681,8 +591,8 @@ struct DGBCCandProducer { auto rtrwTOF = udhelpers::rPVtrwTOF(colTracks, col.numContrib()); auto nCharge = udhelpers::netCharge(colTracks); - getFITinfo(fitInfo, bcnum, bcs, ft0s, fv0as, fdds); - updateUDTables(false, bcnum, bc.runNumber(), col.posX(), col.posY(), col.posZ(), + udhelpers::getFITinfo(fitInfo, bcnum, bcs, ft0s, fv0as, fdds); + updateUDTables(false, col.globalIndex(), bcnum, bc.runNumber(), col.posX(), col.posY(), col.posZ(), col.numContrib(), nCharge, rtrwTOF, colTracks, fitInfo); // fill UDZdcs if (bc.has_zdc()) { @@ -731,7 +641,7 @@ struct DGBCCandProducer { auto rtrwTOF = udhelpers::rPVtrwTOF(tracksArray, tracksArray.size()); auto nCharge = udhelpers::netCharge(tracksArray); - getFITinfo(fitInfo, bcnum, bcs, ft0s, fv0as, fdds); + udhelpers::getFITinfo(fitInfo, bcnum, bcs, ft0s, fv0as, fdds); // distinguish different cases if (bc.globalBC() == bcnum) { @@ -750,9 +660,9 @@ struct DGBCCandProducer { vpos[2] = -3.; } - updateUDTables(false, bcnum, tibc.runNumber(), vpos[0], vpos[1], vpos[2], + int64_t colID = withCollision ? col.globalIndex() : -1; + updateUDTables(false, colID, bcnum, tibc.runNumber(), vpos[0], vpos[1], vpos[2], tracksArray.size(), nCharge, rtrwTOF, tracksArray, fitInfo); - // fill UDZdcs if (bc.globalBC() == bcnum) { if (bc.has_zdc()) { diff --git a/PWGUD/TableProducer/DGCandProducer.cxx b/PWGUD/TableProducer/DGCandProducer.cxx index c1b6651f663..c2a0d8eb8f2 100644 --- a/PWGUD/TableProducer/DGCandProducer.cxx +++ b/PWGUD/TableProducer/DGCandProducer.cxx @@ -24,7 +24,6 @@ using namespace o2::framework; using namespace o2::framework::expressions; struct DGCandProducer { - // get a DGCutparHolder DGCutparHolder diffCuts = DGCutparHolder(); Configurable DGCuts{"DGCuts", {}, "DG event cuts"}; @@ -32,14 +31,10 @@ struct DGCandProducer { // DG selector DGSelector dgSelector; - void init(InitContext&) - { - diffCuts = (DGCutparHolder)DGCuts; - } - // data tables Produces outputCollisions; Produces outputCollisionsSels; + Produces outputCollsLabels; Produces outputZdcs; Produces outputTracks; Produces outputTracksCov; @@ -47,21 +42,14 @@ struct DGCandProducer { Produces outputTracksPID; Produces outputTracksExtra; Produces outputTracksFlag; + Produces outputFwdTracks; + Produces outputFwdTracksExtra; + Produces outputTracksLabel; - // MC tables - Produces outputMcCollisions; - Produces outputMcParticles; - Produces outputMcTrackLabels; - - // define histograms + // initialize histogram registry HistogramRegistry registry{ "registry", - { - {"pt1Vspt2", "#pt1Vspt2", {HistType::kTH2F, {{100, -3., 3.}, {100, -3., 3.0}}}}, - {"TPCsignal1", "#TPCsignal1", {HistType::kTH2F, {{200, -3., 3.}, {200, 0., 100.0}}}}, - {"TPCsignal2", "#TPCsignal2", {HistType::kTH2F, {{200, -3., 3.}, {200, 0., 100.0}}}}, - {"sig1VsSig2TPC", "#sig1VsSig2TPC", {HistType::kTH2F, {{100, 0., 100.}, {100, 0., 100.}}}}, - }}; + {}}; // data inputs using CCs = soa::Join; @@ -70,119 +58,33 @@ struct DGCandProducer { using BC = BCs::iterator; using TCs = soa::Join; + aod::TOFSignal, aod::pidTOFbeta, + aod::pidTOFFullEl, aod::pidTOFFullMu, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr>; using FWs = aod::FwdTracks; - // MC inputs - using MCCCs = soa::Join; - using MCCC = MCCCs::iterator; - using MCTCs = soa::Join; - using MCTC = MCTCs::iterator; - - // extract FIT information - void getFITinfo(upchelpers::FITInfo& info, uint64_t const& bcnum, BCs const& bcs, aod::FT0s const& ft0s, aod::FV0As const& fv0as, aod::FDDs const& fdds) + // function to update UDFwdTracks, UDFwdTracksExtra + template + void updateUDFwdTrackTables(TFwdTrack const& fwdtrack, uint64_t const& bcnum) { - // find bc with globalBC = bcnum - Partition selbc = aod::bc::globalBC == bcnum; - selbc.bindTable(bcs); - - // if BC exists then update FIT information for this BC - if (selbc.size() > 0) { - auto bc = selbc.begin(); - - // FT0 - if (bc.has_foundFT0()) { - auto ft0 = ft0s.iteratorAt(bc.foundFT0Id()); - info.timeFT0A = ft0.timeA(); - info.timeFT0C = ft0.timeC(); - const auto& ampsA = ft0.amplitudeA(); - const auto& ampsC = ft0.amplitudeC(); - info.ampFT0A = 0.; - for (auto amp : ampsA) { - info.ampFT0A += amp; - } - info.ampFT0C = 0.; - for (auto amp : ampsC) { - info.ampFT0C += amp; - } - info.triggerMaskFT0 = ft0.triggerMask(); - } - - // FV0A - if (bc.has_foundFV0()) { - auto fv0a = fv0as.iteratorAt(bc.foundFV0Id()); - info.timeFV0A = fv0a.time(); - const auto& amps = fv0a.amplitude(); - info.ampFV0A = 0.; - for (auto amp : amps) { - info.ampFV0A += amp; - } - info.triggerMaskFV0A = fv0a.triggerMask(); - } - - // FDD - if (bc.has_foundFDD()) { - auto fdd = fdds.iteratorAt(bc.foundFDDId()); - info.timeFDDA = fdd.timeA(); - info.timeFDDC = fdd.timeC(); - const auto& ampsA = fdd.chargeA(); - const auto& ampsC = fdd.chargeC(); - info.ampFDDA = 0.; - for (auto amp : ampsA) { - info.ampFDDA += amp; - } - info.ampFDDC = 0.; - for (auto amp : ampsC) { - info.ampFDDC += amp; - } - info.triggerMaskFDD = fdd.triggerMask(); - } - } - - // fill BG and BB flags in adjacent BCs [-16, 15] - // compute range to check - auto minbc = bcnum - 16; - auto maxbc = bcnum + 15; - Partition bcrange = aod::bc::globalBC >= minbc && aod::bc::globalBC <= maxbc; - bcrange.bindTable(bcs); - - // loop over bcrange and check - for (auto const& bc2u : bcrange) { - - // 0 <= bit <= 31 - auto bit = bc2u.globalBC() - minbc; - if (!bc2u.selection_bit(evsel::kNoBGT0A)) - SETBIT(info.BGFT0Apf, bit); - if (!bc2u.selection_bit(evsel::kNoBGT0C)) - SETBIT(info.BGFT0Cpf, bit); - if (bc2u.selection_bit(evsel::kIsBBT0A)) - SETBIT(info.BBFT0Apf, bit); - if (bc2u.selection_bit(evsel::kIsBBT0C)) - SETBIT(info.BBFT0Cpf, bit); - if (!bc2u.selection_bit(evsel::kNoBGV0A)) - SETBIT(info.BGFV0Apf, bit); - if (bc2u.selection_bit(evsel::kIsBBV0A)) - SETBIT(info.BBFV0Apf, bit); - if (!bc2u.selection_bit(evsel::kNoBGFDA)) - SETBIT(info.BGFDDApf, bit); - if (!bc2u.selection_bit(evsel::kNoBGFDC)) - SETBIT(info.BGFDDCpf, bit); - if (bc2u.selection_bit(evsel::kIsBBFDA)) - SETBIT(info.BBFDDApf, bit); - if (bc2u.selection_bit(evsel::kIsBBFDC)) - SETBIT(info.BBFDDCpf, bit); - } + outputFwdTracks(outputCollisions.lastIndex(), + fwdtrack.px(), fwdtrack.py(), fwdtrack.pz(), fwdtrack.sign(), + bcnum, fwdtrack.trackTime(), fwdtrack.trackTimeRes()); + outputFwdTracksExtra(fwdtrack.nClusters(), + fwdtrack.pDca(), + fwdtrack.rAtAbsorberEnd(), + fwdtrack.chi2(), + fwdtrack.chi2MatchMCHMID(), + fwdtrack.mchBitMap(), + fwdtrack.midBitMap(), + fwdtrack.midBoards()); } // function to update UDTracks, UDTracksCov, UDTracksDCA, UDTracksPID, UDTracksExtra, UDTracksFlag, // and UDTrackCollisionIDs template - void updateUDTrackTables(TTrack const& track, uint64_t const& bcnum) + void updateUDTrackTables(int64_t lastIndex, TTrack const& track, uint64_t const& bcnum) { - outputTracks(outputCollisions.lastIndex(), + outputTracks(lastIndex, track.px(), track.py(), track.pz(), track.sign(), bcnum, track.trackTime(), track.trackTimeRes()); @@ -198,6 +100,8 @@ struct DGCandProducer { track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), + track.betaerror(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), @@ -222,77 +126,24 @@ struct DGCandProducer { track.detectorMap()); outputTracksFlag(track.has_collision(), track.isPVContributor()); - LOGF(debug, " %d %d %d %f %f %f %f %f", - track.isPVContributor(), track.isQualityTrack(), track.isGlobalTrack(), track.px(), track.py(), track.pz(), track.pt(), track.p()); + outputTracksLabel(track.globalIndex()); } - // this function properly updates UDMcCollisions and UDMcParticles and returns the value - // deltaIndex, which is needed to correct the McParticles indices - // For a given McCollision all associated McParticles are saved - template - void updateMcUDTables(TMcCollision const& McCol, - TMcParticles const& McParts, - TBC const& mcbc, - int64_t& deltaIndex) + void init(InitContext&) { - // save McCol - outputMcCollisions(mcbc.globalBC(), - McCol.generatorsID(), - McCol.posX(), - McCol.posY(), - McCol.posZ(), - McCol.t(), - McCol.weight(), - McCol.impactParameter()); - - // save McParts - // calculate conversion from old indices to new indices - // old = mcpart.globalIndex() - // new = old + deltaIndex - // deltaIndex = [outputMcParticles.lastIndex() - McParts.iteratorAt(0).globalIndex() + 1] - deltaIndex = outputMcParticles.lastIndex() - McParts.iteratorAt(0).globalIndex() + 1; - LOGF(debug, " deltaIndex %i", deltaIndex); - - // new mother and daughter ids - std::vector newmids; - int32_t newdids[2] = {-1, -1}; - - // all particles of the McCollision are saved - for (auto mcpart : McParts) { - // correct mother and daughter IDs - newmids.clear(); - auto oldmids = mcpart.mothersIds(); - for (uint ii = 0; ii < oldmids.size(); ii++) { - auto newval = oldmids[ii] < 0 ? oldmids[ii] : oldmids[ii] + deltaIndex; - LOGF(debug, " mid %i / %i", oldmids[ii], newval); - newmids.push_back(newval); - } - auto olddids = mcpart.daughtersIds(); - for (uint ii = 0; ii < olddids.size(); ii++) { - auto newval = olddids[ii] < 0 ? olddids[ii] : olddids[ii] + deltaIndex; - LOGF(debug, " did %i / %i", olddids[ii], newval); - newdids[ii] = newval; - } - LOGF(debug, " ms %i ds %i", oldmids.size(), olddids.size()); + diffCuts = (DGCutparHolder)DGCuts; - // update UDMcParticles - outputMcParticles(outputMcCollisions.lastIndex(), - mcpart.pdgCode(), - mcpart.statusCode(), - mcpart.flags(), - newmids, - newdids, - mcpart.weight(), - mcpart.px(), - mcpart.py(), - mcpart.pz(), - mcpart.e()); - } + // add histograms for the different process functions + registry.add("reco/Stat", "Cut statistics; Selection criterion; Collisions", {HistType::kTH1F, {{14, -0.5, 13.5}}}); + registry.add("reco/pt1Vspt2", "2 prong events, p_{T} versus p_{T}", {HistType::kTH2F, {{100, -3., 3.}, {100, -3., 3.0}}}); + registry.add("reco/TPCsignal1", "2 prong events, TPC signal of particle 1", {HistType::kTH2F, {{200, -3., 3.}, {200, 0., 100.0}}}); + registry.add("reco/TPCsignal2", "2 prong events, TPC signal of particle 2", {HistType::kTH2F, {{200, -3., 3.}, {200, 0., 100.0}}}); + registry.add("reco/sig1VsSig2TPC", "2 prong events, TPC signal versus TPC signal", {HistType::kTH2F, {{100, 0., 100.}, {100, 0., 100.}}}); } // process function for real data - void processData(CC const& collision, BCs const& bcs, TCs& tracks, FWs& fwdtracks, - aod::Zdcs& zdcs, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) + void process(CC const& collision, BCs const& bcs, TCs& tracks, FWs& fwdtracks, + aod::Zdcs& zdcs, aod::FT0s& ft0s, aod::FV0As& fv0as, aod::FDDs& fdds) { LOGF(debug, " collision %d", collision.globalIndex()); // nominal BC @@ -310,12 +161,14 @@ struct DGCandProducer { auto isDGEvent = dgSelector.IsSelected(diffCuts, collision, bcRange, tracks, fwdtracks); // save DG candidates + registry.get(HIST("reco/Stat"))->Fill(0., 1.); + registry.get(HIST("reco/Stat"))->Fill(isDGEvent + 1, 1.); if (isDGEvent == 0) { LOGF(debug, " Data: good collision!"); // fill FITInfo upchelpers::FITInfo fitInfo{}; - getFITinfo(fitInfo, bc.globalBC(), bcs, ft0s, fv0as, fdds); + udhelpers::getFITinfo(fitInfo, bc.globalBC(), bcs, ft0s, fv0as, fdds); // update DG candidates tables auto rtrwTOF = udhelpers::rPVtrwTOF(tracks, collision.numContrib()); @@ -331,6 +184,18 @@ struct DGCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); + outputCollsLabels(collision.globalIndex()); + + // update DGTracks tables + for (auto& track : tracks) { + updateUDTrackTables(outputCollisions.lastIndex(), track, bc.globalBC()); + } + + // update DGFwdTracks tables + for (auto& fwdtrack : fwdtracks) { + updateUDFwdTrackTables(fwdtrack, bc.globalBC()); + } + // fill UDZdcs if (bc.has_zdc()) { auto zdc = bc.zdc(); @@ -342,12 +207,8 @@ struct DGCandProducer { outputZdcs(outputCollisions.lastIndex(), enes, chEs, amps, times, chTs); } - // update DGTracks tables - for (auto& track : tracks) { - updateUDTrackTables(track, bc.globalBC()); - } - // produce TPC signal histograms for 2-track events + LOGF(info, "DG candidate: number of PV tracks %d", collision.numContrib()); if (collision.numContrib() == 2) { auto cnt = 0; float pt1 = 0., pt2 = 0.; @@ -368,120 +229,251 @@ struct DGCandProducer { cnt, tr.isGlobalTrack(), tr.pt(), tr.itsNCls(), tr.tpcNClsCrossedRows(), tr.hasTRD(), tr.hasTOF()); } } - registry.get(HIST("pt1Vspt2"))->Fill(pt1, pt2); - registry.get(HIST("TPCsignal1"))->Fill(pt1, signalTPC1); - registry.get(HIST("TPCsignal2"))->Fill(pt2, signalTPC2); - registry.get(HIST("sig1VsSig2TPC"))->Fill(signalTPC1, signalTPC2); + registry.get(HIST("reco/pt1Vspt2"))->Fill(pt1, pt2); + registry.get(HIST("reco/TPCsignal1"))->Fill(pt1, signalTPC1); + registry.get(HIST("reco/TPCsignal2"))->Fill(pt2, signalTPC2); + registry.get(HIST("reco/sig1VsSig2TPC"))->Fill(signalTPC1, signalTPC2); } } } - PROCESS_SWITCH(DGCandProducer, processData, "Process real data", false); +}; - Preslice tracksPerCollision = aod::track::collisionId; - Preslice fwdTracksPerCollision = aod::fwdtrack::collisionId; +struct McDGCandProducer { + // MC tables + Produces outputMcCollisions; + Produces outputMcParticles; + Produces outputMcCollsLabels; + Produces outputMcTrackLabels; - // process function for MC data - void processMc(aod::McCollision const& McCol, - aod::McParticles const& McParts, - MCCCs const& collisions, - BCs const& bcs, - MCTCs const& tracks, - FWs const& fwdtracks, - aod::Zdcs const& zdcs, - aod::FT0s const& ft0s, - aod::FV0As const& fv0as, - aod::FDDs const& fdds) //) + using CCs = soa::Join; + using BCs = soa::Join; + using TCs = soa::Join; + using UDCCs = soa::Join; + using UDTCs = soa::Join; + + // prepare slices + SliceCache cache; + PresliceUnsorted mcPartsPerMcCollision = aod::mcparticle::mcCollisionId; + Preslice udtracksPerUDCollision = aod::udtrack::udCollisionId; + + // initialize histogram registry + HistogramRegistry registry{ + "registry", + {}}; + + // this function properly updates UDMcCollisions and UDMcParticles and returns the value + // deltaIndex, which is needed to correct the McParticles indices + // For a given McCollision all associated McParticles are saved + template + void updateMcUDTables(TMcCollision const& mccol, + TMcParticles const& McParts, + int64_t& deltaIndex) { - for (auto McPart : McParts) { - LOGF(debug, "McCol %i McPart %i", McCol.globalIndex(), McPart.globalIndex()); - } + // save mccol + outputMcCollisions(mccol.bcId(), + mccol.generatorsID(), + mccol.posX(), + mccol.posY(), + mccol.posZ(), + mccol.t(), + mccol.weight(), + mccol.impactParameter()); - // is this a central diffractive event? - // by default it is assumed to be a MB event - bool isPythiaDiff = udhelpers::isPythiaCDE(McParts); - bool isGraniittiDiff = udhelpers::isGraniittiCDE(McParts); - LOGF(debug, "mcCol %i type %i / %i / %i", (int)McCol.globalIndex(), !isPythiaDiff && !isGraniittiDiff, isPythiaDiff, isGraniittiDiff); - /* - // mctruth - int mctruth = -1; - if (isPythiaDiff) { - mctruth = 1; - } else if (isGraniittiDiff) { - mctruth = 2; - } - */ + // save McParts + // calculate conversion from old indices to new indices + // old = mcpart.globalIndex() + // new = old + deltaIndex + // deltaIndex = [outputMcParticles.lastIndex() - McParts.iteratorAt(0).globalIndex() + 1] + deltaIndex = outputMcParticles.lastIndex() - McParts.iteratorAt(0).globalIndex() + 1; + LOGF(debug, " deltaIndex (%d) = lastIndex (%d) - McPartsfirst (%d) + 1", deltaIndex, outputMcParticles.lastIndex(), McParts.iteratorAt(0).globalIndex()); - // MC BC - auto mcbc = McCol.bc_as(); + // new mother and daughter ids + std::vector newmids; + int32_t newdids[2] = {-1, -1}; - // save MCTruth of all diffractive events - bool mcColIsSaved = false; - int64_t deltaIndex = 0; - auto nMcParts0 = outputMcParticles.lastIndex(); - if (isPythiaDiff || isGraniittiDiff) { - // update tables UDMcCollisions and UDMcParticles - updateMcUDTables(McCol, McParts, mcbc, deltaIndex); - mcColIsSaved = true; - } + // all particles of the McCollision are saved + for (auto mcpart : McParts) { + // correct mother and daughter IDs + newmids.clear(); + auto oldmids = mcpart.mothersIds(); + for (uint ii = 0; ii < oldmids.size(); ii++) { + auto newval = oldmids[ii] < 0 ? oldmids[ii] : oldmids[ii] + deltaIndex; + LOGF(debug, " mid %i / %i", oldmids[ii], newval); + newmids.push_back(newval); + } + auto olddids = mcpart.daughtersIds(); + for (uint ii = 0; ii < olddids.size(); ii++) { + auto newval = olddids[ii] < 0 ? olddids[ii] : olddids[ii] + deltaIndex; + LOGF(debug, " did %i / %i", olddids[ii], newval); + newdids[ii] = newval; + } + LOGF(debug, " ms %i ds %i", oldmids.size(), olddids.size()); - // loop over all reconstructed collisions associated with McCol - for (auto collision : collisions) { - // get the tracks belonging to collision - auto collisionTracks = tracks.sliceBy(tracksPerCollision, collision.globalIndex()); - auto collisionFwdTracks = fwdtracks.sliceBy(fwdTracksPerCollision, collision.globalIndex()); - LOGF(debug, " tracks %i / %i", (int)collisionTracks.size(), collisionFwdTracks.size()); + // update UDMcParticles + outputMcParticles(outputMcCollisions.lastIndex(), + mcpart.pdgCode(), + mcpart.statusCode(), + mcpart.flags(), + newmids, + newdids, + mcpart.weight(), + mcpart.px(), + mcpart.py(), + mcpart.pz(), + mcpart.e()); + } + } - auto bc = collision.bc_as(); - LOGF(debug, " BC mc %i reco %i", mcbc.globalBC(), bc.globalBC()); + void init(InitContext& context) + { + // add histograms for the different process functions + if (context.mOptions.get("processMC")) { + registry.add("mcTruth/collisions", "Number of associated collisions", {HistType::kTH1F, {{11, -0.5, 10.5}}}); + registry.add("mcTruth/collType", "Collision type", {HistType::kTH1F, {{4, -0.5, 3.5}}}); + registry.add("mcTruth/IVMpt", "Invariant mass versus p_{T}", {HistType::kTH2F, {{150, 0.0, 3.0}, {150, 0.0, 3.0}}}); + } + } - // is this a collision to be saved? - // obtain slice of compatible BCs - auto bcRange = udhelpers::MCcompatibleBCs(collision, diffCuts.NDtcoll(), bcs, diffCuts.minNBCs()); + // process function for MC data + // save all GRANIITTI diffractive events and the MC truth of the DG events + void processMC(aod::McCollisions const& mccols, aod::McParticles const& mcparts, + UDCCs const& dgcands, UDTCs const& udtracks, + CCs const& collisions, BCs const& bcs, TCs const& tracks) + { - // apply DG selection - auto isDGEvent = dgSelector.IsSelected(diffCuts, collision, bcRange, collisionTracks, collisionFwdTracks); - LOGF(debug, " isDG %i", (int)isDGEvent); + // loop over McCollisions and UDCCs simultaneously + auto mccol = mccols.iteratorAt(0); + auto dgcand = dgcands.iteratorAt(0); + auto lastmccol = mccols.iteratorAt(mccols.size() - 1); + auto lastdgcand = dgcands.iteratorAt(dgcands.size() - 1); - // save information of DG events - if (isDGEvent == 0) { - LOGF(debug, " MC: good collision!"); + int64_t lastSaved = -1; + int64_t deltaIndex = 0; + int64_t firstIndex = 0, lastIndex = 0; + while (true) { + // determine the next dgcand with an associated collision + while (!dgcand.has_collision() && dgcand != lastdgcand) { + outputMcCollsLabels(-1); + dgcand++; + } + if (!dgcand.has_collision()) { + // no dgcand left + outputMcCollsLabels(-1); + break; + } - // update UDMcCollisions and UDMcParticles if not already done - if (!mcColIsSaved) { - updateMcUDTables(McCol, McParts, mcbc, deltaIndex); - mcColIsSaved = true; + // related mc truth + auto dgcandCol = dgcand.collision_as(); + if (!dgcandCol.has_mcCollision()) { + // this collision has no MC truth + outputMcCollsLabels(-1); + continue; + } + auto mcdg = dgcandCol.mcCollision(); + auto dgmcId = mcdg.globalIndex(); + + // save also all GRANIITTI diffractive events + // keep UD Mc sorted according to AOD Mc + auto mccolId = mccol.globalIndex(); + while (mccolId <= dgmcId) { + auto mcPartsSlice = mcparts.sliceBy(mcPartsPerMcCollision, mccol.globalIndex()); + bool isGraniittiDiff = udhelpers::isGraniittiCDE(mcPartsSlice); + bool isPythiaDiff = udhelpers::isPythiaCDE(mcPartsSlice); + registry.get(HIST("mcTruth/collType"))->Fill(0., 1.); + registry.get(HIST("mcTruth/collType"))->Fill(1., (!isPythiaDiff && !isGraniittiDiff) * 1.); + registry.get(HIST("mcTruth/collType"))->Fill(2., isPythiaDiff * 1.); + registry.get(HIST("mcTruth/collType"))->Fill(3., isGraniittiDiff * 1.); + + if (isGraniittiDiff || isPythiaDiff) { + firstIndex = outputMcParticles.lastIndex() + 1; + updateMcUDTables(mccol, mcPartsSlice, deltaIndex); + lastSaved = mccolId; + + auto ivm = udhelpers::ivmGraniittiCDE(mcPartsSlice); + registry.get(HIST("mcTruth/IVMpt"))->Fill(ivm.M(), ivm.Perp()); + } + if (mccol == lastmccol) { + break; } + mccol++; + mccolId = mccol.globalIndex(); + } + + // save the MC truth of the actual dgcand + // but check if this has not been added to the table yet + if (lastSaved != dgmcId) { + auto mcPartsSlice = mcparts.sliceBy(mcPartsPerMcCollision, mccol.globalIndex()); + firstIndex = outputMcParticles.lastIndex() + 1; + updateMcUDTables(mccol, mcPartsSlice, deltaIndex); + lastSaved = mccolId; - // UDCollisions - auto rtrwTOF = udhelpers::rPVtrwTOF(collisionTracks, collision.numContrib()); - outputCollisions(bc.globalBC(), bc.runNumber(), - collision.posX(), collision.posY(), collision.posZ(), - collision.numContrib(), udhelpers::netCharge(tracks), - rtrwTOF); - - // UDTracks, UDTrackCollisionID, UDTracksExtras, UDMcTrackLabels - for (auto& track : collisionTracks) { - // but save only the Primary Vertex tracks - updateUDTrackTables(track, bc.globalBC()); - - // properly correct the index into the UDMcParticles tables with deltaIndex - auto newval = track.mcParticleId() < 0 ? track.mcParticleId() : track.mcParticleId() + deltaIndex; - // only associations with McParticles belonging to the actual McCollision are supported - if ((newval < nMcParts0) || (newval > outputMcParticles.lastIndex())) { - LOGF(info, " UDMcParticles index out of range %i (%i - %i)", newval, nMcParts0 + 1, outputMcParticles.lastIndex()); - newval = -1; + auto ivm = udhelpers::ivmGraniittiCDE(mcPartsSlice); + registry.get(HIST("mcTruth/IVMpt"))->Fill(ivm.M(), ivm.Perp()); + } + outputMcCollsLabels(outputMcCollisions.lastIndex()); + + // save the mclabels of the related tracks into outputMcTrackLabels + lastIndex = outputMcParticles.lastIndex(); + auto colTracks = udtracks.sliceByCached(aod::udtrack::udCollisionId, dgcand.globalIndex(), cache); + for (auto colTrack : colTracks) { + // colTrack (UDTCs) -> track (TCs) -> mcTrack (McParticles) -> udMcTrack (UDMcParticles) + auto trackId = colTrack.trackId(); + if (trackId >= 0) { + auto track = colTrack.track_as(); + auto mcTrackId = track.mcParticleId(); + if (mcTrackId >= 0) { + auto udMcTrackId = mcTrackId + deltaIndex; + outputMcTrackLabels(udMcTrackId, track.mcMask()); + } else { + outputMcTrackLabels(-1, track.mcMask()); } - outputMcTrackLabels(newval, track.mcMask()); + } else { + outputMcTrackLabels(-1, -1); } } + + // next dg candidate + if (dgcand == lastdgcand) { + break; + } + dgcand++; + } + + // save remaining GRANIITTI diffractive events + while (mccol != lastmccol) { + auto mcPartsSlice = mcparts.sliceBy(mcPartsPerMcCollision, mccol.globalIndex()); + bool isGraniittiDiff = udhelpers::isGraniittiCDE(mcPartsSlice); + bool isPythiaDiff = udhelpers::isPythiaCDE(mcPartsSlice); + registry.get(HIST("mcTruth/collType"))->Fill(0., 1.); + registry.get(HIST("mcTruth/collType"))->Fill(1., (!isPythiaDiff && !isGraniittiDiff) * 1.); + registry.get(HIST("mcTruth/collType"))->Fill(2., isPythiaDiff * 1.); + registry.get(HIST("mcTruth/collType"))->Fill(3., isGraniittiDiff * 1.); + + if (isGraniittiDiff || isPythiaDiff) { + updateMcUDTables(mccol, mcPartsSlice, deltaIndex); + + // update IVM versus pT + auto ivm = udhelpers::ivmGraniittiCDE(mcPartsSlice); + registry.get(HIST("mcTruth/IVMpt"))->Fill(ivm.M(), ivm.Perp()); + } + mccol++; } } - PROCESS_SWITCH(DGCandProducer, processMc, "Process MC data", false); + PROCESS_SWITCH(McDGCandProducer, processMC, "Produce MC tables", false); + + void processDummy(aod::Collisions const& collisions) + { + // do nothing + LOGF(info, "Running dummy process function!"); + } + PROCESS_SWITCH(McDGCandProducer, processDummy, "Dummy function", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{ + WorkflowSpec workflow{ adaptAnalysisTask(cfgc, TaskName{"dgcandproducer"}), - }; + adaptAnalysisTask(cfgc, TaskName{"mcdgcandproducer"})}; + + return workflow; } diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index 7f7a8d76a41..20d6cdfd5cb 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -73,7 +73,8 @@ struct UpcCandProducer { using BarrelTracks = o2::soa::Join; + o2::aod::TOFSignal, o2::aod::pidTOFbeta, + o2::aod::pidTOFFullEl, o2::aod::pidTOFFullMu, o2::aod::pidTOFFullPi, o2::aod::pidTOFFullKa, o2::aod::pidTOFFullPr>; typedef std::pair> BCTracksPair; @@ -191,6 +192,8 @@ struct UpcCandProducer { // and calculate new MC table IDs for (int32_t mcPartID = 0; mcPartID < nMCParticles; mcPartID++) { const auto& mcPart = mcParticles.iteratorAt(mcPartID); + if (!mcPart.has_mcCollision()) + continue; int32_t mcEventID = mcPart.mcCollisionId(); const auto& mcEvent = mcCollisions.iteratorAt(mcEventID); bool isSignal = mcEvent.generatorsID() == fSignalGenID; @@ -302,6 +305,7 @@ struct UpcCandProducer { track.tpcNClsShared(), track.trdPattern(), track.itsChi2NCl(), track.tpcChi2NCl(), track.trdChi2(), track.tofChi2(), track.tpcSignal(), track.tofSignal(), track.trdSignal(), track.length(), track.tofExpMom(), track.detectorMap()); udTracksPID(track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.betaerror(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()); udTracksDCA(track.dcaZ(), track.dcaXY()); udTracksFlags(colId, track.isPVContributor()); @@ -350,24 +354,15 @@ struct UpcCandProducer { o2::aod::FDDs const& fdds, o2::aod::FV0As const& fv0as) { - const uint64_t range = 16; - uint64_t left = midbc >= range ? midbc - range : 0; - uint64_t right = fMaxBC >= midbc + range ? midbc + range : fMaxBC; - - std::pair dummyPair(left, 0); - auto curit = std::lower_bound(v.begin(), v.end(), dummyPair, - [](const std::pair& left, const std::pair& right) { return left.first < right.first; }); - - if (curit == v.end()) // no BCs with FT0 info at all - return; - - uint64_t curbc = curit->first; - while (curbc <= right) { - uint64_t bit = curbc - (midbc - range); - int64_t bcGlId = curit->second; - const auto& bc = bcs.iteratorAt(bcGlId); - if (bc.has_foundFT0()) { - const auto& ft0 = bc.foundFT0(); + auto it = std::find_if(v.begin(), + v.end(), + [midbc](const std::pair& p) { return p.first == midbc; }); + + if (it != v.end()) { + auto bcId = it->second; + auto bcEntry = bcs.iteratorAt(bcId); + if (bcEntry.has_foundFT0()) { + auto ft0 = bcEntry.foundFT0(); fitInfo.timeFT0A = ft0.timeA(); fitInfo.timeFT0C = ft0.timeC(); const auto& ampsA = ft0.amplitudeA(); @@ -379,30 +374,18 @@ struct UpcCandProducer { for (auto amp : ampsC) fitInfo.ampFT0C += amp; fitInfo.triggerMaskFT0 = ft0.triggerMask(); - if (!bc.selection_bit(evsel::kNoBGT0A)) - SETBIT(fitInfo.BGFT0Apf, bit); - if (!bc.selection_bit(evsel::kNoBGT0C)) - SETBIT(fitInfo.BGFT0Cpf, bit); - if (bc.selection_bit(evsel::kIsBBT0A)) - SETBIT(fitInfo.BBFT0Apf, bit); - if (bc.selection_bit(evsel::kIsBBT0C)) - SETBIT(fitInfo.BBFT0Cpf, bit); } - if (bc.has_foundFV0()) { - const auto& fv0a = bc.foundFV0(); + if (bcEntry.has_foundFV0()) { + auto fv0a = bcEntry.foundFV0(); fitInfo.timeFV0A = fv0a.time(); const auto& amps = fv0a.amplitude(); fitInfo.ampFV0A = 0.; for (auto amp : amps) fitInfo.ampFV0A += amp; fitInfo.triggerMaskFV0A = fv0a.triggerMask(); - if (!bc.selection_bit(evsel::kNoBGV0A)) - SETBIT(fitInfo.BGFV0Apf, bit); - if (bc.selection_bit(evsel::kIsBBV0A)) - SETBIT(fitInfo.BBFV0Apf, bit); } - if (bc.has_foundFDD()) { - const auto& fdd = bc.foundFDD(); + if (bcEntry.has_foundFDD()) { + auto fdd = bcEntry.foundFDD(); fitInfo.timeFDDA = fdd.timeA(); fitInfo.timeFDDC = fdd.timeC(); const auto& ampsA = fdd.chargeA(); @@ -416,15 +399,45 @@ struct UpcCandProducer { fitInfo.ampFDDC += amp; } fitInfo.triggerMaskFDD = fdd.triggerMask(); - if (!bc.selection_bit(evsel::kNoBGFDA)) - SETBIT(fitInfo.BGFDDApf, bit); - if (!bc.selection_bit(evsel::kNoBGFDC)) - SETBIT(fitInfo.BGFDDCpf, bit); - if (bc.selection_bit(evsel::kIsBBFDA)) - SETBIT(fitInfo.BBFDDApf, bit); - if (bc.selection_bit(evsel::kIsBBFDC)) - SETBIT(fitInfo.BBFDDCpf, bit); } + } + + const uint64_t range = 16; + uint64_t left = midbc >= range ? midbc - range : 0; + uint64_t right = fMaxBC >= midbc + range ? midbc + range : fMaxBC; + + std::pair dummyPair(left, 0); + auto curit = std::lower_bound(v.begin(), v.end(), dummyPair, + [](const std::pair& left, const std::pair& right) { return left.first < right.first; }); + + if (curit == v.end()) // no BCs with FT0 info at all + return; + + uint64_t curbc = curit->first; + while (curbc <= right) { + uint64_t bit = curbc - (midbc - range); + int64_t bcGlId = curit->second; + const auto& bc = bcs.iteratorAt(bcGlId); + if (!bc.selection_bit(o2::aod::evsel::kNoBGT0A)) + SETBIT(fitInfo.BGFT0Apf, bit); + if (!bc.selection_bit(o2::aod::evsel::kNoBGT0C)) + SETBIT(fitInfo.BGFT0Cpf, bit); + if (bc.selection_bit(o2::aod::evsel::kIsBBT0A)) + SETBIT(fitInfo.BBFT0Apf, bit); + if (bc.selection_bit(o2::aod::evsel::kIsBBT0C)) + SETBIT(fitInfo.BBFT0Cpf, bit); + if (!bc.selection_bit(o2::aod::evsel::kNoBGV0A)) + SETBIT(fitInfo.BGFV0Apf, bit); + if (bc.selection_bit(o2::aod::evsel::kIsBBV0A)) + SETBIT(fitInfo.BBFV0Apf, bit); + if (!bc.selection_bit(o2::aod::evsel::kNoBGFDA)) + SETBIT(fitInfo.BGFDDApf, bit); + if (!bc.selection_bit(o2::aod::evsel::kNoBGFDC)) + SETBIT(fitInfo.BGFDDCpf, bit); + if (bc.selection_bit(o2::aod::evsel::kIsBBFDA)) + SETBIT(fitInfo.BBFDDApf, bit); + if (bc.selection_bit(o2::aod::evsel::kIsBBFDC)) + SETBIT(fitInfo.BBFDDCpf, bit); ++curit; if (curit == v.end()) break; @@ -494,7 +507,7 @@ struct UpcCandProducer { } else { trackBC = ambIter->second; } - int64_t tint = std::round(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS); + int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS); uint64_t bc = trackBC + tint; if (bc > fMaxBC) continue; @@ -520,8 +533,15 @@ struct UpcCandProducer { std::unordered_map& ambFwdTrBCs) { for (const auto& trk : fwdTracks) { - if (trk.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) - continue; + if (upcCuts.getTrackType() != -1) { // need to filter by type ? + if (upcCuts.getTrackType() == 5) { // is MCH-MID or MCH ? + if (trk.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack && + trk.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MCHStandaloneTrack) + continue; + } + if (trk.trackType() != upcCuts.getTrackType()) // getTrackType < 5 -> check exact track type + continue; + } if (!applyFwdCuts(trk)) continue; int64_t trkId = trk.globalIndex(); @@ -535,10 +555,8 @@ struct UpcCandProducer { } else { trackBC = ambIter->second; } - int64_t tint = std::round(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS); + int64_t tint = TMath::FloorNint(trk.trackTime() / o2::constants::lhc::LHCBunchSpacingNS); uint64_t bc = trackBC + tint; - if (bc > fMaxBC) - continue; if (nContrib <= upcCuts.getMaxNContrib()) addTrack(bcsMatchedTrIdsMID, bc, trkId); } @@ -828,12 +846,13 @@ struct UpcCandProducer { uint32_t nMIDtracks = fwdTrackIDs.size(); uint32_t nBarrelTracks = barrelTrackIDs.size(); // TOF + ITS-TPC tracks uint16_t numContrib = nBarrelTracks + nMIDtracks; + uint64_t bc = pairMID.first; // sanity check - if (nBarrelTracks != fNBarProngs || nMIDtracks != fNFwdProngs) + if (nBarrelTracks != fNBarProngs || nMIDtracks != fNFwdProngs) { continue; + } // fetching FT0, FDD, FV0 information // if there is no relevant signal, dummy info will be used - uint64_t bc = pairMID.first; upchelpers::FITInfo fitInfo{}; processFITInfo(fitInfo, bc, indexBCglId, bcs, ft0s, fdds, fv0as); if (fFilterFT0) { @@ -852,7 +871,7 @@ struct UpcCandProducer { RgtrwTOF = RgtrwTOF / static_cast(numContrib); // store used tracks fillFwdTracks(fwdTracks, fwdTrackIDs, candID, bc, mcFwdTrackLabels); - fillBarrelTracks(barrelTracks, barrelTrackIDs, candID, bc, mcBarrelTrackLabels, ambFwdTrBCs); + fillBarrelTracks(barrelTracks, barrelTrackIDs, candID, bc, mcBarrelTrackLabels, ambBarrelTrBCs); eventCandidates(bc, runNumber, dummyX, dummyY, dummyZ, numContrib, netCharge, RgtrwTOF); eventCandidatesSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, fitInfo.triggerMaskFDD, @@ -870,6 +889,90 @@ struct UpcCandProducer { bcsMatchedTrIdsTOFTagged.clear(); } + void createCandidatesFwd(ForwardTracks const& fwdTracks, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + BCsWithBcSels const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FT0s const& ft0s, + o2::aod::FDDs const& fdds, + o2::aod::FV0As const& fv0as, + const o2::aod::McFwdTrackLabels* mcFwdTrackLabels) + { + fMaxBC = bcs.iteratorAt(bcs.size() - 1).globalBC(); // restrict ITS-TPC track search to [0, fMaxBC] + + // pairs of global BCs and vectors of matched track IDs: + std::vector bcsMatchedTrIdsMID; + + // trackID -> index in amb. track table + std::unordered_map ambFwdTrBCs; + collectAmbTrackBCs<1>(ambFwdTrBCs, ambFwdTracks); + + collectForwardTracks(bcsMatchedTrIdsMID, + bcs, collisions, + fwdTracks, ambFwdTracks, ambFwdTrBCs); + + uint32_t nBCsWithMID = bcsMatchedTrIdsMID.size(); + + std::sort(bcsMatchedTrIdsMID.begin(), bcsMatchedTrIdsMID.end(), + [](const auto& left, const auto& right) { return left.first < right.first; }); + + // todo: calculate position of UD collision? + float dummyX = 0.; + float dummyY = 0.; + float dummyZ = 0.; + + std::vector> indexBCglId; + indexBCglId.reserve(bcs.size()); + for (const auto& bc : bcs) { + if (bc.has_foundFT0() || bc.has_foundFV0() || bc.has_foundFDD()) + indexBCglId.emplace_back(std::make_pair(bc.globalBC(), bc.globalIndex())); + } + + int32_t runNumber = bcs.iteratorAt(0).runNumber(); + + // storing n-prong matches + int32_t candID = 0; + for (uint32_t ibc = 0; ibc < nBCsWithMID; ++ibc) { + auto& pairMID = bcsMatchedTrIdsMID[ibc]; + auto& fwdTrackIDs = pairMID.second; + uint32_t nMIDtracks = fwdTrackIDs.size(); + uint16_t numContrib = nMIDtracks; + uint64_t bc = pairMID.first; + // sanity check + if (nMIDtracks != fNFwdProngs) { + continue; + } + // fetching FT0, FDD, FV0 information + // if there is no relevant signal, dummy info will be used + upchelpers::FITInfo fitInfo{}; + processFITInfo(fitInfo, bc, indexBCglId, bcs, ft0s, fdds, fv0as); + if (fFilterFT0) { + if (!checkFT0(fitInfo, false)) + continue; + } + int8_t netCharge = 0; + float RgtrwTOF = 0.; + for (auto id : fwdTrackIDs) { + const auto& tr = fwdTracks.iteratorAt(id); + netCharge += tr.sign(); + } + // store used tracks + fillFwdTracks(fwdTracks, fwdTrackIDs, candID, bc, mcFwdTrackLabels); + eventCandidates(bc, runNumber, dummyX, dummyY, dummyZ, numContrib, netCharge, RgtrwTOF); + eventCandidatesSels(fitInfo.ampFT0A, fitInfo.ampFT0C, fitInfo.timeFT0A, fitInfo.timeFT0C, fitInfo.triggerMaskFT0, + fitInfo.ampFDDA, fitInfo.ampFDDC, fitInfo.timeFDDA, fitInfo.timeFDDC, fitInfo.triggerMaskFDD, + fitInfo.ampFV0A, fitInfo.timeFV0A, fitInfo.triggerMaskFV0A, + fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, + fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, + fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); + candID++; + } + + indexBCglId.clear(); + ambFwdTrBCs.clear(); + bcsMatchedTrIdsMID.clear(); + } + // data processors // _________________________________________________ @@ -958,10 +1061,47 @@ struct UpcCandProducer { fNewPartIDs.clear(); } + // create candidates for forward region + // forward: n fwd tracks + void processForward(ForwardTracks const& fwdTracks, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + BCsWithBcSels const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FT0s const& ft0s, + o2::aod::FDDs const& fdds, + o2::aod::FV0As const& fv0as) + { + fDoMC = false; + createCandidatesFwd(fwdTracks, ambFwdTracks, + bcs, collisions, + ft0s, fdds, fv0as, + (o2::aod::McFwdTrackLabels*)nullptr); + } + + void processForwardMC(ForwardTracks const& fwdTracks, + o2::aod::AmbiguousFwdTracks const& ambFwdTracks, + BCsWithBcSels const& bcs, + o2::aod::Collisions const& collisions, + o2::aod::FT0s const& ft0s, + o2::aod::FDDs const& fdds, + o2::aod::FV0As const& fv0as, + o2::aod::McCollisions const& mcCollisions, o2::aod::McParticles const& mcParticles, + o2::aod::McFwdTrackLabels const& mcFwdTrackLabels) + { + fDoMC = true; + skimMCInfo(mcCollisions, mcParticles, bcs); + createCandidatesFwd(fwdTracks, ambFwdTracks, + bcs, collisions, + ft0s, fdds, fv0as, + &mcFwdTrackLabels); + } + PROCESS_SWITCH(UpcCandProducer, processSemiFwd, "Produce candidates in semiforward/forward region", false); PROCESS_SWITCH(UpcCandProducer, processCentral, "Produce candidates in central region", false); PROCESS_SWITCH(UpcCandProducer, processSemiFwdMC, "Produce candidates in semiforward/forward region with MC information", false); PROCESS_SWITCH(UpcCandProducer, processCentralMC, "Produce candidates in central region with MC information", false); + PROCESS_SWITCH(UpcCandProducer, processForward, "Produce caniddates in forward region", false); + PROCESS_SWITCH(UpcCandProducer, processForwardMC, "Produce caniddates in forward region with MC information", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGUD/Tasks/DGCandAnalyzer.cxx b/PWGUD/Tasks/DGCandAnalyzer.cxx index 3c78763da70..8b328bd044d 100644 --- a/PWGUD/Tasks/DGCandAnalyzer.cxx +++ b/PWGUD/Tasks/DGCandAnalyzer.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// \brief Analyses reduced tables (DGCandidates, DGTracks) of DG candidates produced with DGCandProducer +// \brief Analyses UD tables (DGCandidates, DGTracks) of DG candidates produced with DGCandProducer // \author Paul Buehler, paul.buehler@oeaw.ac.at // \since 06.06.2022 @@ -23,7 +23,6 @@ #include "Common/DataModel/PIDResponse.h" #include "PWGUD/DataModel/UDTables.h" #include "PWGUD/Core/UDHelpers.h" -#include "PWGUD/Core/DGCutparHolder.h" #include "PWGUD/Core/DGPIDSelector.h" #include "PWGUD/Core/UDGoodRunSelector.h" @@ -45,7 +44,6 @@ struct DGCandAnalyzer { TDatabasePDG* pdg = nullptr; // get a DGCutparHolder and DGAnaparHolder - DGCutparHolder diffCuts = DGCutparHolder(); Configurable DGCuts{"DGCuts", {}, "DG event cuts"}; // analysis cuts @@ -70,14 +68,14 @@ struct DGCandAnalyzer { // define histograms HistogramRegistry registry{ "registry", - {{"nDGperRun", "Number of DG collisions per run", {HistType::kTH1D, {{1, 0, 1}}}}, - {"nIVMs", "Number of IVMs per DG collision", {HistType::kTH1F, {{36, -0.5, 35.5}}}}, - {"candCase", "#candCase", {HistType::kTH1F, {{5, -0.5, 4.5}}}}}}; + {}}; using UDCollisionsFull = soa::Join; using UDCollisionFull = UDCollisionsFull::iterator; - using UDTracksFull = soa::Join; + using UDTracksFull = soa::Join; + // using UDTracksFull = soa::Join; + // a function to fill 2Prong histograms template void fillSignalHists(DGParticle ivm, TTrack const& dgtracks, DGPIDSelector pidsel) { @@ -91,35 +89,35 @@ struct DGCandAnalyzer { auto m1 = particleMass(pdg, pidsel.getAnaPars().PIDs()[0]); auto ene1 = sqrt(pow(tr1.px(), 2.) + pow(tr1.py(), 2.) + pow(tr1.pz(), 2.) + m1); auto lv1 = TLorentzVector(tr1.px(), tr1.py(), tr1.pz(), ene1); - LOGF(debug, "pid1 %f mass %f energy %f", pidsel.getAnaPars().PIDs()[0], m1, ene1); auto signalTPC1 = tr1.tpcSignal(); - auto signalTOF1 = tr1.tofSignal() / 1.E6; + auto signalTOF1 = tr1.tofSignal() / 1.E4; auto tr2 = dgtracks.begin() + ivm.trkinds()[1]; auto m2 = particleMass(pdg, pidsel.getAnaPars().PIDs()[1]); auto ene2 = sqrt(pow(tr2.px(), 2.) + pow(tr2.py(), 2.) + pow(tr2.pz(), 2.) + m2); auto lv2 = TLorentzVector(tr2.px(), tr2.py(), tr2.pz(), ene2); - LOGF(debug, "pid2 %f mass %f energy %f", pidsel.getAnaPars().PIDs()[1], m2, ene2); auto signalTPC2 = tr2.tpcSignal(); - auto signalTOF2 = tr2.tofSignal() / 1.E6; + auto signalTOF2 = tr2.tofSignal() / 1.E4; - registry.get(HIST("TPCsignal1"))->Fill(tr1.tpcInnerParam(), signalTPC1); - registry.get(HIST("TPCsignal2"))->Fill(tr2.tpcInnerParam(), signalTPC2); - registry.get(HIST("sig1VsSig2TPC"))->Fill(signalTPC1, signalTPC2); - registry.get(HIST("eta1Vseta2"))->Fill(lv1.Eta(), lv2.Eta()); + LOGF(debug, "TOF signals %f %f", signalTOF1, signalTOF2); + + registry.fill(HIST("2Prong/TPCsignal1"), tr1.tpcInnerParam(), signalTPC1); + registry.fill(HIST("2Prong/TPCsignal2"), tr2.tpcInnerParam(), signalTPC2); + registry.fill(HIST("2Prong/sig1VsSig2TPC"), signalTPC1, signalTPC2); + registry.fill(HIST("2Prong/eta1Vseta2"), lv1.Eta(), lv2.Eta()); if (tr1.hasTOF()) { - registry.get(HIST("TOFsignal1"))->Fill(lv1.P(), signalTOF1); + registry.fill(HIST("2Prong/TOFsignal1"), lv1.P(), signalTOF1); } if (tr2.hasTOF()) { - registry.get(HIST("TOFsignal2"))->Fill(lv2.P(), signalTOF2); + registry.fill(HIST("2Prong/TOFsignal2"), lv2.P(), signalTOF2); } if (tr1.hasTOF() && tr2.hasTOF()) { - registry.get(HIST("sig1VsSig2TOF"))->Fill(signalTOF1, signalTOF2); + registry.fill(HIST("2Prong/sig1VsSig2TOF"), signalTOF1, signalTOF2); } } - void init(InitContext&) + void init(InitContext& context) { // initalise ccdb ccdb->setURL(o2::base::NameConf::getCCDBServer()); @@ -129,7 +127,6 @@ struct DGCandAnalyzer { // PDG pdg = TDatabasePDG::Instance(); - diffCuts = (DGCutparHolder)DGCuts; anaPars = (DGAnaparHolder)DGPars; pidsel.init(anaPars); grsel.init(goodRunsFile); @@ -142,63 +139,90 @@ struct DGCandAnalyzer { const AxisSpec axisIVM{IVMAxis, "IVM axis for histograms"}; const AxisSpec axispt{ptAxis, "pt axis for histograms"}; - registry.add("nSigmaTPCPEl", "#nSigmaTPCPEl", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); - registry.add("nSigmaTPCPPi", "#nSigmaTPCPPi", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); - registry.add("nSigmaTPCPMu", "#nSigmaTPCPMu", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); - registry.add("nSigmaTPCPKa", "#nSigmaTPCPKa", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); - registry.add("nSigmaTPCPPr", "#nSigmaTPCPPr", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); - - registry.add("trackQC", "#trackQC", {HistType::kTH1F, {{5, -0.5, 4.5}}}); - registry.add("dcaXYDG", "#dcaXYDG", {HistType::kTH1F, {{400, -2., 2.}}}); - registry.add("ptTrkdcaXYDG", "#ptTrkdcaXYDG", {HistType::kTH2F, {axispt, {80, -2., 2.}}}); - registry.add("dcaZDG", "#dcaZDG", {HistType::kTH1F, {{800, -20., 20.}}}); - registry.add("ptTrkdcaZDG", "#ptTrkdcaZDG", {HistType::kTH2F, {axispt, {400, -20., 20.}}}); - registry.add("IVMptSysDG", "#IVMptSysDG", {HistType::kTH2F, {axisIVM, axispt}}); - registry.add("IVMptTrkDG", "#IVMptTrkDG", {HistType::kTH2F, {axisIVM, axispt}}); - - const AxisSpec axisnsTOF{nsTOFAxis, "nSigma TOF axis for histograms"}; - registry.add("nSigmaTOFPEl", "#nSigmaTOFPEl", {HistType::kTH2F, {axispt, axisnsTOF}}); - registry.add("nSigmaTOFPPi", "#nSigmaTOFPPi", {HistType::kTH2F, {axispt, axisnsTOF}}); - registry.add("nSigmaTOFPMu", "#nSigmaTOFPMu", {HistType::kTH2F, {axispt, axisnsTOF}}); - registry.add("nSigmaTOFPKa", "#nSigmaTOFPKa", {HistType::kTH2F, {axispt, axisnsTOF}}); - registry.add("nSigmaTOFPPr", "#nSigmaTOFPPr", {HistType::kTH2F, {axispt, axisnsTOF}}); - - // FIT signals - registry.add("FT0AAmplitude", "#FT0AAmplitude", {HistType::kTH1F, {{5000, 0., 5000.}}}); - registry.add("FT0CAmplitude", "#FT0CAmplitude", {HistType::kTH1F, {{5000, 0., 5000.}}}); - registry.add("FV0AAmplitude", "#FV0AAmplitude", {HistType::kTH1F, {{5000, 0., 5000.}}}); - registry.add("FDDAAmplitude", "#FDDAAmplitude", {HistType::kTH1F, {{5000, 0., 5000.}}}); - registry.add("FDDCAmplitude", "#FDDCAmplitude", {HistType::kTH1F, {{5000, 0., 5000.}}}); - - registry.add("BBT0A", "#BBT0A", {HistType::kTH1F, {{32, -16.5, 15.5}}}); - registry.add("BBT0C", "#BBT0C", {HistType::kTH1F, {{32, -16.5, 15.5}}}); - registry.add("BBV0A", "#BBV0A", {HistType::kTH1F, {{32, -16.5, 15.5}}}); - registry.add("BBFDDA", "#BBFDDA", {HistType::kTH1F, {{32, -16.5, 15.5}}}); - registry.add("BBFDDC", "#BBFDDC", {HistType::kTH1F, {{32, -16.5, 15.5}}}); - - // 2 track events - registry.add("TPCChi2NCl1", "#TPCChi2NCl1", {HistType::kTH1F, {{200, 0., 50.}}}); - registry.add("TPCChi2NCl2", "#TPCChi2NCl2", {HistType::kTH1F, {{200, 0., 50.}}}); - registry.add("TPCsignal1", "#TPCsignal1", {HistType::kTH2F, {{1000, 0., 10.}, {500, 0., 500.}}}); - registry.add("TPCsignal2", "#TPCsignal2", {HistType::kTH2F, {{1000, 0., 10.}, {500, 0., 500.}}}); - registry.add("sig1VsSig2TPC", "#sig1VsSig2TPC", {HistType::kTH2F, {{300, 0., 300.}, {300, 0., 300.}}}); - registry.add("TOFsignal1", "#TOFsignal1", {HistType::kTH2F, {{1000, 0., 10.}, {400, -100., 100.}}}); - registry.add("TOFsignal2", "#TOFsignal2", {HistType::kTH2F, {{1000, 0., 10.}, {400, -100., 100.}}}); - registry.add("sig1VsSig2TOF", "#sig1VsSig2TOF", {HistType::kTH2F, {{160, -20., 60.}, {160, -20., 60.}}}); - registry.add("eta1Vseta2", "#eta1Vseta2", {HistType::kTH2F, {{200, -2.0, 2.0}, {200, -2.0, 2.0}}}); - registry.add("2Trackpt1pt2", "#2Trackpt1pt2", {HistType::kTH2F, {axispt, axispt}}); - registry.add("2Trackpt1eta1", "#2Trackpt1eta1", {HistType::kTH2F, {axispt, {200, -2.0, 2.0}}}); - registry.add("2Trackpt2eta2", "#2Trackpt2eta2", {HistType::kTH2F, {axispt, {200, -2.0, 2.0}}}); - registry.add("2TrackAngle", "#2TrackAngle", {HistType::kTH1F, {{140, -0.2, 3.3}}}); - registry.add("2TrackAngleIVM", "#2TrackAngleIVM", {HistType::kTH2F, {axisIVM, {140, -0.2, 3.3}}}); - registry.add("2Tracketa1IVM", "#2Tracketa1IVM", {HistType::kTH2F, {axisIVM, {160, -2.0, 2.0}}}); - registry.add("2Tracketa2IVM", "#2Tracketa2IVM", {HistType::kTH2F, {axisIVM, {160, -2.0, 2.0}}}); + + if (context.mOptions.get("processReco")) { + registry.add("stat/candCaseAll", "Types of all DG candidates", {HistType::kTH1F, {{5, -0.5, 4.5}}}); + registry.add("stat/candCaseSel", "Types of all selectedDG candidates", {HistType::kTH1F, {{5, -0.5, 4.5}}}); + registry.add("stat/nDGperRun", "Number of DG collisions per run", {HistType::kTH1D, {{1, 0, 1}}}); + + registry.add("tracks/nSigmaTPCPEl", "nSigma TPC for electrons", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); + registry.add("tracks/nSigmaTPCPPi", "nSigma TPC for pions", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); + registry.add("tracks/nSigmaTPCPMu", "nSigma TPC for muons", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); + registry.add("tracks/nSigmaTPCPKa", "nSigma TPC for kaons", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); + registry.add("tracks/nSigmaTPCPPr", "nSigma TPC for protons", {HistType::kTH2F, {axispt, {100, -20.0, 20.0}}}); + + const AxisSpec axisnsTOF{nsTOFAxis, "nSigma TOF axis for histograms"}; + registry.add("tracks/nSigmaTOFPEl", "nSigma TOF for electrons versus pT", {HistType::kTH2F, {axispt, axisnsTOF}}); + registry.add("tracks/nSigmaTOFPPi", "nSigma TOF for pions versus pT", {HistType::kTH2F, {axispt, axisnsTOF}}); + registry.add("tracks/nSigmaTOFPMu", "nSigma TOF for muons versus pT", {HistType::kTH2F, {axispt, axisnsTOF}}); + registry.add("tracks/nSigmaTOFPKa", "nSigma TOF for kaons versus pT", {HistType::kTH2F, {axispt, axisnsTOF}}); + registry.add("tracks/nSigmaTOFPPr", "nSigma TOF for protons versus pT", {HistType::kTH2F, {axispt, axisnsTOF}}); + + registry.add("tracks/trackHits", "Track hits in various detectors", {HistType::kTH1F, {{5, -0.5, 4.5}}}); + registry.add("tracks/dcaXYDG", "dcaXY in DG candidates", {HistType::kTH1F, {{200, -0.5, 0.5}}}); + registry.add("tracks/dcaZDG", "dcaZ in DG candidates", {HistType::kTH1F, {{400, -2., 2.}}}); + registry.add("tracks/TPCNCl", "Number of found TPC clusters", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("tracks/TPCChi2NCl", "TPC chi2 per cluster of tracks", {HistType::kTH1F, {{200, 0., 50.}}}); + registry.add("tracks/ptTrkdcaXYDG", "dcaXY versus track pT in DG candidates", {HistType::kTH2F, {axispt, {100, -0.5, 0.5}}}); + registry.add("tracks/ptTrkdcaZDG", "dcaZ versus track pT in DG candidates", {HistType::kTH2F, {axispt, {200, -2., 2.}}}); + + registry.add("system/nUnlikeIVMs", "Number of IVMs per DG collision", {HistType::kTH1F, {{36, -0.5, 35.5}}}); + registry.add("system/unlikeIVMptSysDG", "Invariant mass versus system pT in DG candidates", {HistType::kTH2F, {axisIVM, axispt}}); + registry.add("system/unlikeIVMptTrkDG", "Invariant mass versus track pT in DG candidates", {HistType::kTH2F, {axisIVM, axispt}}); + registry.add("system/nLikeIVMs", "Number of IVMs per DG collision", {HistType::kTH1F, {{36, -0.5, 35.5}}}); + registry.add("system/likeIVMptSysDG", "Invariant mass versus system pT in DG candidates", {HistType::kTH2F, {axisIVM, axispt}}); + registry.add("system/likeIVMptTrkDG", "Invariant mass versus track pT in DG candidates", {HistType::kTH2F, {axisIVM, axispt}}); + + // FIT signals + registry.add("FIT/FT0AAmplitude", "Total amplitude in FV0A", {HistType::kTH1F, {{5000, 0., 5000.}}}); + registry.add("FIT/FT0CAmplitude", "Total amplitude in FT0A", {HistType::kTH1F, {{5000, 0., 5000.}}}); + registry.add("FIT/FV0AAmplitude", "Total amplitude in FT0C", {HistType::kTH1F, {{5000, 0., 5000.}}}); + registry.add("FIT/FDDAAmplitude", "Total amplitude in FDDA", {HistType::kTH1F, {{5000, 0., 5000.}}}); + registry.add("FIT/FDDCAmplitude", "Total amplitude in FDDC", {HistType::kTH1F, {{5000, 0., 5000.}}}); + + registry.add("FIT/BBFV0A", "FV0A signal in neighbouring BCs", {HistType::kTH1F, {{32, -16.5, 15.5}}}); + registry.add("FIT/BBFT0A", "FT0A signal in neighbouring BCs", {HistType::kTH1F, {{32, -16.5, 15.5}}}); + registry.add("FIT/BBFT0C", "FT0C signal in neighbouring BCs", {HistType::kTH1F, {{32, -16.5, 15.5}}}); + registry.add("FIT/BBFDDA", "FDDA signal in neighbouring BCs", {HistType::kTH1F, {{32, -16.5, 15.5}}}); + registry.add("FIT/BBFDDC", "FDDC signal in neighbouring BCs", {HistType::kTH1F, {{32, -16.5, 15.5}}}); + + // 2 track events + registry.add("2Prong/TPCNCl1", "Number of found TPC clusters of track 1", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("2Prong/TPCNCl2", "Number of found TPC clusters of track 2", {HistType::kTH1F, {{200, 0., 200.}}}); + registry.add("2Prong/TPCChi2NCl1", "TPC chi2 of track 1", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add("2Prong/TPCChi2NCl2", "TPC chi2 of track 2", {HistType::kTH1F, {{1000, 0., 10.}}}); + registry.add("2Prong/TPCsignal1", "TPC signal of track 1", {HistType::kTH2F, {{1000, 0., 10.}, {5000, 0., 500.}}}); + registry.add("2Prong/TPCsignal2", "TPC signal of track 2", {HistType::kTH2F, {{1000, 0., 10.}, {5000, 0., 500.}}}); + registry.add("2Prong/sig1VsSig2TPC", "TPC signals of track 1 versus track 2", {HistType::kTH2F, {{300, 0., 150.}, {300, 0., 150.}}}); + registry.add("2Prong/TOFsignal1", "TOF signal of track 1", {HistType::kTH2F, {{1000, 0., 10.}, {2000, -5., 5.}}}); + registry.add("2Prong/TOFsignal2", "TOF signal of track 2", {HistType::kTH2F, {{1000, 0., 10.}, {2000, -5., 5.}}}); + registry.add("2Prong/sig1VsSig2TOF", "TOF signals of track 1 versus track 2", {HistType::kTH2F, {{1000, -5., 5.}, {1000, -5., 5.}}}); + registry.add("2Prong/eta1Vseta2", "etas of track 1 versus track 2", {HistType::kTH2F, {{200, -2.0, 2.0}, {200, -2.0, 2.0}}}); + registry.add("2Prong/pt1pt2", "pTs of track 1 versus track 2", {HistType::kTH2F, {axispt, axispt}}); + registry.add("2Prong/pt1eta1", "pT versus eta of track 1", {HistType::kTH2F, {axispt, {200, -2.0, 2.0}}}); + registry.add("2Prong/pt2eta2", "pT versus eta of track 2", {HistType::kTH2F, {axispt, {200, -2.0, 2.0}}}); + registry.add("2Prong/Angle", "Angle between both tracks", {HistType::kTH1F, {{175, -0.2, 3.3}}}); + registry.add("2Prong/AngleIVM", "Angle versis invariant mass", {HistType::kTH2F, {axisIVM, {175, -0.2, 3.3}}}); + registry.add("2Prong/pt1IVM", "pT of track 1 versus invariant mass", {HistType::kTH2F, {axisIVM, axispt}}); + registry.add("2Prong/pt2IVM", "pT of track 2 versus invariant mass", {HistType::kTH2F, {axisIVM, axispt}}); + registry.add("2Prong/eta1IVM", "eta of track 1 versus invariant mass", {HistType::kTH2F, {axisIVM, {200, -2.0, 2.0}}}); + registry.add("2Prong/eta2IVM", "eta of track 2 versus invariant mass", {HistType::kTH2F, {axisIVM, {200, -2.0, 2.0}}}); + registry.add("2Prong/chi2NCl1IVM", "TPC chi2 of track 1 versus invariant mass", {HistType::kTH2F, {axisIVM, {200, 0, 2.0}}}); + registry.add("2Prong/chi2NCl2IVM", "TPC chi2 of track 2 versus invariant mass", {HistType::kTH2F, {axisIVM, {200, 0, 2.0}}}); + registry.add("2Prong/NCl1IVM", "Number of found TPC clusters of track 1 versus invariant mass", {HistType::kTH2F, {axisIVM, {200, 0, 200.}}}); + registry.add("2Prong/NCl2IVM", "Number of found TPC clusters of track 2 versus invariant mass", {HistType::kTH2F, {axisIVM, {200, 0, 200.}}}); + } + + if (context.mOptions.get("processMcTruth")) { + registry.add("mcTruth/collType", "Collision type", {HistType::kTH1F, {{4, -0.5, 3.5}}}); + registry.add("mcTruth/IVMpt", "Invariant mass versus p_{T}", {HistType::kTH2F, {axisIVM, axispt}}); + } } - void process(UDCollisionFull const& dgcand, UDTracksFull const& dgtracks) + void processReco(UDCollisionFull const& dgcand, UDTracksFull const& dgtracks) { // count collisions - registry.get(HIST("candCase"))->Fill(0., 1.); + registry.fill(HIST("stat/candCaseAll"), 0., 1.); // accept only selected run numbers int run = dgcand.runNumber(); @@ -237,6 +261,14 @@ struct DGCandAnalyzer { if (candCaseSel > 0 && candCase != candCaseSel) { return; } + registry.fill(HIST("stat/candCaseAll"), candCase, 1.); + + // fill FIT amplitude histograms + registry.fill(HIST("FIT/FT0AAmplitude"), dgcand.totalFT0AmplitudeA(), 1.); + registry.fill(HIST("FIT/FT0CAmplitude"), dgcand.totalFT0AmplitudeC(), 1.); + registry.fill(HIST("FIT/FV0AAmplitude"), dgcand.totalFV0AmplitudeA(), 1.); + registry.fill(HIST("FIT/FDDAAmplitude"), dgcand.totalFDDAmplitudeA(), 1.); + registry.fill(HIST("FIT/FDDCAmplitude"), dgcand.totalFDDAmplitudeC(), 1.); // skip events with too few/many tracks Partition PVContributors = aod::udtrack::isPVContributor == true; @@ -244,13 +276,13 @@ struct DGCandAnalyzer { if (dgcand.numContrib() != PVContributors.size()) { LOGF(info, "Missmatch of PVContributors %d != %d", dgcand.numContrib(), PVContributors.size()); } - if (dgcand.numContrib() < diffCuts.minNTracks() || dgcand.numContrib() > diffCuts.maxNTracks()) { - LOGF(debug, "Rejected 1: %d not in range [%d, %d].", dgcand.numContrib(), diffCuts.minNTracks(), diffCuts.maxNTracks()); + if (dgcand.numContrib() < anaPars.minNTracks() || dgcand.numContrib() > anaPars.maxNTracks()) { + LOGF(debug, "Rejected 1: %d not in range [%d, %d].", dgcand.numContrib(), anaPars.minNTracks(), anaPars.maxNTracks()); return; } // skip events with out-of-range net charge - auto netChargeValues = diffCuts.netCharges(); + auto netChargeValues = anaPars.netCharges(); if (std::find(netChargeValues.begin(), netChargeValues.end(), dgcand.netCharge()) == netChargeValues.end()) { LOGF(debug, "Rejected 2: %d not in set.", dgcand.netCharge()); return; @@ -258,7 +290,7 @@ struct DGCandAnalyzer { // skip events with out-of-range rgtrwTOF auto rtrwTOF = udhelpers::rPVtrwTOF(dgtracks, PVContributors.size()); - auto minRgtrwTOF = candCase != 1 ? 1.0 : diffCuts.minRgtrwTOF(); + auto minRgtrwTOF = candCase != 1 ? 1.0 : anaPars.minRgtrwTOF(); if (rtrwTOF < minRgtrwTOF) { LOGF(debug, "Rejected 3: %f below threshold of %f.", rtrwTOF, minRgtrwTOF); return; @@ -268,56 +300,52 @@ struct DGCandAnalyzer { auto bitMin = anaPars.dBCMin() + 16; auto bitMax = anaPars.dBCMax() + 16; for (auto bit = bitMin; bit <= bitMax; bit++) { - if (TESTBIT(dgcand.bbFT0Apf(), bit) || - TESTBIT(dgcand.bbFT0Cpf(), bit) || - TESTBIT(dgcand.bbFV0Apf(), bit) || - TESTBIT(dgcand.bbFDDApf(), bit) || - TESTBIT(dgcand.bbFDDCpf(), bit)) { + if (anaPars.FITvetoes()[0] && TESTBIT(dgcand.bbFV0Apf(), bit)) + return; + if (anaPars.FITvetoes()[1] && TESTBIT(dgcand.bbFT0Apf(), bit)) + return; + if (anaPars.FITvetoes()[2] && TESTBIT(dgcand.bbFT0Cpf(), bit)) + return; + if (anaPars.FITvetoes()[3] && TESTBIT(dgcand.bbFDDApf(), bit)) + return; + if (anaPars.FITvetoes()[4] && TESTBIT(dgcand.bbFDDCpf(), bit)) return; - } } - // fill FIT amplitude histograms - registry.get(HIST("FT0AAmplitude"))->Fill(dgcand.totalFT0AmplitudeA(), 1.); - registry.get(HIST("FT0CAmplitude"))->Fill(dgcand.totalFT0AmplitudeC(), 1.); - registry.get(HIST("FV0AAmplitude"))->Fill(dgcand.totalFV0AmplitudeA(), 1.); - registry.get(HIST("FDDAAmplitude"))->Fill(dgcand.totalFDDAmplitudeA(), 1.); - registry.get(HIST("FDDCAmplitude"))->Fill(dgcand.totalFDDAmplitudeC(), 1.); - // fill BBFlag histograms for (auto bit = 0; bit < 33; bit++) { - registry.get(HIST("BBT0A"))->Fill(bit - 16, TESTBIT(dgcand.bbFT0Apf(), bit)); - registry.get(HIST("BBT0C"))->Fill(bit - 16, TESTBIT(dgcand.bbFT0Cpf(), bit)); - registry.get(HIST("BBV0A"))->Fill(bit - 16, TESTBIT(dgcand.bbFV0Apf(), bit)); - registry.get(HIST("BBFDDA"))->Fill(bit - 16, TESTBIT(dgcand.bbFDDApf(), bit)); - registry.get(HIST("BBFDDC"))->Fill(bit - 16, TESTBIT(dgcand.bbFDDCpf(), bit)); + registry.fill(HIST("FIT/BBFV0A"), bit - 16, TESTBIT(dgcand.bbFV0Apf(), bit)); + registry.fill(HIST("FIT/BBFT0A"), bit - 16, TESTBIT(dgcand.bbFT0Apf(), bit)); + registry.fill(HIST("FIT/BBFT0C"), bit - 16, TESTBIT(dgcand.bbFT0Cpf(), bit)); + registry.fill(HIST("FIT/BBFDDA"), bit - 16, TESTBIT(dgcand.bbFDDApf(), bit)); + registry.fill(HIST("FIT/BBFDDC"), bit - 16, TESTBIT(dgcand.bbFDDCpf(), bit)); } // find track combinations which are compatible with PID cuts auto nIVMs = pidsel.computeIVMs(PVContributors); - LOGF(debug, "Number of IVMs %d", nIVMs); - - // update candCase histogram - if (nIVMs > 0) { - registry.get(HIST("candCase"))->Fill(candCase, 1.); - // check bcnum - if (bcnums.find(bcnum) != bcnums.end()) { - LOGF(info, "candCase %i bcnum %i allready found! ", candCase, bcnum); - registry.get(HIST("candCase"))->Fill(4, 1.); - return; - } else { - bcnums.insert(bcnum); - } - // update histogram nDGperRun - registry.get(HIST("nDGperRun"))->Fill(Form("%d", run), 1.); - } else { + // process the unlike sign combinations + if (nIVMs[0] == 0 && nIVMs[1] == 0) { LOGF(debug, "Rejected 4: no IVMs."); + return; + } + + // update histogram stat/candCase and stat/nDGperRun + registry.fill(HIST("stat/candCaseSel"), 0, 1.); + registry.fill(HIST("stat/candCaseSel"), candCase, 1.); + + // check bcnum + if (bcnums.find(bcnum) != bcnums.end()) { + LOGF(info, "candCase %d bcnum %d allready found! ", candCase, bcnum); + registry.fill(HIST("stat/candCaseSel"), 4, 1.); + } else { + bcnums.insert(bcnum); } + registry.get(HIST("stat/nDGperRun"))->Fill(Form("%d", run), 1); // update histograms - registry.get(HIST("nIVMs"))->Fill(nIVMs, 1.); - for (auto ivm : pidsel.IVMs()) { + int goodIVMs = 0; + for (auto ivm : pidsel.unlikeIVMs()) { // cut on pt-system if (ivm.Perp() < anaPars.minptsys() || ivm.Perp() > anaPars.maxptsys()) { continue; @@ -337,70 +365,161 @@ struct DGCandAnalyzer { LOGF(debug, "angle %f (%f / %f)", angle, anaPars.minAlpha(), anaPars.maxAlpha()); if (angle < anaPars.minAlpha() || angle > anaPars.maxAlpha()) { continue; - } else { - registry.get(HIST("2TrackAngle"))->Fill(angle, 1.); - registry.get(HIST("2TrackAngleIVM"))->Fill(ivm.M(), angle, 1.); } - registry.get(HIST("TPCChi2NCl1"))->Fill(trk1.tpcChi2NCl(), 1.); - registry.get(HIST("TPCChi2NCl2"))->Fill(trk2.tpcChi2NCl(), 1.); - registry.get(HIST("2Trackpt1eta1"))->Fill(trk1.pt(), v1.Eta(), 1.); - registry.get(HIST("2Trackpt2eta2"))->Fill(trk2.pt(), v2.Eta(), 1.); - registry.get(HIST("2Trackpt1pt2"))->Fill(trk1.pt(), trk2.pt(), 1.); - registry.get(HIST("2Tracketa1IVM"))->Fill(ivm.M(), v1.Eta(), 1.); - registry.get(HIST("2Tracketa2IVM"))->Fill(ivm.M(), v2.Eta(), 1.); + // update 2Prong histograms + registry.fill(HIST("2Prong/Angle"), angle, 1.); + registry.fill(HIST("2Prong/AngleIVM"), ivm.M(), angle, 1.); + + registry.fill(HIST("2Prong/TPCChi2NCl1"), trk1.tpcChi2NCl(), 1.); + registry.fill(HIST("2Prong/TPCChi2NCl2"), trk2.tpcChi2NCl(), 1.); + registry.fill(HIST("2Prong/pt1eta1"), trk1.pt(), v1.Eta(), 1.); + registry.fill(HIST("2Prong/pt2eta2"), trk2.pt(), v2.Eta(), 1.); + registry.fill(HIST("2Prong/pt1pt2"), trk1.pt(), trk2.pt(), 1.); + registry.fill(HIST("2Prong/pt1IVM"), ivm.M(), trk1.pt(), 1.); + registry.fill(HIST("2Prong/pt2IVM"), ivm.M(), trk2.pt(), 1.); + registry.fill(HIST("2Prong/eta1IVM"), ivm.M(), v1.Eta(), 1.); + registry.fill(HIST("2Prong/eta2IVM"), ivm.M(), v2.Eta(), 1.); + registry.fill(HIST("2Prong/chi2NCl1IVM"), ivm.M(), trk1.tpcChi2NCl(), 1.); + registry.fill(HIST("2Prong/chi2NCl2IVM"), ivm.M(), trk2.tpcChi2NCl(), 1.); + + auto nTPCCL = trk1.tpcNClsFindable() - trk1.tpcNClsFindableMinusFound(); + registry.fill(HIST("2Prong/TPCNCl1"), nTPCCL, 1.); + registry.fill(HIST("2Prong/NCl1IVM"), ivm.M(), nTPCCL, 1.); + nTPCCL = trk2.tpcNClsFindable() - trk2.tpcNClsFindableMinusFound(); + registry.fill(HIST("2Prong/TPCNCl2"), nTPCCL, 1.); + registry.fill(HIST("2Prong/NCl2IVM"), ivm.M(), nTPCCL, 1.); + + fillSignalHists(ivm, PVContributors, pidsel); } - registry.get(HIST("IVMptSysDG"))->Fill(ivm.M(), ivm.Perp()); + // update system/IVMptSysDG + registry.fill(HIST("system/unlikeIVMptSysDG"), ivm.M(), ivm.Perp()); for (auto ind : ivm.trkinds()) { auto track = PVContributors.begin() + ind; - registry.get(HIST("trackQC"))->Fill(0., 1.); - registry.get(HIST("trackQC"))->Fill(1., track.hasITS() * 1.); - registry.get(HIST("trackQC"))->Fill(2., track.hasTPC() * 1.); - registry.get(HIST("trackQC"))->Fill(3., track.hasTRD() * 1.); - registry.get(HIST("trackQC"))->Fill(4., track.hasTOF() * 1.); - - // registry.get(HIST("dcaXYDG"))->Fill(track.dcaXY()); - // registry.get(HIST("ptTrkdcaXYDG"))->Fill(track.pt(), track.dcaXY()); - // registry.get(HIST("dcaZDG"))->Fill(track.dcaZ()); - // registry.get(HIST("ptTrkdcaZDG"))->Fill(track.pt(), track.dcaZ()); + registry.fill(HIST("system/unlikeIVMptTrkDG"), ivm.M(), track.pt()); + } + goodIVMs++; + } - registry.get(HIST("IVMptTrkDG"))->Fill(ivm.M(), track.pt()); + // fill histograms with PV track information of collisions with DG candidates + registry.fill(HIST("system/nUnlikeIVMs"), goodIVMs, 1.); + if (goodIVMs > 0) { + + // loop over PV tracks and update histograms + for (auto track : PVContributors) { + registry.fill(HIST("tracks/trackHits"), 0., 1.); + registry.fill(HIST("tracks/trackHits"), 1., track.hasITS() * 1.); + registry.fill(HIST("tracks/trackHits"), 2., track.hasTPC() * 1.); + registry.fill(HIST("tracks/trackHits"), 3., track.hasTRD() * 1.); + registry.fill(HIST("tracks/trackHits"), 4., track.hasTOF() * 1.); + + registry.fill(HIST("tracks/dcaXYDG"), track.dcaXY()); + registry.fill(HIST("tracks/ptTrkdcaXYDG"), track.pt(), track.dcaXY()); + registry.fill(HIST("tracks/dcaZDG"), track.dcaZ()); + registry.fill(HIST("tracks/ptTrkdcaZDG"), track.pt(), track.dcaZ()); + registry.fill(HIST("tracks/TPCNCl"), track.tpcNClsFindable() - track.tpcNClsFindableMinusFound(), 1.); + registry.fill(HIST("tracks/TPCChi2NCl"), track.tpcChi2NCl(), 1.); // fill nSigma histograms /* auto mom = sqrt(pow(track.px(), 2) + pow(track.py(), 2) + pow(track.pz(), 2)); - registry.get(HIST("nSigmaTPCPEl"))->Fill(track.tpcInnerParam(), track.tpcNSigmaEl()); - registry.get(HIST("nSigmaTPCPPi"))->Fill(track.tpcInnerParam(), track.tpcNSigmaPi()); - registry.get(HIST("nSigmaTPCPMu"))->Fill(track.tpcInnerParam(), track.tpcNSigmaMu()); - registry.get(HIST("nSigmaTPCPKa"))->Fill(track.tpcInnerParam(), track.tpcNSigmaKa()); - registry.get(HIST("nSigmaTPCPPr"))->Fill(track.tpcInnerParam(), track.tpcNSigmaPr()); + registry.fill(HIST("tracks/nSigmaTPCPEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); + registry.fill(HIST("tracks/nSigmaTPCPPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); + registry.fill(HIST("tracks/nSigmaTPCPMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + registry.fill(HIST("tracks/nSigmaTPCPKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); + registry.fill(HIST("tracks/nSigmaTPCPPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); */ - registry.get(HIST("nSigmaTPCPEl"))->Fill(track.pt(), track.tpcNSigmaEl()); - registry.get(HIST("nSigmaTPCPPi"))->Fill(track.pt(), track.tpcNSigmaPi()); - registry.get(HIST("nSigmaTPCPMu"))->Fill(track.pt(), track.tpcNSigmaMu()); - registry.get(HIST("nSigmaTPCPKa"))->Fill(track.pt(), track.tpcNSigmaKa()); - registry.get(HIST("nSigmaTPCPPr"))->Fill(track.pt(), track.tpcNSigmaPr()); + registry.fill(HIST("tracks/nSigmaTPCPEl"), track.pt(), track.tpcNSigmaEl()); + registry.fill(HIST("tracks/nSigmaTPCPPi"), track.pt(), track.tpcNSigmaPi()); + registry.fill(HIST("tracks/nSigmaTPCPMu"), track.pt(), track.tpcNSigmaMu()); + registry.fill(HIST("tracks/nSigmaTPCPKa"), track.pt(), track.tpcNSigmaKa()); + registry.fill(HIST("tracks/nSigmaTPCPPr"), track.pt(), track.tpcNSigmaPr()); if (track.hasTOF()) { LOGF(debug, "tofNSigmaPi %f", track.tofNSigmaPi()); /* - registry.get(HIST("nSigmaTOFPEl"))->Fill(mom, track.tofNSigmaEl()); - registry.get(HIST("nSigmaTOFPPi"))->Fill(mom, track.tofNSigmaPi()); - registry.get(HIST("nSigmaTOFPMu"))->Fill(mom, track.tofNSigmaMu()); - registry.get(HIST("nSigmaTOFPKa"))->Fill(mom, track.tofNSigmaKa()); - registry.get(HIST("nSigmaTOFPPr"))->Fill(mom, track.tofNSigmaPr()); + registry.fill(HIST("nSigmaTOFPEl"), mom, track.tofNSigmaEl()); + registry.fill(HIST("nSigmaTOFPPi"), mom, track.tofNSigmaPi()); + registry.fill(HIST("nSigmaTOFPMu"), mom, track.tofNSigmaMu()); + registry.fill(HIST("nSigmaTOFPKa"), mom, track.tofNSigmaKa()); + registry.fill(HIST("nSigmaTOFPPr"), mom, track.tofNSigmaPr()); */ - registry.get(HIST("nSigmaTOFPEl"))->Fill(track.pt(), track.tofNSigmaEl()); - registry.get(HIST("nSigmaTOFPPi"))->Fill(track.pt(), track.tofNSigmaPi()); - registry.get(HIST("nSigmaTOFPMu"))->Fill(track.pt(), track.tofNSigmaMu()); - registry.get(HIST("nSigmaTOFPKa"))->Fill(track.pt(), track.tofNSigmaKa()); - registry.get(HIST("nSigmaTOFPPr"))->Fill(track.pt(), track.tofNSigmaPr()); + registry.fill(HIST("tracks/nSigmaTOFPEl"), track.pt(), track.tofNSigmaEl()); + registry.fill(HIST("tracks/nSigmaTOFPPi"), track.pt(), track.tofNSigmaPi()); + registry.fill(HIST("tracks/nSigmaTOFPMu"), track.pt(), track.tofNSigmaMu()); + registry.fill(HIST("tracks/nSigmaTOFPKa"), track.pt(), track.tofNSigmaKa()); + registry.fill(HIST("tracks/nSigmaTOFPPr"), track.pt(), track.tofNSigmaPr()); } } - // fillSignalHists(ivm, dgtracks, pidsel); - fillSignalHists(ivm, PVContributors, pidsel); } + + // process the like sign combinations + goodIVMs = 0; + for (auto ivm : pidsel.likeIVMs()) { + // cut on pt-system + if (ivm.Perp() < anaPars.minptsys() || ivm.Perp() > anaPars.maxptsys()) { + continue; + } + + // applicable to 2-track events - cut on angle between two tracks + if (anaPars.nCombine() == 2) { + auto ind1 = ivm.trkinds()[0]; + auto trk1 = PVContributors.begin() + ind1; + auto v1 = TVector3(trk1.px(), trk1.py(), trk1.pz()); + auto ind2 = ivm.trkinds()[1]; + auto trk2 = PVContributors.begin() + ind2; + auto v2 = TVector3(trk2.px(), trk2.py(), trk2.pz()); + + // cut on angle + auto angle = v1.Angle(v2); + LOGF(debug, "angle %f (%f / %f)", angle, anaPars.minAlpha(), anaPars.maxAlpha()); + if (angle < anaPars.minAlpha() || angle > anaPars.maxAlpha()) { + continue; + } + } + + // update system/IVMptSysDG + registry.fill(HIST("system/likeIVMptSysDG"), ivm.M(), ivm.Perp()); + for (auto ind : ivm.trkinds()) { + auto track = PVContributors.begin() + ind; + registry.fill(HIST("system/likeIVMptTrkDG"), ivm.M(), track.pt()); + } + goodIVMs++; + } + registry.fill(HIST("system/nLikeIVMs"), goodIVMs, 1.); } + + PROCESS_SWITCH(DGCandAnalyzer, processReco, "Analyse reconstructed data", true); + + using UDMcCollisionsFull = aod::UDMcCollisions; + using UDMcCollisionFull = UDMcCollisionsFull::iterator; + using UDMcTracksFull = aod::UDMcParticles; + + void processMcTruth(UDMcCollisionFull const& mcCollison, UDMcTracksFull const& mcParts) + { + + // which type of event is this + // 0: MB + // 1: Pythia diffractive + // 2: GRANIITTI diffractive + bool isPythiaDiff = udhelpers::isPythiaCDE(mcParts); + bool isGraniittiDiff = udhelpers::isGraniittiCDE(mcParts); + registry.get(HIST("mcTruth/collType"))->Fill(0., 1.); + registry.get(HIST("mcTruth/collType"))->Fill(1., (!isPythiaDiff && !isGraniittiDiff) * 1.); + registry.get(HIST("mcTruth/collType"))->Fill(2., isPythiaDiff * 1.); + registry.get(HIST("mcTruth/collType"))->Fill(3., isGraniittiDiff * 1.); + + // compute GRANIITTI event invariant mass + if (!isGraniittiDiff) { + return; + } + auto ivm = udhelpers::ivmGraniittiCDE(mcParts); + + // update histograms + registry.get(HIST("mcTruth/IVMpt"))->Fill(ivm.M(), ivm.Perp(), 1.); + } + + PROCESS_SWITCH(DGCandAnalyzer, processMcTruth, "Analyse MC truth", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGUD/Tasks/diffMCDataScanner.cxx b/PWGUD/Tasks/diffMCDataScanner.cxx index 9b3a88b92da..e4d29c693fa 100644 --- a/PWGUD/Tasks/diffMCDataScanner.cxx +++ b/PWGUD/Tasks/diffMCDataScanner.cxx @@ -116,7 +116,7 @@ struct collisionsInfo { std::vector const lims{0.0, 0.0, 0.0, 0.0, 0.0}; // amplitude thresholds: FV0A, FT0A, FT0C, FDDA, FDDC auto isDGcandidate = true; for (auto& bc : bcSlice) { - if (!udhelpers::cleanFIT(bc, lims)) { + if (!udhelpers::cleanFIT(bc, 4., lims)) { isDGcandidate = false; break; } @@ -147,7 +147,6 @@ struct collisionsInfo { // update histograms with track information LOGF(debug, "Number of tracks: Vertex %d, total %d, global %d", collision.numContrib(), cntAll, cntGlobal); - LOGF(debug, "Number of SPD cluster: %d", collision.spdClusters()); registry.get(HIST("numberTracks"))->Fill(cntAll); registry.get(HIST("numberVtxTracks"))->Fill(collision.numContrib()); registry.get(HIST("numberGlobalTracks"))->Fill(cntGlobal); @@ -200,7 +199,7 @@ struct BCInfo { {{"numberCollisions", "#numberCollisions", {HistType::kTH1F, {{11, -0.5, 10.5}}}}, {"numberCollisionsGT", "#numberCollisionsGT", {HistType::kTH1F, {{11, -0.5, 10.5}}}}, {"Aliases", "#Aliases", {HistType::kTH1F, {{kNaliases, 0., kNaliases}}}}, - {"Selection", "#Selection", {HistType::kTH1F, {{evsel::kNsel, 0., evsel::kNsel}}}}, + {"Selection", "#Selection", {HistType::kTH1F, {{aod::evsel::kNsel, 0., aod::evsel::kNsel}}}}, {"DetectorSignals", "#DetectorSignals", {HistType::kTH1F, {{6, 0., 6}}}}}}; void init(o2::framework::InitContext&) @@ -232,7 +231,7 @@ struct BCInfo { } // update Selection - for (auto ii = 0; ii < evsel::kNsel; ii++) { + for (auto ii = 0; ii < aod::evsel::kNsel; ii++) { registry.get(HIST("Selection"))->Fill(ii, bc.selection_bit(ii)); } diff --git a/PWGUD/Tasks/diffMCQA.cxx b/PWGUD/Tasks/diffMCQA.cxx index a54b0c29d81..1039c297d1e 100644 --- a/PWGUD/Tasks/diffMCQA.cxx +++ b/PWGUD/Tasks/diffMCQA.cxx @@ -71,9 +71,12 @@ struct DiffMCQA { // add histograms for the different process functions if (context.mOptions.get("processMCTruth")) { registry.add("MCTruth/Stat", "Simulated event type; event type; Entries", {HistType::kTH1F, {{4, 0.5, 4.5}}}); + registry.add("MCTruth/recCols", "Number of reconstructed collisions; Number of reconstructed collisions; Entries", {HistType::kTH1F, {{31, -0.5, 30.5}}}); } if (context.mOptions.get("processMain")) { + registry.add("all/mcCols", "Has MC truth collision; Has MC truth collision; Entries", {HistType::kTH1F, {{2, -0.5, 1.5}}}); + // non diffractive events registry.add("nonDiff/Stat", "Cut statistics; Selection criterion; Collisions", {HistType::kTH1F, {{20, -0.5, 19.5}}}); registry.add("nonDiff/cleanFIT", "Statistics of collisions with empty FIT; Multiple of collision time resolution; FIT status; Collisions", {HistType::kTH2F, {{10, -0.5, 9.5}, {2, -0.5, 1.5}}}); @@ -93,8 +96,8 @@ struct DiffMCQA { registry.add("nonDiff/dEdxTPCDG", "DG: TPC signal versus signed track momentum; Signed track momentum [GeV/c]; TPC signal; Tracks", {HistType::kTH2F, {{100, 0., 5.0}, {3000, 0., 30000.}}}); registry.add("nonDiff/dEdxTOFDG", "DG: TOF signal versus signed track momentum; Signed track momentum [GeV/c]; TOF signal; Tracks", {HistType::kTH2F, {{100, 0., 5.0}, {1000, 0., 500000.}}}); registry.add("nonDiff/netChargeDG", "DG: Net charge; Net charge; DG collisions", {HistType::kTH1F, {{21, -10.5, 10.5}}}); - registry.add("nonDiff/IVMptSysDG", "DG: Invariant mass versus p_{T, system}; Invarian mass [GeV/c^2]; p_{T, system} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); - registry.add("nonDiff/IVMptTrkDG", "DG: Invariant mass versus p_{T, tracks}; Invarian mass [GeV/c^2]; p_{T, tracks} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); + registry.add("nonDiff/IVMptSysDG", "DG: Invariant mass versus p_{T, system}; Invarian mass [GeV/c^2]; p_{T, system} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 2.5}, {350, 0., 3.5}}}); + registry.add("nonDiff/IVMptTrkDG", "DG: Invariant mass versus p_{T, tracks}; Invarian mass [GeV/c^2]; p_{T, tracks} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 2.5}, {350, 0., 3.5}}}); // PYTHIA8 diffractive events registry.add("MBRDiff/Stat", "Cut statistics; Selection criterion; Collisions", {HistType::kTH1F, {{20, -0.5, 19.5}}}); registry.add("MBRDiff/cleanFIT", "Statistics of collisions with empty FIT; Multiple of collision time resolution; FIT status; Collisions", {HistType::kTH2F, {{10, -0.5, 9.5}, {2, -0.5, 1.5}}}); @@ -114,8 +117,8 @@ struct DiffMCQA { registry.add("MBRDiff/dEdxTPCDG", "DG: TPC signal versus signed track momentum; Signed track momentum [GeV/c]; TPC signal; Tracks", {HistType::kTH2F, {{100, 0., 5.0}, {3000, 0., 30000.}}}); registry.add("MBRDiff/dEdxTOFDG", "DG: TOF signal versus signed track momentum; Signed track momentum [GeV/c]; TOF signal; Tracks", {HistType::kTH2F, {{100, 0., 5.0}, {1000, 0., 500000.}}}); registry.add("MBRDiff/netChargeDG", "DG: Net charge; Net charge; DG collisions", {HistType::kTH1F, {{21, -10.5, 10.5}}}); - registry.add("MBRDiff/IVMptSysDG", "DG: Invariant mass versus p_{T, system}; Invarian mass [GeV/c^2]; p_{T, system} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); - registry.add("MBRDiff/IVMptTrkDG", "DG: Invariant mass versus p_{T, tracks}; Invarian mass [GeV/c^2]; p_{T, tracks} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); + registry.add("MBRDiff/IVMptSysDG", "DG: Invariant mass versus p_{T, system}; Invarian mass [GeV/c^2]; p_{T, system} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 2.5}, {350, 0., 3.5}}}); + registry.add("MBRDiff/IVMptTrkDG", "DG: Invariant mass versus p_{T, tracks}; Invarian mass [GeV/c^2]; p_{T, tracks} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 2.5}, {350, 0., 3.5}}}); // GRANIITTI diffractive events registry.add("Diff/Stat", "Cut statistics; Selection criterion; Collisions", {HistType::kTH1F, {{20, -0.5, 19.5}}}); registry.add("Diff/cleanFIT", "Statistics of collisions with empty FIT; Multiple of collision time resolution; FIT status; Collisions", {HistType::kTH2F, {{10, -0.5, 9.5}, {2, -0.5, 1.5}}}); @@ -135,8 +138,8 @@ struct DiffMCQA { registry.add("Diff/dEdxTPCDG", "DG: TPC signal versus signed track momentum; Signed track momentum [GeV/c]; TPC signal; Tracks", {HistType::kTH2F, {{100, 0., 5.0}, {3000, 0., 30000.}}}); registry.add("Diff/dEdxTOFDG", "DG: TOF signal versus signed track momentum; Signed track momentum [GeV/c]; TOF signal; Tracks", {HistType::kTH2F, {{100, 0., 5.0}, {1000, 0., 500000.}}}); registry.add("Diff/netChargeDG", "DG: Net charge; Net charge; DG collisions", {HistType::kTH1F, {{21, -10.5, 10.5}}}); - registry.add("Diff/IVMptSysDG", "DG: Invariant mass versus p_{T, system}; Invarian mass [GeV/c^2]; p_{T, system} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); - registry.add("Diff/IVMptTrkDG", "DG: Invariant mass versus p_{T, tracks}; Invarian mass [GeV/c^2]; p_{T, tracks} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 5.}, {350, 0., 3.5}}}); + registry.add("Diff/IVMptSysDG", "DG: Invariant mass versus p_{T, system}; Invarian mass [GeV/c^2]; p_{T, system} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 2.5}, {350, 0., 3.5}}}); + registry.add("Diff/IVMptTrkDG", "DG: Invariant mass versus p_{T, tracks}; Invarian mass [GeV/c^2]; p_{T, tracks} [GeV/c]; DG collisions", {HistType::kTH2F, {{100, 0., 2.5}, {350, 0., 3.5}}}); } if (context.mOptions.get("processFV0")) { @@ -207,32 +210,33 @@ struct DiffMCQA { LOGF(info, " Size of abcrs %i and afbcrs %i", abcrs.size(), afbcrs.size()); } - Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice partPerMcCollision = aod::mcparticle::mcCollisionId; // ............................................................................................................... - void processMCTruth(CCs const& collisions, aod::McCollisions const& mccollisions, aod::McParticles const& McParts) + void processMCTruth(aod::McCollision const& mccollision, soa::SmallGroups const& collisions, aod::McParticles const& McParts) { - LOGF(info, "Number of mc collisions %d collisions %d", mccollisions.size(), collisions.size()); + LOGF(info, "Number of collisions %d", collisions.size()); + LOGF(info, "Number of McParts %d", McParts.size()); // is this a central diffractive event? // by default it is assumed to be a MB event bool isPythiaDiff = false; bool isGraniittiDiff = false; - for (auto mccol : mccollisions) { - registry.get(HIST("MCTruth/Stat"))->Fill(1., 1.); - auto MCPartSlice = McParts.sliceBy(perMcCollision, mccol.globalIndex()); - isPythiaDiff = udhelpers::isPythiaCDE(MCPartSlice); - isGraniittiDiff = udhelpers::isGraniittiCDE(MCPartSlice); - if (isPythiaDiff) { - registry.get(HIST("MCTruth/Stat"))->Fill(3., 1.); - } else if (isGraniittiDiff) { - registry.get(HIST("MCTruth/Stat"))->Fill(4., 1.); - } else { - registry.get(HIST("MCTruth/Stat"))->Fill(2., 1.); - } + registry.get(HIST("MCTruth/Stat"))->Fill(1., 1.); + isPythiaDiff = udhelpers::isPythiaCDE(McParts); + isGraniittiDiff = udhelpers::isGraniittiCDE(McParts); + if (isPythiaDiff) { + registry.get(HIST("MCTruth/Stat"))->Fill(3., 1.); + } else if (isGraniittiDiff) { + registry.get(HIST("MCTruth/Stat"))->Fill(4., 1.); + } else { + registry.get(HIST("MCTruth/Stat"))->Fill(2., 1.); } + + // number of reconstructed collision + registry.get(HIST("MCTruth/recCols"))->Fill(collisions.size(), 1.); } - PROCESS_SWITCH(DiffMCQA, processMCTruth, "Process NC truth", true); + PROCESS_SWITCH(DiffMCQA, processMCTruth, "Process MC truth", true); // ............................................................................................................... void processMain(CC const& collision, BCs const& bct0s, @@ -249,10 +253,14 @@ struct DiffMCQA { bool isPythiaDiff = false; bool isGraniittiDiff = false; if (collision.has_mcCollision()) { + registry.get(HIST("all/mcCols"))->Fill(1., 1.); + auto MCCol = collision.mcCollision(); - auto MCPartSlice = McParts.sliceBy(perMcCollision, MCCol.globalIndex()); + auto MCPartSlice = McParts.sliceBy(partPerMcCollision, MCCol.globalIndex()); isPythiaDiff = udhelpers::isPythiaCDE(MCPartSlice); isGraniittiDiff = udhelpers::isGraniittiCDE(MCPartSlice); + } else { + registry.get(HIST("all/mcCols"))->Fill(0., 1.); } // global tracks @@ -284,18 +292,18 @@ struct DiffMCQA { } // test influence of BCrange width - for (int NDtcoll = 0; NDtcoll < 10; NDtcoll++) { - auto bcSlice = udhelpers::MCcompatibleBCs(collision, NDtcoll, bct0s, 0); + for (int minBcs = 0; minBcs < 10; minBcs++) { + auto bcSlice = udhelpers::MCcompatibleBCs(collision, 0, bct0s, minBcs); isDGcandidate = true; for (auto& bc : bcSlice) { - isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits()); + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits()); } if (isPythiaDiff) { - registry.get(HIST("MBRDiff/cleanFIT"))->Fill(NDtcoll, isDGcandidate * 1.); + registry.get(HIST("MBRDiff/cleanFIT"))->Fill(minBcs, isDGcandidate * 1.); } else if (isGraniittiDiff) { - registry.get(HIST("Diff/cleanFIT"))->Fill(NDtcoll, isDGcandidate * 1.); + registry.get(HIST("Diff/cleanFIT"))->Fill(minBcs, isDGcandidate * 1.); } else { - registry.get(HIST("nonDiff/cleanFIT"))->Fill(NDtcoll, isDGcandidate * 1.); + registry.get(HIST("nonDiff/cleanFIT"))->Fill(minBcs, isDGcandidate * 1.); } } @@ -367,13 +375,13 @@ struct DiffMCQA { // no FIT signal in bcSlice / collision if (doCleanFITBC) { for (auto const& bc : bcSlice) { - if (!udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits())) { + if (!udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits())) { isDGcandidate = false; break; } } } else { - if (!udhelpers::cleanFITCollision(collision, diffCuts.FITAmpLimits())) { + if (!udhelpers::cleanFITCollision(collision, diffCuts.maxFITtime(), diffCuts.FITAmpLimits())) { isDGcandidate = false; } } diff --git a/PWGUD/Tasks/diffQA.cxx b/PWGUD/Tasks/diffQA.cxx index 7534f347ea3..4affd4b96d2 100644 --- a/PWGUD/Tasks/diffQA.cxx +++ b/PWGUD/Tasks/diffQA.cxx @@ -311,13 +311,13 @@ struct DiffQA { // no FIT signal in bcSlice / collision if (doCleanFITBC) { for (auto const& bc : bcSlice) { - if (!udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits())) { + if (!udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits())) { isDGcandidate = false; break; } } } else { - if (!udhelpers::cleanFITCollision(collision, diffCuts.FITAmpLimits())) { + if (!udhelpers::cleanFITCollision(collision, diffCuts.maxFITtime(), diffCuts.FITAmpLimits())) { isDGcandidate = false; } } @@ -525,7 +525,7 @@ struct DiffQA { ampFV0A = ampFT0A = ampFT0C = ampFDDA = ampFDDC = 0.; isDGcandidate = true; for (auto const& bc : bcSlice) { - isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits()); + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits()); if (bc.has_foundFV0()) { ampFV0A += udhelpers::FV0AmplitudeA(bc.foundFV0()); @@ -565,7 +565,7 @@ struct DiffQA { ampFV0A = ampFT0A = ampFT0C = ampFDDA = ampFDDC = 0.; isDGcandidate = true; for (auto const& bc : bcSlice) { - isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.FITAmpLimits()); + isDGcandidate &= udhelpers::cleanFIT(bc, diffCuts.maxFITtime(), diffCuts.FITAmpLimits()); if (bc.has_foundFV0()) { ampFV0A += udhelpers::FV0AmplitudeA(bc.foundFV0()); @@ -602,7 +602,7 @@ struct DiffQA { // check FT0 to be empty auto bc = collision.foundBC_as(); - if (udhelpers::cleanFT0(bc, 0., 0.)) { + if (udhelpers::cleanFT0(bc, diffCuts.maxFITtime(), 0., 0.)) { // only collisions with empty FT0 arrive here registry.get(HIST("cleanFT0/Stat"))->Fill(2., 1.); diff --git a/PWGUD/Tasks/upcAnalysis.cxx b/PWGUD/Tasks/upcAnalysis.cxx index f5f2adb909e..74a007314e0 100644 --- a/PWGUD/Tasks/upcAnalysis.cxx +++ b/PWGUD/Tasks/upcAnalysis.cxx @@ -21,6 +21,7 @@ #include "TLorentzVector.h" using namespace o2; +using namespace o2::aod::evsel; using namespace o2::framework; using namespace o2::framework::expressions; @@ -35,11 +36,11 @@ struct UPCAnalysis { void process(soa::Join::iterator const& col, soa::Filtered> const& tracks) { - bool checkV0 = col.bbV0A() || col.bbV0C() || col.bgV0A() || col.bgV0C(); + bool checkV0 = col.selection_bit(kIsBBV0A) || col.selection_bit(kIsBBV0C) || !col.selection_bit(kNoBGV0A) || !col.selection_bit(kNoBGV0C); if (checkV0) { return; } - bool checkFDD = col.bbFDA() || col.bbFDC() || col.bgFDA() || col.bgFDC(); + bool checkFDD = col.selection_bit(kIsBBFDA) || col.selection_bit(kIsBBFDC) || !col.selection_bit(kNoBGFDA) || !col.selection_bit(kNoBGFDC); if (checkFDD) { return; } diff --git a/PWGUD/Tasks/upcForward.cxx b/PWGUD/Tasks/upcForward.cxx index 8f671b0b07c..3a3c6ec722d 100644 --- a/PWGUD/Tasks/upcForward.cxx +++ b/PWGUD/Tasks/upcForward.cxx @@ -19,17 +19,20 @@ for now AO2D.root I am using is #include "Framework/AnalysisDataModel.h" #include "Common/DataModel/EventSelection.h" #include "iostream" -#include "Common/DataModel/EventSelection.h" #include #include #include #include "TLorentzVector.h" #include "Common/CCDB/TriggerAliases.h" + using namespace std; using namespace o2; +using namespace o2::aod::evsel; using namespace o2::framework; using namespace o2::framework::expressions; + #define mmuon 0.1057 // mass of muon + struct UPCForward { // defining histograms using histogram registry HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -73,15 +76,15 @@ struct UPCForward { bool isnegative = kFALSE; // V0 and FD information - bool isBeamBeamV0A = bc.bbV0A(); - bool isBeamGasV0A = bc.bgV0A(); - // bool isBeamBeamV0C = bc.bbV0C(); - bool isBeamGasV0C = bc.bgV0C(); - - bool isBeamBeamFDA = bc.bbFDA(); - bool isBeamGasFDA = bc.bgFDA(); - bool isBeamBeamFDC = bc.bbFDC(); - bool isBeamGasFDC = bc.bgFDC(); + bool isBeamBeamV0A = bc.selection_bit(kIsBBV0A); + bool isBeamGasV0A = !bc.selection_bit(kNoBGV0A); + // bool isBeamBeamV0C = bc.selection_bit(kIsBBV0C); + bool isBeamGasV0C = !bc.selection_bit(kNoBGV0C); + + bool isBeamBeamFDA = bc.selection_bit(kIsBBFDA); + bool isBeamGasFDA = !bc.selection_bit(kNoBGFDA); + bool isBeamBeamFDC = bc.selection_bit(kIsBBFDC); + bool isBeamGasFDC = !bc.selection_bit(kNoBGFDC); // offline V0 and FD selection bool isV0Selection = isBeamBeamV0A || isBeamGasV0A || isBeamGasV0C; diff --git a/Scripts/find_dependencies.py b/Scripts/find_dependencies.py index 08db2c1dc0c..5a4c152ef23 100755 --- a/Scripts/find_dependencies.py +++ b/Scripts/find_dependencies.py @@ -31,6 +31,7 @@ import argparse import glob +import hashlib import json import os import subprocess as sp # nosec B404 @@ -104,9 +105,7 @@ def get_outputs(specs_wf: dict, device=""): for dev in specs_wf: if device and dev["name"] != device: continue - list_outputs += [ - i["description"] for i in dev["outputs"] if i["origin"] == "AOD" - ] + list_outputs += [i["description"] for i in dev["outputs"] if i["origin"] == "AOD"] return list(dict.fromkeys(list_outputs)) # Remove duplicities @@ -141,9 +140,7 @@ def get_table_producers(table: str, dic_wf_all: dict, case_sensitive=False): for wf, dic_wf in dic_wf_all.items(): # Loop over devices for dev in dic_wf: - outputs = [ - o if case_sensitive else o.lower() for o in dic_wf[dev]["outputs"] - ] + outputs = [o if case_sensitive else o.lower() for o in dic_wf[dev]["outputs"]] if table in outputs: list_producers.append(wf) return list(dict.fromkeys(list_producers)) # Remove duplicities @@ -207,9 +204,7 @@ def get_tree_for_workflow( return dic_wf_tree -def get_tree_for_table( - tab: str, dic_wf_all: dict, dic_wf_tree=None, case_sensitive=False, levels_max=0 -): +def get_tree_for_table(tab: str, dic_wf_all: dict, dic_wf_tree=None, case_sensitive=False, levels_max=0): """Get the dependency tree of tables and workflows needed to produce this table.""" if dic_wf_tree is None: dic_wf_tree = {} @@ -219,9 +214,7 @@ def get_tree_for_table( if levels_max != 0: # Search for more dependencies only if needed. print("\nWorkflow dependency tree:\n") for p in producers: - get_tree_for_workflow( - p, dic_wf_all, dic_wf_tree, case_sensitive, 0, levels_max - ) + get_tree_for_workflow(p, dic_wf_all, dic_wf_tree, case_sensitive, 0, levels_max) else: print("No producers found") return dic_wf_tree @@ -309,9 +302,7 @@ def main(): # return # print(producers) # print_workflows(dic_wf_all_simple, producers) - get_tree_for_table( - table, dic_wf_all_simple, dic_deps, case_sensitive, n_levels - ) + get_tree_for_table(table, dic_wf_all_simple, dic_deps, case_sensitive, n_levels) # Find workflow dependencies if workflows: @@ -320,9 +311,7 @@ def main(): if not workflow: msg_fatal("Bad workflow") # print_workflows(dic_wf_all_simple, [workflow]) - get_tree_for_workflow( - workflow, dic_wf_all_simple, dic_deps, case_sensitive, 0, n_levels - ) + get_tree_for_workflow(workflow, dic_wf_all_simple, dic_deps, case_sensitive, 0, n_levels) # Print the tree dictionary with dependencies # print("\nTree\n") @@ -330,9 +319,10 @@ def main(): # Produce topology graph. if graph_suffix and dic_deps: - basename = "_".join( - (tables if tables else []) + (workflows if workflows else []) - ) + basename = "_".join((tables if tables else []) + (workflows if workflows else [])) + # Set a short file name when the full name would be longer than 255 characters. + if len(basename) > 251: + basename = "o2_dependencies_" + hashlib.sha1(basename.encode(), usedforsecurity=False).hexdigest() ext_graph = graph_suffix path_file_dot = basename + ".gv" path_file_graph = basename + "." + ext_graph diff --git a/Tools/KFparticle/KFUtilities.h b/Tools/KFparticle/KFUtilities.h index ce97274eab9..4a393ebcefe 100644 --- a/Tools/KFparticle/KFUtilities.h +++ b/Tools/KFparticle/KFUtilities.h @@ -56,9 +56,9 @@ KFPTrack createKFPTrack(const o2::track::TrackParametrizationWithError& t int16_t tpcNClsFound, float tpcChi2NCl) { - array trkpos_par; - array trkmom_par; - array trk_cov; + std::array trkpos_par; + std::array trkmom_par; + std::array trk_cov; trackparCov.getXYZGlo(trkpos_par); trackparCov.getPxPyPzGlo(trkmom_par); trackparCov.getCovXYZPxPyPzGlo(trk_cov); @@ -123,7 +123,7 @@ float cpaFromKF(KFParticle kfp, KFParticle PV) py = kfp.GetPy(); pz = kfp.GetPz(); - float cpa = RecoDecay::cpa(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}, array{px, py, pz}); + float cpa = RecoDecay::cpa(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); return cpa; } @@ -144,7 +144,7 @@ float cpaXYFromKF(KFParticle kfp, KFParticle PV) px = kfp.GetPx(); py = kfp.GetPy(); - float cpaXY = RecoDecay::cpaXY(array{xVtxP, yVtxP}, array{xVtxS, yVtxS}, array{px, py}); + float cpaXY = RecoDecay::cpaXY(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, std::array{px, py}); return cpaXY; } @@ -168,13 +168,13 @@ float cosThetaStarFromKF(int ip, int pdgvtx, int pdgprong0, int pdgprong1, KFPar px1 = kfpprong1.GetPx(); py1 = kfpprong1.GetPy(); pz1 = kfpprong1.GetPz(); - array m = {0., 0.}; + std::array m = {0., 0.}; m[0] = TDatabasePDG::Instance()->GetParticle(pdgprong0)->Mass(); m[1] = TDatabasePDG::Instance()->GetParticle(pdgprong1)->Mass(); double mTot = TDatabasePDG::Instance()->GetParticle(pdgvtx)->Mass(); int iProng = ip; - float cosThetastar = RecoDecay::cosThetaStar(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m, mTot, iProng); + float cosThetastar = RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m, mTot, iProng); return cosThetastar; } @@ -200,7 +200,7 @@ float impParXYFromKF(KFParticle kfpParticle, KFParticle Vertex) py = kfpParticle.GetPy(); pz = kfpParticle.GetPz(); - float impParXY = RecoDecay::impParXY(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}, array{px, py, pz}); + float impParXY = RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); return impParXY; } diff --git a/Tools/KFparticle/qaKFEventTrack.cxx b/Tools/KFparticle/qaKFEventTrack.cxx index 3fdd80c6f5d..bed7ada7a4b 100644 --- a/Tools/KFparticle/qaKFEventTrack.cxx +++ b/Tools/KFparticle/qaKFEventTrack.cxx @@ -67,7 +67,6 @@ struct qaKFEventTrack { Configurable isRun3{"isRun3", true, "Is Run3 dataset"}; Configurable ccdbUrl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; - Configurable ccdbPathGeo{"ccdbPathGeo", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; Service ccdb; @@ -156,9 +155,6 @@ struct qaKFEventTrack { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(ccdbPathGeo); - } runNumber = 0; const AxisSpec axisVertexPosX{100, -0.05, 0.05, "X [cm]"}; @@ -579,9 +575,6 @@ struct qaKFEvent { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(ccdbPathGeo); - } runNumber = 0; } /// End init diff --git a/Tools/KFparticle/qaKFEventTrack.h b/Tools/KFparticle/qaKFEventTrack.h index bec8a5e1dfb..399a3139a91 100644 --- a/Tools/KFparticle/qaKFEventTrack.h +++ b/Tools/KFparticle/qaKFEventTrack.h @@ -14,12 +14,10 @@ #ifndef TOOLS_KFPARTICLE_QAKFEVENTTRACK_H_ #define TOOLS_KFPARTICLE_QAKFEVENTTRACK_H_ + #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Common/Core/trackUtilities.h" -using namespace o2; -using namespace o2::framework; -using namespace o2::track; enum FlagsTracks { kITS = BIT(0), diff --git a/Tools/KFparticle/qaKFParticle.cxx b/Tools/KFparticle/qaKFParticle.cxx index a1b26bd6a2f..0726aad3483 100644 --- a/Tools/KFparticle/qaKFParticle.cxx +++ b/Tools/KFparticle/qaKFParticle.cxx @@ -68,7 +68,6 @@ struct qaKFParticle { Configurable isRun3{"isRun3", true, "Is Run3 dataset"}; Configurable ccdbUrl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; - Configurable ccdbPathGeo{"ccdbPathGeo", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; Service ccdb; @@ -191,9 +190,6 @@ struct qaKFParticle { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(ccdbPathGeo); - } runNumber = 0; const AxisSpec axisVertexPosX{100, -0.05, 0.05, "X [cm]"}; @@ -965,7 +961,7 @@ struct qaKFParticle { int sourceD0 = 0; int sourceD0Bar = 0; - auto indexRec = RecoDecay::getMatchedMCRec(mcParticles, std::array{track1, track2}, 421, array{211, -321}, true, &sign); + auto indexRec = RecoDecay::getMatchedMCRec(mcParticles, std::array{track1, track2}, 421, std::array{211, -321}, true, &sign); if (indexRec > -1) { auto particle = mcParticles.rawIteratorAt(indexRec); flag = RecoDecay::getCharmHadronOrigin(mcParticles, particle); diff --git a/Tools/KFparticle/qaKFParticle.h b/Tools/KFparticle/qaKFParticle.h index b0a8693decf..afb23851cb5 100644 --- a/Tools/KFparticle/qaKFParticle.h +++ b/Tools/KFparticle/qaKFParticle.h @@ -14,12 +14,10 @@ #ifndef TOOLS_KFPARTICLE_QAKFPARTICLE_H_ #define TOOLS_KFPARTICLE_QAKFPARTICLE_H_ + #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Common/Core/trackUtilities.h" -using namespace o2; -using namespace o2::framework; -using namespace o2::track; enum Source { kPrompt = BIT(0), diff --git a/Tools/KFparticle/qaKFParticleLc.cxx b/Tools/KFparticle/qaKFParticleLc.cxx index 922072456ec..0561b784506 100644 --- a/Tools/KFparticle/qaKFParticleLc.cxx +++ b/Tools/KFparticle/qaKFParticleLc.cxx @@ -68,7 +68,6 @@ struct qaKFParticleLc { Configurable isRun3{"isRun3", true, "Is Run3 dataset"}; Configurable ccdbUrl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable ccdbPathLut{"ccdbPathLut", "GLO/Param/MatLUT", "Path for LUT parametrization"}; - Configurable ccdbPathGeo{"ccdbPathGeo", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "Path of the grp file (Run 2)"}; Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; Service ccdb; @@ -194,9 +193,6 @@ struct qaKFParticleLc { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbPathLut)); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(ccdbPathGeo); - } runNumber = 0; } /// End init diff --git a/Tools/KFparticle/qaKFParticleLc.h b/Tools/KFparticle/qaKFParticleLc.h index 8df0e08aba3..8c57232f99a 100644 --- a/Tools/KFparticle/qaKFParticleLc.h +++ b/Tools/KFparticle/qaKFParticleLc.h @@ -14,12 +14,10 @@ #ifndef TOOLS_KFPARTICLE_QAKFPARTICLELC_H_ #define TOOLS_KFPARTICLE_QAKFPARTICLELC_H_ + #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Common/Core/trackUtilities.h" -using namespace o2; -using namespace o2::framework; -using namespace o2::track; enum Source { kPrompt = BIT(0), diff --git a/Tools/ML/MlResponse.h b/Tools/ML/MlResponse.h new file mode 100644 index 00000000000..ebfb39ba44a --- /dev/null +++ b/Tools/ML/MlResponse.h @@ -0,0 +1,208 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MlResponse.h +/// \brief Class to compute the ML response for analysis selections +/// \author Fabio Catalano , CERN +/// \author Alexandre Bigot , IPHC Strasbourg + +#ifndef TOOLS_ML_MLRESPONSE_H_ +#define TOOLS_ML_MLRESPONSE_H_ + +#include + +#include +#include +#include + +#include "CCDB/CcdbApi.h" +#include "Framework/Array2D.h" + +#include "Tools/ML/model.h" + +namespace o2 +{ +namespace cuts_ml +{ +// direction of the cut +enum CutDirection { + CutGreater = 0, // require score < cut value + CutSmaller, // require score > cut value + CutNot // do not cut on score +}; +} // namespace cuts_ml +namespace analysis +{ +template +class MlResponse +{ + public: + /// Default constructor + MlResponse() = default; + /// Default destructor + virtual ~MlResponse() = default; + + /// Configure class instance (import configurables) + /// \param binsLimits is a vector containing bins limits + /// \param cuts is a LabeledArray containing selections per bin + /// \param cutDir is a vector telling whether to reject score values greater or smaller than the threshold + /// \param nClasses is the number of classes for each model + void configure(const std::vector& binsLimits, const o2::framework::LabeledArray& cuts, const std::vector& cutDir, const uint8_t& nClasses) + { + mBinsLimits = binsLimits; + mCuts = cuts; + mCutDir = cutDir; + mNClasses = nClasses; + mNModels = binsLimits.size() - 1; + mModels = std::vector(mNModels); + mPaths = std::vector(mNModels); + } + + /// Set models paths to CCDB + /// \param onnxFiles is a vector of onnx file names, one for each bin + /// \param ccdbApi is the CCDB API + /// \param pathCCDB is the model path in CCDB + /// \param timestampCCDB is the CCDB timestamp + void setModelPathsCCDB(const std::vector& onnxFiles, const o2::ccdb::CcdbApi& ccdbApi, std::string pathCCDB, int64_t timestampCCDB) + { + if (onnxFiles.size() != mNModels) { + LOG(fatal) << "Number of expected models different from the one set! Please check your configurables."; + } + + uint8_t counterModel{0}; + for (const auto& onnxFile : onnxFiles) { + std::map metadata; + bool retrieveSuccess = ccdbApi.retrieveBlob(pathCCDB, ".", metadata, timestampCCDB, false, onnxFile); + if (retrieveSuccess) { + mPaths[counterModel] = onnxFile; + } else { + LOG(fatal) << "Error encountered while accessing the ML model from CCDB! Maybe the ML model doesn't exist yet for this runnumber/timestamp?"; + } + ++counterModel; + } + } + + /// Set models paths to local or cvmfs + /// \param onnxFiles is a vector of onnx file names, one for each bin + void setModelPathsLocal(const std::vector& onnxFiles) + { + if (onnxFiles.size() != mNModels) { + LOG(fatal) << "Number of expected models different from the one set! Please check your configurables."; + } + + mPaths = onnxFiles; + } + + /// Initialize class instance (initialize OnnxModels) + /// \param enableOptimizations is a switch no enable optimizations + /// \param threads is the number of active threads + void init(bool enableOptimizations = false, int threads = 0) + { + uint8_t counterModel{0}; + for (const auto& path : mPaths) { + mModels[counterModel].initModel(path, enableOptimizations, threads); + ++counterModel; + } + } + + /// Get vector with model predictions + /// \param input a vector containing the values of features used in the model + /// \param nModel is the model index + /// \return model prediction for each class and the selected model + template + std::vector getModelOutput(T1& input, const T2& nModel) + { + T* outputPtr = mModels[nModel].evalModel(input); + return std::vector{outputPtr, outputPtr + mNClasses}; + } + + /// Finds pT bin in an array. + /// \param bins array of pT bins + /// \param value pT + /// \return index of the pT bin + /// \note Accounts for the offset so that pt bin array can be used to also configure a histogram axis. + template + int findBin(T1 const& binsPt, T2 value) + { + if (value < binsPt->front()) { + return -1; + } + if (value >= binsPt->back()) { + return -1; + } + return std::distance(binsPt->begin(), std::upper_bound(binsPt->begin(), binsPt->end(), value)) - 1; + } + + /// ML selections + /// \param input is the input features + /// \param pt is the candidate transverse momentum + /// \return boolean telling if model predictions pass the cuts + template + bool isSelectedMl(T1& input, const T2& pt) + { + auto nModel = findBin(&mBinsLimits, pt); + auto output = getModelOutput(input, nModel); + uint8_t iClass{0}; + for (const auto& outputValue : output) { + uint8_t dir = mCutDir.at(iClass); + if (dir != o2::cuts_ml::CutDirection::CutNot) { + if (dir == o2::cuts_ml::CutDirection::CutGreater && outputValue > mCuts.get(nModel, iClass)) { + return false; + } + if (dir == o2::cuts_ml::CutDirection::CutSmaller && outputValue < mCuts.get(nModel, iClass)) { + return false; + } + } + ++iClass; + } + return true; + } + + /// ML selections + /// \param input is the input features + /// \param pt is the candidate transverse momentum + /// \param output is a container to be filled with model output + /// \return boolean telling if model predictions pass the cuts + template + bool isSelectedMl(T1& input, const T2& pt, std::vector& output) + { + auto nModel = findBin(&mBinsLimits, pt); + output = getModelOutput(input, nModel); + uint8_t iClass{0}; + for (const auto& outputValue : output) { + uint8_t dir = mCutDir.at(iClass); + if (dir != o2::cuts_ml::CutDirection::CutNot) { + if (dir == o2::cuts_ml::CutDirection::CutGreater && outputValue > mCuts.get(nModel, iClass)) { + return false; + } + if (dir == o2::cuts_ml::CutDirection::CutSmaller && outputValue < mCuts.get(nModel, iClass)) { + return false; + } + } + ++iClass; + } + return true; + } + + protected: + std::vector mModels; // OnnxModel objects, one for each bin + uint8_t mNModels = 1; // number of bins + uint8_t mNClasses = 3; // number of model classes + std::vector mBinsLimits = {}; // bin limits of the variable (e.g. pT) used to select which model to use + std::vector mPaths = {""}; // paths to the models, one for each bin + std::vector mCutDir = {}; // direction of the cuts on the model scores (no cut is also supported) + o2::framework::LabeledArray mCuts = {}; // array of cut values to apply on the model scores +}; + +} // namespace analysis +} // namespace o2 + +#endif // TOOLS_ML_MLRESPONSE_H_ diff --git a/Tools/PIDML/CMakeLists.txt b/Tools/PIDML/CMakeLists.txt index ce51dbc8351..cb2f87f4204 100644 --- a/Tools/PIDML/CMakeLists.txt +++ b/Tools/PIDML/CMakeLists.txt @@ -46,5 +46,5 @@ o2physics_add_dpl_workflow(qa-pid-ml o2physics_add_dpl_workflow(kaon-pid-ml SOURCES KaonPidTask.cxx JOB_POOL analysis - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore ONNXRuntime::ONNXRuntime O2::CCDB O2Physics::DataModel + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore ONNXRuntime::ONNXRuntime O2::CCDB O2Physics::DataModel COMPONENT_NAME Analysis) diff --git a/Tools/PIDML/pidML.h b/Tools/PIDML/pidML.h index 638bd5c0637..821da7efc42 100644 --- a/Tools/PIDML/pidML.h +++ b/Tools/PIDML/pidML.h @@ -20,8 +20,6 @@ #include "Framework/AnalysisDataModel.h" #include "Common/DataModel/PIDResponse.h" -using namespace o2; - namespace o2::aod { namespace pidtracks diff --git a/Tools/PIDML/pidOnnxInterface.h b/Tools/PIDML/pidOnnxInterface.h index 20bbeaa0ed2..0cf8b473d4a 100644 --- a/Tools/PIDML/pidOnnxInterface.h +++ b/Tools/PIDML/pidOnnxInterface.h @@ -45,11 +45,8 @@ static const std::vector cutVarLabels = { "TPC", "TPC + TOF", "TPC + TOF + TRD"}; } // namespace pidml_pt_cuts -using namespace pidml_pt_cuts; -using namespace o2::framework; - struct PidONNXInterface { - PidONNXInterface(std::string& localPath, std::string& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi& ccdbApi, uint64_t timestamp, std::vector const& pids, LabeledArray const& pTLimits, std::vector const& minCertainties, bool autoMode) : mNPids{pids.size()}, mPTLimits{pTLimits} + PidONNXInterface(std::string& localPath, std::string& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi& ccdbApi, uint64_t timestamp, std::vector const& pids, o2::framework::LabeledArray const& pTLimits, std::vector const& minCertainties, bool autoMode) : mNPids{pids.size()}, mPTLimits{pTLimits} { if (pids.size() == 0) { LOG(fatal) << "PID ML Interface needs at least 1 output pid to predict"; @@ -119,12 +116,12 @@ struct PidONNXInterface { void fillDefaultConfiguration(std::vector& minCertainties) { // FIXME: A more sophisticated strategy should be based on pid values as well - mPTLimits = LabeledArray{cuts[0], nPids, nCutVars, pidLabels, cutVarLabels}; + mPTLimits = o2::framework::LabeledArray{pidml_pt_cuts::cuts[0], pidml_pt_cuts::nPids, pidml_pt_cuts::nCutVars, pidml_pt_cuts::pidLabels, pidml_pt_cuts::cutVarLabels}; minCertainties = std::vector(mNPids, 0.5); } std::vector mModels; std::size_t mNPids; - LabeledArray mPTLimits; + o2::framework::LabeledArray mPTLimits; }; #endif // TOOLS_PIDML_PIDONNXINTERFACE_H_ diff --git a/Tutorials/CMakeLists.txt b/Tutorials/CMakeLists.txt index c4534e4e830..feb0d900122 100644 --- a/Tutorials/CMakeLists.txt +++ b/Tutorials/CMakeLists.txt @@ -109,7 +109,7 @@ o2physics_add_dpl_workflow(event-mixing-validation o2physics_add_dpl_workflow(mc-histograms SOURCES src/mcHistograms.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME AnalysisTutorial) o2physics_add_dpl_workflow(ccdbaccess @@ -196,7 +196,7 @@ o2physics_add_dpl_workflow(conditional-expressions o2physics_add_dpl_workflow(using-pdg SOURCES src/usingPDGService.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME AnalysisTutorial) o2physics_add_dpl_workflow(propagated-tracks @@ -228,4 +228,3 @@ o2physics_add_dpl_workflow(consume SOURCES src/consume.cxx PUBLIC_LINK_LIBRARIES O2::Framework COMPONENT_NAME AnalysisTutorial) - diff --git a/Tutorials/PWGEM/CMakeLists.txt b/Tutorials/PWGEM/CMakeLists.txt index 083cbcfa883..227254f66e1 100644 --- a/Tutorials/PWGEM/CMakeLists.txt +++ b/Tutorials/PWGEM/CMakeLists.txt @@ -9,6 +9,8 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. +add_subdirectory(pcm) + o2physics_add_dpl_workflow(emc-cluster-step0 SOURCES emcclustertutorial.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore diff --git a/Tutorials/PWGEM/Cocktail/configs/ini_example.ini b/Tutorials/PWGEM/Cocktail/configs/ini_example.ini index 3d95f11a32f..b562383bcf2 100644 --- a/Tutorials/PWGEM/Cocktail/configs/ini_example.ini +++ b/Tutorials/PWGEM/Cocktail/configs/ini_example.ini @@ -1,3 +1,3 @@ [GeneratorExternal] fileName = ${O2DPG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C -funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json","5TeV_0005_wRatio_etatest",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",0) \ No newline at end of file +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json","5TeV_0005_wRatio_etatest",100,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",0) diff --git a/Tutorials/PWGEM/Cocktail/configs/sim_config.json b/Tutorials/PWGEM/Cocktail/configs/sim_config.json index 7a4f699359d..e6800ff071d 100644 --- a/Tutorials/PWGEM/Cocktail/configs/sim_config.json +++ b/Tutorials/PWGEM/Cocktail/configs/sim_config.json @@ -4,7 +4,7 @@ "selectedMothers": 63, "paramFile": "PATH/Cocktail/files/parametrizations/PbPb_5TeV.json", "paramFileDir": "5TeV_0005_wRatio", - "numberOfParticles": 350, + "numberOfParticles": 100, "minPt": 0.0, "maxPt": 30.0, "yGenRange": 1.1, diff --git a/Tutorials/PWGEM/Cocktail/run_lmee_lf_cocktail.py b/Tutorials/PWGEM/Cocktail/run_lmee_lf_cocktail.py index 0119f7265d2..cdfd77660c2 100644 --- a/Tutorials/PWGEM/Cocktail/run_lmee_lf_cocktail.py +++ b/Tutorials/PWGEM/Cocktail/run_lmee_lf_cocktail.py @@ -120,7 +120,6 @@ def run_only_simulation(args): def run_only_analysis_task(args): - sim_log_name = "readerlog" ana_log_name = "analog" name="kineReader" @@ -132,52 +131,28 @@ def run_only_analysis_task(args): kin_file = abspath(args.input) json_file = abspath(args.ana_config_file) - sim_log_file = join(output_dir,sim_log_name) ana_log_file = join(output_dir,ana_log_name) if not exists(output_dir): os.makedirs(output_dir) os.chdir(output_dir) - f = root.TFile(kin_file) - tree = f.Get("o2sim") - nEvents = tree.GetEntries() - print(f"Found {nEvents} events in {kin_file}") - - sim_command_to_run = ['o2-sim','-g','extkinO2','-n',str(nEvents),'-o',output_name,'--extKinFile',kin_file,'--noGeant','--forwardKine','--noDiscOutput'] - print("running reader with: ",end='') - print(*sim_command_to_run) - print("redirect reader output to "+sim_log_file) - - fs = open(sim_log_file, "w") - simproc = subprocess.Popen(sim_command_to_run, stdout=fs, stderr=subprocess.STDOUT) + publisher_command_to_run = ['o2-sim-kine-publisher','--kineFileName',kin_file,'--aggregate-timeframe','1','-b'] + ana_command_to_run = ['o2-analysis-em-lmee-lf-cocktail','--configuration','json://'+json_file,'-b'] - proxy_command_to_run = ['o2-sim-mctracks-proxy','--nevents',str(nEvents),'--o2sim-pid',str(simproc.pid)] - ana_command_to_run = ['o2-analysis-em-lmee-lf-cocktail', '--configuration','json://'+json_file,'-b'] print("running analysis with: ",end='') - print(*proxy_command_to_run,end='') + print(*publisher_command_to_run,end='') print(" | ",end='') print(*ana_command_to_run) print("redirect analysis output to "+ana_log_file) - fa = open(ana_log_file,"w") - proxyproc = subprocess.Popen(proxy_command_to_run, stdout=subprocess.PIPE) - anaproc = subprocess.Popen(ana_command_to_run, stdin=proxyproc.stdout, stdout=fa, stderr=subprocess.STDOUT) + command=' '.join(publisher_command_to_run) + ' | ' + ' '.join(ana_command_to_run) print("\nrunning...\n") - simproc.communicate() - if not simproc.returncode==0: - print("ERROR: Reader finished with error. See "+abspath(join(args.output,name+"_serverlog"))+" and "+sim_log_file+" for details\n") - proxyproc.kill(); - anaproc.kill(); - proxyproc.communicate() - anaproc.communicate() - fs.close() - fa.close() + returncode = os.system(command+' > '+ana_log_file) print("...done\n") - - if not anaproc.returncode==0: + if not returncode==0: print("ERROR: Analysis task finished with error. See "+abspath(join(args.output,"analog"))+" for details\n") else: print("Analysis task finished successful. Histograms in "+output_dir+"/AnalysisResults.root\n") @@ -186,10 +161,10 @@ def run_only_analysis_task(args): clean(args.output,name,False) - if (not simproc.returncode) and (not anaproc.returncode): - return 0 - else: + if not returncode==0: return 1 + else: + return 0 def run_full(args): sim_log_name = "simlog" @@ -221,7 +196,7 @@ def run_full(args): fs = open(sim_log_file, "w") simproc = subprocess.Popen(sim_command_to_run, stdout=fs, stderr=subprocess.STDOUT) - proxy_command_to_run = ['o2-sim-mctracks-proxy','--nevents',args.nEvents,'--o2sim-pid',str(simproc.pid)] + proxy_command_to_run = ['o2-sim-mctracks-proxy','--nevents',args.nEvents,'--o2sim-pid',str(simproc.pid),'--aggregate-timeframe','1','-b'] ana_command_to_run = ['o2-analysis-em-lmee-lf-cocktail','--configuration','json://'+json_file,'-b'] print("running analysis with: ",end='') print(*proxy_command_to_run,end='') diff --git a/Tutorials/PWGEM/pcm/CMakeLists.txt b/Tutorials/PWGEM/pcm/CMakeLists.txt new file mode 100644 index 00000000000..e3ec5e02758 --- /dev/null +++ b/Tutorials/PWGEM/pcm/CMakeLists.txt @@ -0,0 +1,15 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +o2physics_add_dpl_workflow(pcm-tutorial + SOURCES pcmtutorial.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME AnalysisTutorial) diff --git a/Tutorials/PWGEM/pcm/pcmtutorial.cxx b/Tutorials/PWGEM/pcm/pcmtutorial.cxx new file mode 100644 index 00000000000..0832ef18ebc --- /dev/null +++ b/Tutorials/PWGEM/pcm/pcmtutorial.cxx @@ -0,0 +1,152 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \brief tutorial for pcm analysis. +/// \author daiki.sekihata@cern.ch + +#include +#include + +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Common/Core/trackUtilities.h" +#include "CommonConstants/PhysicsConstants.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +struct PCMTutorial { + + Configurable mincrossedrows{"mincrossedrows", 40, "min. crossed rows"}; + Configurable maxchi2tpc{"maxchi2tpc", 4.0, "max. chi2/NclsTPC"}; + Configurable minpt{"minpt", 0.05, "min pt for track"}; + Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; + Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 4.0, "max. TPC n sigma for electron"}; + Configurable dcamin{"dcamin", 0.1, "dcamin"}; + Configurable dcamax{"dcamax", 1e+10, "dcamax"}; + + HistogramRegistry fRegistry{ + "fRegistry", + { + {"hVertexZ", "z vtx; z vtx (cm);Number of Events", {HistType::kTH1F, {{100, -50.f, +50.f}}}}, + {"hV0Pt", "p_{T} of V0;V0 p_{T} (GeV/c)", {HistType::kTH1F, {{1000, 0.f, 10.f}}}}, + {"hV0MK0S", "mass K0S;m_{#pi^{+}#pi^{-}} (GeV/c^{2})", {HistType::kTH1F, {{200, 0.4f, 0.6f}}}}, + {"hV0MGamma", "mass #gamma;m_{ee} (GeV/c^{2})", {HistType::kTH1F, {{100, 0.f, 0.1f}}}}, + {"hV0EtaPhi", "#eta vs. #varphi of V0;#varphi (rad.);#eta", {HistType::kTH2F, {{72, 0.f, TMath::TwoPi()}, {200, -1.f, +1.f}}}}, + {"hV0AP", "Armenteros Podolanski;#alpha;q_{T} (GeV/c)", {HistType::kTH2F, {{200, -1, +1}, {250, 0.0, 0.25f}}}}, + {"hMgg", "2-photon invariant mass;m_{#gamma#gamma} (GeV/c^{2})", {HistType::kTH1F, {{200, 0.f, 0.8f}}}}, + }, + }; + + void init(InitContext const&) + { + auto hEventCounter = fRegistry.add("hEventCounter", "hEventCounter", kTH1F, {{5, 0.5f, 5.5f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "all"); + hEventCounter->GetXaxis()->SetBinLabel(2, "FT0AND"); + hEventCounter->GetXaxis()->SetBinLabel(3, "|Z_{vtx}| < 10 cm"); + } + + template + bool checkV0(TV0 const& v0) + { + if (!checkAP(v0.alpha(), v0.qtarm(), 0.95, 0.03)) { // select photon conversions + return false; + } + auto pos = v0.template posTrack_as(); // positive daughter + auto ele = v0.template negTrack_as(); // negative daughter + if (!checkV0leg(pos) || !checkV0leg(ele)) { + return false; + } + return true; + } + + template + bool checkV0leg(TTrack const& track) + { + if (!track.hasITS() && !track.hasTPC()) { + return false; + } + + if (track.pt() < minpt || abs(track.eta()) > maxeta) { + return false; + } + if (abs(track.dcaXY()) < dcamin || dcamax < abs(track.dcaXY())) { + return false; + } + + if (track.tpcNClsCrossedRows() < mincrossedrows || track.tpcChi2NCl() > maxchi2tpc) { + return false; + } + if (abs(track.tpcNSigmaEl()) > maxTPCNsigmaEl) { + return false; + } + return true; + } + + using MyTracks = soa::Join; + using MyCollisions = soa::Join; + Preslice perCollision = aod::v0data::collisionId; + + void process(MyCollisions const& collisions, aod::BCsWithTimestamps const&, aod::V0Datas const& v0s, MyTracks const& tracks) + { + for (auto& collision : collisions) { + fRegistry.fill(HIST("hEventCounter"), 1); + + if (!collision.sel8()) { + continue; + } + fRegistry.fill(HIST("hEventCounter"), 2); + + if (abs(collision.posZ()) > 10.f) { + continue; + } + fRegistry.fill(HIST("hEventCounter"), 3); + fRegistry.fill(HIST("hVertexZ"), collision.posZ()); + + auto v0s_per_coll = v0s.sliceBy(perCollision, collision.globalIndex()); + for (auto& v0 : v0s_per_coll) { + fRegistry.fill(HIST("hV0AP"), v0.alpha(), v0.qtarm()); + + if (!checkV0(v0)) { + continue; + } + + fRegistry.fill(HIST("hV0Pt"), v0.pt()); + fRegistry.fill(HIST("hV0EtaPhi"), v0.phi(), v0.eta()); + fRegistry.fill(HIST("hV0MK0S"), v0.mK0Short()); + fRegistry.fill(HIST("hV0MGamma"), v0.mGamma()); + + } // end of v0 loop + + for (auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(v0s_per_coll, v0s_per_coll))) { + if (!checkV0(g1) || !checkV0(g2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + fRegistry.fill(HIST("hMgg"), v12.M()); + } // end of pairing loop + } // end of collision loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"pcm-tutorial"})}; +} diff --git a/Tutorials/PWGHF/taskMini.cxx b/Tutorials/PWGHF/taskMini.cxx index 8bff496fd66..80dabac7bb3 100644 --- a/Tutorials/PWGHF/taskMini.cxx +++ b/Tutorials/PWGHF/taskMini.cxx @@ -27,6 +27,7 @@ #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" using namespace o2; @@ -35,12 +36,6 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; -// Constants -static const double massPi = RecoDecay::getMassPDG(kPiPlus); -static const double massK = RecoDecay::getMassPDG(kKPlus); -static const auto arrMassPiK = std::array{massPi, massK}; -static const auto arrMassKPi = std::array{massK, massPi}; - // Track selection ===================================================================== namespace o2::aod @@ -71,7 +66,7 @@ struct HfTagSelTracks { "registry", {}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { const TString strTitle = "D^{0} candidates"; const TString strPt = "#it{p}_{T}^{track} (GeV/#it{c})"; @@ -84,7 +79,7 @@ struct HfTagSelTracks { void process(TracksWithDca const& tracks) { - for (auto const& track : tracks) { + for (const auto& track : tracks) { bool statusProng = true; auto ptTrack = track.pt(); @@ -151,6 +146,8 @@ struct HfTrackIndexSkimCreator { Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations if chi2/chi2old > this"}; + HfHelper hfHelper; + using SelectedTracks = soa::Filtered>; Filter filterSelectTracks = aod::hf_seltrack::isSelProng == true; @@ -163,7 +160,7 @@ struct HfTrackIndexSkimCreator { {"hVtx2ProngZ", "2-prong candidates;#it{z}_{sec. vtx.} (cm);entries", {HistType::kTH1F, {{1000, -20., 20.}}}}, {"hMassD0ToPiK", "D^{0} candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 0., 5.}}}}}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { } @@ -181,14 +178,14 @@ struct HfTrackIndexSkimCreator { df2.setUseAbsDCA(useAbsDCA); // loop over positive tracks - for (auto const& trackPos1 : tracks) { + for (const auto& trackPos1 : tracks) { if (trackPos1.signed1Pt() < 0) { continue; } auto trackParVarPos1 = getTrackParCov(trackPos1); // loop over negative tracks - for (auto const& trackNeg1 : tracks) { + for (const auto& trackNeg1 : tracks) { if (trackNeg1.signed1Pt() > 0) { continue; } @@ -201,8 +198,8 @@ struct HfTrackIndexSkimCreator { // get secondary vertex const auto& secondaryVertex = df2.getPCACandidate(); // get track momenta - array pVec0; - array pVec1; + std::array pVec0; + std::array pVec1; df2.getTrack(0).getPxPyPzGlo(pVec0); df2.getTrack(1).getPxPyPzGlo(pVec1); @@ -215,7 +212,7 @@ struct HfTrackIndexSkimCreator { registry.fill(HIST("hVtx2ProngY"), secondaryVertex[1]); registry.fill(HIST("hVtx2ProngZ"), secondaryVertex[2]); std::array, 2> arrMom = {pVec0, pVec1}; - auto mass2Prong = RecoDecay::m(arrMom, arrMassPiK); + auto mass2Prong = RecoDecay::m(arrMom, std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassKPlus}); registry.fill(HIST("hMassD0ToPiK"), mass2Prong); } } @@ -251,7 +248,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptProng1, //! pt of prong 1 [](float px, float py) -> float { return RecoDecay::pt(px, py); }); // candidate properties DECLARE_SOA_DYNAMIC_COLUMN(DecayLength, decayLength, //! decay length of candidate - [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { return RecoDecay::distance(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}); }); + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS) -> float { return RecoDecay::distance(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}); }); DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! pt of candidate [](float px, float py) -> float { return RecoDecay::pt(px, py); }); DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! px of candidate @@ -261,29 +258,9 @@ DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! py of candidate DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! pz of candidate float, 1.f * pzProng0 + 1.f * pzProng1); DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! invariant mass of candidate - [](float px0, float py0, float pz0, float px1, float py1, float pz1, const array& m) -> float { return RecoDecay::m(array{array{px0, py0, pz0}, array{px1, py1, pz1}}, m); }); + [](float px0, float py0, float pz0, float px1, float py1, float pz1, const std::array& m) -> float { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, m); }); DECLARE_SOA_DYNAMIC_COLUMN(CPA, cpa, //! cosine of pointing angle of candidate - [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::cpa(array{xVtxP, yVtxP, zVtxP}, array{xVtxS, yVtxS, zVtxS}, array{px, py, pz}); }); - -/// @brief Invariant mass of a D0 -> π K candidate -/// @tparam T -/// @param candidate -/// @return invariant mass -template -auto invMassD0(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kPiPlus), RecoDecay::getMassPDG(kKPlus)}); -} - -/// @brief Invariant mass of a D0bar -> K π candidate -/// @tparam T -/// @param candidate -/// @return invariant mass -template -auto invMassD0bar(const T& candidate) -{ - return candidate.m(array{RecoDecay::getMassPDG(kKPlus), RecoDecay::getMassPDG(kPiPlus)}); -} + [](float xVtxP, float yVtxP, float zVtxP, float xVtxS, float yVtxS, float zVtxS, float px, float py, float pz) -> float { return RecoDecay::cpa(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, std::array{px, py, pz}); }); } // namespace hf_cand_prong2 // Candidate table @@ -325,6 +302,8 @@ struct HfCandidateCreator2Prong { Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any X is smaller than this"}; Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations if chi2/chi2old > this"}; + HfHelper hfHelper; + double massPiK{0.}; double massKPi{0.}; @@ -347,7 +326,7 @@ struct HfCandidateCreator2Prong { df.setUseAbsDCA(useAbsDCA); // loop over pairs of track indices - for (auto const& rowTrackIndexProng2 : rowsTrackIndexProng2) { + for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { auto track0 = rowTrackIndexProng2.prong0_as(); auto track1 = rowTrackIndexProng2.prong1_as(); auto trackParVarPos1 = getTrackParCov(track0); @@ -363,8 +342,8 @@ struct HfCandidateCreator2Prong { auto trackParVar1 = df.getTrack(1); // get track momenta - array pVec0; - array pVec1; + std::array pVec0; + std::array pVec1; trackParVar0.getPxPyPzGlo(pVec0); trackParVar1.getPxPyPzGlo(pVec1); @@ -379,8 +358,8 @@ struct HfCandidateCreator2Prong { // fill histograms // calculate invariant masses auto arrayMomenta = std::array{pVec0, pVec1}; - massPiK = RecoDecay::m(arrayMomenta, arrMassPiK); - massKPi = RecoDecay::m(arrayMomenta, arrMassKPi); + massPiK = RecoDecay::m(arrayMomenta, std::array{o2::analysis::pdg::MassPiPlus, o2::analysis::pdg::MassKPlus}); + massKPi = RecoDecay::m(arrayMomenta, std::array{o2::analysis::pdg::MassKPlus, o2::analysis::pdg::MassPiPlus}); hMass->Fill(massPiK); // hMass->Fill(massKPi); } @@ -425,9 +404,20 @@ struct HfCandidateSelectorD0 { Configurable cpaMin{"cpaMin", 0.98, "Min. cosine of pointing angle"}; Configurable massWindow{"massWindow", 0.4, "Half-width of the invariant-mass window"}; + HfHelper hfHelper; + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + using TracksWithPid = soa::Join; + aod::pidTPCFullPi, aod::pidTPCFullKa, + aod::pidTOFFullPi, aod::pidTOFFullKa>; + + void init(InitContext const&) + { + selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-nSigmaTpc, nSigmaTpc); + selectorKaon = selectorPion; + } /// Conjugate-independent topological cuts /// \param candidate is candidate @@ -457,11 +447,11 @@ struct HfCandidateSelectorD0 { { // invariant-mass cut if (trackPion.sign() > 0) { - if (std::abs(invMassD0(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > massWindow) { + if (std::abs(hfHelper.invMassD0ToPiK(candidate) - o2::analysis::pdg::MassD0) > massWindow) { return false; } } else { - if (std::abs(invMassD0bar(candidate) - RecoDecay::getMassPDG(pdg::Code::kD0)) > massWindow) { + if (std::abs(hfHelper.invMassD0barToKPi(candidate) - o2::analysis::pdg::MassD0) > massWindow) { return false; } } @@ -471,15 +461,8 @@ struct HfCandidateSelectorD0 { void process(aod::HfCandProng2 const& candidates, TracksWithPid const&) { - TrackSelectorPID selectorPion(kPiPlus); - selectorPion.setRangePtTPC(ptPidTpcMin, ptPidTpcMax); - selectorPion.setRangeNSigmaTPC(-nSigmaTpc, nSigmaTpc); - - TrackSelectorPID selectorKaon(selectorPion); - selectorKaon.setPDG(kKPlus); - // looping over 2-prong candidates - for (auto const& candidate : candidates) { + for (const auto& candidate : candidates) { // final selection flag: 0 - rejected, 1 - accepted int statusD0 = 0; @@ -505,31 +488,31 @@ struct HfCandidateSelectorD0 { } // track-level PID selection - int pidTrackPosKaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackPos); - int pidTrackPosPion = selectorPion.getStatusTrackPIDTpcOrTof(trackPos); - int pidTrackNegKaon = selectorKaon.getStatusTrackPIDTpcOrTof(trackNeg); - int pidTrackNegPion = selectorPion.getStatusTrackPIDTpcOrTof(trackNeg); + int pidTrackPosKaon = selectorKaon.statusTpcOrTof(trackPos); + int pidTrackPosPion = selectorPion.statusTpcOrTof(trackPos); + int pidTrackNegKaon = selectorKaon.statusTpcOrTof(trackNeg); + int pidTrackNegPion = selectorPion.statusTpcOrTof(trackNeg); int pidD0 = -1; int pidD0bar = -1; - if (pidTrackPosPion == TrackSelectorPID::Status::PIDAccepted && - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted) { + if (pidTrackPosPion == TrackSelectorPID::Accepted && + pidTrackNegKaon == TrackSelectorPID::Accepted) { pidD0 = 1; // accept D0 - } else if (pidTrackPosPion == TrackSelectorPID::Status::PIDRejected || - pidTrackNegKaon == TrackSelectorPID::Status::PIDRejected || - pidTrackNegPion == TrackSelectorPID::Status::PIDAccepted || - pidTrackPosKaon == TrackSelectorPID::Status::PIDAccepted) { + } else if (pidTrackPosPion == TrackSelectorPID::Rejected || + pidTrackNegKaon == TrackSelectorPID::Rejected || + pidTrackNegPion == TrackSelectorPID::Accepted || + pidTrackPosKaon == TrackSelectorPID::Accepted) { pidD0 = 0; // exclude D0 } - if (pidTrackNegPion == TrackSelectorPID::Status::PIDAccepted && - pidTrackPosKaon == TrackSelectorPID::Status::PIDAccepted) { + if (pidTrackNegPion == TrackSelectorPID::Accepted && + pidTrackPosKaon == TrackSelectorPID::Accepted) { pidD0bar = 1; // accept D0bar - } else if (pidTrackPosPion == TrackSelectorPID::Status::PIDAccepted || - pidTrackNegKaon == TrackSelectorPID::Status::PIDAccepted || - pidTrackNegPion == TrackSelectorPID::Status::PIDRejected || - pidTrackPosKaon == TrackSelectorPID::Status::PIDRejected) { + } else if (pidTrackPosPion == TrackSelectorPID::Accepted || + pidTrackNegKaon == TrackSelectorPID::Accepted || + pidTrackNegPion == TrackSelectorPID::Rejected || + pidTrackPosKaon == TrackSelectorPID::Rejected) { pidD0bar = 0; // exclude D0bar } @@ -557,13 +540,15 @@ struct HfTaskD0 { Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection flag for D0 bar"}; + HfHelper hfHelper; + Partition> selectedD0Candidates = aod::hf_selcandidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_selcandidate_d0::isSelD0bar >= selectionFlagD0bar; HistogramRegistry registry{ "registry", {}}; - void init(o2::framework::InitContext&) + void init(InitContext&) { const TString strTitle = "D^{0} candidates"; const TString strPt = "#it{p}_{T} (GeV/#it{c})"; @@ -575,12 +560,12 @@ struct HfTaskD0 { void process(soa::Join const& candidates) { - for (auto const& candidate : selectedD0Candidates) { + for (const auto& candidate : selectedD0Candidates) { if (candidate.isSelD0() >= selectionFlagD0) { - registry.fill(HIST("hMass"), invMassD0(candidate)); + registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate)); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { - registry.fill(HIST("hMass"), invMassD0bar(candidate)); + registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate)); } registry.fill(HIST("hPtCand"), candidate.pt()); registry.fill(HIST("hCpaVsPtCand"), candidate.cpa(), candidate.pt()); diff --git a/Tutorials/PWGUD/UDTutorial_02b.cxx b/Tutorials/PWGUD/UDTutorial_02b.cxx index 57b4fc4b31b..9ed26018c48 100644 --- a/Tutorials/PWGUD/UDTutorial_02b.cxx +++ b/Tutorials/PWGUD/UDTutorial_02b.cxx @@ -94,7 +94,7 @@ struct UDTutorial02b { } // skip events with out-of-range net charge - auto netChargeValues = anaPars.netCharges(); + auto netChargeValues = anaPars.unlikeCharges(); if (std::find(netChargeValues.begin(), netChargeValues.end(), dgcand.netCharge()) == netChargeValues.end()) { if (verbose) { LOGF(info, " Candidate rejected: Net charge %d not in selected set.", dgcand.netCharge()); @@ -127,11 +127,11 @@ struct UDTutorial02b { // find track combinations which are compatible with PID cuts auto nIVMs = pidsel.computeIVMs(PVContributors); if (verbose) { - LOGF(info, "< Found %d candidates", nIVMs); + LOGF(info, "< Found %d/%d candidates", nIVMs[0], nIVMs[1]); } // update histograms - for (auto ivm : pidsel.IVMs()) { + for (auto ivm : pidsel.unlikeIVMs()) { // cut on pt-system if (ivm.Perp() < anaPars.minptsys() || ivm.Perp() > anaPars.maxptsys()) { continue; diff --git a/Tutorials/Skimming/spectraUPCProvider.cxx b/Tutorials/Skimming/spectraUPCProvider.cxx index fe7b81c374d..053b7437080 100644 --- a/Tutorials/Skimming/spectraUPCProvider.cxx +++ b/Tutorials/Skimming/spectraUPCProvider.cxx @@ -24,6 +24,7 @@ #include "DataModel/UDDerived.h" using namespace o2; +using namespace o2::aod::evsel; using namespace o2::framework; using namespace o2::framework::expressions; @@ -33,17 +34,17 @@ struct UPCSpectraProviderTask { Filter trackFilter = (requireGlobalTrackInFilter()); - void process(soa::Join::iterator const& collision, soa::Filtered> const& tracks) + void process(soa::Join::iterator const& col, soa::Filtered> const& tracks) { - bool checkV0 = collision.bbV0A() || collision.bbV0C() || collision.bgV0A() || collision.bgV0C(); + bool checkV0 = col.selection_bit(kIsBBV0A) || col.selection_bit(kIsBBV0C) || !col.selection_bit(kNoBGV0A) || !col.selection_bit(kNoBGV0C); if (checkV0) { return; } - bool checkFDD = collision.bbFDA() || collision.bbFDC() || collision.bgFDA() || collision.bgFDC(); + bool checkFDD = col.selection_bit(kIsBBFDA) || col.selection_bit(kIsBBFDC) || !col.selection_bit(kNoBGFDA) || !col.selection_bit(kNoBGFDC); if (checkFDD) { return; } - if (!collision.alias_bit(kCUP9)) { + if (!col.alias_bit(kCUP9)) { return; } if (tracks.size() != 2) { diff --git a/Tutorials/Skimming/spectraUPCReference.cxx b/Tutorials/Skimming/spectraUPCReference.cxx index 41d4997a800..f0a26f248f8 100644 --- a/Tutorials/Skimming/spectraUPCReference.cxx +++ b/Tutorials/Skimming/spectraUPCReference.cxx @@ -22,6 +22,7 @@ #include "TLorentzVector.h" using namespace o2; +using namespace o2::aod::evsel; using namespace o2::framework; using namespace o2::framework::expressions; @@ -40,11 +41,11 @@ struct UPCSpectraReferenceTask { void process(soa::Join::iterator const& col, soa::Filtered> const& tracks) { - bool checkV0 = col.bbV0A() || col.bbV0C() || col.bgV0A() || col.bgV0C(); + bool checkV0 = col.selection_bit(kIsBBV0A) || col.selection_bit(kIsBBV0C) || !col.selection_bit(kNoBGV0A) || !col.selection_bit(kNoBGV0C); if (checkV0) { return; } - bool checkFDD = col.bbFDA() || col.bbFDC() || col.bgFDA() || col.bgFDC(); + bool checkFDD = col.selection_bit(kIsBBFDA) || col.selection_bit(kIsBBFDC) || !col.selection_bit(kNoBGFDA) || !col.selection_bit(kNoBGFDC); if (checkFDD) { return; } diff --git a/Tutorials/src/configurableObjects.cxx b/Tutorials/src/configurableObjects.cxx index a2556baf256..210d93c0dac 100644 --- a/Tutorials/src/configurableObjects.cxx +++ b/Tutorials/src/configurableObjects.cxx @@ -14,10 +14,11 @@ /// \author /// \since +#include + #include "configurableCut.h" #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" -#include using namespace o2; using namespace o2::framework; @@ -55,6 +56,8 @@ auto printMatrix(Array2D const& m) static constexpr float defaultm[3][4] = {{1.1, 1.2, 1.3, 1.4}, {2.1, 2.2, 2.3, 2.4}, {3.1, 3.2, 3.3, 3.4}}; static LabeledArray la{&defaultm[0][0], 3, 4, {"r 1", "r 2", "r 3"}, {"c 1", "c 2", "c 3", "c 4"}}; +const std::string defaultmS[3][4] = {{"One.One", "One.Two", "One.Three", "One.Four"}, {"Two.One", "Two.Two", "Two.Three", "Two.Four"}, {"Three.One", "Three.Two", "Three.Three", "Three.Four"}}; +static LabeledArray laS{&defaultmS[0][0], 3, 4, {"rS 1", "rS 2", "rS 3"}, {"cS 1", "cS 2", "cS 3", "cS 4"}}; struct ConfigurableObjectDemo { // Simple type configurables @@ -71,7 +74,8 @@ struct ConfigurableObjectDemo { Configurable> farray{"farray", {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}, "generic float array"}; Configurable> darray{"darray", {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}, "generic double array"}; Configurable> vmatrix{"matrix", {&defaultm[0][0], 3, 4}, "generic matrix"}; - Configurable> vla{"vla", {defaultm[0], 3, 4, {"r 1", "r 2", "r 3"}, {"c 1", "c 2", "c 3", "c 4"}}, "labeled array"}; + Configurable> vla{"vla", {defaultm[0], 3, 4, {"r 1", "r 2", "r 3"}, {"c 1", "c 2", "c 3", "c 4"}}, "labeled array with float content"}; + Configurable> vlaS{"vlaS", {defaultmS[0], 3, 4, {"rS 1", "rS 2", "rS 3"}, {"cS 1", "cS 2", "cS 3", "cS 4"}}, "labeled array with string content"}; // Configurables can be grouped into `ConfigurableGroup`s. // Their names must be unique. @@ -93,7 +97,8 @@ struct ConfigurableObjectDemo { auto fvec = (std::vector)farray; LOGF(info, "Float array: %s", printArray(fvec).c_str()); LOGF(info, "Matrix: %s", printMatrix((Array2D)vmatrix)); - LOGF(info, "Labeled:\n %s\n %s\n %s", printArray(vla->getLabelsRows()), printArray(vla->getLabelsCols()), printMatrix(vla->getData())); + LOGF(info, "Labeled float array:\n %s\n %s\n %s", printArray(vla->getLabelsRows()), printArray(vla->getLabelsCols()), printMatrix(vla->getData())); + LOGF(info, "Labeled std::string array:\n %s\n %s\n %s", printArray(vlaS->getLabelsRows()), printArray(vlaS->getLabelsCols()), printMatrix(vlaS->getData())); }; void process(aod::Collision const&, aod::Tracks const& tracks) diff --git a/Tutorials/src/mcHistograms.cxx b/Tutorials/src/mcHistograms.cxx index 075a02f45ac..2257edae593 100644 --- a/Tutorials/src/mcHistograms.cxx +++ b/Tutorials/src/mcHistograms.cxx @@ -42,7 +42,7 @@ struct VertexDistribution { // Simple analysis of PhysicalPrimary particles struct PhysicalPrimaryCharge { OutputObj charge{TH1F("charge_prim", "charge_prim", 100, -5, 5)}; - Service pdgDB; + Service pdg; void process(aod::McParticles const& mcParticles) { @@ -50,7 +50,7 @@ struct PhysicalPrimaryCharge { if (!particle.isPhysicalPrimary()) { continue; } - auto pdgParticle = pdgDB->GetParticle(particle.pdgCode()); + auto pdgParticle = pdg->GetParticle(particle.pdgCode()); if (!pdgParticle) { continue; } @@ -117,6 +117,10 @@ struct AccessMcTruth { aod::McParticles const& mcParticles, aod::McCollisions const& mcCollisions) { // access MC truth information with mcCollision() and mcParticle() methods + if (!collision.has_mcCollision()) { + LOGF(warning, "No MC collision for this collision, skip..."); + return; + } if (reduceOutput < 2) { LOGF(info, "vtx-z (data) = %f | vtx-z (MC) = %f", collision.posZ(), collision.mcCollision().posZ()); } @@ -146,7 +150,7 @@ struct AccessMcTruth { } }; -// Loop over MCColisions and get corresponding collisions (there can be more than one) +// Loop over MCCollisions and get corresponding collisions (there can be more than one) // For each of them get the corresponding tracks // Note the use of "SmallGroups" template, that allows to handle both Run 2, where // we have exactly 1-to-1 correspondence between collisions and mc collisions, and diff --git a/Tutorials/src/propagatedTracks.cxx b/Tutorials/src/propagatedTracks.cxx index e1f3a9f7242..eb27376dfa5 100644 --- a/Tutorials/src/propagatedTracks.cxx +++ b/Tutorials/src/propagatedTracks.cxx @@ -28,6 +28,7 @@ #include "Framework/runDataProcessing.h" using namespace o2; +using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/Tutorials/src/usingPDGService.cxx b/Tutorials/src/usingPDGService.cxx index d0f673b5686..72b0188142e 100644 --- a/Tutorials/src/usingPDGService.cxx +++ b/Tutorials/src/usingPDGService.cxx @@ -11,24 +11,31 @@ #include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "TDatabasePDG.h" #include "Framework/runDataProcessing.h" using namespace o2; using namespace o2::framework; struct UsePdgDatabase { - Service pdg; + Service pdg; OutputObj particleCharges{TH1F("charges", ";charge;entries", 201, -10.1, 10.1)}; + OutputObj particleMasses{TH1F("masses", ";mass (GeV/#it{c}^{2});entries", 1000, 0., 10.)}; void process(aod::McCollision const&, aod::McParticles const& particles) { - for (auto& particle : particles) { - auto pdgInfo = pdg->GetParticle(particle.pdgCode()); + for (auto const& particle : particles) { + auto pdgCode = particle.pdgCode(); + // Using the o2::framework::O2DatabasePDGImpl features + auto mass = pdg->Mass(pdgCode); + if (mass >= 0.) { + particleMasses->Fill(mass); + } + // Using the TDatabasePDG features + auto pdgInfo = pdg->GetParticle(pdgCode); if (pdgInfo != nullptr) { particleCharges->Fill(pdgInfo->Charge()); } else { - LOGF(warn, "[%d] unknown particle with PDG code %d", particle.globalIndex(), particle.pdgCode()); + LOGF(warn, "[%d] unknown particle with PDG code %d", particle.globalIndex(), pdgCode); } } } diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000000..edc61be3e96 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,12 @@ +[tool.black] +line-length = 120 + +[tool.isort] +profile = "black" + +[tool.pyright] +reportMissingImports = false +reportUnboundVariable = false + +[tool.ruff] +line-length = 120 diff --git a/pyrightconfig.json b/pyrightconfig.json deleted file mode 100644 index fd2a73c530c..00000000000 --- a/pyrightconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "reportMissingImports": false, - "reportUnboundVariable": false -}