Skip to content
Merged
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
174 changes: 82 additions & 92 deletions PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -15,38 +15,38 @@
/// \author Gyula Bencedi, gyula.bencedi@cern.ch
/// \since Nov 2024

#include <algorithm>
#include <chrono>
#include <cmath>
#include <numeric>
#include <vector>
#include <string>
#include "Functions.h"
#include "Index.h"
#include "bestCollisionTable.h"

#include "CCDB/BasicCCDBManager.h"
#include "Common/CCDB/ctpRateFetcher.h"
#include "Common/DataModel/Centrality.h"
#include "Common/DataModel/CollisionAssociationTables.h"
#include "Common/DataModel/EventSelection.h"
#include "Common/DataModel/Multiplicity.h"
#include "Common/DataModel/TrackSelectionTables.h"

#include "CCDB/BasicCCDBManager.h"
#include "CommonConstants/MathConstants.h"
#include "Framework/ASoAHelpers.h"
#include "Framework/AnalysisDataModel.h"
#include "Framework/AnalysisTask.h"
#include "Framework/Configurable.h"
#include "Framework/O2DatabasePDGPlugin.h"
#include "Framework/RuntimeError.h"
#include "Framework/runDataProcessing.h"

#include "Common/CCDB/ctpRateFetcher.h"
#include "Common/DataModel/Centrality.h"
#include "Common/DataModel/CollisionAssociationTables.h"
#include "Common/DataModel/EventSelection.h"
#include "Common/DataModel/Multiplicity.h"
#include "Common/DataModel/TrackSelectionTables.h"
#include "CommonConstants/MathConstants.h"

#include "MathUtils/Utils.h"
#include "ReconstructionDataFormats/GlobalTrackID.h"

#include "TPDGCode.h"

#include "Functions.h"
#include "Index.h"
#include "bestCollisionTable.h"
#include <algorithm>
#include <chrono>
#include <cmath>
#include <numeric>
#include <string>
#include <unordered_map>
#include <vector>

using namespace o2;
using namespace o2::framework;
Expand All @@ -65,6 +65,7 @@
AxisSpec phiAxis = {629, 0, TwoPI, "Rad", "#phi"};
AxisSpec etaAxis = {20, -4., -2.};
AxisSpec centAxis{100, 0, 100, "centrality"};
AxisSpec chiSqAxis = {100, 0., 1000.};

struct DndetaMFTPbPb {
SliceCache cache;
Expand All @@ -83,6 +84,11 @@
false,
true};

Configurable<bool> cfgDoIR{"cfgDoIR", false, "Flag to retrieve Interaction rate from CCDB"};
Configurable<bool> cfgUseIRCut{"cfgUseIRCut", false, "Flag to cut on IR rate"};
Configurable<bool> cfgIRCrashOnNull{"cfgIRCrashOnNull", false, "Flag to avoid CTP RateFetcher crash"};
Configurable<std::string> cfgIRSource{"cfgIRSource", "T0VTX", "Estimator of the interaction rate (Pb-Pb: ZNC hadronic)"};

struct : ConfigurableGroup {
Configurable<bool> usephiCut{"usephiCut", false, "use azimuthal angle cut"};
Configurable<float> phiCut{"phiCut", 0.1f,
Expand All @@ -93,9 +99,10 @@
Configurable<float> maxEta{"maxEta", -2.5f, ""};
Configurable<int> minNclusterMft{"minNclusterMft", 5,
"minimum number of MFT clusters"};
Configurable<bool> useChi2Cut{"useChi2Cut", false, "use track chi2 cut"};
Configurable<float> maxChi2{"maxChi2", 10.f, ""};
Configurable<double> minPt{"minPt", 0., "minimum pT of the MFT tracks"};
Configurable<bool> requireCA{

Check failure on line 105 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/configurable]

Use lowerCamelCase for names of configurables and use the same name for the struct member as for the JSON string. (Declare the type and names on the same line.)
"requireCA", false, "Use Cellular Automaton track-finding algorithm"};
Configurable<float> maxDCAxy{"maxDCAxy", 2.0f, "Cut on dcaXY"};
} trackCuts;
Expand All @@ -104,30 +111,29 @@
Configurable<float> maxZvtx{"maxZvtx", 10.0f, "Cut on z-vtx"};
Configurable<bool> useZDiffCut{"useZDiffCut", false,
"use Zvtx reco-mc diff. cut"};
Configurable<float> maxZvtxDiff{

Check failure on line 114 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/configurable]

Use lowerCamelCase for names of configurables and use the same name for the struct member as for the JSON string. (Declare the type and names on the same line.)
"maxZvtxDiff", 1.0f,
"max allowed Z vtx difference for reconstruced collisions (cm)"};
Configurable<bool> requireNoCollInTimeRangeStrict{"requireNoCollInTimeRangeStrict", true, " requireNoCollInTimeRangeStrict"};
Configurable<bool> requireNoCollInRofStrict{"requireNoCollInRofStrict", true, "requireNoCollInRofStrict"};
Configurable<bool> requireNoCollInRofStandard{"requireNoCollInRofStandard", false, "requireNoCollInRofStandard"};
Configurable<bool> requireNoHighMultCollInPrevRof{"requireNoHighMultCollInPrevRof", true, "requireNoHighMultCollInPrevRof"};
Configurable<bool> requireNoCollInTimeRangeStd{

Check failure on line 121 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/configurable]

Use lowerCamelCase for names of configurables and use the same name for the struct member as for the JSON string. (Declare the type and names on the same line.)
"requireNoCollInTimeRangeStd", false,
"reject collisions corrupted by the cannibalism, with other collisions "
"within +/- 10 microseconds"};
Configurable<bool> requireNoCollInTimeRangeNarrow{

Check failure on line 125 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/configurable]

Use lowerCamelCase for names of configurables and use the same name for the struct member as for the JSON string. (Declare the type and names on the same line.)
"requireNoCollInTimeRangeNarrow", false,
"reject collisions corrupted by the cannibalism, with other collisions "
"within +/- 10 microseconds"};
Configurable<uint> occupancyEstimator{

Check failure on line 129 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/configurable]

Use lowerCamelCase for names of configurables and use the same name for the struct member as for the JSON string. (Declare the type and names on the same line.)
"occupancyEstimator", 1,
"Occupancy estimator: 1 = trackOccupancyInTimeRange, 2 = "
"ft0cOccupancyInTimeRange"};
Configurable<float> minOccupancy{

Check failure on line 133 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/configurable]

Use lowerCamelCase for names of configurables and use the same name for the struct member as for the JSON string. (Declare the type and names on the same line.)
"minOccupancy", -1, "minimum occupancy from neighbouring collisions"};
Configurable<float> maxOccupancy{

Check failure on line 135 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/configurable]

Use lowerCamelCase for names of configurables and use the same name for the struct member as for the JSON string. (Declare the type and names on the same line.)
"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"};
Configurable<bool> cfgSelInteractionRate{"cfgSelInteractionRate", false, " Get Interaction rate from CCDB"};
Configurable<float> minIR{"minIR", -1, "minimum IR (kHz) collisions"};
Configurable<float> maxIR{"maxIR", -1, "maximum IR (kHz) collisions"};
} eventCuts;
Expand All @@ -154,7 +160,13 @@
"latest acceptable timestamp of creation for the object"};
Configurable<std::string> ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch",
"url of the ccdb repository"};

int mRunNumber{-1};
uint64_t mSOR{0};
double mMinSeconds{-1.};
std::unordered_map<int, TH2*> gHadronicRate;
ctpRateFetcher rateFetcher;
TH2* gCurrentHadronicRate;

/// @brief init function, definition of histograms
void init(InitContext&)
Expand Down Expand Up @@ -221,7 +233,7 @@
}

auto hev = registry.add<TH1>("hEvtSel", "hEvtSel", HistType::kTH1F,
{{16, -0.5f, +15.5f}});
{{14, -0.5f, +13.5f}});
hev->GetXaxis()->SetBinLabel(1, "All collisions");
hev->GetXaxis()->SetBinLabel(2, "Ev. sel.");
hev->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV");
Expand All @@ -235,8 +247,6 @@
hev->GetXaxis()->SetBinLabel(11, "kNoHighMultCollInPrevRof");
hev->GetXaxis()->SetBinLabel(12, "Below min occup.");
hev->GetXaxis()->SetBinLabel(13, "Above max occup.");
hev->GetXaxis()->SetBinLabel(14, "Below min IR (kHz)");
hev->GetXaxis()->SetBinLabel(15, "Above max IR (kHz)");

auto hBcSel = registry.add<TH1>("hBcSel", "hBcSel", HistType::kTH1F,
{{3, -0.5f, +2.5f}});
Expand All @@ -257,9 +267,6 @@
x->SetBinLabel(1, "All");
x->SetBinLabel(2, "Selected");

qaregistry.add("hOccIRate", "hOccIRate", HistType::kTH2F,
{occupancyAxis, irBins});

registry.add({"Events/NtrkZvtx",
"; N_{trk}; Z_{vtx} (cm); occupancy",
{HistType::kTHnSparseF, {multAxis, zAxis, occupancyAxis}}});
Expand All @@ -274,10 +281,10 @@
qaregistry.add(
{"Tracks/Chi2Eta",
"; #chi^{2}; #it{#eta}; occupancy",
{HistType::kTHnSparseF, {{600, 0, 20}, etaAxis, occupancyAxis}}});
{HistType::kTHnSparseF, {chiSqAxis, etaAxis, occupancyAxis}}});
qaregistry.add({"Tracks/Chi2",
"; #chi^{2};",
{HistType::kTH2F, {{600, 0, 20}, occupancyAxis}}});
{HistType::kTH2F, {chiSqAxis, occupancyAxis}}});
qaregistry.add(
{"Tracks/NclustersEta",
"; nClusters; #eta; occupancy",
Expand Down Expand Up @@ -343,9 +350,6 @@
hstat->GetAxis(0)->SetBinLabel(1, "All");
hstat->GetAxis(0)->SetBinLabel(2, "Selected");

qaregistry.add("hCentOccIRate", "hCentOccIRate", HistType::kTHnSparseF,
{centralityAxis, occupancyAxis, irBins});

qaregistry.add({"Events/Centrality/hCent",
"; centrality; occupancy",
{HistType::kTH2F, {centAxis, occupancyAxis}},
Expand Down Expand Up @@ -375,11 +379,11 @@
{"Tracks/Centrality/Chi2Eta",
"; #chi^{2}; #it{#eta}; centrality; occupancy",
{HistType::kTHnSparseF,
{{600, 0, 20}, etaAxis, centralityAxis, occupancyAxis}}});
{chiSqAxis, etaAxis, centralityAxis, occupancyAxis}}});
qaregistry.add({"Tracks/Centrality/Chi2",
"; #chi^{2}; centrality; occupancy",
{HistType::kTHnSparseF,
{{600, 0, 20}, centralityAxis, occupancyAxis}}});
{chiSqAxis, centralityAxis, occupancyAxis}}});
qaregistry.add({"Tracks/Centrality/NclustersEta",
"; nClusters; #eta; centrality; occupancy",
{HistType::kTHnSparseF,
Expand Down Expand Up @@ -735,35 +739,15 @@
using FiltBestTracks = soa::Filtered<aod::BestCollisionsFwd>;
using FiltParticles = soa::Filtered<aod::McParticles>;

bool isIRSelected(CollBCs::iterator const& bc, bool fillHis = false)
{
double ir = (eventCuts.minIR >= 0 || eventCuts.maxIR >= 0)
? rateFetcher.fetch(ccdb.service, bc.timestamp(),
bc.runNumber(), "ZNC hadronic") *
1.e-3
: -1;
if (eventCuts.minIR >= 0 && ir < eventCuts.minIR) {
return false;
}
if (fillHis) {
registry.fill(HIST("hEvtSel"), 13);
}
if (eventCuts.maxIR >= 0 && ir > eventCuts.maxIR) {
return false;
}
if (fillHis) {
registry.fill(HIST("hEvtSel"), 14);
}
return true;
}

template <typename T>
bool isTrackSelected(const T& track)
{
if (track.eta() < trackCuts.minEta || track.eta() > trackCuts.maxEta)
return false;
if (track.chi2() > trackCuts.maxChi2)
return false;
if (trackCuts.useChi2Cut) {
if (track.chi2() > trackCuts.maxChi2)
return false;
}
if (trackCuts.requireCA && !track.isCA())
return false;
if (track.nClusters() < trackCuts.minNclusterMft)
Expand Down Expand Up @@ -928,6 +912,24 @@
return -1.f;
}

void initHadronicRate(CollBCs::iterator const& bc)
{
if (mRunNumber == bc.runNumber()) {
return;
}
mRunNumber = bc.runNumber();
if (gHadronicRate.find(mRunNumber) == gHadronicRate.end()) {
auto runDuration = ccdb->getRunDuration(mRunNumber);
mSOR = runDuration.first;
mMinSeconds = std::floor(mSOR * 1.e-3); /// round tsSOR to the highest integer lower than tsSOR
double maxSec = std::ceil(runDuration.second * 1.e-3); /// round tsEOR to the lowest integer higher than tsEOR
const AxisSpec axisSeconds{static_cast<int>((maxSec - mMinSeconds) / 20.f), 0, maxSec - mMinSeconds, "Seconds since SOR"};
int hadronicRateBins = static_cast<int>(eventCuts.maxIR - eventCuts.minIR);
gHadronicRate[mRunNumber] = registry.add<TH2>(Form("HadronicRate/%i", mRunNumber), ";Time since SOR (s);Hadronic rate (kHz)", kTH2D, {axisSeconds, {hadronicRateBins, eventCuts.minIR, eventCuts.maxIR}}).get();
}
gCurrentHadronicRate = gHadronicRate[mRunNumber];
}

template <bool fillHis = false, typename C>
bool isGoodEvent(C const& collision)
{
Expand Down Expand Up @@ -1024,7 +1026,7 @@
if (p != nullptr) {
charge = p->Charge();
}
return std::abs(charge) >= 3.;

Check failure on line 1029 in PWGMM/Mult/Tasks/dndetaMFTPbPb.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.
}

template <bool isCent, typename P>
Expand Down Expand Up @@ -1110,10 +1112,6 @@
auto occ = getOccupancy(collision, eventCuts.occupancyEstimator);
float c = getRecoCent(collision);
auto bc = collision.template foundBC_as<CollBCs>();
double ir = rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(),
"ZNC hadronic") *
1.e-3;

if constexpr (has_reco_cent<C>) {
registry.fill(HIST("Events/Centrality/Selection"), 1., c, occ);
} else {
Expand All @@ -1123,21 +1121,23 @@
if (!isGoodEvent<true>(collision)) {
return;
}
if (eventCuts.cfgSelInteractionRate) {
if (!isIRSelected(bc, true)) {

if (cfgDoIR) {
initHadronicRate(bc);
double ir = rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), cfgIRSource, cfgIRCrashOnNull) * 1.e-3;
double seconds = bc.timestamp() * 1.e-3 - mMinSeconds;
if (cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate
return;
}
gCurrentHadronicRate->Fill(seconds, ir);
}

auto z = collision.posZ();
if constexpr (has_reco_cent<C>) {
registry.fill(HIST("Events/Centrality/Selection"), 2., c, occ);
qaregistry.fill(HIST("Events/Centrality/hZvtxCent"), z, c, occ);
qaregistry.fill(HIST("Events/Centrality/hCent"), c, occ);
qaregistry.fill(HIST("hCentOccIRate"), c, occ, ir);

} else {
qaregistry.fill(HIST("hOccIRate"), occ, ir);
registry.fill(HIST("Events/Selection"), 2., occ);
}

Expand All @@ -1155,16 +1155,11 @@
template <typename C>
void processDatawBestTracks(
typename C::iterator const& collision, FiltMftTracks const& tracks,
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks,
CollBCs const& /*bcs*/)
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks, CollBCs const& /*bcs*/)
{
auto occ = getOccupancy(collision, eventCuts.occupancyEstimator);
float c = getRecoCent(collision);
auto bc = collision.template foundBC_as<CollBCs>();
double ir = rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(),
"ZNC hadronic") *
1.e-3;

if constexpr (has_reco_cent<C>) {
registry.fill(HIST("Events/Centrality/Selection"), 1., c, occ);
} else {
Expand All @@ -1174,19 +1169,22 @@
if (!isGoodEvent<false>(collision)) {
return;
}
if (eventCuts.cfgSelInteractionRate) {
if (!isIRSelected(bc, true)) {

if (cfgDoIR) {
initHadronicRate(bc);
double ir = rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), cfgIRSource, cfgIRCrashOnNull) * 1.e-3;
double seconds = bc.timestamp() * 1.e-3 - mMinSeconds;
if (cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate
return;
}
gCurrentHadronicRate->Fill(seconds, ir);
}

auto z = collision.posZ();
if constexpr (has_reco_cent<C>) {
registry.fill(HIST("Events/Centrality/Selection"), 2., c, occ);
qaregistry.fill(HIST("hCentOccIRate"), c, occ, ir);
} else {
registry.fill(HIST("Events/Selection"), 2., occ);
qaregistry.fill(HIST("hOccIRate"), occ, ir);
}

auto nBestTrks = countBestTracks<C, true>(tracks, besttracks, z, c, occ);
Expand Down Expand Up @@ -1256,8 +1254,7 @@

void processDatawBestTracksInclusive(
Colls::iterator const& collision, FiltMftTracks const& tracks,
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks,
CollBCs const& bcs)
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks, CollBCs const& bcs)
{
processDatawBestTracks<Colls>(collision, tracks, besttracks, bcs);
}
Expand All @@ -1268,8 +1265,7 @@

void processDatawBestTracksCentFT0C(
CollsCentFT0C::iterator const& collision, FiltMftTracks const& tracks,
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks,
CollBCs const& bcs)
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks, CollBCs const& bcs)
{
processDatawBestTracks<CollsCentFT0C>(collision, tracks, besttracks, bcs);
}
Expand All @@ -1281,11 +1277,9 @@
void processDatawBestTracksCentFT0CVariant1(
CollsCentFT0CVariant1::iterator const& collision,
FiltMftTracks const& tracks,
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks,
CollBCs const& bcs)
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks, CollBCs const& bcs)
{
processDatawBestTracks<CollsCentFT0CVariant1>(collision, tracks, besttracks,
bcs);
processDatawBestTracks<CollsCentFT0CVariant1>(collision, tracks, besttracks, bcs);
}

PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentFT0CVariant1,
Expand All @@ -1295,8 +1289,7 @@

void processDatawBestTracksCentFT0M(
CollsCentFT0M::iterator const& collision, FiltMftTracks const& tracks,
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks,
CollBCs const& bcs)
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks, CollBCs const& bcs)
{
processDatawBestTracks<CollsCentFT0M>(collision, tracks, besttracks, bcs);
}
Expand All @@ -1307,11 +1300,9 @@

void processDatawBestTracksCentNGlobal(
CollsCentNGlobal::iterator const& collision, FiltMftTracks const& tracks,
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks,
CollBCs const& bcs)
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks, CollBCs const& bcs)
{
processDatawBestTracks<CollsCentNGlobal>(collision, tracks, besttracks,
bcs);
processDatawBestTracks<CollsCentNGlobal>(collision, tracks, besttracks, bcs);
}

PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentNGlobal,
Expand All @@ -1321,8 +1312,7 @@

void processDatawBestTracksCentMFT(
CollsCentMFT::iterator const& collision, FiltMftTracks const& tracks,
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks,
CollBCs const& bcs)
soa::SmallGroups<aod::BestCollisionsFwd> const& besttracks, CollBCs const& bcs)
{
processDatawBestTracks<CollsCentMFT>(collision, tracks, besttracks, bcs);
}
Expand All @@ -1348,7 +1338,7 @@

float cgen = -1;
if constexpr (has_reco_cent<C>) {
float crec_min = 105.f;

Check failure on line 1341 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/function-variable]

Use lowerCamelCase for names of functions and variables.
for (const auto& collision : collisions) {
if (isGoodEvent<false>(collision)) {
float c = getRecoCent(collision);
Expand Down Expand Up @@ -1551,7 +1541,7 @@
bool gtZeroColl = false;
float cgen = -1;
if constexpr (has_reco_cent<C>) {
float crec_min = 105.f;

Check failure on line 1544 in PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx

View workflow job for this annotation

GitHub Actions / O2 linter

[name/function-variable]

Use lowerCamelCase for names of functions and variables.
for (const auto& collision : collisions) {
if (isGoodEvent<false>(collision)) {
float c = getRecoCent(collision);
Expand Down
Loading