From 914741d7b93419aaf68fecf525c5fc7d23c1298e Mon Sep 17 00:00:00 2001 From: Nicolo' Jacazio Date: Tue, 20 Oct 2020 15:11:31 +0200 Subject: [PATCH] Split track extension and selection - Create directory for ALICE3 related studies - Add selection task for Run5 - Add method to check single cut - Add task to fill QA info for track cuts - Add header for standard cut object creation --- Analysis/Core/CMakeLists.txt | 1 + .../Core/include/Analysis/TrackSelection.h | 61 ++++++++++++++++ .../include/Analysis/TrackSelectionDefaults.h | 53 ++++++++++++++ Analysis/Core/src/TrackSelection.cxx | 4 +- Analysis/Tasks/ALICE3/CMakeLists.txt | 16 +++++ .../Tasks/ALICE3/alice3-trackselection.cxx | 56 +++++++++++++++ Analysis/Tasks/CMakeLists.txt | 6 ++ Analysis/Tasks/trackextension.cxx | 65 +++++++++++++++++ Analysis/Tasks/trackqa.cxx | 38 ++++++++-- Analysis/Tasks/trackselection.cxx | 72 +------------------ 10 files changed, 296 insertions(+), 76 deletions(-) create mode 100644 Analysis/Core/include/Analysis/TrackSelectionDefaults.h create mode 100644 Analysis/Tasks/ALICE3/CMakeLists.txt create mode 100644 Analysis/Tasks/ALICE3/alice3-trackselection.cxx create mode 100644 Analysis/Tasks/trackextension.cxx diff --git a/Analysis/Core/CMakeLists.txt b/Analysis/Core/CMakeLists.txt index 145b41d3ed9ce..d6dca70436d7e 100644 --- a/Analysis/Core/CMakeLists.txt +++ b/Analysis/Core/CMakeLists.txt @@ -23,6 +23,7 @@ o2_target_root_dictionary(AnalysisCore HEADERS include/Analysis/StepTHn.h include/Analysis/CorrelationContainer.h include/Analysis/TrackSelection.h + include/Analysis/TrackSelectionDefaults.h include/Analysis/VarManager.h include/Analysis/HistogramManager.h include/Analysis/AnalysisCut.h diff --git a/Analysis/Core/include/Analysis/TrackSelection.h b/Analysis/Core/include/Analysis/TrackSelection.h index d67702fcdbbb7..f4e6edf67c985 100644 --- a/Analysis/Core/include/Analysis/TrackSelection.h +++ b/Analysis/Core/include/Analysis/TrackSelection.h @@ -26,6 +26,27 @@ class TrackSelection public: TrackSelection() = default; + enum class TrackCuts : int { + kTrackType = 0, + kPtRange, + kEtaRange, + kTPCNCls, + kTPCCrossedRows, + kTPCCrossedRowsOverNCls, + kTPCChi2NDF, + kTPCRefit, + kITSNCls, + kITSChi2NDF, + kITSRefit, + kITSHits, + kGoldenChi2, + kDCAxy, + kDCAz, + kNCuts + }; + + static const std::string mCutNames[static_cast(TrackCuts::kNCuts)]; + // Temporary function to check if track passes selection criteria. To be replaced by framework filters. template bool IsSelected(T const& track) @@ -51,6 +72,46 @@ class TrackSelection } } + // Temporary function to check if track passes a given selection criteria. To be replaced by framework filters. + template + bool IsSelected(T const& track, const TrackCuts& cut) + { + switch (cut) { + case TrackCuts::kTrackType: + return track.trackType() == mTrackType; + case TrackCuts::kPtRange: + return track.pt() >= mMinPt && track.pt() <= mMaxPt; + case TrackCuts::kEtaRange: + return track.eta() >= mMinEta && track.eta() <= mMaxEta; + case TrackCuts::kTPCNCls: + return track.tpcNClsFound() >= mMinNClustersTPC; + case TrackCuts::kTPCCrossedRows: + return track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC; + case TrackCuts::kTPCCrossedRowsOverNCls: + return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; + case TrackCuts::kTPCChi2NDF: + return track.itsNCls() >= mMinNClustersITS; + case TrackCuts::kTPCRefit: + return track.itsChi2NCl() <= mMaxChi2PerClusterITS; + case TrackCuts::kITSNCls: + return track.tpcChi2NCl() <= mMaxChi2PerClusterTPC; + case TrackCuts::kITSChi2NDF: + return (mRequireITSRefit) ? (track.flags() & o2::aod::track::ITSrefit) : true; + case TrackCuts::kITSRefit: + return (mRequireTPCRefit) ? (track.flags() & o2::aod::track::TPCrefit) : true; + case TrackCuts::kITSHits: + return (mRequireGoldenChi2) ? (track.flags() & o2::aod::track::GoldenChi2) : true; + case TrackCuts::kGoldenChi2: + return FulfillsITSHitRequirements(track.itsClusterMap()); + case TrackCuts::kDCAxy: + return abs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + case TrackCuts::kDCAz: + return abs(track.dcaZ()) <= mMaxDcaZ; + default: + return false; + } + } + void SetTrackType(o2::aod::track::TrackTypeEnum trackType) { mTrackType = trackType; } void SetPtRange(float minPt = 0.f, float maxPt = 1e10f) { diff --git a/Analysis/Core/include/Analysis/TrackSelectionDefaults.h b/Analysis/Core/include/Analysis/TrackSelectionDefaults.h new file mode 100644 index 0000000000000..bddbf5c560141 --- /dev/null +++ b/Analysis/Core/include/Analysis/TrackSelectionDefaults.h @@ -0,0 +1,53 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// 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 TrackSelectionDefaults.h +/// \brief Class for the definition of standard track selection objects +/// \since 20-10-2020 +/// + +#ifndef TrackSelectionDefaults_H +#define TrackSelectionDefaults_H + +#include "Framework/DataTypes.h" + +// Default track selection requiring one hit in the SPD +TrackSelection getGlobalTrackSelection() +{ + TrackSelection selectedTracks; + selectedTracks.SetTrackType(o2::aod::track::Run2GlobalTrack); + selectedTracks.SetPtRange(0.1f, 1e10f); + selectedTracks.SetEtaRange(-0.8f, 0.8f); + selectedTracks.SetRequireITSRefit(true); + selectedTracks.SetRequireTPCRefit(true); + selectedTracks.SetRequireGoldenChi2(true); + selectedTracks.SetMinNCrossedRowsTPC(70); + selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); + selectedTracks.SetMaxChi2PerClusterTPC(4.f); + selectedTracks.SetRequireHitsInITSLayers(1, {0, 1}); // one hit in any SPD layer + selectedTracks.SetMaxChi2PerClusterITS(36.f); + selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); + selectedTracks.SetMaxDcaZ(2.f); + return selectedTracks; +} + +// Default track selection requiring no hit in the SPD and one in the innermost +// SDD -> complementary tracks to global selection +TrackSelection getGlobalTrackSelectionSDD() +{ + TrackSelection selectedTracks = getGlobalTrackSelection(); + selectedTracks.ResetITSRequirements(); + selectedTracks.SetRequireNoHitsInITSLayers({0, 1}); // no hit in SPD layers + selectedTracks.SetRequireHitsInITSLayers(1, {2}); // one hit in first SDD layer + return selectedTracks; +} + +#endif diff --git a/Analysis/Core/src/TrackSelection.cxx b/Analysis/Core/src/TrackSelection.cxx index 15773743f0eb7..5e7ff6fa41fd0 100644 --- a/Analysis/Core/src/TrackSelection.cxx +++ b/Analysis/Core/src/TrackSelection.cxx @@ -26,4 +26,6 @@ bool TrackSelection::FulfillsITSHitRequirements(uint8_t itsClusterMap) } } return true; -}; +} + +const std::string TrackSelection::mCutNames[static_cast(TrackSelection::TrackCuts::kNCuts)] = {"TrackType", "PtRange", "EtaRange", "TPCNCls", "TPCCrossedRows", "TPCCrossedRowsOverNCls", "TPCChi2NDF", "TPCRefit", "ITSNCls", "ITSChi2NDF", "ITSRefit", "ITSHits", "GoldenChi2", "DCAxy", "DCAz"}; diff --git a/Analysis/Tasks/ALICE3/CMakeLists.txt b/Analysis/Tasks/ALICE3/CMakeLists.txt new file mode 100644 index 0000000000000..7734d35e2289b --- /dev/null +++ b/Analysis/Tasks/ALICE3/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright CERN and copyright holders of ALICE O2. This software is distributed +# under the terms of the GNU General Public License v3 (GPL Version 3), copied +# verbatim in the file "COPYING". +# +# See http://alice-o2.web.cern.ch/license for full licensing information. +# +# 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. + +o2_add_dpl_workflow(alice3-trackselection + SOURCES alice3-trackselection.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + + diff --git a/Analysis/Tasks/ALICE3/alice3-trackselection.cxx b/Analysis/Tasks/ALICE3/alice3-trackselection.cxx new file mode 100644 index 0000000000000..53928e1e4523f --- /dev/null +++ b/Analysis/Tasks/ALICE3/alice3-trackselection.cxx @@ -0,0 +1,56 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// 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 performing basic track selection. +// + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/trackUtilities.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +//**************************************************************************************** +/** + * Produce track filter table. + */ +//**************************************************************************************** +struct TrackSelectionTask { + Produces filterTable; + + void init(InitContext&) + { + } + + void process(soa::Join const& tracks) + { + for (auto& track : tracks) { + filterTable(kTRUE, + kTRUE); + } + } +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask("track-selection")}; + return workflow; +} diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 9f5ef647a7c46..e56c4c6476024 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -14,8 +14,14 @@ add_subdirectory(PWGHF) add_subdirectory(PWGJE) add_subdirectory(PWGLF) add_subdirectory(PWGUD) +add_subdirectory(ALICE3) +o2_add_dpl_workflow(trackextension + SOURCES trackextension.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(trackselection SOURCES trackselection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisDataModel O2::AnalysisCore diff --git a/Analysis/Tasks/trackextension.cxx b/Analysis/Tasks/trackextension.cxx new file mode 100644 index 0000000000000..1be057fff8e3b --- /dev/null +++ b/Analysis/Tasks/trackextension.cxx @@ -0,0 +1,65 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// 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 performing basic track selection. +// + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionTables.h" +#include "Analysis/trackUtilities.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +//**************************************************************************************** +/** + * Produce the more complicated derived track quantities needed for track selection. + * FIXME: we shall run this only if all other selections are passed to avoid + * FIXME: computing overhead and errors in calculations + */ +//**************************************************************************************** +struct TrackExtensionTask { + + Produces extendedTrackQuantities; + + void process(aod::Collision const& collision, aod::FullTracks const& tracks) + { + for (auto& track : tracks) { + + std::array dca{1e10f, 1e10f}; + // FIXME: temporary solution to remove tracks that should not be there after conversion + if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && std::abs(track.x()) < 10.f) { + float magField = 5.0; // in kG (FIXME: get this from CCDB) + auto trackPar = getTrackPar(track); + trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, magField, &dca); + } + extendedTrackQuantities(dca[0], dca[1]); + + // TODO: add realtive pt resolution sigma(pt)/pt \approx pt * sigma(1/pt) + // TODO: add geometrical length / fiducial volume + } + } +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask("track-extension")}; + return workflow; +} diff --git a/Analysis/Tasks/trackqa.cxx b/Analysis/Tasks/trackqa.cxx index 438ec2399123c..a5241b677070b 100644 --- a/Analysis/Tasks/trackqa.cxx +++ b/Analysis/Tasks/trackqa.cxx @@ -14,12 +14,11 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Analysis/MC.h" #include "Framework/HistogramRegistry.h" - -#include - +#include "Analysis/MC.h" #include "Analysis/TrackSelectionTables.h" +#include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionDefaults.h" using namespace o2; using namespace o2::framework; @@ -28,7 +27,8 @@ using namespace o2::framework::expressions; void customize(std::vector& workflowOptions) { std::vector options{ - {"mc", VariantType::Bool, false, {"Add MC QA histograms."}}}; + {"mc", VariantType::Bool, false, {"Add MC QA histograms."}}, + {"add-cut-qa", VariantType::Int, 0, {"Add track cut QA histograms."}}}; std::swap(workflowOptions, options); } #include "Framework/runDataProcessing.h" @@ -144,6 +144,28 @@ struct TrackQATask { } }; +struct TrackCutQATask { + HistogramRegistry cuts{"Cuts", true, {}, OutputObjHandlingPolicy::QAObject}; + TrackSelection selectedTracks = getGlobalTrackSelection(); + static constexpr int ncuts = static_cast(TrackSelection::TrackCuts::kNCuts); + void init(InitContext&) + { + cuts.add("single_cut", ";Cut;Tracks", kTH1D, {{ncuts, 0, ncuts}}); + for (int i = 0; i < ncuts; i++) { + cuts.get("single_cut")->GetXaxis()->SetBinLabel(1 + i, TrackSelection::mCutNames[i].data()); + } + } + + void process(soa::Join::iterator const& track) + { + for (int i = 0; i < ncuts; i++) { + if (selectedTracks.IsSelected(track, static_cast(i))) { + cuts.fill("single_cut", i); + } + } + } +}; + //**************************************************************************************** /** * QA task including MC truth info. @@ -169,10 +191,14 @@ struct TrackQATaskMC { //**************************************************************************************** WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - bool isMC = cfgc.options().get("mc"); + const bool isMC = cfgc.options().get("mc"); + const int add_cut_qa = cfgc.options().get("add-cut-qa"); WorkflowSpec workflow; workflow.push_back(adaptAnalysisTask("track-qa-histograms")); + if (add_cut_qa) { + workflow.push_back(adaptAnalysisTask("track-cut-qa-histograms")); + } if (isMC) { workflow.push_back(adaptAnalysisTask("track-qa-histograms-mc")); } diff --git a/Analysis/Tasks/trackselection.cxx b/Analysis/Tasks/trackselection.cxx index f2067e796d5fe..a8425576eaaff 100644 --- a/Analysis/Tasks/trackselection.cxx +++ b/Analysis/Tasks/trackselection.cxx @@ -14,80 +14,16 @@ #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include - -#include - +#include "Framework/runDataProcessing.h" #include "Analysis/TrackSelection.h" +#include "Analysis/TrackSelectionDefaults.h" #include "Analysis/TrackSelectionTables.h" -#include "Framework/runDataProcessing.h" #include "Analysis/trackUtilities.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -// Default track selection requiring one hit in the SPD -TrackSelection getGlobalTrackSelection() -{ - TrackSelection selectedTracks; - selectedTracks.SetTrackType(aod::track::Run2GlobalTrack); - selectedTracks.SetPtRange(0.1f, 1e10f); - selectedTracks.SetEtaRange(-0.8f, 0.8f); - selectedTracks.SetRequireITSRefit(true); - selectedTracks.SetRequireTPCRefit(true); - selectedTracks.SetRequireGoldenChi2(true); - selectedTracks.SetMinNCrossedRowsTPC(70); - selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(0.8f); - selectedTracks.SetMaxChi2PerClusterTPC(4.f); - selectedTracks.SetRequireHitsInITSLayers(1, {0, 1}); // one hit in any SPD layer - selectedTracks.SetMaxChi2PerClusterITS(36.f); - selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); - selectedTracks.SetMaxDcaZ(2.f); - return selectedTracks; -} - -// Default track selection requiring no hit in the SPD and one in the innermost -// SDD -> complementary tracks to global selection -TrackSelection getGlobalTrackSelectionSDD() -{ - TrackSelection selectedTracks = getGlobalTrackSelection(); - selectedTracks.ResetITSRequirements(); - selectedTracks.SetRequireNoHitsInITSLayers({0, 1}); // no hit in SPD layers - selectedTracks.SetRequireHitsInITSLayers(1, {2}); // one hit in first SDD layer - return selectedTracks; -} - -//**************************************************************************************** -/** - * Produce the more complicated derived track quantities needed for track selection. - * FIXME: we shall run this only if all other selections are passed to avoid - * FIXME: computing overhead and errors in calculations - */ -//**************************************************************************************** -struct TrackExtensionTask { - - Produces extendedTrackQuantities; - - void process(aod::Collision const& collision, aod::FullTracks const& tracks) - { - for (auto& track : tracks) { - - std::array dca{1e10f, 1e10f}; - // FIXME: temporary solution to remove tracks that should not be there after conversion - if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2GlobalTrack && track.itsChi2NCl() != 0.f && track.tpcChi2NCl() != 0.f && std::abs(track.x()) < 10.f) { - float magField = 5.0; // in kG (FIXME: get this from CCDB) - auto trackPar = getTrackPar(track); - trackPar.propagateParamToDCA({collision.posX(), collision.posY(), collision.posZ()}, magField, &dca); - } - extendedTrackQuantities(dca[0], dca[1]); - - // TODO: add realtive pt resolution sigma(pt)/pt \approx pt * sigma(1/pt) - // TODO: add geometrical length / fiducial volume - } - } -}; - //**************************************************************************************** /** * Produce track filter table. @@ -121,8 +57,6 @@ struct TrackSelectionTask { //**************************************************************************************** WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow{ - adaptAnalysisTask("track-extension"), - adaptAnalysisTask("track-selection")}; + WorkflowSpec workflow{adaptAnalysisTask("track-selection")}; return workflow; }