From a5910ed47c18a76b45cb2985be287d9087deaf69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Wed, 1 Jun 2022 20:15:54 +0200 Subject: [PATCH] DPG: allow hyperloop running on derived data - Separate split and non split tasks - Add more histos for MC - Fix process function of MC --- DPG/Tasks/CMakeLists.txt | 5 + DPG/Tasks/qaEventTrack.cxx | 281 +-------------------------------- DPG/Tasks/qaEventTrack.h | 91 +++++++++++ DPG/Tasks/qaEventTrackLite.cxx | 243 ++++++++++++++++++++++++++++ 4 files changed, 345 insertions(+), 275 deletions(-) create mode 100644 DPG/Tasks/qaEventTrack.h create mode 100644 DPG/Tasks/qaEventTrackLite.cxx diff --git a/DPG/Tasks/CMakeLists.txt b/DPG/Tasks/CMakeLists.txt index 079362bdc26..aab96b43ab1 100644 --- a/DPG/Tasks/CMakeLists.txt +++ b/DPG/Tasks/CMakeLists.txt @@ -14,6 +14,11 @@ o2physics_add_dpl_workflow(qa-event-track PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(qa-event-track-lite + SOURCES qaEventTrackLite.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(qa-efficiency SOURCES qaEfficiency.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/DPG/Tasks/qaEventTrack.cxx b/DPG/Tasks/qaEventTrack.cxx index 6156fda5253..7ec5ada83d0 100644 --- a/DPG/Tasks/qaEventTrack.cxx +++ b/DPG/Tasks/qaEventTrack.cxx @@ -20,12 +20,14 @@ /// This task can also be configured to produce a table with reduced information used for correlation studies for track selection /// +#include "qaEventTrack.h" + #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisDataModel.h" #include "ReconstructionDataFormats/DCA.h" #include "Common/Core/trackUtilities.h" - -#include "Framework/AnalysisDataModel.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/TrackSelection.h" @@ -34,93 +36,10 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; - -void customize(std::vector& workflowOptions) -{ - std::vector options{{"lite", VariantType::Int, 0, {"Run on skimmed DPG tracks"}}}; - std::swap(workflowOptions, options); -} - -#include "Framework/runDataProcessing.h" - -using namespace o2::framework; using namespace o2::dataformats; // TODO: add PID wagons as dependency + include impact parameter studies (same or separate task in workflow??) -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -// Output table declaration -//-------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------- -namespace o2::aod -{ - -namespace dpgcollision -{ -DECLARE_SOA_INDEX_COLUMN(BC, bc); -DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); -DECLARE_SOA_COLUMN(RunNumber, runNumber, int); -} // namespace dpgcollision - -DECLARE_SOA_TABLE(DPGCollisions, "AOD", "DPGCollisions", //! Table of the DPG collisions - collision::PosZ, - dpgcollision::IsEventReject, - dpgcollision::RunNumber); - -namespace dpgtrack -{ -DECLARE_SOA_INDEX_COLUMN(DPGCollision, dpgCollision); //! Index to move from track to collision -DECLARE_SOA_COLUMN(Pt, pt, float); //! Pt -DECLARE_SOA_COLUMN(Eta, eta, float); //! Eta -DECLARE_SOA_COLUMN(Phi, phi, float); //! Phi -DECLARE_SOA_COLUMN(PtReso, ptReso, float); //! Pt resolution -DECLARE_SOA_COLUMN(Sign, sign, short); //! Sign -DECLARE_SOA_COLUMN(HasITS, hasITS, bool); //! Track has the ITS -DECLARE_SOA_COLUMN(HasTPC, hasTPC, bool); //! Track has the TPC -DECLARE_SOA_COLUMN(HasTRD, hasTRD, bool); //! Track has the TRD -DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); //! Track has the TOF -DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, int16_t); //! Clusters found in TPC -DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, int16_t); //! Crossed rows found in TPC -DECLARE_SOA_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, float); //! Crossed rows over findable clusters in TPC -DECLARE_SOA_COLUMN(TPCFoundOverFindableCls, tpcFoundOverFindableCls, float); //! Found over findable clusters in TPC -DECLARE_SOA_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, float); //! Fraction of shared clusters in TPC -DECLARE_SOA_COLUMN(ITSNCls, itsNCls, uint8_t); //! Clusters found in ITS -DECLARE_SOA_COLUMN(ITSNClsInnerBarrel, itsNClsInnerBarrel, uint8_t); //! Clusters found in the inner barrel of the ITS - -} // namespace dpgtrack - -DECLARE_SOA_TABLE(DPGTracks, "AOD", "DPGTracks", //! Table of the DPG tracks - dpgtrack::DPGCollisionId, - dpgtrack::Pt, dpgtrack::Eta, dpgtrack::Phi, dpgtrack::PtReso, - track::Flags, dpgtrack::Sign, - track::DcaXY, track::DcaZ, track::Length, - track::ITSClusterMap, - track::ITSChi2NCl, track::TPCChi2NCl, track::TRDChi2, track::TOFChi2, - dpgtrack::HasITS, dpgtrack::HasTPC, dpgtrack::HasTRD, dpgtrack::HasTOF, - dpgtrack::TPCNClsFound, dpgtrack::TPCNClsCrossedRows, - dpgtrack::TPCCrossedRowsOverFindableCls, dpgtrack::TPCFoundOverFindableCls, dpgtrack::TPCFractionSharedCls, - dpgtrack::ITSNCls, dpgtrack::ITSNClsInnerBarrel); - -namespace dpgparticles -{ -DECLARE_SOA_COLUMN(PtMC, ptMC, float); //! Pt MC -DECLARE_SOA_COLUMN(EtaMC, etaMC, float); //! Eta MC -DECLARE_SOA_COLUMN(PhiMC, phiMC, float); //! Phi MC -DECLARE_SOA_COLUMN(ProductionMode, productionMode, int); //! ProductionMode i.e. non matched (-1), physical primary (0), weak decay product (1) or material (2) - -} // namespace dpgparticles - -DECLARE_SOA_TABLE(DPGRecoParticles, "AOD", "DPGRecoPart", //! Table of the DPG reconstructed particles - dpgparticles::PtMC, dpgparticles::EtaMC, dpgparticles::PhiMC, - mcparticle::PdgCode, dpgparticles::ProductionMode); - -DECLARE_SOA_TABLE(DPGNonRecoParticles, "AOD", "DPGNonRecoPart", //! Table of the DPG particles - dpgparticles::PtMC, dpgparticles::EtaMC, dpgparticles::PhiMC, - mcparticle::PdgCode, dpgparticles::ProductionMode, - mcparticle::Vx, mcparticle::Vy, mcparticle::Vz); -} // namespace o2::aod - //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- // Task declaration @@ -273,7 +192,7 @@ struct qaEventTrack { if (!collision.has_mcCollision()) { return; } - const auto particlesInCollision = particles.sliceBy(aod::mcparticle::mcCollisionId, collision.mcCollision().globalIndex()); + const auto& particlesInCollision = particles.sliceBy(aod::mcparticle::mcCollisionId, collision.mcCollision().globalIndex()); tableNonRecoParticles.reserve(particlesInCollision.size() - nTracks); for (const auto& particle : particlesInCollision) { const auto partReconstructed = std::find(recoPartIndices.begin(), recoPartIndices.end(), particle.globalIndex()) != recoPartIndices.end(); @@ -295,197 +214,9 @@ struct qaEventTrack { } }; -struct qaEventTrackLite { // Lite version of the QA task to run on skimmed dataset - 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, 2.0, 5.0, 10.0, 20.0, 50.0}, ""}; - ConfigurableAxis binsImpPar{"binsImpPar", {200, -0.15, 0.15}, "Impact parameter binning (cm)"}; - - HistogramRegistry histos; - - Configurable bItsStandalone{"bItsStandalone", false, "Select only ITS standalone DPG tracks"}; - Configurable bTpcOnly{"bTpcOnly", false, "Select only TPC only DPG tracks"}; - Configurable bItsTpcMatched{"bItsTpcMatched", false, "Select ITS-TPC matched DPG tracks"}; - // Kinematic selections - Configurable ptMin{"ptMin", 0., "Minimum track pt"}; - Configurable etaMin{"etaMin", -10., "Minimum eta for DPG tracks"}; - Configurable etaMax{"etaMax", 10., "Maximum eta for DPG tracks"}; - // ITS selections - Configurable chi2ItsMin{"chi2ItsMin", -1001.f, "Max ITS chi2"}; - Configurable chi2ItsMax{"chi2ItsMax", 1000.f, "Max ITS chi2"}; - // TPC selections - Configurable nClusterTpcMin{"nClusterTpcMin", -1001, "Minimum number of TPC clusters"}; - Configurable nCrossedRowsTpcMin{"nCrossedRowsTpcMin", -1001, "Minimum number of TPC crossed rows"}; - Configurable nCrossedRowsTpcOverFindableClustersTpcMin{"nCrossedRowsTpcOverFindableClustersTpcMin", -1, "Minimum ratio between TPC crossed rows and findable clusters"}; - Configurable chi2TpcMin{"chi2TpcMin", -1001.f, "Max TPC chi2"}; - Configurable chi2TpcMax{"chi2TpcMax", 1000.f, "Max TPC chi2"}; - // TOF selections - Configurable chi2TofMin{"chi2TofMin", -1001.f, "Max TOF chi2"}; - Configurable lengthMin{"lengthMin", -1001.f, "Min length"}; - - void init(InitContext const&) - { - const AxisSpec axisPt{binsPt, "#it{p}_{T} [GeV/c]"}; - - // kine histograms - histos.add("Tracks/VertexPositionZ", "", kTH1D, {{100, -20.f, 20.f, "Vertex Z [cm]"}}); - histos.add("Tracks/Kine/pt", "#it{p}_{T};#it{p}_{T} [GeV/c]", kTH1D, {{axisPt}}); - histos.add("Tracks/Kine/eta", "#eta;#eta", kTH1D, {{800, -2., 2.}}); - histos.add("Tracks/Kine/phi", "#phi;#phi [rad]", kTH1D, {{180, 0., 2 * M_PI}}); - histos.add("Tracks/length", "track length in cm;#it{Length} [cm];", kTH1D, {{400, 0, 1000}}); - const AxisSpec axisImpParRPhi{binsImpPar, "#it{d}_{r#it{#varphi}} (#cm)"}; - const AxisSpec axisImpParZAxis{binsImpPar, "#it{d}_{z} (#cm)"}; - histos.add("Tracks/dcaXY", "distance of closest approach in #it{xy} plane", kTH1D, {axisImpParRPhi}); - histos.add("Tracks/dcaZ", "distance of closest approach in #it{z}", kTH1D, {axisImpParZAxis}); - histos.add("Tracks/dcaXYvsPt", "d_#it{xy} vs. #it{p}_{T}", kTH2D, {axisPt, axisImpParRPhi}); - histos.add("Tracks/dcaZvsPt", "d_#it{z} vs. #it{p}_{T}", kTH2D, {axisPt, axisImpParRPhi}); - - // its histograms - histos.add("Tracks/ITS/itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", kTH1D, {{100, 0, 40}}); - histos.add("Tracks/ITS/itsNCl", "ITS number of clusters;# clusters ITS", kTH1D, {{8, -0.5, 7.5}}); - histos.add("Tracks/ITS/itsNClvsItsHitmap", "ITS number of clusters vs. ITS hitmap;# clusters ITS; ITS hitmap", kTH2D, {{8, -0.5, 7.5, "# clusters ITS"}, {128, 0, 128, "ITS hitmap"}}); - // tpc histograms - histos.add("Tracks/TPC/tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {{100, 0, 10}}); - histos.add("Tracks/TPC/tpcNClsFound", "number of found TPC clusters;# 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/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {{60, 0.7, 1.3}}); - histos.add("Tracks/TPC/tpcNClsFoundvsPt", "", kTH2D, {axisPt, {165, -0.5, 164.5, "# clusters TPC"}}); - histos.add("Tracks/TPC/tpcCrossedRowsvsPt", "", kTH2D, {axisPt, {165, -0.5, 164.5, "# crossed rows TPC"}}); - histos.add("Tracks/TPC/tpcCrossedRowsOverFindableClsvsPt", "", kTH2D, {axisPt, {60, 0.7, 1.3, "crossed rows / findable clusters TPC"}}); - // trd histograms - histos.add("Tracks/TRD/trdChi2", "chi2 in TRD", kTH1D, {{100, 0, 10, "chi2 / cluster TRD"}}); - // tof histograms - histos.add("Tracks/TOF/tofChi2", "chi2 in TOF", kTH1D, {{100, 0, 10, "chi2 / cluster TOF"}}); - // matching histogram - histos.add("Tracks/matchedDet", "matched detectors", kTH1D, {{4, 0.5, 4.5, ""}}); - histos.get(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(1, "hasTPC"); - histos.get(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(2, "hasITS"); - histos.get(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(3, "hasTRD"); - histos.get(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(4, "hasTOF"); - // kinematics - histos.add("Tracks/relativeResoPt", "relative #it{p}_{T} resolution;#sigma(#it{p}_{T})/#it{p}_{T};#it{p}_{T};", kTH2D, {{axisPt, {500, 0., 1, "#sigma{#it{p}}/#it{p}_{T}"}}}); - histos.add("Tracks/relativeResoPtMean", "mean relative #it{p}_{T} resolution;#LT(#it{p}_{T})/#it{p}_{T}#GT;#it{p}_{T};", kTProfile, {axisPt}); - - // MC histograms - if (doprocessMCLite) { - histos.add("Particle/PDGs", "Particle PDGs;PDG Code", kTH1D, {{100, 0.f, 100.f}}); - } - } - - /////////////// - /// Filters /// - /////////////// - // Kinematics - Filter ptCut = o2::aod::dpgtrack::pt > ptMin; - Filter etaCut = etaMin < o2::aod::dpgtrack::eta && o2::aod::dpgtrack::eta < etaMax; - // Detector matching - Filter itsStandaloneTracks = (bItsStandalone.node() == false) || (o2::aod::dpgtrack::hasITS == true && o2::aod::dpgtrack::hasTPC == false); - Filter tpcOnlyTracks = (bTpcOnly.node() == false) || (o2::aod::dpgtrack::hasITS == false && o2::aod::dpgtrack::hasTPC == true); - Filter itsTpcMatchedTracks = (bItsTpcMatched.node() == false) || (o2::aod::dpgtrack::hasITS == true && o2::aod::dpgtrack::hasTPC == true); - // ITS - Filter itsChi2 = (bTpcOnly.node() == true) || (chi2ItsMin < o2::aod::track::itsChi2NCl && o2::aod::track::itsChi2NCl < chi2ItsMax); - // TPC - Filter tpcChi2s = (bItsStandalone.node() == true) || (chi2TpcMin < o2::aod::track::tpcChi2NCl && o2::aod::track::tpcChi2NCl < chi2TpcMax); - Filter tpcNclusters = (bItsStandalone.node() == true) || (o2::aod::dpgtrack::tpcNClsFound > (int16_t)nClusterTpcMin); - Filter tpcNcrossedRows = (bItsStandalone.node() == true) || (o2::aod::dpgtrack::tpcNClsCrossedRows > (int16_t)nCrossedRowsTpcMin); - Filter tpcNcrossedRowsOverFindableClusters = (bItsStandalone.node() == true) || (o2::aod::dpgtrack::tpcCrossedRowsOverFindableCls > nCrossedRowsTpcOverFindableClustersTpcMin); - // TOF - Filter tofChi = o2::aod::track::tofChi2 > chi2TofMin; - Filter length = o2::aod::track::length > lengthMin; - - // Process data - void processDataLite(o2::soa::Filtered const& tracks, aod::DPGCollisions const&) - { - for (const auto& track : tracks) { - histos.fill(HIST("Tracks/VertexPositionZ"), track.dpgCollision().posZ()); - histos.fill(HIST("Tracks/Kine/pt"), track.pt()); - histos.fill(HIST("Tracks/Kine/eta"), track.eta()); - histos.fill(HIST("Tracks/Kine/phi"), track.phi()); - histos.fill(HIST("Tracks/dcaXY"), track.dcaXY()); - histos.fill(HIST("Tracks/dcaZ"), track.dcaZ()); - histos.fill(HIST("Tracks/dcaXYvsPt"), track.pt(), track.dcaXY()); - histos.fill(HIST("Tracks/dcaZvsPt"), track.pt(), track.dcaZ()); - histos.fill(HIST("Tracks/length"), track.length()); - histos.fill(HIST("Tracks/ITS/itsChi2NCl"), track.itsChi2NCl()); - histos.fill(HIST("Tracks/ITS/itsNCl"), track.itsNCls()); - histos.fill(HIST("Tracks/ITS/itsNClvsItsHitmap"), track.itsNCls(), track.itsClusterMap()); - histos.fill(HIST("Tracks/TPC/tpcChi2NCl"), track.tpcChi2NCl()); - histos.fill(HIST("Tracks/TPC/tpcNClsFound"), track.tpcNClsFound()); - histos.fill(HIST("Tracks/TPC/tpcCrossedRows"), track.tpcNClsCrossedRows()); - histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("Tracks/TPC/tpcNClsFoundvsPt"), track.pt(), track.tpcNClsFound()); - histos.fill(HIST("Tracks/TPC/tpcCrossedRowsvsPt"), track.pt(), track.tpcNClsCrossedRows()); - histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableClsvsPt"), track.pt(), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("Tracks/TRD/trdChi2"), track.trdChi2()); - histos.fill(HIST("Tracks/TOF/tofChi2"), track.tofChi2()); - if (track.hasTPC()) { - histos.fill(HIST("Tracks/matchedDet"), 1); - } - if (track.hasITS()) { - histos.fill(HIST("Tracks/matchedDet"), 2); - } - if (track.hasTRD()) { - histos.fill(HIST("Tracks/matchedDet"), 3); - } - if (track.hasTOF()) { - histos.fill(HIST("Tracks/matchedDet"), 4); - } - histos.fill(HIST("Tracks/relativeResoPt"), track.pt(), track.ptReso()); - histos.fill(HIST("Tracks/relativeResoPtMean"), track.pt(), track.ptReso()); - } - } - PROCESS_SWITCH(qaEventTrackLite, processDataLite, "process data lite", true); - - // Process MC - void processMCLite(o2::soa::Filtered> const& tracks, aod::DPGCollisions const&) - { - for (const auto& track : tracks) { - if (track.productionMode() == 0) { - histos.get(HIST("Particle/PDGs"))->Fill(Form("%i", track.pdgCode()), 1); - } - - histos.fill(HIST("Tracks/Kine/pt"), track.pt()); - histos.fill(HIST("Tracks/Kine/eta"), track.eta()); - histos.fill(HIST("Tracks/Kine/phi"), track.phi()); - histos.fill(HIST("Tracks/dcaXY"), track.dcaXY()); - histos.fill(HIST("Tracks/dcaZ"), track.dcaZ()); - histos.fill(HIST("Tracks/dcaXYvsPt"), track.pt(), track.dcaXY()); - histos.fill(HIST("Tracks/dcaZvsPt"), track.pt(), track.dcaZ()); - histos.fill(HIST("Tracks/length"), track.length()); - histos.fill(HIST("Tracks/ITS/itsChi2NCl"), track.itsChi2NCl()); - histos.fill(HIST("Tracks/TPC/tpcChi2NCl"), track.tpcChi2NCl()); - histos.fill(HIST("Tracks/TPC/tpcNClsFound"), track.tpcNClsFound()); - histos.fill(HIST("Tracks/TPC/tpcCrossedRows"), track.tpcNClsCrossedRows()); - histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("Tracks/TPC/tpcNClsFoundvsPt"), track.pt(), track.tpcNClsFound()); - histos.fill(HIST("Tracks/TPC/tpcCrossedRowsvsPt"), track.pt(), track.tpcNClsCrossedRows()); - histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableClsvsPt"), track.pt(), track.tpcCrossedRowsOverFindableCls()); - histos.fill(HIST("Tracks/TRD/trdChi2"), track.trdChi2()); - histos.fill(HIST("Tracks/TOF/tofChi2"), track.tofChi2()); - if (track.hasTPC()) { - histos.fill(HIST("Tracks/matchedDet"), 1); - } - if (track.hasITS()) { - histos.fill(HIST("Tracks/matchedDet"), 2); - } - if (track.hasTRD()) { - histos.fill(HIST("Tracks/matchedDet"), 3); - } - if (track.hasTOF()) { - histos.fill(HIST("Tracks/matchedDet"), 4); - } - } - } - PROCESS_SWITCH(qaEventTrackLite, processMCLite, "process MC lite", false); -}; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow; - if (cfgc.options().get("lite")) { - workflow.push_back(adaptAnalysisTask(cfgc)); - } else { - workflow.push_back(adaptAnalysisTask(cfgc)); - } - return workflow; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } //-------------------------------------------------------------------------------------------------- diff --git a/DPG/Tasks/qaEventTrack.h b/DPG/Tasks/qaEventTrack.h new file mode 100644 index 00000000000..c765a60db05 --- /dev/null +++ b/DPG/Tasks/qaEventTrack.h @@ -0,0 +1,91 @@ +// 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 qaEventTrack.h +/// \author Mario Krüger +/// \author Mattia Faggin +/// \author Nicolò Jacazio +/// \brief Header file for QA tasks for the track and the event properties. +/// + +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/TrackSelectionTables.h" + +// Output table declaration +namespace o2::aod +{ + +namespace dpgcollision +{ +DECLARE_SOA_INDEX_COLUMN(BC, bc); +DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +} // namespace dpgcollision + +DECLARE_SOA_TABLE(DPGCollisions, "AOD", "DPGCollisions", //! Table of the DPG collisions + collision::PosZ, + dpgcollision::IsEventReject, + dpgcollision::RunNumber); + +namespace dpgtrack +{ +DECLARE_SOA_INDEX_COLUMN(DPGCollision, dpgCollision); //! Index to move from track to collision +DECLARE_SOA_COLUMN(Pt, pt, float); //! Pt +DECLARE_SOA_COLUMN(Eta, eta, float); //! Eta +DECLARE_SOA_COLUMN(Phi, phi, float); //! Phi +DECLARE_SOA_COLUMN(PtReso, ptReso, float); //! Pt resolution +DECLARE_SOA_COLUMN(Sign, sign, short); //! Sign +DECLARE_SOA_COLUMN(HasITS, hasITS, bool); //! Track has the ITS +DECLARE_SOA_COLUMN(HasTPC, hasTPC, bool); //! Track has the TPC +DECLARE_SOA_COLUMN(HasTRD, hasTRD, bool); //! Track has the TRD +DECLARE_SOA_COLUMN(HasTOF, hasTOF, bool); //! Track has the TOF +DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, int16_t); //! Clusters found in TPC +DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, int16_t); //! Crossed rows found in TPC +DECLARE_SOA_COLUMN(TPCCrossedRowsOverFindableCls, tpcCrossedRowsOverFindableCls, float); //! Crossed rows over findable clusters in TPC +DECLARE_SOA_COLUMN(TPCFoundOverFindableCls, tpcFoundOverFindableCls, float); //! Found over findable clusters in TPC +DECLARE_SOA_COLUMN(TPCFractionSharedCls, tpcFractionSharedCls, float); //! Fraction of shared clusters in TPC +DECLARE_SOA_COLUMN(ITSNCls, itsNCls, uint8_t); //! Clusters found in ITS +DECLARE_SOA_COLUMN(ITSNClsInnerBarrel, itsNClsInnerBarrel, uint8_t); //! Clusters found in the inner barrel of the ITS + +} // namespace dpgtrack + +DECLARE_SOA_TABLE(DPGTracks, "AOD", "DPGTracks", //! Table of the DPG tracks + dpgtrack::DPGCollisionId, + dpgtrack::Pt, dpgtrack::Eta, dpgtrack::Phi, dpgtrack::PtReso, + track::Flags, dpgtrack::Sign, + track::DcaXY, track::DcaZ, track::Length, + track::ITSClusterMap, + track::ITSChi2NCl, track::TPCChi2NCl, track::TRDChi2, track::TOFChi2, + dpgtrack::HasITS, dpgtrack::HasTPC, dpgtrack::HasTRD, dpgtrack::HasTOF, + dpgtrack::TPCNClsFound, dpgtrack::TPCNClsCrossedRows, + dpgtrack::TPCCrossedRowsOverFindableCls, dpgtrack::TPCFoundOverFindableCls, dpgtrack::TPCFractionSharedCls, + dpgtrack::ITSNCls, dpgtrack::ITSNClsInnerBarrel); + +namespace dpgparticles +{ +DECLARE_SOA_COLUMN(PtMC, ptMC, float); //! Pt MC +DECLARE_SOA_COLUMN(EtaMC, etaMC, float); //! Eta MC +DECLARE_SOA_COLUMN(PhiMC, phiMC, float); //! Phi MC +DECLARE_SOA_COLUMN(ProductionMode, productionMode, int); //! ProductionMode i.e. non matched (-1), physical primary (0), weak decay product (1) or material (2) + +} // namespace dpgparticles + +DECLARE_SOA_TABLE(DPGRecoParticles, "AOD", "DPGRecoPart", //! Table of the DPG reconstructed particles + dpgparticles::PtMC, dpgparticles::EtaMC, dpgparticles::PhiMC, + mcparticle::PdgCode, dpgparticles::ProductionMode); + +DECLARE_SOA_TABLE(DPGNonRecoParticles, "AOD", "DPGNonRecoPart", //! Table of the DPG particles + dpgparticles::PtMC, dpgparticles::EtaMC, dpgparticles::PhiMC, + mcparticle::PdgCode, dpgparticles::ProductionMode, + mcparticle::Vx, mcparticle::Vy, mcparticle::Vz); +} // namespace o2::aod diff --git a/DPG/Tasks/qaEventTrackLite.cxx b/DPG/Tasks/qaEventTrackLite.cxx new file mode 100644 index 00000000000..12ba24de1e5 --- /dev/null +++ b/DPG/Tasks/qaEventTrackLite.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 qaEventTrackLite.cxx +/// \author Mario Krüger +/// \author Mattia Faggin +/// \author Nicolò Jacazio +/// \brief Light version of the task to produce QA objects for the track and the event properties. +/// This task runs on prefiltered data +/// + +#include "qaEventTrack.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/DCA.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::dataformats; + +// Lite version of the QA task to run on skimmed dataset +struct qaEventTrackLite { + // Binning + 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, 2.0, 5.0, 10.0, 20.0, 50.0}, ""}; + ConfigurableAxis binsImpPar{"binsImpPar", {200, -0.15, 0.15}, "Impact parameter binning (cm)"}; + ConfigurableAxis binsEta{"binsEta", {800, -2., 2.}, "Eta binning"}; + ConfigurableAxis binsPhi{"binsPhi", {180, 0., 2 * M_PI}, "Phi binning"}; + + HistogramRegistry histos; + + Configurable bItsStandalone{"bItsStandalone", false, "Select only ITS standalone DPG tracks"}; + Configurable bTpcOnly{"bTpcOnly", false, "Select only TPC only DPG tracks"}; + Configurable bItsTpcMatched{"bItsTpcMatched", false, "Select ITS-TPC matched DPG tracks"}; + // Kinematic selections + Configurable ptMin{"ptMin", 0., "Minimum track pt"}; + Configurable etaMin{"etaMin", -10., "Minimum eta for DPG tracks"}; + Configurable etaMax{"etaMax", 10., "Maximum eta for DPG tracks"}; + // ITS selections + Configurable chi2ItsMin{"chi2ItsMin", -1001.f, "Max ITS chi2"}; + Configurable chi2ItsMax{"chi2ItsMax", 1000.f, "Max ITS chi2"}; + // TPC selections + Configurable nClusterTpcMin{"nClusterTpcMin", -1001, "Minimum number of TPC clusters"}; + Configurable nCrossedRowsTpcMin{"nCrossedRowsTpcMin", -1001, "Minimum number of TPC crossed rows"}; + Configurable nCrossedRowsTpcOverFindableClustersTpcMin{"nCrossedRowsTpcOverFindableClustersTpcMin", -1, "Minimum ratio between TPC crossed rows and findable clusters"}; + Configurable chi2TpcMin{"chi2TpcMin", -1001.f, "Max TPC chi2"}; + Configurable chi2TpcMax{"chi2TpcMax", 1000.f, "Max TPC chi2"}; + // TOF selections + Configurable chi2TofMin{"chi2TofMin", -1001.f, "Max TOF chi2"}; + Configurable lengthMin{"lengthMin", -1001.f, "Min length"}; + + void init(InitContext const&) + { + const AxisSpec axisPt{binsPt, "#it{p}_{T} [GeV/c]"}; + const AxisSpec axisEta{binsEta, "#it{#eta}"}; + const AxisSpec axisPhi{binsPhi, "#it{#phi} [rad]"}; + + // kine histograms + histos.add("Tracks/VertexPositionZ", "", kTH1D, {{100, -20.f, 20.f, "Vertex Z [cm]"}}); + histos.add("Tracks/Kine/pt", "#it{p}_{T}", kTH1D, {axisPt}); + histos.add("Tracks/Kine/eta", "#eta", kTH1D, {axisEta}); + histos.add("Tracks/Kine/phi", "#phi", kTH1D, {axisPhi}); + histos.add("Tracks/length", "track length in cm;#it{Length} [cm];", kTH1D, {{400, 0, 1000}}); + const AxisSpec axisImpParRPhi{binsImpPar, "#it{d}_{r#it{#varphi}} (#cm)"}; + const AxisSpec axisImpParZAxis{binsImpPar, "#it{d}_{z} (#cm)"}; + histos.add("Tracks/dcaXY", "distance of closest approach in #it{xy} plane", kTH1D, {axisImpParRPhi}); + histos.add("Tracks/dcaZ", "distance of closest approach in #it{z}", kTH1D, {axisImpParZAxis}); + histos.add("Tracks/dcaXYvsPt", "d_#it{xy} vs. #it{p}_{T}", kTH2D, {axisPt, axisImpParRPhi}); + histos.add("Tracks/dcaZvsPt", "d_#it{z} vs. #it{p}_{T}", kTH2D, {axisPt, axisImpParRPhi}); + + // its histograms + histos.add("Tracks/ITS/itsChi2NCl", "chi2 per ITS cluster;chi2 / cluster ITS", kTH1D, {{100, 0, 40}}); + histos.add("Tracks/ITS/itsNCl", "ITS number of clusters;# clusters ITS", kTH1D, {{8, -0.5, 7.5}}); + histos.add("Tracks/ITS/itsNClvsItsHitmap", "ITS number of clusters vs. ITS hitmap;# clusters ITS; ITS hitmap", kTH2D, {{8, -0.5, 7.5, "# clusters ITS"}, {128, 0, 128, "ITS hitmap"}}); + // tpc histograms + histos.add("Tracks/TPC/tpcChi2NCl", "chi2 per cluster in TPC;chi2 / cluster TPC", kTH1D, {{100, 0, 10}}); + histos.add("Tracks/TPC/tpcNClsFound", "number of found TPC clusters;# 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/tpcCrossedRowsOverFindableCls", "crossed TPC rows over findable clusters;crossed rows / findable clusters TPC", kTH1D, {{60, 0.7, 1.3}}); + histos.add("Tracks/TPC/tpcNClsFoundvsPt", "", kTH2D, {axisPt, {165, -0.5, 164.5, "# clusters TPC"}}); + histos.add("Tracks/TPC/tpcCrossedRowsvsPt", "", kTH2D, {axisPt, {165, -0.5, 164.5, "# crossed rows TPC"}}); + histos.add("Tracks/TPC/tpcCrossedRowsOverFindableClsvsPt", "", kTH2D, {axisPt, {60, 0.7, 1.3, "crossed rows / findable clusters TPC"}}); + // trd histograms + histos.add("Tracks/TRD/trdChi2", "chi2 in TRD", kTH1D, {{100, 0, 10, "chi2 / cluster TRD"}}); + // tof histograms + histos.add("Tracks/TOF/tofChi2", "chi2 in TOF", kTH1D, {{100, 0, 10, "chi2 / cluster TOF"}}); + // matching histogram + histos.add("Tracks/matchedDet", "matched detectors", kTH1D, {{4, 0.5, 4.5, ""}}); + histos.get(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(1, "hasTPC"); + histos.get(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(2, "hasITS"); + histos.get(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(3, "hasTRD"); + histos.get(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(4, "hasTOF"); + // kinematics + histos.add("Tracks/relativeResoPt", "relative #it{p}_{T} resolution;#sigma(#it{p}_{T})/#it{p}_{T};#it{p}_{T};", kTH2D, {{axisPt, {500, 0., 1, "#sigma{#it{p}}/#it{p}_{T}"}}}); + histos.add("Tracks/relativeResoPtMean", "mean relative #it{p}_{T} resolution;#LT(#it{p}_{T})/#it{p}_{T}#GT;#it{p}_{T};", kTProfile, {axisPt}); + + // MC histograms + if (doprocessMCLite) { + histos.add("Particles/PDGs", "Particle PDGs;PDG Code", kTH1D, {{100, 0.f, 100.f}}); + histos.add("Particles/Kine/pt", "Particle #it{p}_{T}", kTH1D, {axisPt}); + histos.add("Particles/Kine/eta", "Particle #eta", kTH1D, {axisEta}); + histos.add("Particles/Kine/phi", "Particle #phi", kTH1D, {axisPhi}); + } + } + + /////////////// + /// Filters /// + /////////////// + // Kinematics + Filter ptCut = o2::aod::dpgtrack::pt > ptMin; + Filter etaCut = etaMin < o2::aod::dpgtrack::eta && o2::aod::dpgtrack::eta < etaMax; + // Detector matching + Filter itsStandaloneTracks = (bItsStandalone.node() == false) || (o2::aod::dpgtrack::hasITS == true && o2::aod::dpgtrack::hasTPC == false); + Filter tpcOnlyTracks = (bTpcOnly.node() == false) || (o2::aod::dpgtrack::hasITS == false && o2::aod::dpgtrack::hasTPC == true); + Filter itsTpcMatchedTracks = (bItsTpcMatched.node() == false) || (o2::aod::dpgtrack::hasITS == true && o2::aod::dpgtrack::hasTPC == true); + // ITS + Filter itsChi2 = (bTpcOnly.node() == true) || (chi2ItsMin < o2::aod::track::itsChi2NCl && o2::aod::track::itsChi2NCl < chi2ItsMax); + // TPC + Filter tpcChi2s = (bItsStandalone.node() == true) || (chi2TpcMin < o2::aod::track::tpcChi2NCl && o2::aod::track::tpcChi2NCl < chi2TpcMax); + Filter tpcNclusters = (bItsStandalone.node() == true) || (o2::aod::dpgtrack::tpcNClsFound > (int16_t)nClusterTpcMin); + Filter tpcNcrossedRows = (bItsStandalone.node() == true) || (o2::aod::dpgtrack::tpcNClsCrossedRows > (int16_t)nCrossedRowsTpcMin); + Filter tpcNcrossedRowsOverFindableClusters = (bItsStandalone.node() == true) || (o2::aod::dpgtrack::tpcCrossedRowsOverFindableCls > nCrossedRowsTpcOverFindableClustersTpcMin); + // TOF + Filter tofChi = o2::aod::track::tofChi2 > chi2TofMin; + Filter length = o2::aod::track::length > lengthMin; + + // Process data + void processDataLite(o2::soa::Filtered const& tracks, aod::DPGCollisions const&) + { + for (const auto& track : tracks) { + histos.fill(HIST("Tracks/VertexPositionZ"), track.dpgCollision().posZ()); + histos.fill(HIST("Tracks/Kine/pt"), track.pt()); + histos.fill(HIST("Tracks/Kine/eta"), track.eta()); + histos.fill(HIST("Tracks/Kine/phi"), track.phi()); + histos.fill(HIST("Tracks/dcaXY"), track.dcaXY()); + histos.fill(HIST("Tracks/dcaZ"), track.dcaZ()); + histos.fill(HIST("Tracks/dcaXYvsPt"), track.pt(), track.dcaXY()); + histos.fill(HIST("Tracks/dcaZvsPt"), track.pt(), track.dcaZ()); + histos.fill(HIST("Tracks/length"), track.length()); + histos.fill(HIST("Tracks/ITS/itsChi2NCl"), track.itsChi2NCl()); + histos.fill(HIST("Tracks/ITS/itsNCl"), track.itsNCls()); + histos.fill(HIST("Tracks/ITS/itsNClvsItsHitmap"), track.itsNCls(), track.itsClusterMap()); + histos.fill(HIST("Tracks/TPC/tpcChi2NCl"), track.tpcChi2NCl()); + histos.fill(HIST("Tracks/TPC/tpcNClsFound"), track.tpcNClsFound()); + histos.fill(HIST("Tracks/TPC/tpcCrossedRows"), track.tpcNClsCrossedRows()); + histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("Tracks/TPC/tpcNClsFoundvsPt"), track.pt(), track.tpcNClsFound()); + histos.fill(HIST("Tracks/TPC/tpcCrossedRowsvsPt"), track.pt(), track.tpcNClsCrossedRows()); + histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableClsvsPt"), track.pt(), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("Tracks/TRD/trdChi2"), track.trdChi2()); + histos.fill(HIST("Tracks/TOF/tofChi2"), track.tofChi2()); + if (track.hasTPC()) { + histos.fill(HIST("Tracks/matchedDet"), 1); + } + if (track.hasITS()) { + histos.fill(HIST("Tracks/matchedDet"), 2); + } + if (track.hasTRD()) { + histos.fill(HIST("Tracks/matchedDet"), 3); + } + if (track.hasTOF()) { + histos.fill(HIST("Tracks/matchedDet"), 4); + } + histos.fill(HIST("Tracks/relativeResoPt"), track.pt(), track.ptReso()); + histos.fill(HIST("Tracks/relativeResoPtMean"), track.pt(), track.ptReso()); + } + } + PROCESS_SWITCH(qaEventTrackLite, processDataLite, "process data lite", true); + + // Process MC + void processMCLite(o2::soa::Filtered> const& tracks, aod::DPGCollisions const&, aod::DPGNonRecoParticles const& particles) + { + for (const auto& track : tracks) { + if (track.productionMode() == 0) { + histos.get(HIST("Particles/PDGs"))->Fill(Form("%i", track.pdgCode()), 1); + } + + histos.fill(HIST("Particles/Kine/pt"), track.ptMC()); + histos.fill(HIST("Particles/Kine/eta"), track.etaMC()); + histos.fill(HIST("Particles/Kine/phi"), track.phiMC()); + + histos.fill(HIST("Tracks/Kine/pt"), track.pt()); + histos.fill(HIST("Tracks/Kine/eta"), track.eta()); + histos.fill(HIST("Tracks/Kine/phi"), track.phi()); + histos.fill(HIST("Tracks/dcaXY"), track.dcaXY()); + histos.fill(HIST("Tracks/dcaZ"), track.dcaZ()); + histos.fill(HIST("Tracks/dcaXYvsPt"), track.pt(), track.dcaXY()); + histos.fill(HIST("Tracks/dcaZvsPt"), track.pt(), track.dcaZ()); + histos.fill(HIST("Tracks/length"), track.length()); + histos.fill(HIST("Tracks/ITS/itsChi2NCl"), track.itsChi2NCl()); + histos.fill(HIST("Tracks/TPC/tpcChi2NCl"), track.tpcChi2NCl()); + histos.fill(HIST("Tracks/TPC/tpcNClsFound"), track.tpcNClsFound()); + histos.fill(HIST("Tracks/TPC/tpcCrossedRows"), track.tpcNClsCrossedRows()); + histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("Tracks/TPC/tpcNClsFoundvsPt"), track.pt(), track.tpcNClsFound()); + histos.fill(HIST("Tracks/TPC/tpcCrossedRowsvsPt"), track.pt(), track.tpcNClsCrossedRows()); + histos.fill(HIST("Tracks/TPC/tpcCrossedRowsOverFindableClsvsPt"), track.pt(), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("Tracks/TRD/trdChi2"), track.trdChi2()); + histos.fill(HIST("Tracks/TOF/tofChi2"), track.tofChi2()); + if (track.hasTPC()) { + histos.fill(HIST("Tracks/matchedDet"), 1); + } + if (track.hasITS()) { + histos.fill(HIST("Tracks/matchedDet"), 2); + } + if (track.hasTRD()) { + histos.fill(HIST("Tracks/matchedDet"), 3); + } + if (track.hasTOF()) { + histos.fill(HIST("Tracks/matchedDet"), 4); + } + } + + for (const auto& particle : particles) { + histos.fill(HIST("Particles/Kine/pt"), particle.ptMC()); + histos.fill(HIST("Particles/Kine/eta"), particle.etaMC()); + histos.fill(HIST("Particles/Kine/phi"), particle.phiMC()); + } + } + PROCESS_SWITCH(qaEventTrackLite, processMCLite, "process MC lite", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +}