diff --git a/PWGLF/TableProducer/Resonances/CMakeLists.txt b/PWGLF/TableProducer/Resonances/CMakeLists.txt index 05e51ad1511..a2776b9dedf 100644 --- a/PWGLF/TableProducer/Resonances/CMakeLists.txt +++ b/PWGLF/TableProducer/Resonances/CMakeLists.txt @@ -22,7 +22,7 @@ o2physics_add_dpl_workflow(f1protonreducedtable o2physics_add_dpl_workflow(doublephitable SOURCES doublephitable.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(filterf1proton diff --git a/PWGLF/TableProducer/Resonances/doublephitable.cxx b/PWGLF/TableProducer/Resonances/doublephitable.cxx index 0c116305cac..9a72a1b9706 100644 --- a/PWGLF/TableProducer/Resonances/doublephitable.cxx +++ b/PWGLF/TableProducer/Resonances/doublephitable.cxx @@ -17,6 +17,8 @@ #include "PWGLF/DataModel/ReducedDoublePhiTables.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/Zorro.h" +#include "Common/Core/ZorroSummary.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" @@ -55,11 +57,27 @@ struct doublephitable { Produces redPhiEvents; Produces phiTrack; + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + /// Event selection + struct : ConfigurableGroup { + std::string prefix = std::string("EventSel"); + Configurable ConfEvtSelectZvtx{"ConfEvtSelectZvtx", true, "Event selection includes max. z-Vertex"}; + Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable ConfEvtSel8{"ConfEvtSel8", true, "Event selection sel8"}; + } EventSel; + // events Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; // Configurable cfgCutCentralityMax{"cfgCutCentralityMax", 0.0f, "Accepted maximum Centrality"}; // Configurable cfgCutCentralityMin{"cfgCutCentralityMin", 100.0f, "Accepted minimum Centrality"}; // track + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "ccdb-url"}; + Configurable useTrigger{"useTrigger", true, "use Trigger"}; Configurable useGlobalTrack{"useGlobalTrack", true, "use Global track"}; Configurable cfgCutTOFBeta{"cfgCutTOFBeta", 0.0, "cut TOF beta"}; Configurable cfgCutCharge{"cfgCutCharge", 0.0, "cut on Charge"}; @@ -67,7 +85,7 @@ struct doublephitable { Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; - Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; + Configurable nsigmaCutTPC{"nsigmacutTPC", -2.0, "Value of the TPC Nsigma cut"}; Configurable nsigmaCutTOF{"nsigmaCutTOF", 3.0, "Value of the TOF Nsigma cut"}; Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; @@ -77,12 +95,13 @@ struct doublephitable { ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.0, 10.}, "#it{p}_{T} (GeV/#it{c})"}; Configurable minPhiMass{"minPhiMass", 1.01, "Minimum phi mass"}; Configurable maxPhiMass{"maxPhiMass", 1.03, "Maximum phi mass"}; + Configurable nsigmaCutTPCPreSel{"nsigmacutTPCPreSel", 3.0, "Value of the TPC Nsigma cut Pre selection"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; // Filter centralityFilter = (nabs(aod::cent::centFT0C) < cfgCutCentralityMax && nabs(aod::cent::centFT0C) > cfgCutCentralityMin); Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); - Filter PIDcutFilter = nabs(aod::pidtpc::tpcNSigmaKa) < nsigmaCutTPC; + Filter PIDcutFilter = nabs(aod::pidtpc::tpcNSigmaKa) < nsigmaCutTPCPreSel; using EventCandidates = soa::Filtered>; using TrackCandidates = soa::Filtered>; @@ -91,6 +110,7 @@ struct doublephitable { Partition posTracks = aod::track::signed1Pt > cfgCutCharge; Partition negTracks = aod::track::signed1Pt < cfgCutCharge; + OutputObj hProcessedEvents{TH1D("hProcessedEvents", ";; Number of events", 4, 0.0f, 4.0f)}; // Histogram HistogramRegistry qaRegistry{"QAHistos", { {"hEventstat", "hEventstat", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, @@ -102,10 +122,34 @@ struct doublephitable { double massKa = o2::constants::physics::MassKPlus; + void init(o2::framework::InitContext&) + { + ccdb->setURL(url.value); + ccdbApi.init(url); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + zorroSummary.setObject(zorro.getZorroSummary()); + hProcessedEvents->GetXaxis()->SetBinLabel(1, "All Trigger events"); + hProcessedEvents->GetXaxis()->SetBinLabel(2, "Events with Double Phi Trigger"); + hProcessedEvents->GetXaxis()->SetBinLabel(3, "Events eith trigger and Evsel"); + hProcessedEvents->GetXaxis()->SetBinLabel(4, "Final Event"); + } + template + bool isSelectedEvent(T const& col) + { + if (EventSel.ConfEvtSelectZvtx && std::abs(col.posZ()) > EventSel.ConfEvtZvtx) { + return false; + } + if (EventSel.ConfEvtSel8 && !col.sel8()) { + return false; + } + return true; + } template bool selectionTrack(const T& candidate) { - if (useGlobalTrack && !(candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() > cfgITScluster && candidate.tpcNClsFound() > cfgTPCcluster)) { + if (useGlobalTrack && !(candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() > cfgITScluster && candidate.tpcNClsCrossedRows() > cfgTPCcluster)) { return false; } return true; @@ -113,40 +157,29 @@ struct doublephitable { template bool selectionPID(const T& candidate) { - if (!candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { + if (candidate.pt() < 0.5 && candidate.tpcNSigmaKa() > nsigmaCutTPC && candidate.tpcNSigmaKa() < 3.0) { return true; } - if (candidate.hasTOF() && candidate.beta() > cfgCutTOFBeta && TMath::Abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC && TMath::Abs(candidate.tofNSigmaKa()) < nsigmaCutTOF) { - return true; + if (candidate.pt() >= 0.5) { + if (!candidate.hasTOF() && candidate.tpcNSigmaKa() > nsigmaCutTPC && candidate.tpcNSigmaKa() < 2.0) { + return true; + } + if (candidate.hasTOF() && candidate.beta() > cfgCutTOFBeta && TMath::Sqrt(candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) < nsigmaCutTOF) { + return true; + } } return false; } - // deep angle cut on pair to remove photon conversion - template - bool selectionPair(const T1& candidate1, const T2& candidate2) - { - double pt1, pt2, pz1, pz2, p1, p2, angle; - pt1 = candidate1.pt(); - pt2 = candidate2.pt(); - pz1 = candidate1.pz(); - pz2 = candidate2.pz(); - p1 = candidate1.p(); - p2 = candidate2.p(); - angle = TMath::ACos((pt1 * pt2 + pz1 * pz2) / (p1 * p2)); - if (isDeepAngle && angle < cfgDeepAngle) { - return false; - } - return true; - } + int currentRunNumber = -999; + int lastRunNumber = -999; ROOT::Math::PxPyPzMVector KaonPlus, KaonMinus, PhiMesonMother, PhiVectorDummy, Phid1dummy, Phid2dummy; void processPhiReducedTable(EventCandidates::iterator const& collision, TrackCandidates const&, aod::BCsWithTimestamps const&) { o2::aod::ITSResponse itsResponse; bool keepEventDoublePhi = false; int numberPhi = 0; - auto currentRunNumber = collision.bc_as().runNumber(); - auto bc = collision.bc_as(); + std::vector Phid1Index = {}; std::vector Phid2Index = {}; @@ -167,7 +200,25 @@ struct doublephitable { int Npostrack = 0; int Nnegtrack = 0; float centrality = collision.centFT0M(); - if (collision.sel8() && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && collision.selection_bit(aod::evsel::kNoSameBunchPileup) && collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + currentRunNumber = collision.bc_as().runNumber(); + auto bc = collision.bc_as(); + hProcessedEvents->Fill(0.5); + bool zorroSelected = false; + if (currentRunNumber != lastRunNumber) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fTriggerEventDoublePhi"); + zorro.populateHistRegistry(qaRegistry, bc.runNumber()); + lastRunNumber = currentRunNumber; + } + if (useTrigger) { + zorroSelected = zorro.isSelected(collision.template bc_as().globalBC()); + } else { + zorroSelected = true; + } + if (zorroSelected) { + hProcessedEvents->Fill(1.5); + } + if (zorroSelected && isSelectedEvent(collision)) { + hProcessedEvents->Fill(2.5); auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); for (auto track1 : posThisColl) { @@ -179,7 +230,7 @@ struct doublephitable { if (!selectionPID(track1)) { continue; } - if (!(itsResponse.nSigmaITS(track1) > -3.0 && itsResponse.nSigmaITS(track1) < 3.0)) { + if (track1.pt() > 0.4 && track1.pt() < 1.0 && !(itsResponse.nSigmaITS(track1) > -2.0 && itsResponse.nSigmaITS(track1) < 3.0)) { continue; } Npostrack = Npostrack + 1; @@ -188,7 +239,12 @@ struct doublephitable { qaRegistry.fill(HIST("hNsigmaPtkaonTOF"), track1.tofNSigmaKa(), track1.pt()); } auto track1ID = track1.globalIndex(); + for (auto track2 : negThisColl) { + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) { + continue; + } // track selection if (!selectionTrack(track2)) { continue; @@ -197,18 +253,11 @@ struct doublephitable { if (!selectionPID(track2)) { continue; } - if (Npostrack == 1) { - Nnegtrack = Nnegtrack + 1; - } - auto track2ID = track2.globalIndex(); - if (track2ID == track1ID) { + if (track2.pt() > 0.4 && track2.pt() < 1.0 && !(itsResponse.nSigmaITS(track2) > -2.0 && itsResponse.nSigmaITS(track2) < 3.0)) { continue; } - if (!(itsResponse.nSigmaITS(track2) > -3.0 && itsResponse.nSigmaITS(track2) < 3.0)) { - continue; - } - if (!selectionPair(track1, track2)) { - continue; + if (Npostrack == 1) { + Nnegtrack = Nnegtrack + 1; } KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); @@ -252,11 +301,12 @@ struct doublephitable { } } } // select collision - if (numberPhi > 1 && Npostrack > 1 && Nnegtrack > 1) { + if (numberPhi > 1 && zorroSelected && Nnegtrack > 1 && Npostrack > 1) { keepEventDoublePhi = true; + hProcessedEvents->Fill(3.5); } qaRegistry.fill(HIST("hEventstat"), 0.5); - if (keepEventDoublePhi && numberPhi > 1 && Npostrack > 1 && Nnegtrack > 1 && (phiresonance.size() == phiresonanced1.size()) && (phiresonance.size() == phiresonanced2.size())) { + if (keepEventDoublePhi && numberPhi > 1 && (phiresonance.size() == phiresonanced1.size()) && (phiresonance.size() == phiresonanced2.size())) { qaRegistry.fill(HIST("hEventstat"), 1.5); /////////// Fill collision table/////////////// redPhiEvents(bc.globalBC(), currentRunNumber, bc.timestamp(), collision.posZ(), collision.numContrib(), Npostrack, Nnegtrack, centrality); diff --git a/PWGLF/Tasks/Resonances/doublephimeson.cxx b/PWGLF/Tasks/Resonances/doublephimeson.cxx index 78d4e47102d..13e7ce8d83d 100644 --- a/PWGLF/Tasks/Resonances/doublephimeson.cxx +++ b/PWGLF/Tasks/Resonances/doublephimeson.cxx @@ -64,14 +64,16 @@ struct doublephimeson { Configurable minExoticPt{"minExoticPt", 6.0, "Minimum Exotic Pt"}; Configurable minExoticMass{"minExoticMass", 2.0, "Minimum Exotic mass"}; Configurable maxExoticMass{"maxExoticMass", 3.6, "Maximum Exotic mass"}; - Configurable additionalEvsel{"additionalEvsel", false, "Additional event selection"}; + Configurable additionalEvsel{"additionalEvsel", true, "Additional event selection"}; Configurable isDeep{"isDeep", true, "Store deep angle"}; Configurable cutMinNsigmaTPC{"cutMinNsigmaTPC", -2.5, "nsigma cut TPC"}; Configurable cutNsigmaTPC{"cutNsigmaTPC", 3.0, "nsigma cut TPC"}; Configurable cutNsigmaTOF{"cutNsigmaTOF", 3.0, "nsigma cut TOF"}; Configurable momTOFCut{"momTOFCut", 1.8, "minimum pT cut for madnatory TOF"}; Configurable maxKaonPt{"maxKaonPt", 100.0, "maximum kaon pt cut"}; - + Configurable cfgCrossPhiLow{"cfgCrossPhiLow", 1.01, "Lower edge of phi mass window for cross-pairing (ghost) veto"}; + Configurable cfgCrossPhiHigh{"cfgCrossPhiHigh", 1.03, "Upper edge of phi mass window for cross-pairing (ghost) veto"}; + Configurable useParametrized{"useParametrized", false, "Use pT dependent mass peak and width"}; // ------------------------------------------------------------ // pT-dependent phi mass peak and width from single-phi BW fits // @@ -181,7 +183,7 @@ struct doublephimeson { histos.add("hDeltaRkaonplus", "hDeltaRkaonplus", kTH1F, {{800, 0.0, 8.0}}); histos.add("hDeltaRkaonminus", "hDeltaRkaonminus", kTH1F, {{800, 0.0, 8.0}}); histos.add("hPtCorrelation", "hPtCorrelation", kTH2F, {{400, 0.0, 40.0}, {5000, 0.0, 100.0}}); - histos.add("hPtCent", "hPtCent", kTH2F, {{100, 0.0, 100.0}, {100, 0.0, 100.0}}); + histos.add("hMassCent", "hMassCent", kTH3F, {{40, 1.0, 1.04f}, {40, 1.0, 1.04f}, {100, 0.0, 100.0}}); const AxisSpec thnAxisdeltapt{configThnAxisDeltaPt, "Delta pt"}; const AxisSpec thnAxisdaughterpt{configThnAxisDaughterPt, "Daughter pt"}; const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; @@ -1543,7 +1545,7 @@ struct doublephimeson { } } PROCESS_SWITCH(doublephimeson, processopti4, "Process Optimized same event", true); - + double dMNominal = 100.0; void processopti5(aod::RedPhiEvents::iterator const& collision, aod::PhiTracks const& phitracks) { if (additionalEvsel && (collision.numPos() < 2 || collision.numNeg() < 2)) { @@ -1710,29 +1712,23 @@ struct doublephimeson { // LOGF(info,"track share",t1.phid1Index(),t1.phid2Index(),t2.phid1Index(),t2.phid2Index()); continue; } - // const double dMNominal = deltaMPhiNominal(phi1.M(), phi2.M()); const double mCross12 = (k1p + k2m).M(); // K+ from phi1 + K- from phi2 const double mCross21 = (k2p + k1m).M(); // K+ from phi2 + K- from phi1 - const double dMCross = deltaMPhiNominal(mCross12, mCross21); - // Reject this candidate only if the crossed assignment is more phi-like - if (dMCross > 1.01 && dMCross < 1.03) { - // ++nBestPairingRejected; - /* + + const bool cross12IsPhiLike = (mCross12 > cfgCrossPhiLow && mCross12 < cfgCrossPhiHigh); + const bool cross21IsPhiLike = (mCross21 > cfgCrossPhiLow && mCross21 < cfgCrossPhiHigh); + + if (cross12IsPhiLike || cross21IsPhiLike) { LOGF(info, - "Best-pairing rejected: dMNominal = %.6f, dMCross = %.6f, " - "mPhi1 = %.6f, mPhi2 = %.6f, mCross12 = %.6f, mCross21 = %.6f", - dMNominal, - dMCross, + "Best-pairing rejected: mPhi1 = %3.4f, mPhi2 = %3.4f, mCross12 = %3.4f, mCross21 = %3.4f", phi1.M(), phi2.M(), mCross12, mCross21, pair.Pt(), pair.M()); - */ continue; } - histos.fill(HIST("hPhiMass"), phi1.M(), phi2.M(), pair.Pt()); histos.fill(HIST("hPhiMassNormalized"), getNormalizedMPhi(phi1.M(), phi1.Pt()), getNormalizedMPhi(phi2.M(), phi2.Pt()), pair.Pt()); @@ -1767,7 +1763,11 @@ struct doublephimeson { const double pairPt = pair.Pt(); const double dRphi = deltaR(p1.Phi(), p1.Eta(), p2.Phi(), p2.Eta()); const double minDR = minDRV[i]; - const double dMNominal = getDeltaMPhi(p1.M(), p1.Pt(), p2.M(), p2.Pt()); + if (!useParametrized) { + dMNominal = deltaMPhiNominal(p1.M(), p2.M()); + } else { + dMNominal = getDeltaMPhi(p1.M(), p1.Pt(), p2.M(), p2.Pt()); + } const double dMNominalNsigma = getNormalizedDeltaMPhi(p1.M(), p1.Pt(), p2.M(), p2.Pt()); const double denom = std::abs(pairPt - p1.Pt()); @@ -1781,7 +1781,7 @@ struct doublephimeson { } if (pairPt > minExoticPt) { histos.fill(HIST("hPtCorrelation"), pairPt, ptcorr); - histos.fill(HIST("hPtCent"), pairPt, collision.centrality()); + histos.fill(HIST("hMassCent"), p1.M(), p2.M(), collision.centrality()); histos.fill(HIST("SEMassUnlike_AllVars"), M, pairPt, @@ -2215,25 +2215,25 @@ struct doublephimeson { if (dM > maxDeltaMPhi) continue; - TLorentzVector pair = phi1 + phi2; - if (pair.M() < minExoticMass || pair.M() > maxExoticMass) + TLorentzVector pairPhiPhi = phi1 + phi2; + if (pairPhiPhi.M() < minExoticMass || pairPhiPhi.M() > maxExoticMass) continue; const double minDR = minKaonDeltaR(c1.kplus, c2.kplus, c1.kminus, c2.kminus); const double dR = deltaR(phi1.Phi(), phi1.Eta(), phi2.Phi(), phi2.Eta()); // same definition as SE - const double ptcorr = (pair.Pt() - phi1.Pt() != 0.) - ? phi1.Pt() / (pair.Pt() - phi1.Pt()) + const double ptcorr = (pairPhiPhi.Pt() - phi1.Pt() != 0.) + ? phi1.Pt() / (pairPhiPhi.Pt() - phi1.Pt()) : 0.; histos.fill(HIST("MEMassUnlike"), - pair.M(), // M(phi-phi) - minDR, // min ΔR among all kaon pairs - pair.Pt(), // pT(phi-phi) - dR, // ΔR(phi1, phi2) - dM, // Δm(phi) - ptcorr); // pT correlation + pairPhiPhi.M(), // M(phi-phi) + minDR, // min ΔR among all kaon pairs + pairPhiPhi.Pt(), // pT(phi-phi) + dR, // ΔR(phi1, phi2) + dM, // Δm(phi) + ptcorr); // pT correlation // --- NEW: compute z and A from phi candidates (no cuts) --- const double pt1 = phi1.Pt(); @@ -2244,7 +2244,7 @@ struct doublephimeson { const double z = pt1 / ptsum; const double A = std::abs(pt1 - pt2) / ptsum; // --- Fill NEW THnSparse (no cuts) --- - histos.fill(HIST("MEMassUnlike_DeltaRZA"), pair.M(), pair.Pt(), pair.Pt() * dR, z, A, dM); + histos.fill(HIST("MEMassUnlike_DeltaRZA"), pairPhiPhi.M(), pairPhiPhi.Pt(), pairPhiPhi.Pt() * dR, z, A, dM); } } }