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
12 changes: 11 additions & 1 deletion ALICE3/Tasks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ o2physics_add_dpl_workflow(alice3-pid-ftof-qa
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(alice3-pid-separation-power
SOURCES alice3SeparationPower.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(alice3-cdeuteron
SOURCES alice3-cdeuteron.cxx
PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore
Expand All @@ -52,4 +57,9 @@ o2physics_add_dpl_workflow(alice3-dilepton
o2physics_add_dpl_workflow(alice3-taskcorrelationddbar
SOURCES alice3-taskcorrelationDDbar.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
COMPONENT_NAME Analysis)
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(alice3-efficiency
SOURCES alice3Efficiency.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
COMPONENT_NAME Analysis)
103 changes: 103 additions & 0 deletions ALICE3/Tasks/alice3Efficiency.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// 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 alice3Efficiency.cxx
///
/// \brief This task produces the efficiency
///
/// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT)
/// \since May 27, 2025
///

#include <map>
#include <vector>

#include "Framework/AnalysisTask.h"
#include "Framework/runDataProcessing.h"
#include "Framework/HistogramRegistry.h"
#include "Framework/ConfigParamRegistry.h"
#include "TEfficiency.h"
#include "THashList.h"

using namespace o2;
using namespace o2::framework;
std::map<int, TEfficiency*> effVsPt;
std::map<int, TEfficiency*> effVsEta;

struct alice3Efficiency {
Configurable<std::vector<int>> pdgCodes{"pdgCodes", {211}, "List of PDG codes to consider for efficiency calculation"};
OutputObj<THashList> outList{"output"};
Configurable<std::pair<float, float>> etaRange{"etaRange", {-5.f, 5.f}, "Eta range for efficiency calculation"};
void init(o2::framework::InitContext&)
{
outList.setObject(new THashList);
auto createEff = [&](const char* baseName, const char* axisTitle, int pdg, int nBins, double min, double max) {
auto eff = new TEfficiency(Form("%s_pdg%d", baseName, pdg),
Form("Efficiency for PDG %d; %s; Efficiency", pdg, axisTitle),
nBins, min, max);
outList->Add(eff);
return eff;
};
for (auto pdg : pdgCodes.value) {
effVsPt[pdg] = createEff("efficiency", "p_{T} (GeV/c)", pdg, 100, 0, 10);
effVsEta[pdg] = createEff("efficiency_eta", "#eta", pdg, 100, -5, 5);
}
}

void process(soa::Join<aod::Tracks, o2::aod::McTrackLabels> const& tracks,
aod::McParticles const& mcParticles)
{
std::map<int, std::vector<int64_t>> pdgIndices;

// Lambda function to select particles after all cuts
auto isParticleSelected = [&](const o2::aod::McParticle& p) {
if (!p.isPhysicalPrimary()) {
return false;
}
if (p.eta() < etaRange.value.first) {
return false;
}
if (p.eta() > etaRange.value.second) {
return false;
}
return true;
};
for (const auto& track : tracks) {
if (!track.has_mcParticle()) {
continue;
}
const auto& mcParticle = track.mcParticle();
if (!isParticleSelected(mcParticle)) {
continue;
}
pdgIndices[mcParticle.pdgCode()].push_back(mcParticle.globalIndex());
}

for (auto& mc : mcParticles) {
if (effVsPt.find(mc.pdgCode()) == effVsPt.end()) {
continue;
}
if (!isParticleSelected(mc)) {
continue;
}
std::vector<int64_t>& indices = pdgIndices[mc.pdgCode()];
// Fill efficiency histogram
const bool found = std::find(indices.begin(), indices.end(), mc.globalIndex()) != indices.end();
effVsPt[mc.pdgCode()]->Fill(found, mc.pt());
effVsEta[mc.pdgCode()]->Fill(found, mc.eta());
}
}
};

WorkflowSpec defineDataProcessing(ConfigContext const& ctx)
{
return WorkflowSpec{adaptAnalysisTask<alice3Efficiency>(ctx)};
}
106 changes: 106 additions & 0 deletions ALICE3/Tasks/alice3SeparationPower.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// 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 alice3SeparationPower.cxx
///
/// \brief This task produces the separation power of the ALICE3 detector
///
/// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT)
/// \since May 13, 2025
///

#include <utility>
#include <map>
#include <string>
#include <vector>

#include "Framework/AnalysisDataModel.h"
#include "Framework/AnalysisTask.h"
#include "Framework/runDataProcessing.h"
#include "Framework/RunningWorkflowInfo.h"
#include "Framework/HistogramRegistry.h"
#include "TProfile2D.h"
#include "THashList.h"
#include "ALICE3/DataModel/OTFTOF.h"
#include "ALICE3/DataModel/OTFRICH.h"

using namespace o2;
using namespace o2::framework;

std::array<TProfile2D*, 5> separationInnerTOF;
std::array<TProfile2D*, 5> separationOuterTOF;
std::array<TProfile2D*, 5> separationRICH;
struct alice3SeparationPower {

ConfigurableAxis etaAxis{"etaAxis", {100, -1.f, 1.f}, "Binning in eta"};
HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject};
OutputObj<THashList> listSeparation{"separationPower"};
void init(o2::framework::InitContext&)
{
listSeparation.setObject(new THashList);
for (int i = 0; i < 5; i++) {
auto createEfficiency = [&](const char* name, const char* title) {
TProfile2D* eff = new TProfile2D(Form("%s_%d", name, i),
Form("%s_%d;%s", title, i, "#it{p}_{T} (GeV/#it{c});#it{#eta}"),
100, 0.f, 10.f,
100, 0.f, 10.f);
listSeparation->Add(eff);
return eff;
};
separationInnerTOF[i] = createEfficiency("separationInnerTOF", "separationInnerTOF");
separationOuterTOF[i] = createEfficiency("separationOuterTOF", "separationOuterTOF");
separationRICH[i] = createEfficiency("separationRICH", "separationRICH");
}
}

void process(soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const& /*collision*/,
soa::Join<aod::Tracks, aod::TracksCov, aod::McTrackLabels, aod::UpgradeTofMC, aod::UpgradeTof> const& tracks,
aod::McParticles const&,
aod::McCollisions const&)
{
for (const auto& track : tracks) {
if (!track.has_mcParticle()) {
continue;
}
// Check that all the nsigmas are numbers (sanity check)
for (int i = 0; i < 5; i++) {
if (std::isnan(track.nSigmaInnerTOF(i)) || std::isnan(track.nSigmaOuterTOF(i))) {
LOG(fatal) << "Unrecognized nsigma for " << i << " " << track.nSigmaInnerTOF(i) << " " << track.nSigmaOuterTOF(i);
}
}

const auto& mcParticle = track.mcParticle();
// Separation electron pion
switch (std::abs(mcParticle.pdgCode())) {
{
case 211: // electron-pion separation
separationInnerTOF[0]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(0));
separationOuterTOF[0]->Fill(track.pt(), track.eta(), track.nSigmaOuterTOF(0));
// separationRICH[0]->Fill(track.pt(), track.eta(), track.nSigmaElectronRich() );
break;
case 321: // pion-kaon separation
separationInnerTOF[1]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(1));
separationOuterTOF[1]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(1));
// separationRICH[1]->Fill(track.pt(), track.eta(), track.nSigmaPionRich() );
break;
case 2212: // kaon-proton separation
separationInnerTOF[2]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(2));
separationOuterTOF[2]->Fill(track.pt(), track.eta(), track.nSigmaInnerTOF(2));
// separationRICH[2]->Fill((track.nSigmaKaonRich() > 3.f), track.pt(), track.eta());
default:
break;
}
}
}
}
};

WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask<alice3SeparationPower>(cfgc)}; }