diff --git a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx index c10ece98349..0e23058ea7d 100644 --- a/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/nchCumulantsId.cxx @@ -48,6 +48,12 @@ using namespace std; #define ID_BIT_EL 3 #define ID_BIT_DE 4 +#define MC_BIT_PI 0 // MC particle identification bits +#define MC_BIT_KA 1 +#define MC_BIT_PR 2 +#define MC_BIT_EL 3 +#define MC_BIT_DE 4 + #define BITSET(mask, ithBit) ((mask) |= (1 << (ithBit))) // avoid name bitset as std::bitset is already there #define BITCHECK(mask, ithBit) ((mask) & (1 << (ithBit))) // bit check will return int value, not bool, use BITCHECK != 0 in Analysi @@ -108,6 +114,7 @@ struct NchCumulantsId { Configurable checkCollPosZMc{"checkCollPosZMc", false, "checkCollPosZMc"}; Configurable flagUnusedVariableError{"flagUnusedVariableError", false, "flagUnusedVariableError"}; + Configurable cfgDoRejectionForId{"cfgDoRejectionForId", false, "Apply rejection cut before PID selection (selTrackForId)"}; Configurable cfgEvSel01doNoSameBunchPileup{"cfgEvSel01doNoSameBunchPileup", true, "apply kNoSameBunchPileup"}; Configurable cfgEvSel02doIsGoodZvtxFT0vsPV{"cfgEvSel02doIsGoodZvtxFT0vsPV", true, "apply kIsGoodZvtxFT0vsPV"}; @@ -150,6 +157,12 @@ struct NchCumulantsId { Configurable cfgIdPr08NSigmaTOFHighP{"cfgIdPr08NSigmaTOFHighP", 2.0, "cfgIdPr08NSigmaTOFHighP"}; Configurable cfgIdPr09NSigmaRadHighP{"cfgIdPr09NSigmaRadHighP", 4.0, "cfgIdPr09NSigmaRadHighP"}; + Configurable cfgIdElRejLowNSigma{"cfgIdElRejLowNSigma", -3.0, "cfgIdElRejLowNSigma"}; + Configurable cfgIdElRejHighNSigma{"cfgIdElRejHighNSigma", 5.0, "cfgIdElRejHighNSigma"}; + Configurable cfgIdPiRejNSigma{"cfgIdPiRejNSigma", 3.0, "cfgIdPiRejNSigma"}; + Configurable cfgIdKaRejNSigma{"cfgIdKaRejNSigma", 3.0, "cfgIdKaRejNSigma"}; + Configurable cfgIdPrRejNSigma{"cfgIdPrRejNSigma", 3.0, "cfgIdPrRejNSigma"}; + struct : ConfigurableGroup { Configurable cfgVetoId01PiTPC{"cfgVetoId01PiTPC", 3.0, "cfgVetoId01PiTPC"}; Configurable cfgVetoId02PiTOF{"cfgVetoId02PiTOF", 3.0, "cfgVetoId02PiTOF"}; @@ -244,8 +257,13 @@ struct NchCumulantsId { const AxisSpec axisPiCh(101, -1, 100, "Pion_Positive"); const AxisSpec axisAPiCh(101, -1, 100, "Pion_Negative"); + const AxisSpec axisIdTag = {32, -0.5f, 31.5f, "idTag"}; + const AxisSpec axisMcTag = {32, -0.5f, 31.5f, "mcTag"}; + HistogramConfigSpec qnHist1({HistType::kTHnSparseD, {axisNch, axisPosCh, axisNegCh, axisPrCh, axisAPrCh, axisKaCh, axisAKaCh, axisNt, axisCent}}); HistogramConfigSpec qnHist2({HistType::kTHnSparseD, {axisNch, axisPosCh, axisNegCh, axisPiCh, axisAPiCh, axisKaCh, axisAKaCh, axisNt, axisCent}}); + HistogramConfigSpec histTPCPIDSparse({HistType::kTHnSparseD, {axisP, axisTPCNSigma, axisIdTag, axisMcTag}}); + HistogramConfigSpec histTOFPIDSparse({HistType::kTHnSparseD, {axisP, axisTOFNSigma, axisIdTag, axisMcTag}}); HistogramConfigSpec histPPt({HistType::kTH2F, {axisP, axisPt}}); HistogramConfigSpec histPTpcInnerParam({HistType::kTH2F, {axisP, axisTPCInnerParam}}); @@ -265,6 +283,17 @@ struct NchCumulantsId { HistogramConfigSpec histPtMc({HistType::kTH1F, {axisPt}}); + // Register histograms for PID validation + // Register TPC spares per species + hist.add("PIDValidation/tpcSparse_Pi", "p vs tpcNSigmaPi vs idTag vs mcTag (Pion)", histTPCPIDSparse); + hist.add("PIDValidation/tpcSparse_Ka", "p vs tpcNSigmaKa vs idTag vs mcTag (Kaon)", histTPCPIDSparse); + hist.add("PIDValidation/tpcSparse_Pr", "p vs tpcNSigmaPr vs idTag vs mcTag (Proton)", histTPCPIDSparse); + + // Register TOF spares per species + hist.add("PIDValidation/tofSparse_Pi", "p vs tofNSigmaPi vs idTag vs mcTag (Pion)", histTOFPIDSparse); + hist.add("PIDValidation/tofSparse_Ka", "p vs tofNSigmaKa vs idTag vs mcTag (Kaon)", histTOFPIDSparse); + hist.add("PIDValidation/tofSparse_Pr", "p vs tofNSigmaPr vs idTag vs mcTag (Proton)", histTOFPIDSparse); + // QA check histos hist.add("QA/events/preSel/h_VtxZ", "V_{Z}", kTH1D, {axisVtxZ}); @@ -762,8 +791,44 @@ struct NchCumulantsId { } } + template + int getMCTag(const T& track) + { + int mcTag = 0; + if (!track.has_mcParticle()) + return mcTag; + auto mcPart = track.mcParticle(); + int pdgCode = std::abs(mcPart.pdgCode()); + + if (pdgCode == kPiPlus || pdgCode == kPiMinus) + BITSET(mcTag, MC_BIT_PI); + else if (pdgCode == kKPlus || pdgCode == kKMinus) + BITSET(mcTag, MC_BIT_KA); + else if (pdgCode == kProton || pdgCode == kProtonBar) + BITSET(mcTag, MC_BIT_PR); + else if (pdgCode == kElectron || pdgCode == kPositron) + BITSET(mcTag, MC_BIT_EL); + else if (pdgCode == kDeuteron || pdgCode == -kDeuteron) + BITSET(mcTag, MC_BIT_DE); + + return mcTag; + } // //______________________________Identification Functions________________________________________________________________ + // Victor slection cuts for electron and other rejections + template + bool selTrackForId(const T& track) + { + if (cfgIdElRejLowNSigma < track.tpcNSigmaEl() && track.tpcNSigmaEl() < cfgIdElRejHighNSigma && + std::fabs(track.tpcNSigmaPi()) > cfgIdPiRejNSigma && + std::fabs(track.tpcNSigmaKa()) > cfgIdKaRejNSigma && + std::fabs(track.tpcNSigmaPr()) > cfgIdPrRejNSigma) { + return false; + } else { + return true; + } + } + // Pion template bool selPion(const T& track, int& IdMethod) @@ -1137,6 +1202,11 @@ struct NchCumulantsId { nM += hPtEtaForEffCorrection[kCh][kNeg]->GetBinContent(ptEtaBin); } + // Reject electrons first + if (cfgDoRejectionForId && !selTrackForId(track)) { + continue; + } + int idMethod; // pion if (selPion(track, idMethod)) { @@ -1235,17 +1305,34 @@ struct NchCumulantsId { idMethodKa = kUnidentified; idMethodPr = kUnidentified; + // Get MC tag + int mcTag = getMCTag(track); + + // Reject electrons first + if (cfgDoRejectionForId && !selTrackForId(track)) { + continue; + } + if (selPion(track, idMethodPi)) { trackIsPion = true; BITSET(trackIdTag, ID_BIT_PI); + hist.fill(HIST("PIDValidation/tpcSparse_Pi"), track.p(), track.tpcNSigmaPi(), trackIdTag, mcTag); + if (track.hasTOF()) + hist.fill(HIST("PIDValidation/tofSparse_Pi"), track.p(), track.tofNSigmaPi(), trackIdTag, mcTag); } if (selKaon(track, idMethodKa)) { trackIsKaon = true; BITSET(trackIdTag, ID_BIT_KA); + hist.fill(HIST("PIDValidation/tpcSparse_Ka"), track.p(), track.tpcNSigmaKa(), trackIdTag, mcTag); + if (track.hasTOF()) + hist.fill(HIST("PIDValidation/tofSparse_Ka"), track.p(), track.tofNSigmaKa(), trackIdTag, mcTag); } if (selProton(track, idMethodPr)) { trackIsProton = true; BITSET(trackIdTag, ID_BIT_PR); + hist.fill(HIST("PIDValidation/tpcSparse_Pr"), track.p(), track.tpcNSigmaPr(), trackIdTag, mcTag); + if (track.hasTOF()) + hist.fill(HIST("PIDValidation/tofSparse_Pr"), track.p(), track.tofNSigmaPr(), trackIdTag, mcTag); } if constexpr (analysisType == doPurityProcessing) { @@ -1555,6 +1642,8 @@ struct NchCumulantsId { continue; int pdg = mcPart.pdgCode(); + int mcTag = getMCTag(track); + fillTrackQA(track); trackIsPion = false; @@ -1565,17 +1654,41 @@ struct NchCumulantsId { idMethodKa = kUnidentified; idMethodPr = kUnidentified; + // Reject electrons first + if (cfgDoRejectionForId && !selTrackForId(track)) { + continue; + } + + // Fill separate spares for each species if it passes the cut if (selPion(track, idMethodPi)) { trackIsPion = true; BITSET(trackIdTag, ID_BIT_PI); + // Fill TPC sparse for pion + hist.fill(HIST("PIDValidation/tpcSparse_Pi"), track.p(), track.tpcNSigmaPi(), trackIdTag, mcTag); + // Fill TOF sparse for pion if has TOF + if (track.hasTOF()) { + hist.fill(HIST("PIDValidation/tofSparse_Pi"), track.p(), track.tofNSigmaPi(), trackIdTag, mcTag); + } } if (selKaon(track, idMethodKa)) { trackIsKaon = true; BITSET(trackIdTag, ID_BIT_KA); + // Fill TPC sparse for kaon + hist.fill(HIST("PIDValidation/tpcSparse_Ka"), track.p(), track.tpcNSigmaKa(), trackIdTag, mcTag); + // Fill TOF sparse for kaon if has TOF + if (track.hasTOF()) { + hist.fill(HIST("PIDValidation/tofSparse_Ka"), track.p(), track.tofNSigmaKa(), trackIdTag, mcTag); + } } if (selProton(track, idMethodPr)) { trackIsProton = true; BITSET(trackIdTag, ID_BIT_PR); + // Fill TPC sparse for proton + hist.fill(HIST("PIDValidation/tpcSparse_Pr"), track.p(), track.tpcNSigmaPr(), trackIdTag, mcTag); + // Fill TOF sparse for proton if has TOF + if (track.hasTOF()) { + hist.fill(HIST("PIDValidation/tofSparse_Pr"), track.p(), track.tofNSigmaPr(), trackIdTag, mcTag); + } } // bool isKnownCharged = (std::abs(pdg) == kPiPlus || @@ -1614,6 +1727,11 @@ struct NchCumulantsId { nAPiRec += hPtEtaForEffCorrection[kPi][kNeg]->GetBinContent(ptEtaBin); fillRecoTrackQA(recoAnalysis, track); } + // PID band QA for pions + if (idMethodPi == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethodPi == kTPCTOFidentified) + fillIdentificationQA(hist, track); } else if (trackIsKaon) { if (track.sign() > 0) { nKaRec += hPtEtaForEffCorrection[kKa][kPos]->GetBinContent(ptEtaBin); @@ -1622,6 +1740,11 @@ struct NchCumulantsId { nAKaRec += hPtEtaForEffCorrection[kKa][kNeg]->GetBinContent(ptEtaBin); fillRecoTrackQA(recoAnalysis, track); } + // PID band QA for kaons + if (idMethodKa == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethodKa == kTPCTOFidentified) + fillIdentificationQA(hist, track); } else if (trackIsProton) { if (track.sign() > 0) { nPrRec += hPtEtaForEffCorrection[kPr][kPos]->GetBinContent(ptEtaBin); @@ -1630,6 +1753,11 @@ struct NchCumulantsId { nAPrRec += hPtEtaForEffCorrection[kPr][kNeg]->GetBinContent(ptEtaBin); fillRecoTrackQA(recoAnalysis, track); } + // PID band QA for protons + if (idMethodPr == kTPCidentified) + fillIdentificationQA(hist, track); + if (idMethodPr == kTPCTOFidentified) + fillIdentificationQA(hist, track); } // purity check - check pdg aginst sign bool purityPion = false;