Skip to content

Commit 1963f8c

Browse files
committed
Add Nch MC response matrix
1 parent 2a90090 commit 1963f8c

1 file changed

Lines changed: 60 additions & 4 deletions

File tree

PWGCF/GenericFramework/Tasks/flowGfwNonflow.cxx

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,15 @@ struct FlowGfwNonflow {
7878
Configurable<int> cfgMpar{"cfgMpar", 4, "Highest order of pt-pt correlations"};
7979
Configurable<int> cfgCentEstimator{"cfgCentEstimator", 0, "0:FT0C; 1:FT0CVariant1; 2:FT0M; 3:FT0A, 4:NTPV, 5:NGlobal, 6:MFT"};
8080
Configurable<bool> cfgUseNch{"cfgUseNch", false, "Do correlations as function of Nch"};
81-
Configurable<int> cfgUseNchCorrection{"cfgUseNchCorrection", 1, "Use correction for Nch; 0: Use size of tracks table, 1: Use efficiency-corrected Nch values, 2: Use uncorrected Nch values"};
81+
Configurable<int> cfgUseNchCorrection{"cfgUseNchCorrection", 1, "Nch used on the x-axis; 0: tracks table size, 1: efficiency-corrected, 2: accepted reconstructed, 3: response-matrix corrected"};
8282
Configurable<bool> cfgRunByRun{"cfgRunByRun", false, "Use run-by-run NUA"};
8383
Configurable<bool> cfgFillQA{"cfgFillQA", false, "Fill QA histograms"};
8484
Configurable<bool> cfgUseCentralMoments{"cfgUseCentralMoments", true, "Use central moments in vn-pt calculations"};
8585
Configurable<bool> cfgUseMultiplicityFlowWeights{"cfgUseMultiplicityFlowWeights", true, "Enable or disable the use of multiplicity-based event weighting"};
8686
struct : ConfigurableGroup {
8787
Configurable<std::string> cfgEfficiencyPath{"cfgEfficiencyPath", "", "CCDB path to efficiency object"};
8888
Configurable<bool> cfgUse2DEfficiency{"cfgUse2DEfficiency", false, "Toggle the use of 2D (pt, centrality) efficiency versus centrality integrated efficiency"};
89+
Configurable<std::string> cfgNchResponsePath{"cfgNchResponsePath", "", "CCDB path to TH2 response matrix (reconstructed Nch on x, generated Nch on y)"};
8990
Configurable<std::string> cfgAcceptancePath{"cfgAcceptancePath", "", "CCDB path to acceptance object"};
9091
} cfgCorrections;
9192
struct : ConfigurableGroup {
@@ -181,6 +182,7 @@ struct FlowGfwNonflow {
181182

182183
struct Config {
183184
TH1* mEfficiency = nullptr;
185+
TH2* mNchResponse = nullptr;
184186
std::vector<GFWWeights*> mAcceptance;
185187
bool correctionsLoaded = false;
186188
} correctionsConfig;
@@ -379,6 +381,9 @@ struct FlowGfwNonflow {
379381
registry.add("eventQA/before/occ_mult_cent", "; occupancy; N_{ch}; centrality (%)", {HistType::kTH3D, {occAxis, nchAxis, centAxis}});
380382
}
381383
}
384+
if (doprocessMCReco) {
385+
registry.add("MCReco/Nch_reco_gen", "; N_{ch}^{reco}; N_{ch}^{gen}", {HistType::kTH2D, {nchAxis, nchAxis}});
386+
}
382387
registry.add("eventQA/before/centrality", "; centrality (%); Counts", {HistType::kTH1D, {centAxis}});
383388
registry.add("eventQA/before/multiplicity", "; N_{ch}; Counts", {HistType::kTH1D, {nchAxis}});
384389
registry.addClone("eventQA/before/", "eventQA/after/");
@@ -639,9 +644,43 @@ struct FlowGfwNonflow {
639644
}
640645
LOGF(info, "Loaded efficiency histogram from %s", cfgCorrections.cfgEfficiencyPath.value.c_str());
641646
}
647+
if (!cfgCorrections.cfgNchResponsePath.value.empty()) {
648+
correctionsConfig.mNchResponse = ccdb->getForTimeStamp<TH2D>(cfgCorrections.cfgNchResponsePath, timestamp);
649+
if (correctionsConfig.mNchResponse == nullptr) {
650+
LOGF(fatal, "Could not load Nch response matrix from %s", cfgCorrections.cfgNchResponsePath.value.c_str());
651+
}
652+
LOGF(info, "Loaded Nch response matrix from %s", cfgCorrections.cfgNchResponsePath.value.c_str());
653+
} else if (cfgUseNchCorrection == 3) {
654+
LOGF(fatal, "cfgUseNchCorrection=3 requires cfgNchResponsePath");
655+
}
642656
correctionsConfig.correctionsLoaded = true;
643657
}
644658

659+
float getResponseCorrectedNch(const unsigned int multReconstructed) const
660+
{
661+
if (!correctionsConfig.mNchResponse) {
662+
return multReconstructed;
663+
}
664+
const auto* response = correctionsConfig.mNchResponse;
665+
const int recoBin = response->GetXaxis()->FindFixBin(multReconstructed);
666+
if (recoBin < 1 || recoBin > response->GetNbinsX()) {
667+
LOGF(warn, "Reconstructed Nch %u is outside the response matrix; using the uncorrected value", multReconstructed);
668+
return reconstructedNch;
669+
}
670+
double sumWeights = 0.;
671+
double sumGeneratedNch = 0.;
672+
for (int genBin = 1; genBin <= response->GetNbinsY(); ++genBin) {
673+
const double weight = response->GetBinContent(recoBin, genBin);
674+
sumWeights += weight;
675+
sumGeneratedNch += weight * response->GetYaxis()->GetBinCenter(genBin);
676+
}
677+
if (sumWeights <= 0.) {
678+
LOGF(warn, "Response matrix has no entries for reconstructed Nch %u; using the uncorrected value", multReconstructed);
679+
return multReconstructed;
680+
}
681+
return sumGeneratedNch / sumWeights;
682+
}
683+
645684
template <typename TTrack>
646685
double getAcceptance(const TTrack& track, const double& vtxz)
647686
{ // 0 ref, 1 ch, 2 pi, 3 ka, 4 pr
@@ -1014,7 +1053,7 @@ struct FlowGfwNonflow {
10141053
};
10151054

10161055
template <DataType dt, typename TCollision, typename TTracks>
1017-
void processCollision(const TCollision& collision, const TTracks& tracks, const float& centrality, const float& field)
1056+
void processCollision(const TCollision& collision, const TTracks& tracks, const float& centrality, const float& field, const int generatedNch = -1)
10181057
{
10191058
if (tracks.size() < 1) {
10201059
return;
@@ -1037,6 +1076,11 @@ struct FlowGfwNonflow {
10371076
for (const auto& track : tracks) {
10381077
processTrack(track, vtxz, field, centrality, acceptedTracks);
10391078
}
1079+
if constexpr (dt == Reco) {
1080+
if (generatedNch >= 0) {
1081+
registry.fill(HIST("MCReco/Nch_reco_gen"), acceptedTracks.totaluncorr, generatedNch);
1082+
}
1083+
}
10401084
if (dt != Gen && cfgFillQA) {
10411085
registry.fill(HIST("trackQA/after/Nch_corrected"), acceptedTracks.total);
10421086
registry.fill(HIST("trackQA/after/Nch_uncorrected"), acceptedTracks.totaluncorr);
@@ -1053,6 +1097,9 @@ struct FlowGfwNonflow {
10531097
case 2:
10541098
multiplicity = acceptedTracks.totaluncorr;
10551099
break;
1100+
case 3:
1101+
multiplicity = (dt == Gen) ? acceptedTracks.totaluncorr : getResponseCorrectedNch(acceptedTracks.totaluncorr);
1102+
break;
10561103
default:
10571104
multiplicity = tracks.size();
10581105
break;
@@ -1155,8 +1202,10 @@ struct FlowGfwNonflow {
11551202

11561203
using GFWCollisions = soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::CentFT0Cs, aod::CentFT0CVariant1s, aod::CentFT0Ms, aod::CentFV0As, aod::CentNTPVs, aod::CentNGlobals, aod::CentMFTs>>;
11571204
using GFWMCCollisions = soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::CentFT0Cs, aod::CentFT0CVariant1s, aod::CentFT0Ms, aod::CentFV0As, aod::CentNTPVs, aod::CentNGlobals, aod::CentMFTs, aod::McCollisionLabels>;
1205+
using FilteredGFWMCCollisions = soa::Filtered<GFWMCCollisions>;
11581206
using GFWTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection, aod::TracksDCA>>;
11591207
using GFWMCTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TracksExtra, aod::TrackSelection, aod::TracksDCA, aod::McTrackLabels>>;
1208+
Preslice<aod::McParticles> particlesPerMcCollision = aod::mcparticle::mcCollisionId;
11601209

11611210
SliceCache cache;
11621211
Partition<GFWTracks> posTracks = aod::track::signed1Pt > 0.0f;
@@ -1221,7 +1270,7 @@ struct FlowGfwNonflow {
12211270
}
12221271
PROCESS_SWITCH(FlowGfwNonflow, processData, "Process analysis for non-derived data", true);
12231272

1224-
void processMCReco(GFWCollisions::iterator const& collision, aod::BCsWithTimestamps const&, GFWMCTracks const& tracks, aod::McParticles const&)
1273+
void processMCReco(FilteredGFWMCCollisions::iterator const& collision, aod::BCsWithTimestamps const&, GFWMCTracks const& tracks, aod::McParticles const& particles)
12251274
{
12261275
auto bc = collision.bc_as<aod::BCsWithTimestamps>();
12271276
int run = bc.runNumber();
@@ -1265,9 +1314,16 @@ struct FlowGfwNonflow {
12651314
if (cfgFillQA) {
12661315
fillEventQA<After>(collision, tracks);
12671316
}
1317+
unsigned int generatedNch = 0;
1318+
const auto particlesThisCollision = particles.sliceBy(particlesPerMcCollision, collision.mcCollisionId());
1319+
for (const auto& particle : particlesThisCollision) {
1320+
if (particle.isPhysicalPrimary() && particle.eta() > cfgKinematics.cfgEtaNch->first && particle.eta() < cfgKinematics.cfgEtaNch->second && particle.pt() > gfwMemberCache.ptlow && particle.pt() < gfwMemberCache.ptup) {
1321+
++generatedNch;
1322+
}
1323+
}
12681324
loadCorrections(bc);
12691325
auto field = (cfgEventSelection.cfgMagField == DefaultMagneticFieldCut) ? getMagneticField(bc.timestamp()) : static_cast<int>(cfgEventSelection.cfgMagField);
1270-
processCollision<Reco>(collision, tracks, centrality, field);
1326+
processCollision<Reco>(collision, tracks, centrality, field, generatedNch);
12711327
}
12721328
PROCESS_SWITCH(FlowGfwNonflow, processMCReco, "Process analysis for MC reconstructed events", false);
12731329

0 commit comments

Comments
 (0)