Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions DPG/Tasks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
281 changes: 6 additions & 275 deletions DPG/Tasks/qaEventTrack.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -34,93 +36,10 @@
using namespace o2;
using namespace o2::framework;
using namespace o2::framework::expressions;

void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions)
{
std::vector<ConfigParamSpec> 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
Expand Down Expand Up @@ -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();
Expand All @@ -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<bool> bItsStandalone{"bItsStandalone", false, "Select only ITS standalone DPG tracks"};
Configurable<bool> bTpcOnly{"bTpcOnly", false, "Select only TPC only DPG tracks"};
Configurable<bool> bItsTpcMatched{"bItsTpcMatched", false, "Select ITS-TPC matched DPG tracks"};
// Kinematic selections
Configurable<float> ptMin{"ptMin", 0., "Minimum track pt"};
Configurable<float> etaMin{"etaMin", -10., "Minimum eta for DPG tracks"};
Configurable<float> etaMax{"etaMax", 10., "Maximum eta for DPG tracks"};
// ITS selections
Configurable<float> chi2ItsMin{"chi2ItsMin", -1001.f, "Max ITS chi2"};
Configurable<float> chi2ItsMax{"chi2ItsMax", 1000.f, "Max ITS chi2"};
// TPC selections
Configurable<int> nClusterTpcMin{"nClusterTpcMin", -1001, "Minimum number of TPC clusters"};
Configurable<int> nCrossedRowsTpcMin{"nCrossedRowsTpcMin", -1001, "Minimum number of TPC crossed rows"};
Configurable<float> nCrossedRowsTpcOverFindableClustersTpcMin{"nCrossedRowsTpcOverFindableClustersTpcMin", -1, "Minimum ratio between TPC crossed rows and findable clusters"};
Configurable<float> chi2TpcMin{"chi2TpcMin", -1001.f, "Max TPC chi2"};
Configurable<float> chi2TpcMax{"chi2TpcMax", 1000.f, "Max TPC chi2"};
// TOF selections
Configurable<float> chi2TofMin{"chi2TofMin", -1001.f, "Max TOF chi2"};
Configurable<float> 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<TH1>(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(1, "hasTPC");
histos.get<TH1>(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(2, "hasITS");
histos.get<TH1>(HIST("Tracks/matchedDet"))->GetXaxis()->SetBinLabel(3, "hasTRD");
histos.get<TH1>(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<aod::DPGTracks> 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<soa::Join<aod::DPGTracks, aod::DPGNonRecoParticles>> const& tracks, aod::DPGCollisions const&)
{
for (const auto& track : tracks) {
if (track.productionMode() == 0) {
histos.get<TH1>(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<int>("lite")) {
workflow.push_back(adaptAnalysisTask<qaEventTrackLite>(cfgc));
} else {
workflow.push_back(adaptAnalysisTask<qaEventTrack>(cfgc));
}
return workflow;
return WorkflowSpec{adaptAnalysisTask<qaEventTrack>(cfgc)};
}

//--------------------------------------------------------------------------------------------------
Expand Down
Loading