Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion Common/TableProducer/PID/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2019-2020 CERN and copyright holders of ALICE O2.

Check failure on line 1 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Use kebab-case for names of workflows and match the name of the workflow file.
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
# All rights not expressly granted are reserved.
#
Expand All @@ -10,45 +10,45 @@
# or submit itself to any jurisdiction.

# ITS
o2physics_add_dpl_workflow(pid-its

Check failure on line 13 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name pid-its does not match its file name pidITS.cxx. (Matches pidIts.cxx.)
SOURCES pidITS.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
COMPONENT_NAME Analysis)

# TOF
o2physics_add_dpl_workflow(pid-tof-base

Check failure on line 19 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name pid-tof-base does not match its file name pidTOFBase.cxx. (Matches pidTofBase.cxx.)
SOURCES pidTOFBase.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFBase
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(pid-tof

Check failure on line 24 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name pid-tof does not match its file name pidTOF.cxx. (Matches pidTof.cxx.)
SOURCES pidTOF.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFWorkflowUtils
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(pid-tof-merge

Check failure on line 29 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name pid-tof-merge does not match its file name pidTOFMerge.cxx. (Matches pidTofMerge.cxx.)
SOURCES pidTOFMerge.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFWorkflowUtils
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(pid-tof-beta

Check failure on line 34 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name pid-tof-beta does not match its file name pidTOFbeta.cxx. (Matches pidTofBeta.cxx.)
SOURCES pidTOFbeta.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFWorkflowUtils
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(pid-tof-full

Check failure on line 39 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name pid-tof-full does not match its file name pidTOFFull.cxx. (Matches pidTofFull.cxx.)
SOURCES pidTOFFull.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFWorkflowUtils
COMPONENT_NAME Analysis)

# TPC

o2physics_add_dpl_workflow(pid-tpc-base

Check failure on line 46 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name pid-tpc-base does not match its file name pidTPCBase.cxx. (Matches pidTpcBase.cxx.)
SOURCES pidTPCBase.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB
COMPONENT_NAME Analysis)

o2physics_add_dpl_workflow(pid-tpc

Check failure on line 51 in Common/TableProducer/PID/CMakeLists.txt

View workflow job for this annotation

GitHub Actions / O2 linter

[name/o2-workflow]

Workflow name pid-tpc does not match its file name pidTPC.cxx. (Matches pidTpc.cxx.)
SOURCES pidTPC.cxx
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore
COMPONENT_NAME Analysis)
Expand Down
124 changes: 110 additions & 14 deletions Common/TableProducer/PID/pidTPC.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,34 @@
/// \brief Task to produce PID tables for TPC split for each particle.
/// Only the tables for the mass hypotheses requested are filled, and only for the requested table size ("Full" or "Tiny"). The others are sent empty.
///
#include <utility>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
// ROOT includes
#include "TFile.h"
#include "TRandom.h"
#include "TSystem.h"

// O2 includes
#include "MetadataHelper.h"
#include "TableHelper.h"
#include "pidTPCBase.h"

#include "Common/Core/PID/TPCPIDResponse.h"
#include "Common/DataModel/EventSelection.h"
#include "Common/DataModel/Multiplicity.h"
#include "Common/DataModel/PIDResponseTPC.h"
#include "Tools/ML/model.h"

#include "CCDB/BasicCCDBManager.h"
#include "CCDB/CcdbApi.h"
#include "Framework/ASoAHelpers.h"
#include "Framework/AnalysisDataModel.h"
#include "Framework/AnalysisTask.h"
#include "Framework/runDataProcessing.h"
#include "Framework/ASoAHelpers.h"
#include "ReconstructionDataFormats/Track.h"
#include "CCDB/CcdbApi.h"
#include "Common/DataModel/PIDResponseTPC.h"
#include "Common/Core/PID/TPCPIDResponse.h"
#include "Framework/AnalysisDataModel.h"
#include "Common/DataModel/Multiplicity.h"
#include "Common/DataModel/EventSelection.h"
#include "TableHelper.h"
#include "Tools/ML/model.h"
#include "pidTPCBase.h"
#include "MetadataHelper.h"

using namespace o2;
using namespace o2::framework;
Expand Down Expand Up @@ -155,8 +157,10 @@
void init(o2::framework::InitContext& initContext)
{
// Protection for process flags
if ((doprocessStandard && doprocessMcTuneOnData) || (!doprocessStandard && !doprocessMcTuneOnData)) {
LOG(fatal) << "pid-tpc must have only one of the options 'processStandard' OR 'processMcTuneOnData' enabled. Please check your configuration.";
if (!((doprocessStandard && !doprocessStandard2 && !doprocessMcTuneOnData) ||
(!doprocessStandard && doprocessStandard2 && !doprocessMcTuneOnData) ||
(!doprocessStandard && !doprocessStandard2 && doprocessMcTuneOnData))) {
LOG(fatal) << "pid-tpc must have only one of the options 'processStandard', 'processStandard2', 'processMcTuneOnData' enabled. Please check your configuration.";
}
response = new o2::pid::tpc::Response();
// Checking the tables are requested in the workflow and enabling them
Expand Down Expand Up @@ -354,7 +358,7 @@

// Filling a std::vector<float> to be evaluated by the network
// Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector
for (int i = 0; i < 9; i++) { // Loop over particle number for which network correction is used

Check failure on line 361 in Common/TableProducer/PID/pidTPC.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
for (auto const& trk : tracks) {
if (!trk.hasTPC()) {
continue;
Expand Down Expand Up @@ -552,6 +556,98 @@
Partition<TrksMC> mcnotTPCStandaloneTracks = (aod::track::tpcNClsFindable > static_cast<uint8_t>(0)) && ((aod::track::itsClusterSizes > static_cast<uint32_t>(0)) || (aod::track::trdPattern > static_cast<uint8_t>(0)) || (aod::track::tofExpMom > 0.f && aod::track::tofChi2 > 0.f)); // To count number of tracks for use in NN array
Partition<TrksMC> mctracksWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0);

void processStandard2(Coll const& collisions, Trks const& tracks, aod::DEdxsCorrected const& dedxscorrected, aod::BCsWithTimestamps const& bcs)
{
const uint64_t outTable_size = tracks.size();
const uint64_t dedxscorrected_size = dedxscorrected.size();

if (dedxscorrected_size != outTable_size) {
LOG(fatal) << "Size of dEdx corrected table does not match size of tracks! dEdx size: " << dedxscorrected_size << ", tracks size: " << outTable_size;
}

auto reserveTable = [&outTable_size](const Configurable<int>& flag, auto& table) {
if (flag.value != 1) {
return;
}
table.reserve(outTable_size);
};

// Prepare memory for enabled tables
reserveTable(pidFullEl, tablePIDFullEl);
reserveTable(pidFullMu, tablePIDFullMu);
reserveTable(pidFullPi, tablePIDFullPi);
reserveTable(pidFullKa, tablePIDFullKa);
reserveTable(pidFullPr, tablePIDFullPr);
reserveTable(pidFullDe, tablePIDFullDe);
reserveTable(pidFullTr, tablePIDFullTr);
reserveTable(pidFullHe, tablePIDFullHe);
reserveTable(pidFullAl, tablePIDFullAl);

reserveTable(pidTinyEl, tablePIDTinyEl);
reserveTable(pidTinyMu, tablePIDTinyMu);
reserveTable(pidTinyPi, tablePIDTinyPi);
reserveTable(pidTinyKa, tablePIDTinyKa);
reserveTable(pidTinyPr, tablePIDTinyPr);
reserveTable(pidTinyDe, tablePIDTinyDe);
reserveTable(pidTinyTr, tablePIDTinyTr);
reserveTable(pidTinyHe, tablePIDTinyHe);
reserveTable(pidTinyAl, tablePIDTinyAl);

const uint64_t tracksForNet_size = (skipTPCOnly) ? notTPCStandaloneTracks.size() : tracksWithTPC.size();
std::vector<float> network_prediction;

if (useNetworkCorrection) {
network_prediction = createNetworkPrediction(collisions, tracks, bcs, tracksForNet_size);
}

uint64_t count_tracks = 0;
uint64_t count_tracks2 = 0;

for (auto const& trk : tracks) {
// Loop on Tracks

const auto& bc = trk.has_collision() ? collisions.iteratorAt(trk.collisionId()).bc_as<aod::BCsWithTimestamps>() : bcs.begin();
auto dedx_corr = dedxscorrected.iteratorAt(count_tracks2);
count_tracks2++;
if (useCCDBParam && ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0
if (recoPass.value == "") {
LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp());
} else {
LOGP(info, "Retrieving TPC Response for timestamp {} and recoPass {}:", bc.timestamp(), recoPass.value);
}
response = ccdb->getSpecific<o2::pid::tpc::Response>(ccdbPath.value, bc.timestamp(), metadata);
headers = ccdbApi.retrieveHeaders(ccdbPath.value, metadata, bc.timestamp());
if (!response) {
LOGP(warning, "!! Could not find a valid TPC response object for specific pass name {}! Falling back to latest uploaded object.", metadata["RecoPassName"]);
response = ccdb->getForTimeStamp<o2::pid::tpc::Response>(ccdbPath.value, bc.timestamp());
headers = ccdbApi.retrieveHeaders(ccdbPath.value, nullmetadata, bc.timestamp());
if (!response) {
LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp());
}
}
LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << bc.timestamp() << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"];
response->PrintAll();
}
auto makePidTablesDefault = [&trk, &dedx_corr, &collisions, &network_prediction, &count_tracks, &tracksForNet_size, this](const int flagFull, auto& tableFull, const int flagTiny, auto& tableTiny, const o2::track::PID::ID pid) {
makePidTables(flagFull, tableFull, flagTiny, tableTiny, pid, dedx_corr.tpcSignalCorrected(), trk, collisions, network_prediction, count_tracks, tracksForNet_size);
};

makePidTablesDefault(pidFullEl, tablePIDFullEl, pidTinyEl, tablePIDTinyEl, o2::track::PID::Electron);
makePidTablesDefault(pidFullMu, tablePIDFullMu, pidTinyMu, tablePIDTinyMu, o2::track::PID::Muon);
makePidTablesDefault(pidFullPi, tablePIDFullPi, pidTinyPi, tablePIDTinyPi, o2::track::PID::Pion);
makePidTablesDefault(pidFullKa, tablePIDFullKa, pidTinyKa, tablePIDTinyKa, o2::track::PID::Kaon);
makePidTablesDefault(pidFullPr, tablePIDFullPr, pidTinyPr, tablePIDTinyPr, o2::track::PID::Proton);
makePidTablesDefault(pidFullDe, tablePIDFullDe, pidTinyDe, tablePIDTinyDe, o2::track::PID::Deuteron);
makePidTablesDefault(pidFullTr, tablePIDFullTr, pidTinyTr, tablePIDTinyTr, o2::track::PID::Triton);
makePidTablesDefault(pidFullHe, tablePIDFullHe, pidTinyHe, tablePIDTinyHe, o2::track::PID::Helium3);
makePidTablesDefault(pidFullAl, tablePIDFullAl, pidTinyAl, tablePIDTinyAl, o2::track::PID::Alpha);

if (trk.hasTPC() && (!skipTPCOnly || trk.hasITS() || trk.hasTRD() || trk.hasTOF())) {
count_tracks++; // Increment network track counter only if track has TPC, and (not skipping TPConly) or (is not TPConly)
}
}
}
PROCESS_SWITCH(tpcPid, processStandard2, "Creating PID tables with Corrected dEdx", false);
void processMcTuneOnData(CollMC const& collisionsMc, TrksMC const& tracksMc, aod::BCsWithTimestamps const& bcs, aod::McParticles const&)
{
gRandom->SetSeed(0); // Ensure unique seed from UUID for each process call
Expand Down
113 changes: 107 additions & 6 deletions Common/TableProducer/PID/pidTPCBase.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@
/// \brief Base to build tasks for TPC PID tasks.
///

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

// O2 includes
#include "CCDB/BasicCCDBManager.h"
#include "Framework/AnalysisTask.h"
#include "ReconstructionDataFormats/Track.h"
#include "Common/DataModel/FT0Corrected.h"
#include "TableHelper.h"
#include "pidTPCBase.h"

#include "Common/CCDB/ctpRateFetcher.h"
#include "Common/DataModel/FT0Corrected.h"

#include "CCDB/BasicCCDBManager.h"
#include "Framework/AnalysisTask.h"
#include "Framework/runDataProcessing.h"
#include "ReconstructionDataFormats/Track.h"

using namespace o2;
using namespace o2::framework;
Expand Down Expand Up @@ -76,7 +79,105 @@ struct PidMultiplicity {
PROCESS_SWITCH(PidMultiplicity, processStandard, "Process with tracks, needs propagated tracks", true);
};

struct DeDxCorrection {
Produces<aod::DEdxsCorrected> dEdxCorrected;
using BCsRun3 = soa::Join<aod::BCs, aod::Timestamps, aod::BcSels, aod::Run3MatchedToBCSparse>;
using ColEvSels = soa::Join<aod::Collisions, aod::EvSels, aod::Mults>;
using FullTracksIU = soa::Join<aod::TracksIU, aod::TracksExtra>;

uint64_t minGlobalBC = 0;
Service<o2::ccdb::BasicCCDBManager> ccdb;
ctpRateFetcher mRateFetcher;

Str_dEdx_correction str_dedx_correction;

// void init(InitContext& initContext)
void init(o2::framework::InitContext&)
{
ccdb->setURL("http://alice-ccdb.cern.ch");
ccdb->setCaching(true);
ccdb->setLocalObjectValidityChecking();
str_dedx_correction.init();
}

void processRun3(
ColEvSels const& cols,
FullTracksIU const& tracks,
aod::BCsWithTimestamps const& bcs)
{
const uint64_t outTable_size = tracks.size();
dEdxCorrected.reserve(outTable_size);

for (auto const& trk : tracks) {
double hadronicRate;
int multTPC;
int occupancy;
if (trk.has_collision()) {
auto collision = cols.iteratorAt(trk.collisionId());
auto bc = collision.bc_as<aod::BCsWithTimestamps>();
const int runnumber = bc.runNumber();
hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, "ZNC hadronic") * 1.e-3; // kHz
multTPC = collision.multTPC();
occupancy = collision.trackOccupancyInTimeRange();
} else {
auto bc = bcs.begin();
const int runnumber = bc.runNumber();
hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, "ZNC hadronic") * 1.e-3; // kHz
multTPC = 0;
occupancy = 0;
}

float fTPCSignal = trk.tpcSignal();
float fNormMultTPC = multTPC / 11000.;

float fTrackOccN = occupancy / 1000.;
float fOccTPCN = fNormMultTPC * 10; //(fNormMultTPC*10).clip(0,12)
if (fOccTPCN > 12)
fOccTPCN = 12;
else if (fOccTPCN < 0)
fOccTPCN = 0;

float fTrackOccMeanN = hadronicRate / 5;
float side = trk.tgl() > 0 ? 1 : 0;
float a1pt = std::abs(trk.signed1Pt());
float a1pt2 = a1pt * a1pt;
float atgl = std::abs(trk.tgl());
float mbb0R = 50 / fTPCSignal;
if (mbb0R > 1.05)
mbb0R = 1.05;
else if (mbb0R < 0.05)
mbb0R = 0.05;
// float mbb0R = max(0.05, min(50 / fTPCSignal, 1.05));
float a1ptmbb0R = a1pt * mbb0R;
float atglmbb0R = atgl * mbb0R;

std::vector<float> vec_occu = {fTrackOccN, fOccTPCN, fTrackOccMeanN};
std::vector<float> vec_track = {mbb0R, a1pt, atgl, atglmbb0R, a1ptmbb0R, side, a1pt2};

float fTPCSignalN_CR0 = str_dedx_correction.fReal_fTPCSignalN(vec_occu, vec_track);

float mbb0R1 = 50 / (fTPCSignal / fTPCSignalN_CR0);
if (mbb0R1 > 1.05)
mbb0R1 = 1.05;
else if (mbb0R1 < 0.05)
mbb0R1 = 0.05;

std::vector<float> vec_track1 = {mbb0R1, a1pt, atgl, atgl * mbb0R1, a1pt * mbb0R1, side, a1pt2};
float fTPCSignalN_CR1 = str_dedx_correction.fReal_fTPCSignalN(vec_occu, vec_track1);

float corrected_dEdx = fTPCSignal / fTPCSignalN_CR1;
dEdxCorrected(corrected_dEdx);
}
}
PROCESS_SWITCH(DeDxCorrection, processRun3, "dEdx correction process", false);

void processDummy(ColEvSels const&) {}

PROCESS_SWITCH(DeDxCorrection, processDummy, "Do nothing", true);
};

WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
{
return WorkflowSpec{adaptAnalysisTask<PidMultiplicity>(cfgc)};
return WorkflowSpec{adaptAnalysisTask<PidMultiplicity>(cfgc),
adaptAnalysisTask<DeDxCorrection>(cfgc)};
}
46 changes: 46 additions & 0 deletions Common/TableProducer/PID/pidTPCBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,22 @@
#include "Common/DataModel/Multiplicity.h"
#include "Common/DataModel/PIDResponseTPC.h"

#include "TMatrixD.h"

namespace o2::aod
{

namespace pid
{
DECLARE_SOA_COLUMN(TpcSignalCorrected, tpcSignalCorrected, float); //!
}; // namespace pid

DECLARE_SOA_TABLE(PIDMults, "AOD", "PIDMults", //! TPC auxiliary table for the PID
o2::soa::Marker<1>,
mult::MultTPC);
DECLARE_SOA_TABLE_FULL(DEdxsCorrected, "DEdxsCorrected", "AOD", "DEDXCORR", pid::TpcSignalCorrected); //!
using PIDMult = PIDMults::iterator;
using DEdxCorrected = DEdxsCorrected::iterator; //!

} // namespace o2::aod

Expand Down Expand Up @@ -57,4 +66,41 @@ int getPIDIndex(const int pdgCode) // Get O2 PID index corresponding to MC PDG c
}
}

typedef struct Str_dEdx_correction {
TMatrixD fMatrix;
bool warning = true;

// void init(std::vector<double>& params)
void init()
{
double elements[32] = {0.99091, -0.015053, 0.0018912, -0.012305,
0.081387, 0.003205, -0.0087404, -0.0028608,
0.013066, 0.017012, -0.0018469, -0.0052177,
-0.0035655, 0.0017846, 0.0019127, -0.00012964,
0.0049428, 0.0055592, -0.0010618, -0.0016134,
-0.0059098, 0.0013335, 0.00052133, 3.1119e-05,
-0.004882, 0.00077317, -0.0013827, 0.003249,
-0.00063689, 0.0016218, -0.00045215, -1.5815e-05};
fMatrix.ResizeTo(4, 8);
fMatrix.SetMatrixArray(elements);
}

float fReal_fTPCSignalN(std::vector<float>& vec1, std::vector<float>& vec2)
{
float result = 0.f;
// push 1.
vec1.insert(vec1.begin(), 1.0);
vec2.insert(vec2.begin(), 1.0);
for (int i = 0; i < fMatrix.GetNrows(); i++) {
for (int j = 0; j < fMatrix.GetNcols(); j++) {
double param = fMatrix(i, j);
double value1 = i > static_cast<int>(vec1.size()) ? 0 : vec1[i];
double value2 = j > static_cast<int>(vec2.size()) ? 0 : vec2[j];
result += param * value1 * value2;
}
}
return result;
}
} Str_dEdx_correction;

#endif // COMMON_TABLEPRODUCER_PID_PIDTPCBASE_H_
Loading
Loading