From 74cc0a87f9dfd247fb969725edd42bcda34d410f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 14 Jan 2021 08:45:16 +0100 Subject: [PATCH] Add split tables per particle species in PID response - Add user tasks for TOF and TPC spectra dedicated to the usage of the new tables via long join chains - Add tasks for the creation of sub tables per PID - Add user tasks - Avoid local mem copy --- .../AnalysisDataModel/PID/PIDResponse.h | 23 ++ Analysis/Tasks/CMakeLists.txt | 10 + Analysis/Tasks/PWGLF/CMakeLists.txt | 10 + Analysis/Tasks/PWGLF/spectraTOF.cxx | 25 +- Analysis/Tasks/PWGLF/spectraTOF_split.cxx | 99 ++++++++ Analysis/Tasks/PWGLF/spectraTPC.cxx | 45 ++-- Analysis/Tasks/PWGLF/spectraTPC_split.cxx | 177 ++++++++++++++ Analysis/Tasks/pidTOF_split.cxx | 222 ++++++++++++++++++ Analysis/Tasks/pidTPC.cxx | 2 +- Analysis/Tasks/pidTPC_split.cxx | 213 +++++++++++++++++ 10 files changed, 787 insertions(+), 39 deletions(-) create mode 100644 Analysis/Tasks/PWGLF/spectraTOF_split.cxx create mode 100644 Analysis/Tasks/PWGLF/spectraTPC_split.cxx create mode 100644 Analysis/Tasks/pidTOF_split.cxx create mode 100644 Analysis/Tasks/pidTPC_split.cxx diff --git a/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h index 9b9395e084a85..41ceb03a16e03 100644 --- a/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h +++ b/Analysis/DataModel/include/AnalysisDataModel/PID/PIDResponse.h @@ -80,6 +80,7 @@ DECLARE_SOA_TABLE(pidRespTOFbeta, "AOD", "pidRespTOFbeta", ExpBetaEl, ExpBetaElError, SeparationBetaEl, DiffBetaEl); + using namespace pidtof; DECLARE_SOA_TABLE(pidRespTOF, "AOD", "pidRespTOF", // Expected signals @@ -101,6 +102,17 @@ DECLARE_SOA_TABLE(pidRespTOF, "AOD", "pidRespTOF", TOFNSigmaKa, TOFNSigmaPr, TOFNSigmaDe, TOFNSigmaTr, TOFNSigmaHe, TOFNSigmaAl); +// Per particle tables +DECLARE_SOA_TABLE(pidRespTOFEl, "AOD", "pidRespTOFEl", TOFExpSignalDiffEl, TOFExpSigmaEl, TOFNSigmaEl); +DECLARE_SOA_TABLE(pidRespTOFMu, "AOD", "pidRespTOFMu", TOFExpSignalDiffMu, TOFExpSigmaMu, TOFNSigmaMu); +DECLARE_SOA_TABLE(pidRespTOFPi, "AOD", "pidRespTOFPi", TOFExpSignalDiffPi, TOFExpSigmaPi, TOFNSigmaPi); +DECLARE_SOA_TABLE(pidRespTOFKa, "AOD", "pidRespTOFKa", TOFExpSignalDiffKa, TOFExpSigmaKa, TOFNSigmaKa); +DECLARE_SOA_TABLE(pidRespTOFPr, "AOD", "pidRespTOFPr", TOFExpSignalDiffPr, TOFExpSigmaPr, TOFNSigmaPr); +DECLARE_SOA_TABLE(pidRespTOFDe, "AOD", "pidRespTOFDe", TOFExpSignalDiffDe, TOFExpSigmaDe, TOFNSigmaDe); +DECLARE_SOA_TABLE(pidRespTOFTr, "AOD", "pidRespTOFTr", TOFExpSignalDiffTr, TOFExpSigmaTr, TOFNSigmaTr); +DECLARE_SOA_TABLE(pidRespTOFHe, "AOD", "pidRespTOFHe", TOFExpSignalDiffHe, TOFExpSigmaHe, TOFNSigmaHe); +DECLARE_SOA_TABLE(pidRespTOFAl, "AOD", "pidRespTOFAl", TOFExpSignalDiffAl, TOFExpSigmaAl, TOFNSigmaAl); + namespace pidtpc { // Expected signals @@ -156,6 +168,17 @@ DECLARE_SOA_TABLE(pidRespTPC, "AOD", "pidRespTPC", TPCNSigmaKa, TPCNSigmaPr, TPCNSigmaDe, TPCNSigmaTr, TPCNSigmaHe, TPCNSigmaAl); +// Per particle tables +DECLARE_SOA_TABLE(pidRespTPCEl, "AOD", "pidRespTPCEl", TPCExpSignalDiffEl, TPCExpSigmaEl, TPCNSigmaEl); +DECLARE_SOA_TABLE(pidRespTPCMu, "AOD", "pidRespTPCMu", TPCExpSignalDiffMu, TPCExpSigmaMu, TPCNSigmaMu); +DECLARE_SOA_TABLE(pidRespTPCPi, "AOD", "pidRespTPCPi", TPCExpSignalDiffPi, TPCExpSigmaPi, TPCNSigmaPi); +DECLARE_SOA_TABLE(pidRespTPCKa, "AOD", "pidRespTPCKa", TPCExpSignalDiffKa, TPCExpSigmaKa, TPCNSigmaKa); +DECLARE_SOA_TABLE(pidRespTPCPr, "AOD", "pidRespTPCPr", TPCExpSignalDiffPr, TPCExpSigmaPr, TPCNSigmaPr); +DECLARE_SOA_TABLE(pidRespTPCDe, "AOD", "pidRespTPCDe", TPCExpSignalDiffDe, TPCExpSigmaDe, TPCNSigmaDe); +DECLARE_SOA_TABLE(pidRespTPCTr, "AOD", "pidRespTPCTr", TPCExpSignalDiffTr, TPCExpSigmaTr, TPCNSigmaTr); +DECLARE_SOA_TABLE(pidRespTPCHe, "AOD", "pidRespTPCHe", TPCExpSignalDiffHe, TPCExpSigmaHe, TPCNSigmaHe); +DECLARE_SOA_TABLE(pidRespTPCAl, "AOD", "pidRespTPCAl", TPCExpSignalDiffAl, TPCExpSigmaAl, TPCNSigmaAl); + } // namespace o2::aod #endif // O2_FRAMEWORK_PIDRESPONSE_H_ diff --git a/Analysis/Tasks/CMakeLists.txt b/Analysis/Tasks/CMakeLists.txt index 3381c8457c3ef..d947c15445630 100644 --- a/Analysis/Tasks/CMakeLists.txt +++ b/Analysis/Tasks/CMakeLists.txt @@ -38,11 +38,21 @@ o2_add_dpl_workflow(pid-tof PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) +o2_add_dpl_workflow(pid-tof-split + SOURCES pidTOF_split.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(pid-tpc SOURCES pidTPC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore COMPONENT_NAME Analysis) +o2_add_dpl_workflow(pid-tpc-split + SOURCES pidTPC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel O2::AnalysisCore + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(validation SOURCES validation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase diff --git a/Analysis/Tasks/PWGLF/CMakeLists.txt b/Analysis/Tasks/PWGLF/CMakeLists.txt index 6b1d703be7636..0f8529363df8d 100644 --- a/Analysis/Tasks/PWGLF/CMakeLists.txt +++ b/Analysis/Tasks/PWGLF/CMakeLists.txt @@ -18,11 +18,21 @@ o2_add_dpl_workflow(spectra-tof PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) +o2_add_dpl_workflow(spectra-tof-split + SOURCES spectraTOF_split.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(spectra-tpc SOURCES spectraTPC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel COMPONENT_NAME Analysis) +o2_add_dpl_workflow(spectra-tpc-split + SOURCES spectraTPC_split.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel + COMPONENT_NAME Analysis) + o2_add_dpl_workflow(nuclei-spectra SOURCES NucleiSpectraTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2::AnalysisDataModel diff --git a/Analysis/Tasks/PWGLF/spectraTOF.cxx b/Analysis/Tasks/PWGLF/spectraTOF.cxx index 0f7052c4adb7a..6b42a51cda4fc 100644 --- a/Analysis/Tasks/PWGLF/spectraTOF.cxx +++ b/Analysis/Tasks/PWGLF/spectraTOF.cxx @@ -45,9 +45,9 @@ struct TOFSpectraTask { } template - void fillParticleHistos(const T& track, const float nsigma[]) + void fillParticleHistos(const T& track, const float& nsigma) { - if (abs(nsigma[i]) > nsigmacut.value) { + if (abs(nsigma) > nsigmacut.value) { return; } histos.fill(HIST(hp[i]), track.p()); @@ -63,21 +63,18 @@ struct TOFSpectraTask { using TrackCandidates = soa::Filtered>; void process(TrackCandidates::iterator const& track) { - const float nsigma[Np] = {track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), - track.tofNSigmaKa(), track.tofNSigmaPr(), track.tofNSigmaDe(), - track.tofNSigmaTr(), track.tofNSigmaHe(), track.tofNSigmaAl()}; histos.fill(HIST("p/Unselected"), track.p()); histos.fill(HIST("pt/Unselected"), track.pt()); - fillParticleHistos<0>(track, nsigma); - fillParticleHistos<1>(track, nsigma); - fillParticleHistos<2>(track, nsigma); - fillParticleHistos<3>(track, nsigma); - fillParticleHistos<4>(track, nsigma); - fillParticleHistos<5>(track, nsigma); - fillParticleHistos<6>(track, nsigma); - fillParticleHistos<7>(track, nsigma); - fillParticleHistos<8>(track, nsigma); + fillParticleHistos<0>(track, track.tofNSigmaEl()); + fillParticleHistos<1>(track, track.tofNSigmaMu()); + fillParticleHistos<2>(track, track.tofNSigmaPi()); + fillParticleHistos<3>(track, track.tofNSigmaKa()); + fillParticleHistos<4>(track, track.tofNSigmaPr()); + fillParticleHistos<5>(track, track.tofNSigmaDe()); + fillParticleHistos<6>(track, track.tofNSigmaTr()); + fillParticleHistos<7>(track, track.tofNSigmaHe()); + fillParticleHistos<8>(track, track.tofNSigmaAl()); // if (TMath::Abs(track.separationbetael() < 1.f)) { diff --git a/Analysis/Tasks/PWGLF/spectraTOF_split.cxx b/Analysis/Tasks/PWGLF/spectraTOF_split.cxx new file mode 100644 index 0000000000000..6c5d9f241c7b3 --- /dev/null +++ b/Analysis/Tasks/PWGLF/spectraTOF_split.cxx @@ -0,0 +1,99 @@ +// 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 includes +#include "ReconstructionDataFormats/Track.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct TOFSpectraTaskSplit { + static constexpr int Np = 9; + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr std::string_view hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; + static constexpr std::string_view hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + for (int i = 0; i < Np; i++) { + histos.add(hp[i].data(), Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hpt[i].data(), Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + } + histos.add("electronbeta/hp_El", ";#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("electronbeta/hpt_El", ";#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("electronbeta/hlength_El", ";Track Length (cm);Tracks", kTH1D, {{100, 0, 1000}}); + histos.add("electronbeta/htime_El", ";TOF Time (ns);Tracks", kTH1D, {{1000, 0, 600}}); + histos.add("electronbeta/hp_beta_El", ";#it{p} (GeV/#it{c});#beta - #beta_{e};Tracks", kTH2D, {{100, 0, 20}, {100, -0.01, 0.01}}); + histos.add("electronbeta/hp_betasigma_El", ";#it{p} (GeV/#it{c});(#beta - #beta_{e})/#sigma;Tracks", kTH2D, {{100, 0, 20}, {100, -5, 5}}); + } + + template + void fillParticleHistos(const T& track, const float& nsigma) + { + if (abs(nsigma) > nsigmacut.value) { + return; + } + histos.fill(HIST(hp[i]), track.p()); + histos.fill(HIST(hpt[i]), track.pt()); + } + + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == (uint8_t) true) && (aod::track::tofSignal > 0.f); + using TrackCandidates = soa::Filtered>; + void process(TrackCandidates::iterator const& track) + { + histos.fill(HIST("p/Unselected"), track.p()); + histos.fill(HIST("pt/Unselected"), track.pt()); + + fillParticleHistos<0>(track, track.tofNSigmaEl()); + fillParticleHistos<1>(track, track.tofNSigmaMu()); + fillParticleHistos<2>(track, track.tofNSigmaPi()); + fillParticleHistos<3>(track, track.tofNSigmaKa()); + fillParticleHistos<4>(track, track.tofNSigmaPr()); + fillParticleHistos<5>(track, track.tofNSigmaDe()); + fillParticleHistos<6>(track, track.tofNSigmaTr()); + fillParticleHistos<7>(track, track.tofNSigmaHe()); + fillParticleHistos<8>(track, track.tofNSigmaAl()); + + // + if (TMath::Abs(track.separationbetael() < 1.f)) { + histos.fill(HIST("electronbeta/hp_El"), track.p()); + histos.fill(HIST("electronbeta/hpt_El"), track.pt()); + histos.fill(HIST("electronbeta/hlength_El"), track.length()); + histos.fill(HIST("electronbeta/htime_El"), track.tofSignal() / 1000); + histos.fill(HIST("electronbeta/hp_beta_El"), track.p(), track.diffbetael()); + histos.fill(HIST("electronbeta/hp_betasigma_El"), track.p(), track.separationbetael()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const&) +{ + WorkflowSpec workflow{adaptAnalysisTask("tofspectra-split-task")}; + return workflow; +} diff --git a/Analysis/Tasks/PWGLF/spectraTPC.cxx b/Analysis/Tasks/PWGLF/spectraTPC.cxx index 84918ed15f349..45d72cb245723 100644 --- a/Analysis/Tasks/PWGLF/spectraTPC.cxx +++ b/Analysis/Tasks/PWGLF/spectraTPC.cxx @@ -78,9 +78,9 @@ struct TPCSpectraTask { Configurable nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; template - void fillParticleHistos(const T& track, const float nsigma[]) + void fillParticleHistos(const T& track, const float& nsigma) { - if (abs(nsigma[i]) > nsigmacut.value) { + if (abs(nsigma) > nsigmacut.value) { return; } histos.fill(HIST(hp[i]), track.p()); @@ -90,21 +90,18 @@ struct TPCSpectraTask { using TrackCandidates = soa::Filtered>; void process(TrackCandidates::iterator const& track) { - const float nsigma[Np] = {track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), - track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tpcNSigmaDe(), - track.tpcNSigmaTr(), track.tpcNSigmaHe(), track.tpcNSigmaAl()}; histos.fill(HIST("p/Unselected"), track.p()); histos.fill(HIST("pt/Unselected"), track.pt()); - fillParticleHistos<0>(track, nsigma); - fillParticleHistos<1>(track, nsigma); - fillParticleHistos<2>(track, nsigma); - fillParticleHistos<3>(track, nsigma); - fillParticleHistos<4>(track, nsigma); - fillParticleHistos<5>(track, nsigma); - fillParticleHistos<6>(track, nsigma); - fillParticleHistos<7>(track, nsigma); - fillParticleHistos<8>(track, nsigma); + fillParticleHistos<0>(track, track.tpcNSigmaEl()); + fillParticleHistos<1>(track, track.tpcNSigmaMu()); + fillParticleHistos<2>(track, track.tpcNSigmaPi()); + fillParticleHistos<3>(track, track.tpcNSigmaKa()); + fillParticleHistos<4>(track, track.tpcNSigmaPr()); + fillParticleHistos<5>(track, track.tpcNSigmaDe()); + fillParticleHistos<6>(track, track.tpcNSigmaTr()); + fillParticleHistos<7>(track, track.tpcNSigmaHe()); + fillParticleHistos<8>(track, track.tpcNSigmaAl()); } }; @@ -143,16 +140,16 @@ struct TPCPIDQASignalwTOFTask { void process(TrackCandidates::iterator const& track) { // const float mom = track.p(); - const float mom = track.tpcInnerParam(); - histos.fill(HIST(htpcsignal[0]), mom, track.tpcSignal(), track.tofNSigmaEl()); - histos.fill(HIST(htpcsignal[1]), mom, track.tpcSignal(), track.tofNSigmaMu()); - histos.fill(HIST(htpcsignal[2]), mom, track.tpcSignal(), track.tofNSigmaPi()); - histos.fill(HIST(htpcsignal[3]), mom, track.tpcSignal(), track.tofNSigmaKa()); - histos.fill(HIST(htpcsignal[4]), mom, track.tpcSignal(), track.tofNSigmaPr()); - histos.fill(HIST(htpcsignal[5]), mom, track.tpcSignal(), track.tofNSigmaDe()); - histos.fill(HIST(htpcsignal[6]), mom, track.tpcSignal(), track.tofNSigmaTr()); - histos.fill(HIST(htpcsignal[7]), mom, track.tpcSignal(), track.tofNSigmaHe()); - histos.fill(HIST(htpcsignal[8]), mom, track.tpcSignal(), track.tofNSigmaAl()); + // const float mom = track.tpcInnerParam(); + histos.fill(HIST(htpcsignal[0]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaEl()); + histos.fill(HIST(htpcsignal[1]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaMu()); + histos.fill(HIST(htpcsignal[2]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaPi()); + histos.fill(HIST(htpcsignal[3]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaKa()); + histos.fill(HIST(htpcsignal[4]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaPr()); + histos.fill(HIST(htpcsignal[5]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaDe()); + histos.fill(HIST(htpcsignal[6]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaTr()); + histos.fill(HIST(htpcsignal[7]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaHe()); + histos.fill(HIST(htpcsignal[8]), track.tpcInnerParam(), track.tpcSignal(), track.tofNSigmaAl()); } }; diff --git a/Analysis/Tasks/PWGLF/spectraTPC_split.cxx b/Analysis/Tasks/PWGLF/spectraTPC_split.cxx new file mode 100644 index 0000000000000..700b6b94600d3 --- /dev/null +++ b/Analysis/Tasks/PWGLF/spectraTPC_split.cxx @@ -0,0 +1,177 @@ +// 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 includes +#include "ReconstructionDataFormats/Track.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/TrackSelectionTables.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +void customize(std::vector& workflowOptions) +{ + std::vector options{ + {"add-tof-histos", VariantType::Int, 0, {"Generate TPC with TOF histograms"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +#define CANDIDATE_SELECTION \ + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; \ + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; \ + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; \ + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::isGlobalTrack == (uint8_t) true); + +// FIXME: we should put this function in some common header so it has to be defined only once +template +void makelogaxis(T h) +{ + const int nbins = h->GetNbinsX(); + double binp[nbins + 1]; + double max = h->GetXaxis()->GetBinUpEdge(nbins); + double min = h->GetXaxis()->GetBinLowEdge(1); + if (min <= 0) { + min = 0.00001; + } + double lmin = TMath::Log10(min); + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); + for (int i = 0; i < nbins; i++) { + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); + } + binp[nbins] = max + 1; + h->GetXaxis()->Set(nbins, binp); +} + +constexpr int Np = 9; +struct TPCSpectraTaskSplit { + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr std::string_view hp[Np] = {"p/El", "p/Mu", "p/Pi", "p/Ka", "p/Pr", "p/De", "p/Tr", "p/He", "p/Al"}; + static constexpr std::string_view hpt[Np] = {"pt/El", "pt/Mu", "pt/Pi", "pt/Ka", "pt/Pr", "pt/De", "pt/Tr", "pt/He", "pt/Al"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + histos.add("p/Unselected", "Unselected;#it{p} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + histos.add("pt/Unselected", "Unselected;#it{p}_{T} (GeV/#it{c})", kTH1F, {{100, 0, 20}}); + for (int i = 0; i < Np; i++) { + histos.add(hp[i].data(), Form("%s;#it{p} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + histos.add(hpt[i].data(), Form("%s;#it{p}_{T} (GeV/#it{c})", pT[i]), kTH1F, {{100, 0, 20}}); + } + } + + //Defining filters and input + CANDIDATE_SELECTION + + Configurable nsigmacut{"nsigmacut", 3, "Value of the Nsigma cut"}; + + template + void fillParticleHistos(const T& track, const float& nsigma) + { + if (abs(nsigma) > nsigmacut.value) { + return; + } + histos.fill(HIST(hp[i]), track.p()); + histos.fill(HIST(hpt[i]), track.pt()); + } + + using TrackCandidates = soa::Filtered>; + + void process(TrackCandidates::iterator const& track) + { + histos.fill(HIST("p/Unselected"), track.p()); + histos.fill(HIST("pt/Unselected"), track.pt()); + + fillParticleHistos<0>(track, track.tpcNSigmaEl()); + fillParticleHistos<1>(track, track.tpcNSigmaMu()); + fillParticleHistos<2>(track, track.tpcNSigmaPi()); + fillParticleHistos<3>(track, track.tpcNSigmaKa()); + fillParticleHistos<4>(track, track.tpcNSigmaPr()); + fillParticleHistos<5>(track, track.tpcNSigmaDe()); + fillParticleHistos<6>(track, track.tpcNSigmaTr()); + fillParticleHistos<7>(track, track.tpcNSigmaHe()); + fillParticleHistos<8>(track, track.tpcNSigmaAl()); + } +}; + +struct TPCPIDQASignalwTOFTaskSplit { + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr std::string_view htpcsignal[Np] = {"tpcsignal/El", "tpcsignal/Mu", "tpcsignal/Pi", + "tpcsignal/Ka", "tpcsignal/Pr", "tpcsignal/De", + "tpcsignal/Tr", "tpcsignal/He", "tpcsignal/Al"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + template + void addParticleHistos() + { + histos.add(htpcsignal[i].data(), Form(";#it{p} (GeV/#it{c});TPC Signal;N_{#sigma}^{TPC}(%s)", pT[i]), kTH3D, {{1000, 0.001, 20}, {1000, 0, 1000}, {20, -10, 10}}); + makelogaxis(histos.get(HIST(htpcsignal[i]))); + } + + void init(o2::framework::InitContext&) + { + addParticleHistos<0>(); + addParticleHistos<1>(); + addParticleHistos<2>(); + addParticleHistos<3>(); + addParticleHistos<4>(); + addParticleHistos<5>(); + addParticleHistos<6>(); + addParticleHistos<7>(); + addParticleHistos<8>(); + } + + // Filters + CANDIDATE_SELECTION + + Filter trackFilterTOF = (aod::track::tofSignal > 0.f); // Skip tracks without TOF + using TrackCandidates = soa::Filtered>; + + void process(TrackCandidates::iterator const& track) + { + // const float mom = track.p(); + const float mom = track.tpcInnerParam(); + histos.fill(HIST(htpcsignal[0]), mom, track.tpcSignal(), track.tofNSigmaEl()); + histos.fill(HIST(htpcsignal[1]), mom, track.tpcSignal(), track.tofNSigmaMu()); + histos.fill(HIST(htpcsignal[2]), mom, track.tpcSignal(), track.tofNSigmaPi()); + histos.fill(HIST(htpcsignal[3]), mom, track.tpcSignal(), track.tofNSigmaKa()); + histos.fill(HIST(htpcsignal[4]), mom, track.tpcSignal(), track.tofNSigmaPr()); + histos.fill(HIST(htpcsignal[5]), mom, track.tpcSignal(), track.tofNSigmaDe()); + histos.fill(HIST(htpcsignal[6]), mom, track.tpcSignal(), track.tofNSigmaTr()); + histos.fill(HIST(htpcsignal[7]), mom, track.tpcSignal(), track.tofNSigmaHe()); + histos.fill(HIST(htpcsignal[8]), mom, track.tpcSignal(), track.tofNSigmaAl()); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + int TPCwTOF = cfgc.options().get("add-tof-histos"); + WorkflowSpec workflow{adaptAnalysisTask("tpcspectra-split-task")}; + if (TPCwTOF) { + workflow.push_back(adaptAnalysisTask("TPCpidqa-signalwTOF-split-task")); + } + return workflow; +} diff --git a/Analysis/Tasks/pidTOF_split.cxx b/Analysis/Tasks/pidTOF_split.cxx new file mode 100644 index 0000000000000..4e6c83dda0b39 --- /dev/null +++ b/Analysis/Tasks/pidTOF_split.cxx @@ -0,0 +1,222 @@ +// 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 includes +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDTOF.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::pid; +using namespace o2::framework::expressions; +using namespace o2::track; + +void customize(std::vector& workflowOptions) +{ + std::vector options{ + {"add-qa", VariantType::Int, 1, {"Produce TOF PID QA histograms"}}, + {"pid-el", VariantType::Int, 1, {"Produce PID information for the electron mass hypothesis"}}, + {"pid-mu", VariantType::Int, 1, {"Produce PID information for the muon mass hypothesis"}}, + {"pid-pikapr", VariantType::Int, 1, {"Produce PID information for the Pion, Kaon, Proton mass hypothesis"}}, + {"pid-nuclei", VariantType::Int, 1, {"Produce PID information for the Deuteron, Triton, Alpha mass hypothesis"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +template +struct pidTOFTaskPerParticle { + using Trks = soa::Join; + using Coll = aod::Collisions; + Produces tofpid; + DetectorResponse resp; + Service ccdb; + Configurable paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"}; + Configurable sigmaname{"param-sigma", "TOFReso", "Name of the parametrization for the expected sigma, used in both file and CCDB mode"}; + Configurable url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + + void init(o2::framework::InitContext&) + { + ccdb->setURL(url.value); + ccdb->setTimestamp(timestamp.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now objects + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + // + const std::vector p = {0.008, 0.008, 0.002, 40.0}; + resp.SetParameters(DetectorResponse::kSigma, p); + const std::string fname = paramfile.value; + if (!fname.empty()) { // Loading the parametrization from file + resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma); + } else { // Loading it from CCDB + const std::string path = "Analysis/PID/TOF"; + resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp(path + "/" + sigmaname.value, timestamp.value)); + } + } + + void process(Coll const& collisions, Trks const& tracks) + { + constexpr tof::ExpTimes resp_PID = tof::ExpTimes(); + + tofpid.reserve(tracks.size()); + for (auto const& trk : tracks) { + tofpid(resp_PID.GetExpectedSigma(resp, trk.collision(), trk), + resp_PID.GetSeparation(resp, trk.collision(), trk)); + } + } +}; + +struct pidTOFTaskQA { + + static constexpr int Np = 9; + static constexpr std::string_view hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi", + "expected/Ka", "expected/Pr", "expected/De", + "expected/Tr", "expected/He", "expected/Al"}; + static constexpr std::string_view hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", + "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", + "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; + static constexpr std::string_view hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi", + "nsigma/Ka", "nsigma/Pr", "nsigma/De", + "nsigma/Tr", "nsigma/He", "nsigma/Al"}; + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; + + Configurable nBinsP{"nBinsP", 400, "Number of bins for the momentum"}; + Configurable MinP{"MinP", 0.1, "Minimum momentum in range"}; + Configurable MaxP{"MaxP", 5, "Maximum momentum in range"}; + + template + void makelogaxis(T h) + { + const int nbins = h->GetNbinsX(); + double binp[nbins + 1]; + double max = h->GetXaxis()->GetBinUpEdge(nbins); + double min = h->GetXaxis()->GetBinLowEdge(1); + if (min <= 0) { + min = 0.00001; + } + double lmin = TMath::Log10(min); + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); + for (int i = 0; i < nbins; i++) { + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); + } + binp[nbins] = max + 1; + h->GetXaxis()->Set(nbins, binp); + } + + template + void addParticleHistos() + { + // Exp signal + histos.add(hexpected[i].data(), Form(";#it{p} (GeV/#it{c});t_{exp}(%s)", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2e6}}); + makelogaxis(histos.get(HIST(hexpected[i]))); + + // T-Texp + histos.add(hexpected_diff[i].data(), Form(";#it{p} (GeV/#it{c});(t-t_{evt}-t_{exp}(%s))", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {100, -1000, 1000}}); + makelogaxis(histos.get(HIST(hexpected_diff[i]))); + + // NSigma + histos.add(hnsigma[i].data(), Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TOF}(%s)", pT[i]), HistType::kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); + makelogaxis(histos.get(HIST(hnsigma[i]))); + } + + void init(o2::framework::InitContext&) + { + // Event properties + histos.add("event/vertexz", ";Vtx_{z} (cm);Entries", HistType::kTH1F, {{100, -20, 20}}); + histos.add("event/colltime", ";Collision time (ps);Entries", HistType::kTH1F, {{100, -2000, 2000}}); + histos.add("event/tofsignal", ";#it{p} (GeV/#it{c});TOF Signal", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {10000, 0, 2e6}}); + makelogaxis(histos.get(HIST("event/tofsignal"))); + histos.add("event/tofbeta", ";#it{p} (GeV/#it{c});TOF #beta", HistType::kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 2}}); + makelogaxis(histos.get(HIST("event/tofbeta"))); + + addParticleHistos<0>(); + addParticleHistos<1>(); + addParticleHistos<2>(); + addParticleHistos<3>(); + addParticleHistos<4>(); + addParticleHistos<5>(); + addParticleHistos<6>(); + addParticleHistos<7>(); + addParticleHistos<8>(); + } + + template + void fillParticleHistos(const T& t, const float tof, const float exp_diff, const float nsigma) + { + histos.fill(HIST(hexpected[i]), t.p(), tof - exp_diff); + histos.fill(HIST(hexpected_diff[i]), t.p(), exp_diff); + histos.fill(HIST(hnsigma[i]), t.p(), nsigma); + } + + void process(aod::Collision const& collision, soa::Join const& tracks) + { + const float collisionTime_ps = collision.collisionTime() * 1000.f; + histos.fill(HIST("event/vertexz"), collision.posZ()); + histos.fill(HIST("event/colltime"), collisionTime_ps); + + for (auto t : tracks) { + // + if (t.tofSignal() < 0) { // Skipping tracks without TOF + continue; + } + + const float tof = t.tofSignal() - collisionTime_ps; + + // + histos.fill(HIST("event/tofsignal"), t.p(), t.tofSignal()); + histos.fill(HIST("event/tofbeta"), t.p(), t.beta()); + // + fillParticleHistos<0>(t, tof, t.tofExpSignalDiffEl(), t.tofNSigmaEl()); + fillParticleHistos<1>(t, tof, t.tofExpSignalDiffMu(), t.tofNSigmaMu()); + fillParticleHistos<2>(t, tof, t.tofExpSignalDiffPi(), t.tofNSigmaPi()); + fillParticleHistos<3>(t, tof, t.tofExpSignalDiffKa(), t.tofNSigmaKa()); + fillParticleHistos<4>(t, tof, t.tofExpSignalDiffPr(), t.tofNSigmaPr()); + fillParticleHistos<5>(t, tof, t.tofExpSignalDiffDe(), t.tofNSigmaDe()); + fillParticleHistos<6>(t, tof, t.tofExpSignalDiffTr(), t.tofNSigmaTr()); + fillParticleHistos<7>(t, tof, t.tofExpSignalDiffHe(), t.tofNSigmaHe()); + fillParticleHistos<8>(t, tof, t.tofExpSignalDiffAl(), t.tofNSigmaAl()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + auto workflow = WorkflowSpec{}; + if (cfgc.options().get("pid-el")) { + workflow.push_back(adaptAnalysisTask>("pidTOFEl-task")); + } + if (cfgc.options().get("pid-mu")) { + workflow.push_back(adaptAnalysisTask>("pidTOFMu-task")); + } + if (cfgc.options().get("pid-pikapr")) { + workflow.push_back(adaptAnalysisTask>("pidTOFPi-task")); + workflow.push_back(adaptAnalysisTask>("pidTOFKa-task")); + workflow.push_back(adaptAnalysisTask>("pidTOFPr-task")); + } + if (cfgc.options().get("pid-nuclei")) { + workflow.push_back(adaptAnalysisTask>("pidTOFDe-task")); + workflow.push_back(adaptAnalysisTask>("pidTOFTr-task")); + workflow.push_back(adaptAnalysisTask>("pidTOFHe-task")); + workflow.push_back(adaptAnalysisTask>("pidTOFAl-task")); + } + if (cfgc.options().get("add-qa")) { + workflow.push_back(adaptAnalysisTask("pidTOFQA-task")); + } + return workflow; +} diff --git a/Analysis/Tasks/pidTPC.cxx b/Analysis/Tasks/pidTPC.cxx index d94e45954b03d..9255edc774b6e 100644 --- a/Analysis/Tasks/pidTPC.cxx +++ b/Analysis/Tasks/pidTPC.cxx @@ -27,7 +27,7 @@ using namespace o2::track; void customize(std::vector& workflowOptions) { std::vector options{ - {"add-qa", VariantType::Int, 0, {"Produce TOF PID QA histograms"}}}; + {"add-qa", VariantType::Int, 0, {"Produce TPC PID QA histograms"}}}; std::swap(workflowOptions, options); } diff --git a/Analysis/Tasks/pidTPC_split.cxx b/Analysis/Tasks/pidTPC_split.cxx new file mode 100644 index 0000000000000..07620bc48e6c8 --- /dev/null +++ b/Analysis/Tasks/pidTPC_split.cxx @@ -0,0 +1,213 @@ +// 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 includes +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/HistogramRegistry.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include "AnalysisDataModel/PID/PIDResponse.h" +#include "AnalysisDataModel/PID/PIDTPC.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::pid; +using namespace o2::framework::expressions; +using namespace o2::track; + +void customize(std::vector& workflowOptions) +{ + std::vector options{ + {"add-qa", VariantType::Int, 0, {"Produce TPC PID QA histograms"}}, + {"pid-el", VariantType::Int, 0, {"Produce PID information for the electron mass hypothesis"}}, + {"pid-mu", VariantType::Int, 0, {"Produce PID information for the muon mass hypothesis"}}, + {"pid-pikapr", VariantType::Int, 0, {"Produce PID information for the Pion, Kaon, Proton mass hypothesis"}}, + {"pid-nuclei", VariantType::Int, 0, {"Produce PID information for the Deuteron, Triton, Alpha mass hypothesis"}}}; + std::swap(workflowOptions, options); +} + +#include "Framework/runDataProcessing.h" + +template +struct pidTPCTaskPerParticle { + using Trks = soa::Join; + using Coll = aod::Collisions; + Produces
tpcpid; + DetectorResponse resp; + Service ccdb; + Configurable paramfile{"param-file", "", "Path to the parametrization object, if emtpy the parametrization is not taken from file"}; + Configurable signalname{"param-signal", "BetheBloch", "Name of the parametrization for the expected signal, used in both file and CCDB mode"}; + Configurable sigmaname{"param-sigma", "TPCReso", "Name of the parametrization for the expected sigma, used in both file and CCDB mode"}; + Configurable url{"ccdb-url", "http://ccdb-test.cern.ch:8080", "url of the ccdb repository"}; + Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; + + void init(o2::framework::InitContext&) + { + ccdb->setURL(url.value); + ccdb->setTimestamp(timestamp.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now objects + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + // + const std::string fname = paramfile.value; + if (!fname.empty()) { // Loading the parametrization from file + resp.LoadParamFromFile(fname.data(), signalname.value, DetectorResponse::kSignal); + resp.LoadParamFromFile(fname.data(), sigmaname.value, DetectorResponse::kSigma); + } else { // Loading it from CCDB + const std::string path = "Analysis/PID/TPC"; + resp.LoadParam(DetectorResponse::kSignal, ccdb->getForTimeStamp(path + "/" + signalname.value, timestamp.value)); + resp.LoadParam(DetectorResponse::kSigma, ccdb->getForTimeStamp(path + "/" + sigmaname.value, timestamp.value)); + } + } + + void process(Coll const& collisions, Trks const& tracks) + { + constexpr tpc::ELoss resp_PID = tpc::ELoss(); + + tpcpid.reserve(tracks.size()); + for (auto const& trk : tracks) { + tpcpid(resp_PID.GetExpectedSigma(resp, trk.collision(), trk), + resp_PID.GetSeparation(resp, trk.collision(), trk)); + } + } +}; + +struct pidTPCTaskQA { + static constexpr int Np = 9; + static constexpr const char* pT[Np] = {"e", "#mu", "#pi", "K", "p", "d", "t", "^{3}He", "#alpha"}; + static constexpr std::string_view hexpected[Np] = {"expected/El", "expected/Mu", "expected/Pi", + "expected/Ka", "expected/Pr", "expected/De", + "expected/Tr", "expected/He", "expected/Al"}; + static constexpr std::string_view hexpected_diff[Np] = {"expected_diff/El", "expected_diff/Mu", "expected_diff/Pi", + "expected_diff/Ka", "expected_diff/Pr", "expected_diff/De", + "expected_diff/Tr", "expected_diff/He", "expected_diff/Al"}; + static constexpr std::string_view hnsigma[Np] = {"nsigma/El", "nsigma/Mu", "nsigma/Pi", + "nsigma/Ka", "nsigma/Pr", "nsigma/De", + "nsigma/Tr", "nsigma/He", "nsigma/Al"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::QAObject}; + + Configurable nBinsP{"nBinsP", 400, "Number of bins for the momentum"}; + Configurable MinP{"MinP", 0, "Minimum momentum in range"}; + Configurable MaxP{"MaxP", 20, "Maximum momentum in range"}; + + template + void makelogaxis(T h) + { + const int nbins = h->GetNbinsX(); + double binp[nbins + 1]; + double max = h->GetXaxis()->GetBinUpEdge(nbins); + double min = h->GetXaxis()->GetBinLowEdge(1); + if (min <= 0) { + min = 0.00001; + } + double lmin = TMath::Log10(min); + double ldelta = (TMath::Log10(max) - lmin) / ((double)nbins); + for (int i = 0; i < nbins; i++) { + binp[i] = TMath::Exp(TMath::Log(10) * (lmin + i * ldelta)); + } + binp[nbins] = max + 1; + h->GetXaxis()->Set(nbins, binp); + } + + template + void addParticleHistos() + { + // Exp signal + histos.add(hexpected[i].data(), Form(";#it{p} (GeV/#it{c});d#it{E}/d#it{x}_(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); + makelogaxis(histos.get(HIST(hexpected[i]))); + + // Signal - Expected signal + histos.add(hexpected_diff[i].data(), Form(";#it{p} (GeV/#it{c});;d#it{E}/d#it{x} - d#it{E}/d#it{x}(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {1000, -500, 500}}); + makelogaxis(histos.get(HIST(hexpected_diff[i]))); + + // NSigma + histos.add(hnsigma[i].data(), Form(";#it{p} (GeV/#it{c});N_{#sigma}^{TPC}(%s)", pT[i]), kTH2F, {{nBinsP, MinP, MaxP}, {200, -10, 10}}); + makelogaxis(histos.get(HIST(hnsigma[i]))); + } + + void init(o2::framework::InitContext&) + { + // Event properties + histos.add("event/vertexz", ";Vtx_{z} (cm);Entries", kTH1F, {{100, -20, 20}}); + histos.add("event/tpcsignal", ";#it{p} (GeV/#it{c});TPC Signal", kTH2F, {{nBinsP, MinP, MaxP}, {1000, 0, 1000}}); + makelogaxis(histos.get(HIST("event/tpcsignal"))); + + addParticleHistos<0>(); + addParticleHistos<1>(); + addParticleHistos<2>(); + addParticleHistos<3>(); + addParticleHistos<4>(); + addParticleHistos<5>(); + addParticleHistos<6>(); + addParticleHistos<7>(); + addParticleHistos<8>(); + } + + template + void fillParticleHistos(const T& t, const float mom, const float exp_diff, const float nsigma) + { + histos.fill(HIST(hexpected[i]), mom, t.tpcSignal() - exp_diff); + histos.fill(HIST(hexpected_diff[i]), mom, exp_diff); + histos.fill(HIST(hnsigma[i]), t.p(), nsigma); + } + + void process(aod::Collision const& collision, soa::Join const& tracks) + { + histos.fill(HIST("event/vertexz"), collision.posZ()); + + for (auto t : tracks) { + // const float mom = t.p(); + const float mom = t.tpcInnerParam(); + histos.fill(HIST("event/tpcsignal"), mom, t.tpcSignal()); + // + fillParticleHistos<0>(t, mom, t.tpcExpSignalDiffEl(), t.tpcNSigmaEl()); + fillParticleHistos<1>(t, mom, t.tpcExpSignalDiffMu(), t.tpcNSigmaMu()); + fillParticleHistos<2>(t, mom, t.tpcExpSignalDiffPi(), t.tpcNSigmaPi()); + fillParticleHistos<3>(t, mom, t.tpcExpSignalDiffKa(), t.tpcNSigmaKa()); + fillParticleHistos<4>(t, mom, t.tpcExpSignalDiffPr(), t.tpcNSigmaPr()); + fillParticleHistos<5>(t, mom, t.tpcExpSignalDiffDe(), t.tpcNSigmaDe()); + fillParticleHistos<6>(t, mom, t.tpcExpSignalDiffTr(), t.tpcNSigmaTr()); + fillParticleHistos<7>(t, mom, t.tpcExpSignalDiffHe(), t.tpcNSigmaHe()); + fillParticleHistos<8>(t, mom, t.tpcExpSignalDiffAl(), t.tpcNSigmaAl()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + auto workflow = WorkflowSpec{}; + if (cfgc.options().get("pid-el")) { + workflow.push_back(adaptAnalysisTask>("pidTPCEl-task")); + } + if (cfgc.options().get("pid-mu")) { + workflow.push_back(adaptAnalysisTask>("pidTPCMu-task")); + } + if (cfgc.options().get("pid-pikapr")) { + workflow.push_back(adaptAnalysisTask>("pidTPCPi-task")); + workflow.push_back(adaptAnalysisTask>("pidTPCKa-task")); + workflow.push_back(adaptAnalysisTask>("pidTPCPr-task")); + } + if (cfgc.options().get("pid-nuclei")) { + workflow.push_back(adaptAnalysisTask>("pidTPCDe-task")); + workflow.push_back(adaptAnalysisTask>("pidTPCTr-task")); + workflow.push_back(adaptAnalysisTask>("pidTPCHe-task")); + workflow.push_back(adaptAnalysisTask>("pidTPCAl-task")); + } + if (cfgc.options().get("add-qa")) { + workflow.push_back(adaptAnalysisTask("pidTPCQA-task")); + } + return workflow; +} + +return workflow; +}