From 5c21be4e51d7381f957b81edaeecc091095cd548 Mon Sep 17 00:00:00 2001 From: smaff92 Date: Fri, 20 Mar 2026 14:35:59 +0900 Subject: [PATCH 1/4] Temporary functions to quickly QA Prompt Photon MC production. Will merge these function into existing framework, and revamp code for the next PR. --- PWGJE/Tasks/statPromptPhoton.cxx | 439 +++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index 98c52aa45e7..e823f2ce51a 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -96,6 +96,7 @@ struct statPromptPhoton { Configurable cfgTrackFilter{"cfgTrackFilter", "globalTracks", "set track selections"}; Configurable cfgJETracks{"cfgJETracks", false, "Enables running on derived JE data"}; Configurable cfgGenHistograms{"cfgGenHistograms", false, "Enables Generated histograms"}; + Configurable cfgGenReqRec{"cfgGenReqRec", false, "Only consider generated events which are successfully reconstructed"}; Configurable cfgRecHistograms{"cfgRecHistograms", false, "Enables Reconstructed histograms"}; Configurable cfgDataHistograms{"cfgDataHistograms", false, "Enables Data histograms"}; Configurable cfgTriggerMasks{"cfgTriggerMasks", "", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fTrackLowPt,fTrackHighPt,fJetD0ChLowPt,fJetD0ChHighPt,fJetLcChLowPt,fJetLcChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt,fJetNeutralHighPt,fJetNeutralLowPt,fGammaVeryHighPtEMCAL,fGammaVeryHighPtDCAL,fGammaHighPtEMCAL,fGammaHighPtDCAL,fGammaLowPtEMCAL,fGammaLowPtDCAL,fGammaVeryLowPtEMCAL,fGammaVeryLowPtDCAL"}; @@ -191,9 +192,53 @@ struct statPromptPhoton { histos.add("REC_TrueTrigger_V_PtHadSum_Photon", "REC_Trigger_V_PtHadSum_Photon", kTH2F, {{100, 0, 100}, pthadAxis}); histos.add("REC_dR_Photon", "REC_dR_Photon", kTH1F, {{628, 0.0, 2 * TMath::Pi()}}); histos.add("REC_dR_Stern", "REC_dR_Stern", kTH1F, {{628, 0.0, 2 * TMath::Pi()}}); + histos.add("REC_prompt_phiQA", "REC_prompt_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_prompt_etaQA", "REC_prompt_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_prompt_ptQA", "REC_prompt_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_decay_phiQA", "REC_decay_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_decay_etaQA", "REC_decay_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_decay_ptQA", "REC_decay_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_frag_phiQA", "REC_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_frag_etaQA", "REC_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_frag_ptQA", "REC_frag_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_direct_phiQA", "REC_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_direct_etaQA", "REC_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_direct_ptQA", "REC_direct_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_phiQA", "REC_cluster_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_etaQA", "REC_cluster_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_energyQA", "REC_cluster_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_clusteriso_phiQA", "REC_clusteriso_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_clusteriso_etaQA", "REC_clusteriso_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_clusteriso_energyQA", "REC_clusteriso_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_track_phiQA", "REC_track_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_track_etaQA", "REC_track_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_track_ptQA", "REC_track_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_direct_phiQA", "REC_cluster_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_direct_etaQA", "REC_cluster_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_direct_energyQA", "REC_cluster_direct_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_frag_phiQA", "REC_cluster_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_frag_etaQA", "REC_cluster_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_frag_energyQA", "REC_cluster_frag_energyQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("REC_cluster_both_phiQA", "REC_cluster_both_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("REC_cluster_both_etaQA", "REC_cluster_both_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("REC_cluster_both_energyQA", "REC_cluster_both_energyQA", kTH1F, {{82, -1.0, 40.0}}); + } if (cfgGenHistograms) { + histos.add("GEN_prompt_phiQA", "GEN_prompt_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_prompt_etaQA", "GEN_prompt_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_prompt_ptQA", "GEN_prompt_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_decay_phiQA", "GEN_decay_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_decay_etaQA", "GEN_decay_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_decay_ptQA", "GEN_decay_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_frag_phiQA", "GEN_frag_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_frag_etaQA", "GEN_frag_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_frag_ptQA", "GEN_frag_ptQA", kTH1F, {{82, -1.0, 40.0}}); + histos.add("GEN_direct_phiQA", "GEN_direct_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); + histos.add("GEN_direct_etaQA", "GEN_direct_etaQA", kTH1F, {{100, -1, 1}}); + histos.add("GEN_direct_ptQA", "GEN_direct_ptQA", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_nEvents", "GEN_nEvents", kTH1F, {{4, 0.0, 4.0}}); + histos.add("GEN_nEvents_simple", "GEN_nEvents", kTH1F, {{4, 0.0, 4.0}}); histos.add("GEN_True_Trigger_Energy", "GEN_True_Trigger_Energy", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_Particle_Pt", "GEN_Particle_Pt", kTH1F, {{82, -1.0, 40.0}}); histos.add("GEN_True_Photon_Energy", "GEN_True_Photon_Energy", kTH1F, {{8200, -1.0, 40.0}}); @@ -420,6 +465,71 @@ struct statPromptPhoton { }; // end of track selection ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// + //Below is shamelessly stolen from Florian's gammetreeproducer code. + template + T iTopCopy(const T& particle) const + { + int iUp = particle.globalIndex(); + T currentParticle = particle; + int pdgCode = particle.pdgCode(); + auto mothers = particle.template mothers_as(); + while (iUp > 0 && mothers.size() == 1 && mothers[0].globalIndex() > 0 && mothers[0].pdgCode() == pdgCode) { + iUp = mothers[0].globalIndex(); + currentParticle = mothers[0]; + mothers = currentParticle.template mothers_as(); + } + return currentParticle; + } + + /// \brief Checks if a particle is a prompt photon + /// \param particle The MC particle to check + /// \return true if particle is a prompt photon, false otherwise + bool isPromptPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + return true; + } + return false; + } + /// \brief Checks if a particle is a direct prompt photon + /// \param particle The particle to check + /// \return true if particle is a direct prompt photon, false otherwise + bool isDirectPromptPhoton(const auto& particle) + { + // check if particle isa prompt photon + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + // find the top carbon copy + auto topCopy = iTopCopy(particle); + if (topCopy.pdgCode() == PDG_t::kGamma && std::abs(topCopy.getGenStatusCode()) < 40) { // < 40 is particle directly produced in hard scattering + return true; + } + } + return false; + } + /// \brief Checks if a particle is a fragmentation photon + /// \param particle The particle to check + /// \return true if particle is a fragmentation photon, false otherwise + bool isFragmentationPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) < 90) { + // find the top carbon copy + auto topCopy = iTopCopy(particle); + if (topCopy.pdgCode() == PDG_t::kGamma && std::abs(topCopy.getGenStatusCode()) >= 40) { // frag photon + return true; + } + } + return false; + } + /// \brief Checks if a particle is a decay photon + /// \param particle The particle to check + /// \return true if particle is a decay photon, false otherwise + bool isDecayPhoton(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + return true; + } + return false; + } ///////////////////////////////////////////////////////////////////////////// // PROCESS @@ -1364,9 +1474,338 @@ struct statPromptPhoton { PROCESS_SWITCH(statPromptPhoton, processData, "processJE data", false); + int nEventsGenMC_Simple = 0; + void processMCGen_simple(filteredMCCollisions::iterator const& collision, soa::SmallGroups> const& recocolls, aod::JMcParticles const& mcParticles, jfilteredMCClusters const&) + { + nEventsGenMC_Simple++; + if (cfgDebug) { + if ((nEventsGenMC_Simple + 1) % 10000 == 0) { + std::cout << "Processed Gen MC Events: " << nEventsGenMC_Simple << std::endl; + } + } + histos.fill(HIST("GEN_nEvents_simple"), 0.5); + if (fabs(collision.posZ()) > cfgVtxCut) + return; + + if(cfgGenReqRec){ + if (recocolls.size() <= 0) // not reconstructed + return; + for (auto& recocoll : recocolls) { // poorly reconstructed + if (!recocoll.sel8()) + return; + if (fabs(recocoll.posZ()) > cfgVtxCut) + + return; + histos.fill(HIST("GEN_nEvents_simple"), 1.5); + + if (cfgEmcTrigger) { + if (!recocoll.isEmcalReadout()) + return; + } + histos.fill(HIST("GEN_nEvents_simple"), 2.5); + } + } + + // First pass: find all status -23 particles + for (auto& hardParticle : mcParticles) { + if (hardParticle.getGenStatusCode() != -23) continue; + + bool isPhoton23 = (hardParticle.pdgCode() == 22); + + // For prompt: find the final-state photon descending from this -23 photon + // For frag: find any final-state photon descending from this -23 non-photon + // We search all final-state photons and check if they trace back here + + for (auto& mcParticle : mcParticles) { + if (mcParticle.pdgCode() != 22) continue; + if (mcParticle.getGenStatusCode() < 0) continue; + if (std::fabs(mcParticle.getGenStatusCode()) >= 81 || !mcParticle.isPhysicalPrimary()) continue; + + // Chase this final-state photon upward + int chaseindex = -1; + for (auto& mom : mcParticle.mothers_as()) { + chaseindex = mom.globalIndex(); + break; + } + if (chaseindex < 0) continue; + + std::set visited; + bool chase = true; + bool hadronInChain = false; + bool reachedThisHard = false; + bool cleanPhotonChain = true; // all intermediates are photons + + while (chase) { + if (visited.count(chaseindex)) { chase = false; break; } + visited.insert(chaseindex); + + for (auto& particle : mcParticles) { + if (particle.globalIndex() != chaseindex) continue; + + if (particle.globalIndex() == hardParticle.globalIndex()) { + reachedThisHard = true; + chase = false; + break; + } + + int abspdg = std::abs(particle.pdgCode()); + if (abspdg > 100) hadronInChain = true; + if (abspdg != 22) cleanPhotonChain = false; + + int nextindex = -1; + for (auto& mom : particle.mothers_as()) { + nextindex = mom.globalIndex(); + break; + } + if (nextindex < 0) { chase = false; } + else { chaseindex = nextindex; } + break; + } + } + + if (!reachedThisHard) continue; + + if (isPhoton23 && cleanPhotonChain) { + // Case 1: -23 photon, clean photon chain — direct prompt + histos.fill(HIST("GEN_direct_phiQA"), mcParticle.phi()); + histos.fill(HIST("GEN_direct_etaQA"), mcParticle.eta()); + histos.fill(HIST("GEN_direct_ptQA"), mcParticle.pt()); + } else if (!isPhoton23 && !hadronInChain) { + // Case 2: -23 non-photon, no hadrons — fragmentation + histos.fill(HIST("GEN_frag_phiQA"), mcParticle.phi()); + histos.fill(HIST("GEN_frag_etaQA"), mcParticle.eta()); + histos.fill(HIST("GEN_frag_ptQA"), mcParticle.pt()); + } + } // final-state photon loop + } // hard particle loop + } + PROCESS_SWITCH(statPromptPhoton, processMCGen_simple, "processMC_QA_Gen", false); + int nEventsRecMC_simple = 0; + void processMCRec_simple(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, aod::JMcParticles const& mcparticles, BcCandidates const&, jEMCtracks const& emctracks, aod::JetMcCollisions const&) + { + nEventsRecMC_simple++; + if (cfgDebug) { + if ((nEventsRecMC_simple + 1) % 10000 == 0) { + std::cout << "Processed JE Rec MC Events: " << nEventsRecMC_simple << std::endl; + } + } + histos.fill(HIST("REC_nEvents"), 0.5); + if (fabs(collision.posZ()) > cfgVtxCut) + return; + if (!collision.sel8()) + return; + histos.fill(HIST("REC_nEvents"), 1.5); + if (cfgEmcTrigger) { + if (!collision.isEmcalReadout()) + return; + } + histos.fill(HIST("REC_nEvents"), 2.5); + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) + return; + + for (auto& mccluster : mcclusters) { + histos.fill(HIST("REC_M02_BC"), mccluster.m02()); + if (mccluster.m02() < cfgLowM02) + continue; + if (mccluster.m02() > cfgHighM02) + continue; + if (mccluster.energy() < cfgLowClusterE) + continue; + if (mccluster.energy() > cfgHighClusterE) + continue; + if (fabs(mccluster.eta()) > cfgtrkMaxEta) + continue; + int ClusterHasDirectPhoton =0; + int ClusterHasFragPhoton = 0; + auto ClusterParticles = mccluster.mcParticles_as(); + for (auto& clusterparticle : ClusterParticles) { + if (clusterparticle.pdgCode() != 22 && std::fabs(clusterparticle.pdgCode()) != 13) continue; + if (clusterparticle.getGenStatusCode() < 0) continue; + if (std::fabs(clusterparticle.getGenStatusCode()) >= 81) continue; + + int chaseindex = -1; + for (auto& mom : clusterparticle.mothers_as()) { + chaseindex = mom.globalIndex(); + break; + } + if (chaseindex < 0) continue; + + std::set visited; + bool chase = true; + bool hadronInChain = false; + bool cleanPhotonChain = true; + bool adrianprompt = false; + bool adrianfrag = false; + + while (chase) { + if (visited.count(chaseindex)) { chase = false; break; } + visited.insert(chaseindex); + + for (auto& particle : mcparticles) { + if (particle.globalIndex() != chaseindex) continue; + + if (particle.getGenStatusCode() == -23) { + if (particle.pdgCode() == 22 && cleanPhotonChain) { + adrianprompt = true; + } else if (particle.pdgCode() != 22 && !hadronInChain) { + adrianfrag = true; + } + chase = false; + break; + } + + int abspdg = std::abs(particle.pdgCode()); + if (abspdg > 100) hadronInChain = true; + if (abspdg != 22) cleanPhotonChain = false; + + int nextindex = -1; + for (auto& mom : particle.mothers_as()) { + nextindex = mom.globalIndex(); + break; + } + if (nextindex < 0) { chase = false; } + else { chaseindex = nextindex; } + break; + } + } // chase + + if (adrianprompt) { + ClusterHasDirectPhoton++; + histos.fill(HIST("REC_direct_phiQA"), clusterparticle.phi()); + histos.fill(HIST("REC_direct_etaQA"), clusterparticle.eta()); + histos.fill(HIST("REC_direct_ptQA"), clusterparticle.pt()); + } + if (adrianfrag) { + ClusterHasFragPhoton++; + histos.fill(HIST("REC_frag_phiQA"), clusterparticle.phi()); + histos.fill(HIST("REC_frag_etaQA"), clusterparticle.eta()); + histos.fill(HIST("REC_frag_ptQA"), clusterparticle.pt()); + } + } // clusterparticle loop + + if(ClusterHasFragPhoton>0){ + histos.fill(HIST("REC_cluster_frag_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_frag_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_frag_energyQA"), mccluster.energy()); + } + if(ClusterHasDirectPhoton>0){ + histos.fill(HIST("REC_cluster_direct_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_direct_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_direct_energyQA"), mccluster.energy()); + } + if(ClusterHasDirectPhoton>0 && ClusterHasFragPhoton>0){ + histos.fill(HIST("REC_cluster_both_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_both_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_both_energyQA"), mccluster.energy()); + } + + //now we do cluster tracks + bool photontrigger = false; // is a neutral cluster + bool chargetrigger = false; // is definitely not a neutral cluster + auto tracksofcluster = mccluster.matchedTracks_as>(); + // first, we check if veto is required + double sumptT = 0; + bool clusterqa = false; + for (auto& ctrack : tracksofcluster) { + double etaT, phiT; + if (cfgJETracks) { + if (!jetderiveddatautilities::selectTrack(ctrack, trackFilter)) { + continue; + } + auto emctracksPerTrack = emctracks.sliceBy(EMCTrackPerTrack, ctrack.globalIndex()); + auto emctrack = emctracksPerTrack.iteratorAt(0); + etaT = emctrack.etaEmcal(); + phiT = emctrack.phiEmcal(); + } else { + auto ogtrack = ctrack.track_as(); + if (!trackSelection(ogtrack)) { + continue; + } + if (!ogtrack.isGlobalTrack()) { + continue; + } + etaT = ogtrack.trackEtaEmcal(); + phiT = ogtrack.trackPhiEmcal(); + } + + double etaC = mccluster.eta(); + double phiC = mccluster.phi(); + double ptT = ctrack.pt(); + bool etatrigger = false; + bool phitrigger = false; + double phidiff = TVector2::Phi_mpi_pi(mccluster.phi() - ctrack.phi()); + double etadiff = mccluster.eta() - ctrack.eta(); + + if (cfgPtClusterCut) { + if (fabs(etaT - etaC) < (0.010 + pow(ptT + 4.07, -2.5))) { + etatrigger = true; + } + + if (fabs(TVector2::Phi_mpi_pi(phiT - phiC)) < (0.015 + pow(ptT + 3.65, -2.0))) { + phitrigger = true; + } + } else { + if (fabs(etadiff) < 0.05) { + etatrigger = true; + } + + if (fabs(phidiff) < 0.05) { + phitrigger = true; + } + } + + if (etatrigger && phitrigger) { + chargetrigger = true; + sumptT += ptT; + } + if (chargetrigger) { + if (!clusterqa) { + histos.fill(HIST("REC_Cluster_QA"), 1.5); + clusterqa = true; + } + } + histos.fill(HIST("REC_Track_v_Cluster_Phi"), phidiff); + histos.fill(HIST("REC_Track_v_Cluster_Eta"), etadiff); + histos.fill(HIST("REC_Track_v_Cluster_Phi_Eta"), phidiff, etadiff); + histos.fill(HIST("REC_track_phiQA"), ctrack.phi()); + histos.fill(HIST("REC_track_etaQA"), ctrack.eta()); + histos.fill(HIST("REC_track_ptQA"), ctrack.pt()); + } // track of cluster loop + + if (chargetrigger && sumptT > 0) { + double mccluster_over_sumptT = mccluster.energy() / sumptT; + histos.fill(HIST("REC_SumPt_BC"), mccluster_over_sumptT); + if (mccluster_over_sumptT < 1.7) { + histos.fill(HIST("REC_Cluster_QA"), 2.5); // veto fails, cluster is charged + } else { + histos.fill(HIST("REC_Cluster_QA"), 3.5); // veto is good, cluster is converted to neutral cluster + // chargetrigger = false; + histos.fill(HIST("REC_SumPt_AC"), mccluster_over_sumptT); + } + } // sumptT check + + if (!chargetrigger) { + photontrigger = true; + } + + if (photontrigger) { + histos.fill(HIST("REC_clusteriso_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_clusteriso_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_clusteriso_energyQA"), mccluster.energy()); + } + if (chargetrigger) { + histos.fill(HIST("REC_cluster_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_energyQA"), mccluster.energy()); + } + }//clusters + }//main function + PROCESS_SWITCH(statPromptPhoton, processMCRec_simple, "processMC_QA_Rce", false); + }; // end of main struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; }; + From fe18bea43fe8089013a7feabc096180d80e7a587 Mon Sep 17 00:00:00 2001 From: smaff92 Date: Fri, 20 Mar 2026 14:51:16 +0900 Subject: [PATCH 2/4] Removed unused parameter --- PWGJE/Tasks/statPromptPhoton.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index e823f2ce51a..f1a05373cd3 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -1512,9 +1512,9 @@ struct statPromptPhoton { bool isPhoton23 = (hardParticle.pdgCode() == 22); - // For prompt: find the final-state photon descending from this -23 photon - // For frag: find any final-state photon descending from this -23 non-photon - // We search all final-state photons and check if they trace back here + // For prompt: find the final-state photon descending from this -23 photon// + // For frag: find any final-state photon descending from this -23 non-photon// + // We search all final-state photons and check if they trace back here// for (auto& mcParticle : mcParticles) { if (mcParticle.pdgCode() != 22) continue; @@ -1581,7 +1581,7 @@ struct statPromptPhoton { } PROCESS_SWITCH(statPromptPhoton, processMCGen_simple, "processMC_QA_Gen", false); int nEventsRecMC_simple = 0; - void processMCRec_simple(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, aod::JMcParticles const& mcparticles, BcCandidates const&, jEMCtracks const& emctracks, aod::JetMcCollisions const&) + void processMCRec_simple(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const&, soa::Join const&, TrackCandidates const&, aod::JMcParticles const& mcparticles, BcCandidates const&, jEMCtracks const& emctracks, aod::JetMcCollisions const&) { nEventsRecMC_simple++; if (cfgDebug) { From 4868a159c2f30b0f7e69abd994abdf06ee38c261 Mon Sep 17 00:00:00 2001 From: smaff92 Date: Fri, 20 Mar 2026 15:07:35 +0900 Subject: [PATCH 3/4] Fix for megalinter --- PWGJE/Tasks/statPromptPhoton.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index f1a05373cd3..65b3f67530d 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -53,7 +53,7 @@ #include #include #include - +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; From 96ba047f2cc042d989702245f84eb4ff5362700b Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Fri, 20 Mar 2026 06:08:40 +0000 Subject: [PATCH 4/4] Please consider the following formatting changes --- PWGJE/Tasks/statPromptPhoton.cxx | 258 +++++++++++++++++-------------- 1 file changed, 142 insertions(+), 116 deletions(-) diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index 65b3f67530d..4e13332dcfe 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -51,9 +51,9 @@ #include #include +#include #include #include -#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -222,7 +222,6 @@ struct statPromptPhoton { histos.add("REC_cluster_both_phiQA", "REC_cluster_both_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); histos.add("REC_cluster_both_etaQA", "REC_cluster_both_etaQA", kTH1F, {{100, -1, 1}}); histos.add("REC_cluster_both_energyQA", "REC_cluster_both_energyQA", kTH1F, {{82, -1.0, 40.0}}); - } if (cfgGenHistograms) { histos.add("GEN_prompt_phiQA", "GEN_prompt_phiQA", kTH1F, {{640 * 2, 0, 2 * TMath::Pi()}}); @@ -465,7 +464,7 @@ struct statPromptPhoton { }; // end of track selection ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// - //Below is shamelessly stolen from Florian's gammetreeproducer code. + // Below is shamelessly stolen from Florian's gammetreeproducer code. template T iTopCopy(const T& particle) const { @@ -1474,7 +1473,7 @@ struct statPromptPhoton { PROCESS_SWITCH(statPromptPhoton, processData, "processJE data", false); - int nEventsGenMC_Simple = 0; + int nEventsGenMC_Simple = 0; void processMCGen_simple(filteredMCCollisions::iterator const& collision, soa::SmallGroups> const& recocolls, aod::JMcParticles const& mcParticles, jfilteredMCClusters const&) { nEventsGenMC_Simple++; @@ -1487,28 +1486,29 @@ struct statPromptPhoton { if (fabs(collision.posZ()) > cfgVtxCut) return; - if(cfgGenReqRec){ + if (cfgGenReqRec) { if (recocolls.size() <= 0) // not reconstructed - return; + return; for (auto& recocoll : recocolls) { // poorly reconstructed - if (!recocoll.sel8()) - return; - if (fabs(recocoll.posZ()) > cfgVtxCut) - - return; - histos.fill(HIST("GEN_nEvents_simple"), 1.5); - - if (cfgEmcTrigger) { - if (!recocoll.isEmcalReadout()) - return; - } - histos.fill(HIST("GEN_nEvents_simple"), 2.5); + if (!recocoll.sel8()) + return; + if (fabs(recocoll.posZ()) > cfgVtxCut) + + return; + histos.fill(HIST("GEN_nEvents_simple"), 1.5); + + if (cfgEmcTrigger) { + if (!recocoll.isEmcalReadout()) + return; + } + histos.fill(HIST("GEN_nEvents_simple"), 2.5); } } // First pass: find all status -23 particles for (auto& hardParticle : mcParticles) { - if (hardParticle.getGenStatusCode() != -23) continue; + if (hardParticle.getGenStatusCode() != -23) + continue; bool isPhoton23 = (hardParticle.pdgCode() == 22); @@ -1517,9 +1517,12 @@ struct statPromptPhoton { // We search all final-state photons and check if they trace back here// for (auto& mcParticle : mcParticles) { - if (mcParticle.pdgCode() != 22) continue; - if (mcParticle.getGenStatusCode() < 0) continue; - if (std::fabs(mcParticle.getGenStatusCode()) >= 81 || !mcParticle.isPhysicalPrimary()) continue; + if (mcParticle.pdgCode() != 22) + continue; + if (mcParticle.getGenStatusCode() < 0) + continue; + if (std::fabs(mcParticle.getGenStatusCode()) >= 81 || !mcParticle.isPhysicalPrimary()) + continue; // Chase this final-state photon upward int chaseindex = -1; @@ -1527,7 +1530,8 @@ struct statPromptPhoton { chaseindex = mom.globalIndex(); break; } - if (chaseindex < 0) continue; + if (chaseindex < 0) + continue; std::set visited; bool chase = true; @@ -1536,11 +1540,15 @@ struct statPromptPhoton { bool cleanPhotonChain = true; // all intermediates are photons while (chase) { - if (visited.count(chaseindex)) { chase = false; break; } + if (visited.count(chaseindex)) { + chase = false; + break; + } visited.insert(chaseindex); for (auto& particle : mcParticles) { - if (particle.globalIndex() != chaseindex) continue; + if (particle.globalIndex() != chaseindex) + continue; if (particle.globalIndex() == hardParticle.globalIndex()) { reachedThisHard = true; @@ -1549,21 +1557,27 @@ struct statPromptPhoton { } int abspdg = std::abs(particle.pdgCode()); - if (abspdg > 100) hadronInChain = true; - if (abspdg != 22) cleanPhotonChain = false; + if (abspdg > 100) + hadronInChain = true; + if (abspdg != 22) + cleanPhotonChain = false; int nextindex = -1; for (auto& mom : particle.mothers_as()) { nextindex = mom.globalIndex(); break; } - if (nextindex < 0) { chase = false; } - else { chaseindex = nextindex; } + if (nextindex < 0) { + chase = false; + } else { + chaseindex = nextindex; + } break; } } - if (!reachedThisHard) continue; + if (!reachedThisHard) + continue; if (isPhoton23 && cleanPhotonChain) { // Case 1: -23 photon, clean photon chain — direct prompt @@ -1586,7 +1600,7 @@ struct statPromptPhoton { nEventsRecMC_simple++; if (cfgDebug) { if ((nEventsRecMC_simple + 1) % 10000 == 0) { - std::cout << "Processed JE Rec MC Events: " << nEventsRecMC_simple << std::endl; + std::cout << "Processed JE Rec MC Events: " << nEventsRecMC_simple << std::endl; } } histos.fill(HIST("REC_nEvents"), 0.5); @@ -1597,7 +1611,7 @@ struct statPromptPhoton { histos.fill(HIST("REC_nEvents"), 1.5); if (cfgEmcTrigger) { if (!collision.isEmcalReadout()) - return; + return; } histos.fill(HIST("REC_nEvents"), 2.5); if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) @@ -1606,103 +1620,116 @@ struct statPromptPhoton { for (auto& mccluster : mcclusters) { histos.fill(HIST("REC_M02_BC"), mccluster.m02()); if (mccluster.m02() < cfgLowM02) - continue; + continue; if (mccluster.m02() > cfgHighM02) - continue; + continue; if (mccluster.energy() < cfgLowClusterE) - continue; + continue; if (mccluster.energy() > cfgHighClusterE) - continue; + continue; if (fabs(mccluster.eta()) > cfgtrkMaxEta) - continue; - int ClusterHasDirectPhoton =0; + continue; + int ClusterHasDirectPhoton = 0; int ClusterHasFragPhoton = 0; - auto ClusterParticles = mccluster.mcParticles_as(); - for (auto& clusterparticle : ClusterParticles) { - if (clusterparticle.pdgCode() != 22 && std::fabs(clusterparticle.pdgCode()) != 13) continue; - if (clusterparticle.getGenStatusCode() < 0) continue; - if (std::fabs(clusterparticle.getGenStatusCode()) >= 81) continue; - - int chaseindex = -1; - for (auto& mom : clusterparticle.mothers_as()) { - chaseindex = mom.globalIndex(); - break; - } - if (chaseindex < 0) continue; - - std::set visited; - bool chase = true; - bool hadronInChain = false; - bool cleanPhotonChain = true; - bool adrianprompt = false; - bool adrianfrag = false; - - while (chase) { - if (visited.count(chaseindex)) { chase = false; break; } - visited.insert(chaseindex); - - for (auto& particle : mcparticles) { - if (particle.globalIndex() != chaseindex) continue; - - if (particle.getGenStatusCode() == -23) { - if (particle.pdgCode() == 22 && cleanPhotonChain) { - adrianprompt = true; - } else if (particle.pdgCode() != 22 && !hadronInChain) { - adrianfrag = true; - } + auto ClusterParticles = mccluster.mcParticles_as(); + for (auto& clusterparticle : ClusterParticles) { + if (clusterparticle.pdgCode() != 22 && std::fabs(clusterparticle.pdgCode()) != 13) + continue; + if (clusterparticle.getGenStatusCode() < 0) + continue; + if (std::fabs(clusterparticle.getGenStatusCode()) >= 81) + continue; + + int chaseindex = -1; + for (auto& mom : clusterparticle.mothers_as()) { + chaseindex = mom.globalIndex(); + break; + } + if (chaseindex < 0) + continue; + + std::set visited; + bool chase = true; + bool hadronInChain = false; + bool cleanPhotonChain = true; + bool adrianprompt = false; + bool adrianfrag = false; + + while (chase) { + if (visited.count(chaseindex)) { chase = false; break; } + visited.insert(chaseindex); - int abspdg = std::abs(particle.pdgCode()); - if (abspdg > 100) hadronInChain = true; - if (abspdg != 22) cleanPhotonChain = false; + for (auto& particle : mcparticles) { + if (particle.globalIndex() != chaseindex) + continue; - int nextindex = -1; - for (auto& mom : particle.mothers_as()) { - nextindex = mom.globalIndex(); + if (particle.getGenStatusCode() == -23) { + if (particle.pdgCode() == 22 && cleanPhotonChain) { + adrianprompt = true; + } else if (particle.pdgCode() != 22 && !hadronInChain) { + adrianfrag = true; + } + chase = false; + break; + } + + int abspdg = std::abs(particle.pdgCode()); + if (abspdg > 100) + hadronInChain = true; + if (abspdg != 22) + cleanPhotonChain = false; + + int nextindex = -1; + for (auto& mom : particle.mothers_as()) { + nextindex = mom.globalIndex(); + break; + } + if (nextindex < 0) { + chase = false; + } else { + chaseindex = nextindex; + } break; } - if (nextindex < 0) { chase = false; } - else { chaseindex = nextindex; } - break; + } // chase + + if (adrianprompt) { + ClusterHasDirectPhoton++; + histos.fill(HIST("REC_direct_phiQA"), clusterparticle.phi()); + histos.fill(HIST("REC_direct_etaQA"), clusterparticle.eta()); + histos.fill(HIST("REC_direct_ptQA"), clusterparticle.pt()); } - } // chase + if (adrianfrag) { + ClusterHasFragPhoton++; + histos.fill(HIST("REC_frag_phiQA"), clusterparticle.phi()); + histos.fill(HIST("REC_frag_etaQA"), clusterparticle.eta()); + histos.fill(HIST("REC_frag_ptQA"), clusterparticle.pt()); + } + } // clusterparticle loop - if (adrianprompt) { - ClusterHasDirectPhoton++; - histos.fill(HIST("REC_direct_phiQA"), clusterparticle.phi()); - histos.fill(HIST("REC_direct_etaQA"), clusterparticle.eta()); - histos.fill(HIST("REC_direct_ptQA"), clusterparticle.pt()); + if (ClusterHasFragPhoton > 0) { + histos.fill(HIST("REC_cluster_frag_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_frag_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_frag_energyQA"), mccluster.energy()); } - if (adrianfrag) { - ClusterHasFragPhoton++; - histos.fill(HIST("REC_frag_phiQA"), clusterparticle.phi()); - histos.fill(HIST("REC_frag_etaQA"), clusterparticle.eta()); - histos.fill(HIST("REC_frag_ptQA"), clusterparticle.pt()); + if (ClusterHasDirectPhoton > 0) { + histos.fill(HIST("REC_cluster_direct_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_direct_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_direct_energyQA"), mccluster.energy()); + } + if (ClusterHasDirectPhoton > 0 && ClusterHasFragPhoton > 0) { + histos.fill(HIST("REC_cluster_both_phiQA"), mccluster.phi()); + histos.fill(HIST("REC_cluster_both_etaQA"), mccluster.eta()); + histos.fill(HIST("REC_cluster_both_energyQA"), mccluster.energy()); } - } // clusterparticle loop - - if(ClusterHasFragPhoton>0){ - histos.fill(HIST("REC_cluster_frag_phiQA"), mccluster.phi()); - histos.fill(HIST("REC_cluster_frag_etaQA"), mccluster.eta()); - histos.fill(HIST("REC_cluster_frag_energyQA"), mccluster.energy()); - } - if(ClusterHasDirectPhoton>0){ - histos.fill(HIST("REC_cluster_direct_phiQA"), mccluster.phi()); - histos.fill(HIST("REC_cluster_direct_etaQA"), mccluster.eta()); - histos.fill(HIST("REC_cluster_direct_energyQA"), mccluster.energy()); - } - if(ClusterHasDirectPhoton>0 && ClusterHasFragPhoton>0){ - histos.fill(HIST("REC_cluster_both_phiQA"), mccluster.phi()); - histos.fill(HIST("REC_cluster_both_etaQA"), mccluster.eta()); - histos.fill(HIST("REC_cluster_both_energyQA"), mccluster.energy()); - } - //now we do cluster tracks - bool photontrigger = false; // is a neutral cluster - bool chargetrigger = false; // is definitely not a neutral cluster - auto tracksofcluster = mccluster.matchedTracks_as>(); + // now we do cluster tracks + bool photontrigger = false; // is a neutral cluster + bool chargetrigger = false; // is definitely not a neutral cluster + auto tracksofcluster = mccluster.matchedTracks_as>(); // first, we check if veto is required double sumptT = 0; bool clusterqa = false; @@ -1767,7 +1794,7 @@ struct statPromptPhoton { histos.fill(HIST("REC_Track_v_Cluster_Phi"), phidiff); histos.fill(HIST("REC_Track_v_Cluster_Eta"), etadiff); histos.fill(HIST("REC_Track_v_Cluster_Phi_Eta"), phidiff, etadiff); - histos.fill(HIST("REC_track_phiQA"), ctrack.phi()); + histos.fill(HIST("REC_track_phiQA"), ctrack.phi()); histos.fill(HIST("REC_track_etaQA"), ctrack.eta()); histos.fill(HIST("REC_track_ptQA"), ctrack.pt()); } // track of cluster loop @@ -1798,8 +1825,8 @@ struct statPromptPhoton { histos.fill(HIST("REC_cluster_etaQA"), mccluster.eta()); histos.fill(HIST("REC_cluster_energyQA"), mccluster.energy()); } - }//clusters - }//main function + } // clusters + } // main function PROCESS_SWITCH(statPromptPhoton, processMCRec_simple, "processMC_QA_Rce", false); }; // end of main struct @@ -1808,4 +1835,3 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; }; -