From aca32956e498f58a8d8ac71e2aa51022c6a0f249 Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski Date: Wed, 2 Sep 2026 16:10:51 +0200 Subject: [PATCH 1/5] Unify QC + MaterialBudgetTasks --- PWGEM/PhotonMeson/Legacy/CMakeLists.txt | 15 + PWGEM/PhotonMeson/Tasks/CMakeLists.txt | 15 - PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx | 1317 ------------------ PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx | 456 ------ PWGEM/PhotonMeson/Tasks/pcmQC.cxx | 1026 ++++++++++++-- PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx | 822 ----------- 6 files changed, 940 insertions(+), 2711 deletions(-) delete mode 100644 PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx delete mode 100644 PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx delete mode 100644 PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx diff --git a/PWGEM/PhotonMeson/Legacy/CMakeLists.txt b/PWGEM/PhotonMeson/Legacy/CMakeLists.txt index eb838a12cd8..0fae049d13a 100644 --- a/PWGEM/PhotonMeson/Legacy/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Legacy/CMakeLists.txt @@ -38,3 +38,18 @@ o2physics_add_dpl_workflow(gammaconversionstruthonlymc SOURCES gammaConversionsTruthOnlyMc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(material-budget + SOURCES MaterialBudget.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(material-budget-mc + SOURCES MaterialBudgetMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(pcm-qc-mc + SOURCES pcmQCMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index 328f039590f..8afdf504200 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt @@ -31,11 +31,6 @@ o2physics_add_dpl_workflow(pcm-qc PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(pcm-qc-mc - SOURCES pcmQCMC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(dalitz-ee-qc SOURCES dalitzEEQC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore O2Physics::PWGEMDileptonCore @@ -126,16 +121,6 @@ o2physics_add_dpl_workflow(tag-and-probe PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore O2Physics::MLCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(material-budget - SOURCES MaterialBudget.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(material-budget-mc - SOURCES MaterialBudgetMC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(check-mc-v0 SOURCES CheckMCV0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx deleted file mode 100644 index 5baa0ebf6bc..00000000000 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudget.cxx +++ /dev/null @@ -1,1317 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file MaterialBudget.cxx -/// \brief Task to analyse and calculate the material budget weights -/// \author S. Mrozinski, smrozins@cern.ch - -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/DataModel/EventTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" - -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace o2; -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; -using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using namespace o2::aod::pwgem::dilepton::utils; -using o2::constants::math::TwoPI; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyCollisionsMC = soa::Join; -using MyCollisionMC = MyCollisionsMC::iterator; - -using MyMCCollisions = soa::Join; -using MyMCCollision = MyMCCollisions::iterator; - -using MyV0Photons = soa::Join; -using MyV0Photon = MyV0Photons::iterator; - -using MyPrimaryElectrons = soa::Filtered>; -using MyPrimaryElectron = MyPrimaryElectrons::iterator; - -using MyMCV0Legs = soa::Join; -using MyMCV0Leg = MyMCV0Legs::iterator; - -using MyTracks = soa::Join; -struct MaterialBudget { - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - - struct SimplePhoton { - float pt; - float eta; - float phi; - float vz; - float r; - }; - - static constexpr int MaxMixEvents = 5; - std::map, std::deque>> mixingPools; - - std::vector centBinEdges = {0, 10, 30, 50, 90, 200}; - std::vector zvtxBinEdges = {-10, -5, 0, 5, 10}; - - std::tuple getPoolBin(float cent, float zvtx) - { - int centbin = std::lower_bound(centBinEdges.begin(), centBinEdges.end(), cent) - centBinEdges.begin() - 1; - centbin = std::max(0, std::min(centbin, static_cast(centBinEdges.size()) - 2)); - - int zbin = std::lower_bound(zvtxBinEdges.begin(), zvtxBinEdges.end(), zvtx) - zvtxBinEdges.begin() - 1; - zbin = std::max(0, std::min(zbin, static_cast(zvtxBinEdges.size()) - 2)); - return {centbin, zbin}; - } - - HistogramRegistry registry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - - static constexpr std::array ItsClsNames{ - "ITSCls0", "ITSCls1", "ITSCls2", "ITSCls3", - "ITSCls4", "ITSCls5", "ITSCls6", "ITSCls7"}; - - static constexpr std::array EventTypes{"before/", "after/"}; - - Configurable cfgPlotBremsstrahlung{"cfgPlotBremsstrahlung", false, "produce plots to study Bremsstrahlung"}; - Configurable cfgPlotResolution{"cfgPlotResolution", false, "produce plots to study resolution"}; - Configurable cfgPlotPurity{"cfgPlotPurity", false, "produce plots to study purity"}; - Configurable cfgPlotMBDetailed{"cfgPlotMBDetailed", false, "produce plots to study material distribution distribution"}; - Configurable cfgPlotMBGeneral{"cfgPlotMBGeneral", true, "produce plots to study material distribution"}; - Configurable cfgPlotMBCollisions{"cfgPlotMBCollisions", false, "produce plots to study material distribution if collision association is wrong"}; - - ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 2.0}, ""}; - - EMPhotonEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; - Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; - Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - } eventcuts; - - DalitzEECut fDileptonCut; - struct : ConfigurableGroup { - std::string prefix = "dileptoncut_group"; - Configurable cfgMinMass{"cfgMinMass", 0.0, "min mass"}; - Configurable cfgMaxMass{"cfgMaxMass", 0.1, "max mass"}; - Configurable cfgApplyPhiv{"cfgApplyPhiv", true, "flag to apply phiv cut"}; - Configurable cfgRequireItsibAny{"cfgRequireItsibAny", false, "flag to require ITS ib any hits"}; - Configurable cfgRequireItsib1st{"cfgRequireItsib1st", true, "flag to require ITS ib 1st hit"}; - Configurable cfgPhivSlope{"cfgPhivSlope", 0.0185, "slope for m vs. phiv"}; - Configurable cfgPhivIntercept{"cfgPhivIntercept", -0.0280, "intercept for m vs. phiv"}; - - Configurable cfgMinPtTrack{"cfgMinPtTrack", 0.1, "min pT for single track"}; - Configurable cfgMaxEtaTrack{"cfgMaxEtaTrack", 0.8, "max eta for single track"}; - Configurable cfgMinnclusterTPC{"cfgMinnclusterTPC", 0, "min ncluster tpc"}; - Configurable cfgMinnclusterITS{"cfgMinnclusterITS", 5, "min ncluster its"}; - Configurable cfgMinncrossedrows{"cfgMinncrossedrows", 70, "min ncrossed rows"}; - Configurable cfgMaxchi2TPC{"cfgMaxchi2TPC", 4.0, "max chi2/NclsTPC"}; - Configurable cfgMaxchi2ITS{"cfgMaxchi2ITS", 36.0, "max chi2/NclsITS"}; - Configurable cfgMaxDCAxy{"cfgMaxDCAxy", 0.05, "max dca XY for single track in cm"}; - Configurable cfgMaxDCAz{"cfgMaxDCAz", 0.05, "max dca Z for single track in cm"}; - Configurable cfgMaxDCA3dsigmaTrack{"cfgMaxDCA3dsigmaTrack", 1.5, "max DCA 3D in sigma"}; - Configurable cfgMaxFracSharedClustersTPC{"cfgMaxFracSharedClustersTPC", 999.f, "max fraction of shared clusters in TPC"}; - Configurable cfgApplyCutsFromPrefilterDerived{"cfgApplyCutsFromPrefilterDerived", false, "flag to apply prefilter to electron"}; - Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; - Configurable cfgMaxpttrackITSsa{"cfgMaxpttrackITSsa", 0.15, "max pt for ITSsa tracks"}; - - Configurable cfgPIDscheme{"cfgPIDscheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; - Configurable cfgMinTPCNsigmaEl{"cfgMinTPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; - Configurable cfgMaxTPCNsigmaEl{"cfgMaxTPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfgMinTPCNsigmaPi{"cfgMinTPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; - Configurable cfgMaxTPCNsigmaPi{"cfgMaxTPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; - Configurable cfgMinTOFNsigmaEl{"cfgMinTOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; - Configurable cfgMaxTOFNsigmaEl{"cfgMaxTOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; - } dileptoncuts; - - V0PhotonCut fV0PhotonCut; - struct : ConfigurableGroup { - std::string prefix = "pcmcut_group"; - Configurable cfgRequireV0WithITSTPC{"cfgRequireV0WithITSTPC", false, "flag to select V0s with ITS-TPC matched tracks"}; - Configurable cfgRequireV0WithITSOnly{"cfgRequireV0WithITSOnly", false, "flag to select V0s with ITSonly tracks"}; - Configurable cfgRequireV0WithTPCOnly{"cfgRequireV0WithTPCOnly", false, "flag to select V0s with TPConly tracks"}; - Configurable cfgMinPtV0{"cfgMinPtV0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfgMaxPtV0{"cfgMaxPtV0", 1e+10, "max pT for v0 photons at PV"}; - Configurable cfgMinEtaV0{"cfgMinEtaV0", -0.8, "min eta for v0 photons at PV"}; - Configurable cfgMaxEtaV0{"cfgMaxEtaV0", +0.8, "max eta for v0 photons at PV"}; - Configurable cfgMinV0Radius{"cfgMinV0Radius", 4.0, "min v0 radius"}; - Configurable cfgMaxV0Radius{"cfgMaxV0Radius", 90.0, "max v0 radius"}; - Configurable cfgMaxAlphaAp{"cfgMaxAlphaAp", 0.95, "max alpha for AP cut"}; - Configurable cfgMaxQtAp{"cfgMaxQtAp", 0.01, "max qT for AP cut"}; - Configurable cfgMinCospa{"cfgMinCospa", 0.999, "min V0 CosPA"}; - Configurable cfgMaxPca{"cfgMaxPca", 1.5, "max distance btween 2 legs"}; - Configurable cfgMaxChi2kf{"cfgMaxChi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfgRejectV0OnITSib{"cfgRejectV0OnITSib", true, "flag to reject V0s on ITSib"}; - Configurable cfgMinNclusterTPC{"cfgMinNclusterTPC", 0, "min ncluster tpc"}; - Configurable cfgMinNcrossedrows{"cfgMinNcrossedrows", 40, "min ncrossed rows"}; - Configurable cfgMaxFracSharedClustersTPC{"cfgMaxFracSharedClustersTPC", 999.f, "max fraction of shared clusters in TPC"}; - Configurable cfgMaxChi2TPC{"cfgMaxChi2TPC", 4.0, "max chi2/NclsTPC"}; - Configurable cfgMaxChi2ITS{"cfgMaxChi2ITS", 36.0, "max chi2/NclsITS"}; - Configurable cfgMinTPCNsigmaEl{"cfgMinTPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; - Configurable cfgMaxTPCNsigmaEl{"cfgMaxTPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; - Configurable cfgDisableITSonlytrack{"cfgDisableITSonlytrack", false, "flag to disable ITSonly tracks"}; - Configurable cfgDisableTPCOnlytrack{"cfgDisableTPCOnlytrack", false, "flag to disable TPConly tracks"}; - } pcmcuts; - - void init(InitContext&) - { - - defineEMEventCut(); - defineDileptonCut(); - definePCMCut(); - addhistograms(); - } - - void defineEMEventCut() - { - fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); - fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); - fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); - fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); - fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); - } - - void defineDileptonCut() - { - fDileptonCut = DalitzEECut("fDileptonCut", "fDileptonCut"); - - // for pair - fDileptonCut.SetMeeRange(dileptoncuts.cfgMinMass, dileptoncuts.cfgMaxMass); - fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfgPhivIntercept) / dileptoncuts.cfgPhivSlope; }); - fDileptonCut.ApplyPhiV(dileptoncuts.cfgApplyPhiv); - fDileptonCut.RequireITSibAny(dileptoncuts.cfgRequireItsibAny); - fDileptonCut.RequireITSib1st(dileptoncuts.cfgRequireItsib1st); - - // for tracks - fDileptonCut.SetTrackPtRange(dileptoncuts.cfgMinPtTrack, 1e+10f); - fDileptonCut.SetTrackEtaRange(-dileptoncuts.cfgMaxEtaTrack, +dileptoncuts.cfgMaxEtaTrack); - fDileptonCut.SetMinNClustersTPC(dileptoncuts.cfgMinnclusterTPC); - fDileptonCut.SetMinNCrossedRowsTPC(dileptoncuts.cfgMinncrossedrows); - fDileptonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fDileptonCut.SetMaxFracSharedClustersTPC(dileptoncuts.cfgMaxFracSharedClustersTPC); - fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfgMaxchi2TPC); - fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfgMaxchi2ITS); - fDileptonCut.SetNClustersITS(dileptoncuts.cfgMinnclusterITS, 7); - fDileptonCut.SetMaxDcaXY(dileptoncuts.cfgMaxDCAxy); - fDileptonCut.SetMaxDcaZ(dileptoncuts.cfgMaxDCAz); - fDileptonCut.SetTrackDca3DRange(0.f, dileptoncuts.cfgMaxDCA3dsigmaTrack); // in sigma - fDileptonCut.IncludeITSsa(dileptoncuts.includeITSsa, dileptoncuts.cfgMaxpttrackITSsa); - - // for eID - fDileptonCut.SetPIDScheme(dileptoncuts.cfgPIDscheme); - fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfgMinTPCNsigmaEl, dileptoncuts.cfgMaxTPCNsigmaEl); - fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfgMinTPCNsigmaPi, dileptoncuts.cfgMaxTPCNsigmaPi); - fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfgMinTOFNsigmaEl, dileptoncuts.cfgMaxTOFNsigmaEl); - } - - void definePCMCut() - { - fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); - - // for v0 - fV0PhotonCut.SetV0PtRange(pcmcuts.cfgMinPtV0, pcmcuts.cfgMaxPtV0); - fV0PhotonCut.SetV0EtaRange(pcmcuts.cfgMinEtaV0, pcmcuts.cfgMaxEtaV0); - fV0PhotonCut.SetMinCosPA(pcmcuts.cfgMinCospa); - fV0PhotonCut.SetMaxPCA(pcmcuts.cfgMaxPca); - fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfgMaxChi2kf); - fV0PhotonCut.SetRxyRange(pcmcuts.cfgMinV0Radius, pcmcuts.cfgMaxV0Radius); - fV0PhotonCut.SetAPRange(pcmcuts.cfgMaxAlphaAp, pcmcuts.cfgMaxQtAp); - fV0PhotonCut.RejectITSib(pcmcuts.cfgRejectV0OnITSib); - - // for track - fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfgMinNclusterTPC); - fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfgMinNcrossedrows); - fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfgMaxFracSharedClustersTPC); - fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfgMaxChi2TPC); - fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfgMinTPCNsigmaEl, pcmcuts.cfgMaxTPCNsigmaEl); - fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfgMaxChi2ITS); - fV0PhotonCut.SetNClustersITS(0, 7); - fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetDisableITSonly(pcmcuts.cfgDisableITSonlytrack); - fV0PhotonCut.SetDisableTPConly(pcmcuts.cfgDisableTPCOnlytrack); - fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfgRequireV0WithITSTPC); - fV0PhotonCut.SetRequireITSonly(pcmcuts.cfgRequireV0WithITSOnly); - fV0PhotonCut.SetRequireTPConly(pcmcuts.cfgRequireV0WithTPCOnly); - } - - void addhistograms() - { - const AxisSpec axisPt{binsPt, "#it{p}_{T} [GeV/c]"}; - auto hCollisionCounter = registry.add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{10, 0.5, 10.5}}, false); - hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); - hCollisionCounter->GetXaxis()->SetBinLabel(2, "No TF border"); - hCollisionCounter->GetXaxis()->SetBinLabel(3, "No ITS ROF border"); - hCollisionCounter->GetXaxis()->SetBinLabel(4, "No Same Bunch Pileup"); - hCollisionCounter->GetXaxis()->SetBinLabel(5, "Is Vertex ITSTPC"); - hCollisionCounter->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); - hCollisionCounter->GetXaxis()->SetBinLabel(7, "FT0AND"); - hCollisionCounter->GetXaxis()->SetBinLabel(8, "sel8"); - hCollisionCounter->GetXaxis()->SetBinLabel(9, "|Z_{vtx}| < 10 cm"); - hCollisionCounter->GetXaxis()->SetBinLabel(10, "accepted"); - - registry.add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); - registry.add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); - registry.add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); - registry.add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{300, 0, 6000}, {300, 0, 6000}}, false); - registry.add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); - registry.add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); - registry.add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); - registry.add("Event/before/hCentFT0MvsMultNTracksPV", "hCentFT0MvsMultNTracksPV;centrality FT0M (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); - registry.add("Event/before/hMultFT0MvsMultNTracksPV", "hMultFT0MvsMultNTracksPV;mult. FT0M;N_{track} to PV", kTH2F, {{600, 0, 6000}, {600, 0, 6000}}, false); - registry.addClone("Event/before/", "Event/after/"); - - if (cfgPlotMBGeneral) { - - registry.add("MBGeneral", ";z_{conv} (cm); R_{conv} (cm); #eta; #varphi (rad); p_{T}", kTHnSparseF, - {{200, -100.f, 100.f}, - {100, 0.f, 100.f}, - {80, -2, +2}, - {90, 0, o2::constants::math::TwoPI}, - {1000, 0, 10}}, // pT 5 - true); - - registry.add("Pi0/Same", - "Pi0; m_{#gamma#gamma}; #it{p}_{T}; R_{conv} (cm); R_{conv} (cm)", - kTHnSparseF, - {{400, 0.f, 0.3}, // x 0 - {500, 0, 10}, // pT 1 - {100, 0.f, 100.f}, // R of photon 1 - {100, 0.f, 100.f}}, - true); - - registry.add("Dalitz/Same", - "Dalitz; m_{eeγ}; p_{T}; R_{γ} (cm); R_{e+}; R_{e-}", - kTHnSparseF, - {{400, 0.f, 0.5f}, - {500, 0.f, 10.f}, - {100, 0.f, 100.f}}, - true); - - registry.add("Pi0/Mix", "Pi0 mixed-event;m_{#gamma#gamma};p_{T}", kTHnSparseF, - {{400, 0, 0.3}, {500, 0, 10}, {100, 0, 100}, {100, 0, 100}}, true); - } - - if (cfgPlotMBDetailed) { - - registry.add("MBStudiesWireLeft", - "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", - kTHnSparseF, - { - {200, -20.f, 20.f}, // x 0 - {200, -20.f, 20.f}, // y 1 - {80, -20.f, 20.f}, // z 2 - {40, 3.15, 3.4}, // phi 3 - {80, 0.f, 20.f}, // conversion radius 4 - {1000, 0, 10} // pT 5 - }, - true); - - registry.add("MBStudiesWireRight", - "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", - kTHnSparseF, - { - {200, -20.f, 20.f}, // x 0 - {200, -20.f, 20.f}, // y 1 - {80, -20.f, 20.f}, // z 2 - {40, 6.00, 6.15}, // phi 3 - {80, 0.f, 20.f}, // conversion radius 4 - {1000, 0, 10} // pT 5 - }, - true); - - registry.add("MBStudiesWireITS", - "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", - kTHnSparseF, - { - {160, -40.f, 40.f}, // x 0 - {160, -40.f, 40.f}, // y 1 - {80, -40.f, 40.f}, // z 2 - {90, 0, TwoPI}, // phi 3 - {150, 0.f, 60.f}, // conversion radius 4 - {1000, 0, 10} // pT 5 - }, - true); - - registry.add("MBStudiesMFT", - "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", - kTHnSparseF, - { - {160, -80.f, 80.f}, // x 0 - {160, -80.f, 80.f}, // y 1 - {40, -40.f, 40.f}, // z 2 - {90, 0, TwoPI}, // phi 3 - {40, 40.f, 60.f}, // conversion radius 4 - {500, 0, 10} // pT 5 - }, - true); - - registry.add("MBStudiesTPC", - "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", - kTHnSparseF, - { - {160, -90.f, 90.f}, // x 0 - {160, -90.f, 90.f}, // y 1 - {80, -40.f, 40.f}, // z 2 - {90, 0, TwoPI}, // phi 3 - {80, 60.f, 80.f}, // conversion radius 4 - {1000, 0, 10} // pT 5 - }, - true); - - for (int nCls = 0; nCls <= 7; nCls++) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - registry.add(Form("ITSHits/Neg/ITSCls%d", nCls), - Form("Conversion radius NEG legs with %d ITS clusters;R_{conv} (cm);Entries", nCls), - HistType::kTH1F, - {AxisSpec{100, 0.f, 100.f}}); - - registry.add(Form("ITSHits/Pos/ITSCls%d", nCls), - Form("Conversion radius POS legs with %d ITS clusters;R_{conv} (cm);Entries", nCls), - HistType::kTH1F, - {AxisSpec{100, 0.f, 100.f}}); - } - } - - if (cfgPlotResolution) { - - registry.add("ResolutionGen/Z_res", - "Z resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;Δz (cm)", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {120, -30, 30}}, false); - - registry.add("ResolutionGen/R_res", - "R resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;ΔR (cm)", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {120, -30, 30}}, false); - - registry.add("ResolutionGen/Phi_res", - "Phi resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;Δφ", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {100, -0.2f, 0.2f}}, false); - - registry.add("ResolutionGen/Pt_res", - "pT resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;ΔpT/pT_gen", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {200, -1.0f, 1.0f}}, false); - - registry.add("ResolutionGen/Eta_res", - "Eta resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;Δη", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {100, -0.5f, 0.5f}}, false); - - registry.add("ResolutionRec/Z_res", - "Z resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;Δz (cm)", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {120, -30, 30}}, false); - - registry.add("ResolutionRec/R_res", - "R resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;ΔR (cm)", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {120, -30, 30}}, false); - - registry.add("ResolutionRec/Phi_res", - "Phi resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;Δφ", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {100, -0.2f, 0.2f}}, false); - - registry.add("ResolutionRec/Pt_res", - "pT resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;ΔpT/pT_gen", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {200, -1.0f, 1.0f}}, false); - - registry.add("ResolutionRec/Eta_res", - "Eta resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;Δη", - kTHnSparseF, - {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {100, -0.5f, 0.5f}}, false); - } - - if (cfgPlotPurity) { - - registry.add("PhotonPurity", - "Photon purity classification;p_{T} (GeV/c);R_{conv} (cm);#eta;#varphi;category", - kTHnSparseF, - { - {500, 0, 10}, // pT - {200, 0, 100}, // R - {100, -1.0, 1.0}, // eta - {90, 0, o2::constants::math::TwoPI}, // phi - {12, 0.5, 12.5} // purity categories - }, - true); - - auto hPurity = registry.get(HIST("PhotonPurity")); - - auto axis = hPurity->GetAxis(4); - - axis->SetBinLabel(1, "e^{+}e^{-}"); - axis->SetBinLabel(2, "e^{-} + #pi^{+}"); - axis->SetBinLabel(3, "#pi^{-} + e^{+}"); - axis->SetBinLabel(4, "K^{-} + e^{+}"); - axis->SetBinLabel(5, "e^{-} + K^{+}"); - axis->SetBinLabel(6, "#bar{p} + p"); - axis->SetBinLabel(7, "K^{-} + K^{+}"); - axis->SetBinLabel(8, "#pi^{-} + p"); - axis->SetBinLabel(9, "#bar{p} + #pi^{+}"); - axis->SetBinLabel(10, "#mu^{-} + #mu^{+}"); - } - - if (cfgPlotBremsstrahlung) { - - registry.add("Bremsstrahlung/EnergyLossVsR", ";R (cm);E_{loss} (GeV)", - kTH2F, {{50, 0, 100}, {100, 0, 5}}); - registry.add("Bremsstrahlung/EnergyLossXY", ";X (cm);Y (cm)", - kTH2F, {{100, -100, 100}, {100, -100, 100}}); - registry.add("Bremsstrahlung/EnergyLossXYWeigh", ";X (cm);Y (cm)", - kTH2F, {{100, -100, 100}, {100, -100, 100}}); - registry.add("Bremsstrahlung/EnergyLossVsZ", ";Z (cm);E_{loss} (GeV)", - kTH2F, {{100, -100, 100}, {200, 0, 5}}); - - registry.add("Bremsstrahlung/NBrem", ";N_{Brem} per e^{-};Counts", - kTH1I, {{10, 0, 10}}); - - registry.add("Bremsstrahlung/DeltaPoverPvsR", ";R (cm);(p_{Reco}-p_{MC})/p_{MC}", - kTH2F, {{50, 0, 100}, {200, -1, 1}}); - registry.add("Bremsstrahlung/DeltaPtvsR", ";R (cm);(p_{T,Reco}-p_{T,MC})/p_{T,MC}", - kTH2F, {{50, 0, 100}, {300, -2, 2}}); - registry.add("Bremsstrahlung/DeltaPhivsR", ";R (cm);#Delta#varphi (rad)", - kTH2F, {{50, 0, 100}, {200, -0.1, 0.1}}); - registry.add("Bremsstrahlung/DeltaEtavsR", ";R (cm);#Delta#eta", - kTH2F, {{50, 0, 100}, {200, -0.1, 0.1}}); - - registry.add("Bremsstrahlung/Sigma1PtVsR", ";R (cm);#sigma(1/p_{T}) [c/GeV]", - kTH2F, {{50, 0, 100}, {100, 0, 0.1}}); - - registry.add("Bremsstrahlung/SigmaYVsR", ";R (cm);#sigma(y) [cm]", - kTH2F, {{50, 0, 100}, {100, 0, 0.5}}); - registry.add("Bremsstrahlung/SigmaZVsR", ";R (cm);#sigma(z) [cm]", - kTH2F, {{50, 0, 100}, {100, 0, 1.0}}); - - registry.add("Bremsstrahlung/relativeResoPtWBrems", - "relative #it{p}_{T} resolution; #it{p}_{T}; #sigma(#it{p}_{T})/#it{p}_{T}", - kTProfile, - {axisPt}); - - registry.add("Bremsstrahlung/relativeResoPtWOBrems", - "relative #it{p}_{T} resolution; #it{p}_{T}; #sigma(#it{p}_{T})/#it{p}_{T}", - kTProfile, - {axisPt}); - } - - if (cfgPlotMBCollisions) { - - registry.add("RightCollisions/SparseDeltaCol", - "RightCollisions;R_{rec} (cm);#it{p}_{T} (GeV/c);#Delta #it{p}_{T}/#it{p}_{T,gen};#Delta z (cm);#Delta R (cm);#Delta col ID", - kTHnSparseF, - { - {100, 0.f, 100.f}, // R_rec - {200, 0.f, 10.f}, // pT - {200, -1.f, 1.f}, // ΔpT/pT - {200, -20.f, 20.f}, // Δz - {200, -8.f, 8.f}, // ΔR - {21, -10.5, 10.5} // ΔCollisionID - }, - true); - - registry.add("WrongCollisions/SparseDeltaCol", - "WrongCollisions;R_{rec} (cm);#it{p}_{T} (GeV/c);#Delta #it{p}_{T}/#it{p}_{T,gen};#Delta z (cm);#Delta R (cm);#Delta col ID", - kTHnSparseF, - {{100, 0.f, 100.f}, - {200, 0.f, 10.f}, - {200, -1.f, 1.f}, - {200, -20.f, 20.f}, - {200, -8.f, 8.f}, - {21, -10.5, 10.5}}, - true); - } - } - - template - void fillITSClsNeg(HistogramRegistry& reg, float value) - { - if constexpr (N == 0) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Neg/ITSCls0"), value); - } - if constexpr (N == 1) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Neg/ITSCls1"), value); - } - if constexpr (N == 2) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Neg/ITSCls2"), value); - } - if constexpr (N == 3) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Neg/ITSCls3"), value); - } - if constexpr (N == 4) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Neg/ITSCls4"), value); - } - if constexpr (N == 5) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Neg/ITSCls5"), value); - } - if constexpr (N == 6) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Neg/ITSCls6"), value); - } - if constexpr (N == 7) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Neg/ITSCls7"), value); - } - } - - template - void fillITSClsPos(HistogramRegistry& reg, float value) - { - if constexpr (N == 0) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Pos/ITSCls0"), value); - } - if constexpr (N == 1) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Pos/ITSCls1"), value); - } - if constexpr (N == 2) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Pos/ITSCls2"), value); - } - if constexpr (N == 3) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Pos/ITSCls3"), value); - } - if constexpr (N == 4) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Pos/ITSCls4"), value); - } - if constexpr (N == 5) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Pos/ITSCls5"), value); - } - if constexpr (N == 6) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Pos/ITSCls6"), value); - } - if constexpr (N == 7) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - reg.fill(HIST("ITSHits/Pos/ITSCls7"), value); - } - } - - template - void reconstructMesons(const TV0s& v0s) - { - for (auto i = 0; i < v0s.size(); i++) { - auto g1 = v0s.iteratorAt(i); - - for (auto j = i + 1; j < v0s.size(); j++) { - auto g2 = v0s.iteratorAt(j); - - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - registry.fill(HIST("Pi0/Same"), v12.M(), v12.Pt(), - g1.v0radius(), g2.v0radius()); - } - } - } - - void fillClusterNeg(HistogramRegistry& reg, int nCls, float value) - { - switch (nCls) { - case 0: // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillITSClsNeg<0>(reg, value); - break; - case 1: // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillITSClsNeg<1>(reg, value); - break; - case 2: // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillITSClsNeg<2>(reg, value); - break; - case 3: // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillITSClsNeg<3>(reg, value); - break; - case 4: // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillITSClsNeg<4>(reg, value); - break; - case 5: // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillITSClsNeg<5>(reg, value); - break; - case 6: // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillITSClsNeg<6>(reg, value); - break; - case 7: // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillITSClsNeg<7>(reg, value); - break; - default: - break; - } - } - - void fillClusterPos(HistogramRegistry& reg, int nCls, float value) - { - switch (nCls) { - case 0: - fillITSClsPos<0>(reg, value); - break; - case 1: - fillITSClsPos<1>(reg, value); - break; - case 2: - fillITSClsPos<2>(reg, value); - break; - case 3: - fillITSClsPos<3>(reg, value); - break; - case 4: - fillITSClsPos<4>(reg, value); - break; - case 5: - fillITSClsPos<5>(reg, value); - break; - case 6: - fillITSClsPos<6>(reg, value); - break; - case 7: - fillITSClsPos<7>(reg, value); - break; - default: - break; - } - } - template - void fillEventInfo(TCollision const& collision, const float /*weight*/ = 1.f) - { - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 2.0); - } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 3.0); - } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 4.0); - } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 5.0); - } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 6.0); - } - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 7.0); - } - if (collision.sel8()) { - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 8.0); - } - if (std::fabs(collision.posZ()) < 10.0) { // o2-linter: disable=magic-number (vertex position) - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 9.0); - } - - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hZvtx"), collision.posZ()); - - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hMultNTracksPV"), collision.multNTracksPV()); - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C()); - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCentFT0A"), collision.centFT0A()); - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCentFT0C"), collision.centFT0C()); - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCentFT0M"), collision.centFT0M()); - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCentFT0MvsMultNTracksPV"), collision.centFT0M(), collision.multNTracksPV()); - registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hMultFT0MvsMultNTracksPV"), collision.multFT0A() + collision.multFT0C(), collision.multNTracksPV()); - } - template - void reconstructMesonsMixed(const TV0s& current, - const std::deque>& pool) - { - for (const auto& prev : pool) { - for (const auto& g1 : current) { - if (!fV0PhotonCut.IsSelected(g1)) { - continue; - } - for (const auto& g2 : prev) { - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); - ROOT::Math::PtEtaPhiMVector v2(g2.pt, g2.eta, g2.phi, 0.); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - - registry.fill(HIST("Pi0/Mix"), v12.M(), v12.Pt(), - g1.v0radius(), g2.r); - } - } - } - } - - template - void reconstructDalitz(const TV0s& v0s, - const TPositrons& positronsPerCollision, - const TElectrons& electronsPerCollision, - MyCollision const& collision) - { - - for (const auto& g1 : v0s) { - if (!fV0PhotonCut.IsSelected(g1)) { - continue; - } - ROOT::Math::PtEtaPhiMVector vGamma(g1.pt(), g1.eta(), g1.phi(), 0.); - - for (const auto& [pos, ele] : - combinations(CombinationsFullIndexPolicy(positronsPerCollision, - electronsPerCollision))) { - - if (pos.trackId() == ele.trackId()) { - continue; - } - - if (!fDileptonCut.template IsSelectedTrack(pos, collision) || - !fDileptonCut.template IsSelectedTrack(ele, collision)) { - continue; // Track-Cuts - } - - ROOT::Math::PtEtaPhiMVector vPos(pos.pt(), pos.eta(), pos.phi(), - o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector vEle(ele.pt(), ele.eta(), ele.phi(), - o2::constants::physics::MassElectron); - - auto vee = vPos + vEle; - auto veGamma = vGamma + vee; - - registry.fill(HIST("Dalitz/Same"), - veGamma.M(), vee.Pt(), - g1.v0radius()); - } - } - } - - SliceCache cache; - Preslice perCollision = aod::v0photonkf::pmeventId; - Preslice perCollisionElectron = aod::emprimaryelectronda::pmeventId; - - Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; - Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; - - Filter prefilterPrimaryelectron = ifnode(dileptoncuts.cfgApplyCutsFromPrefilterDerived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); - - void processRec(MyCollisions const& collisions, - MyV0Photons const& v0photons, - aod::V0Legs const&, - MyPrimaryElectrons const& electrons) - { - - for (const auto& collision : collisions) { - const std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - fillEventInfo<0>(collision); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - fillEventInfo<1>(collision); - registry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - registry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted - - auto v0sThisCollision = v0photons.sliceBy(perCollision, collision.globalIndex()); - - for (const auto& v0 : v0sThisCollision) { - - if (!fV0PhotonCut.IsSelected(v0)) { - continue; - } - - auto negLeg = v0.template negTrack_as(); - auto posLeg = v0.template posTrack_as(); - - int nClsNeg = 0; - int nClsPos = 0; - - if constexpr (requires { negLeg.itsNCls(); }) { - nClsNeg = negLeg.itsNCls(); - nClsPos = posLeg.itsNCls(); - } else if constexpr (requires { negLeg.itsClusterMap(); }) { - auto countBits = [](uint8_t map) { - return std::bitset<8>(map).count(); - }; - nClsNeg = countBits(negLeg.itsClusterMap()); - nClsPos = countBits(posLeg.itsClusterMap()); - } - if (nClsNeg >= 0 && nClsNeg <= 7) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillClusterNeg(registry, nClsNeg, v0.v0radius()); - } - if (nClsPos >= 0 && nClsPos <= 7) { // o2-linter: disable=magic-number (just numbers for ITS cluster) - fillClusterPos(registry, nClsPos, v0.v0radius()); - } - - if (cfgPlotMBGeneral) { - - registry.fill( - HIST("MBGeneral"), - v0.vz(), // 0 - v0.v0radius(), // 1 - v0.eta(), // 2 - v0.phi(), // 3 - v0.pt()); // 4 - } - - if (cfgPlotMBDetailed) { - - registry.fill( - HIST("MBStudiesWireLeft"), - v0.vx(), // 0 - v0.vy(), // 1 - v0.vz(), // 2 - v0.phi(), // 3 - v0.v0radius(), // 4 - v0.pt()); // 5 - - registry.fill( - HIST("MBStudiesWireRight"), - v0.vx(), // 0 - v0.vy(), // 1 - v0.vz(), // 2 - v0.phi(), // 3 - v0.v0radius(), // 4 - v0.pt()); // 5 - - registry.fill( - HIST("MBStudiesWireITS"), - v0.vx(), // 0 - v0.vy(), // 1 - v0.vz(), // 2 - v0.phi(), // 3 - v0.v0radius(), // 4 - v0.pt()); // 5 - - registry.fill( - HIST("MBStudiesMFT"), - v0.vx(), // 0 - v0.vy(), // 1 - v0.vz(), // 2 - v0.phi(), // 3 - v0.v0radius(), // 4 - v0.pt()); // 5 - - registry.fill( - HIST("MBStudiesTPC"), - v0.vx(), // 0 - v0.vy(), // 1 - v0.vz(), // 2 - v0.phi(), // 3 - v0.v0radius(), // 4 - v0.pt()); // 5 - } - } - - reconstructMesons(v0sThisCollision); - - auto electronsPerCollision = electrons.sliceBy(perCollisionElectron, collision.globalIndex()); - auto positronsPerCollision = positrons.sliceBy(perCollisionElectron, collision.globalIndex()); - - reconstructDalitz(v0sThisCollision, positronsPerCollision, electronsPerCollision, collision); - - auto key = getPoolBin(centralities[cfgCentEstimator], collision.posZ()); - auto& pool = mixingPools[key]; - reconstructMesonsMixed(v0sThisCollision, pool); - - std::vector eventCopy; - eventCopy.reserve(v0sThisCollision.size()); - for (const auto& v0 : v0sThisCollision) { - if (!fV0PhotonCut.IsSelected(v0)) { - continue; - } - eventCopy.push_back({v0.pt(), v0.eta(), v0.phi(), v0.vz(), v0.v0radius()}); - } - pool.emplace_back(std::move(eventCopy)); - - if (pool.size() > MaxMixEvents) { - pool.pop_front(); - } - } - } - - int classifyPurity(int pdgNeg, int pdgPos) - { - if (pdgNeg == kElectron && pdgPos == kPositron) { - return 1; - } - if (pdgNeg == kElectron && pdgPos == kPiPlus) { - return 2; - } - if (pdgNeg == kPiMinus && pdgPos == kPositron) { - return 3; - } - if (pdgNeg == kKMinus && pdgPos == kPositron) { - return 4; - } - if (pdgNeg == kElectron && pdgPos == kKPlus) { - return 5; - } - if (pdgNeg == kProtonBar && pdgPos == kProton) { - return 6; - } - if (pdgNeg == kKMinus && pdgPos == kKPlus) { - return 7; - } - if (pdgNeg == kPiMinus && pdgPos == kProton) { - return 8; - } - if (pdgNeg == kProtonBar && pdgPos == kPiPlus) { - return 9; - } - if (pdgNeg == kMuonMinus && pdgPos == kMuonPlus) { - return 10; - } - return 11; - } - - Partition groupedCollisions = cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax; // this goes to same event. - Filter collisionFilterCommon = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > static_cast(0) && o2::aod::evsel::sel8 == true; // o2-linter: disable=magic-number (vertex position) - Filter collisionFilterCentrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - using MyFilteredCollisions = soa::Filtered; // this goes to same event pairing. - - void processTrue(MyCollisions const&, MyFilteredCollisions const& filteredCollisions, - MyV0Photons const& v0photons, - MyMCV0Legs const&, - aod::EMMCParticles const& mcparticles, - aod::EMMCEvents const&) - { - for (const auto& collision : filteredCollisions) { - - const std::array centralities = { - collision.centFT0M(), - collision.centFT0A(), - collision.centFT0C()}; - - if (centralities[cfgCentEstimator] < cfgCentMin || - cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - fillEventInfo<0>(collision); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - - fillEventInfo<1>(collision); - - registry.fill(HIST("Event/before/hCollisionCounter"), 10.0); - registry.fill(HIST("Event/after/hCollisionCounter"), 10.0); - - auto v0PhotonsColl = v0photons.sliceBy(perCollision, collision.globalIndex()); - - for (const auto& v0 : v0PhotonsColl) { - - auto pos = v0.posTrack_as(); - auto ele = v0.negTrack_as(); - - auto posmc = pos.template emmcparticle_as(); - auto elemc = ele.template emmcparticle_as(); - - if (!fV0PhotonCut.IsSelected(v0)) { - continue; - } - - int purityCat = 12; // default: unmatched - - purityCat = classifyPurity(elemc.pdgCode(), posmc.pdgCode()); - - float rConv = v0.v0radius(); - registry.fill(HIST("PhotonPurity"), - v0.pt(), rConv, v0.eta(), v0.phi(), purityCat); - - int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); - if (photonid < 0) { - continue; - } - - auto mcphoton = mcparticles.iteratorAt(photonid); - - float rRec = v0.v0radius(); - float rGen = std::sqrt(mcphoton.vx() * mcphoton.vx() + - mcphoton.vy() * mcphoton.vy()); - float deltaR = rRec - rGen; - float deltaZ = v0.vz() - mcphoton.vz(); - float deltaPhi = v0.phi() - mcphoton.phi(); - float deltaEta = v0.eta() - mcphoton.eta(); - float deltaPt = v0.pt() - mcphoton.pt(); - - registry.fill(HIST("ResolutionGen/Z_res"), - mcphoton.vz(), rGen, mcphoton.phi(), - mcphoton.eta(), mcphoton.pt(), deltaZ); - - registry.fill(HIST("ResolutionGen/R_res"), - mcphoton.vz(), rGen, mcphoton.phi(), - mcphoton.eta(), mcphoton.pt(), deltaR); - - registry.fill(HIST("ResolutionGen/Phi_res"), - mcphoton.vz(), rGen, mcphoton.phi(), - mcphoton.eta(), mcphoton.pt(), deltaPhi); - - registry.fill(HIST("ResolutionGen/Eta_res"), - mcphoton.vz(), rGen, mcphoton.phi(), - mcphoton.eta(), mcphoton.pt(), deltaEta); - - registry.fill(HIST("ResolutionGen/Pt_res"), - mcphoton.vz(), rGen, mcphoton.phi(), - mcphoton.eta(), mcphoton.pt(), - deltaPt / mcphoton.pt()); - - registry.fill(HIST("ResolutionRec/Z_res"), - v0.vz(), rRec, v0.phi(), v0.eta(), - v0.pt(), deltaZ); - - registry.fill(HIST("ResolutionRec/R_res"), - v0.vz(), rRec, v0.phi(), v0.eta(), - v0.pt(), deltaR); - - registry.fill(HIST("ResolutionRec/Phi_res"), - v0.vz(), rRec, v0.phi(), v0.eta(), - v0.pt(), deltaPhi); - - registry.fill(HIST("ResolutionRec/Eta_res"), - v0.vz(), rRec, v0.phi(), v0.eta(), - v0.pt(), deltaEta); - - registry.fill(HIST("ResolutionRec/Pt_res"), - v0.vz(), rRec, v0.phi(), v0.eta(), - v0.pt(), deltaPt / mcphoton.pt()); - } - } - } - - void processCollAssoc(MyCollisionsMC const& collisions, - MyMCCollisions const&, - aod::EMMCParticles const& mcparticles, - MyV0Photons const& v0photons, - MyMCV0Legs const&) - { - for (auto const& col : collisions) { - - auto mccollision = col.emmcevent_as(); - - auto v0s = v0photons.sliceBy(perCollision, col.globalIndex()); - - int mcColIdDerived = mccollision.globalIndex(); // MC event (derived) global index - - for (auto const& v0 : v0s) { - - if (!fV0PhotonCut.IsSelected(v0)) { - continue; - } - - auto negLeg = v0.negTrack_as(); - auto posLeg = v0.posTrack_as(); - - auto negMC = negLeg.template emmcparticle_as(); - auto posMC = posLeg.template emmcparticle_as(); - - // find the photon mother in MC - int photonId = FindCommonMotherFrom2Prongs(posMC, negMC, -11, 11, 22, mcparticles); - if (photonId < 0) { - continue; - } - - auto mcPhoton = mcparticles.iteratorAt(photonId); - auto trueMcCol = mcPhoton.emmcevent_as(); // MC event where the photon was generated - int trueMcColIndex = trueMcCol.globalIndex(); - - int deltaCol = mcColIdDerived - trueMcColIndex; - - float rRec = v0.v0radius(); - float rGen = std::sqrt(mcPhoton.vx() * mcPhoton.vx() + mcPhoton.vy() * mcPhoton.vy()); - float deltaR = rRec - rGen; - float deltaZ = v0.vz() - mcPhoton.vz(); - float deltaPt = v0.pt() - mcPhoton.pt(); - float relPtRes = (mcPhoton.pt() > 0.f) ? deltaPt / mcPhoton.pt() : 0.f; - - // Fill base debug - registry.fill(HIST("DeltaRecDerived"), deltaCol); - registry.fill(HIST("AllR"), rRec); - - if (deltaCol == 0) { - registry.fill(HIST("RightCollisions/SparseDeltaCol"), - rRec, - v0.pt(), - relPtRes, - deltaZ, - deltaR, - deltaCol); - } else { - registry.fill(HIST("WrongCollisions/SparseDeltaCol"), - rRec, - v0.pt(), - relPtRes, - deltaZ, - deltaR, - deltaCol); - } - - if (deltaCol == 0) { - registry.fill(HIST("RightCollisions/DeltaColvsZ"), v0.vz()); - registry.fill(HIST("RightCollisions/DeltaColvsR"), rRec); - registry.fill(HIST("RightCollisions/DeltaColvspT"), v0.pt()); - registry.fill(HIST("RightCollisions/DeltaColvsZRes"), deltaZ); - registry.fill(HIST("RightCollisions/DeltaColvsRRes"), deltaR); - registry.fill(HIST("RightCollisions/DeltaColvspTRes"), relPtRes); - } else { - registry.fill(HIST("WrongCollisions/DeltaColvsZ"), v0.vz()); - registry.fill(HIST("WrongCollisions/DeltaColvsR"), rRec); - registry.fill(HIST("WrongCollisions/DeltaColvspT"), v0.pt()); - registry.fill(HIST("WrongCollisions/DeltaColvsZRes"), deltaZ); - registry.fill(HIST("WrongCollisions/DeltaColvsRRes"), deltaR); - registry.fill(HIST("WrongCollisions/DeltaColvspTRes"), relPtRes); - } - } - } - } - - void processBremsstrahlung(MyTracks const& tracks, aod::McParticles const& mcparticles) - { - - for (const auto& trk : tracks) { - if (!trk.has_mcParticle()) { - continue; - } - auto mc = trk.mcParticle(); - if (std::abs(mc.pdgCode()) != kElectron) { - continue; - } - - if (trk.pt() < dileptoncuts.cfgMinPtTrack) { - continue; - } - - double pMC = mc.p(); - double ptMC = mc.pt(); - double phiMC = mc.phi(); - double etaMC = mc.eta(); - - double pReco = trk.p(); - double ptReco = trk.pt(); - double phiReco = trk.phi(); - double etaReco = trk.eta(); - - int nBrem = 0; // o2-linter: disable=magic-number - - registry.fill(HIST("Bremsstrahlung/relativeResoPtWOBrems"), trk.pt(), trk.pt() * std::sqrt(trk.c1Pt21Pt2())); - - for (const auto& dId : mc.daughtersIds()) { - if (dId < 0 || dId >= mcparticles.size()) { - continue; - } - auto daughter = mcparticles.iteratorAt(dId); - if (daughter.getProcess() != kPBrem) { - continue; - } - - if (std::abs(daughter.eta()) > pcmcuts.cfgMaxEtaV0) { - continue; - } - - double r = std::hypot(daughter.vx(), daughter.vy()); - double z = daughter.vz(); - - nBrem++; - - registry.fill(HIST("Bremsstrahlung/EnergyLossVsR"), r, daughter.e()); - registry.fill(HIST("Bremsstrahlung/EnergyLossVsZ"), z, daughter.e()); - registry.fill(HIST("Bremsstrahlung/EnergyLossXY"), daughter.vx(), daughter.vy()); - registry.fill(HIST("Bremsstrahlung/EnergyLossXYWeigh"), daughter.vx(), daughter.vy(), daughter.e()); - - registry.fill(HIST("Bremsstrahlung/relativeResoPtWBrems"), trk.pt(), trk.pt() * std::sqrt(trk.c1Pt21Pt2())); - - registry.fill(HIST("Bremsstrahlung/Sigma1PtVsR"), r, trk.sigma1Pt()); - - registry.fill(HIST("Bremsstrahlung/SigmaYVsR"), r, trk.sigmaY()); - registry.fill(HIST("Bremsstrahlung/SigmaZVsR"), r, trk.sigmaZ()); - - if (pMC > 0) { - registry.fill(HIST("Bremsstrahlung/DeltaPoverPvsR"), r, (pReco - pMC) / pMC); - } - if (ptMC > 0) { - registry.fill(HIST("Bremsstrahlung/DeltaPtvsR"), r, (ptReco - ptMC) / ptMC); - } - registry.fill(HIST("Bremsstrahlung/DeltaPhivsR"), r, phiReco - phiMC); - registry.fill(HIST("Bremsstrahlung/DeltaEtavsR"), r, etaReco - etaMC); - } - - registry.fill(HIST("Bremsstrahlung/NBrem"), nBrem); - } - } - - PROCESS_SWITCH(MaterialBudget, processRec, "process material budget", true); - PROCESS_SWITCH(MaterialBudget, processTrue, "process material budget", false); - PROCESS_SWITCH(MaterialBudget, processCollAssoc, "process material budget", false); - PROCESS_SWITCH(MaterialBudget, processBremsstrahlung, "process material budget", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& context) -{ - return WorkflowSpec{ - adaptAnalysisTask(context)}; -} diff --git a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx b/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx deleted file mode 100644 index 4db16a9e817..00000000000 --- a/PWGEM/PhotonMeson/Tasks/MaterialBudgetMC.cxx +++ /dev/null @@ -1,456 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file MaterialBudgetMC.cxx -/// \brief Task to analyse and calculate the material budget weights in MC -/// \author D. Sekihata: daiki.sekihata@cern, S. Mrozinski: smrozins@cern.ch - -#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" -#include "PWGEM/PhotonMeson/Core/PairCut.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/DataModel/EventTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" - -#include "Common/Core/RecoDecay.h" -// -#include "PWGEM/Dilepton/Utils/MCUtilities.h" - -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" - -#include -#include -#include -#include -#include -#include -#include - -#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace o2; -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::photonmeson::photonpair; -using namespace o2::aod::pwgem::photonmeson::utils::mcutil; -using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using namespace o2::aod::pwgem::photon; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyV0Photons = soa::Join; -using MyV0Photon = MyV0Photons::iterator; - -using MyMCV0Legs = soa::Join; -using MyMCV0Leg = MyMCV0Legs::iterator; - -struct MaterialBudgetMC { - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; - - Configurable maxY{"maxY", 0.9, "maximum rapidity for generated particles"}; - Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; - Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; - Configurable fConfigTagCuts{"cfgTagCuts", "qc", "Comma separated list of V0 photon cuts for tag"}; - Configurable fConfigProbeCuts{"cfgProbeCuts", "qc,wwire_ib", "Comma separated list of V0 photon cuts for probe"}; - Configurable fConfigPairCuts{"cfgPairCuts", "nocut", "Comma separated list of pair cuts"}; - - Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon - EMPhotonEventCut fEMEventCut; - static constexpr std::array event_types = {"before", "after"}; - - OutputObj fOutputEvent{"Event"}; - OutputObj fOutputV0{"V0"}; - OutputObj fOutputPair{"Pair"}; // 2-photon pair - OutputObj fOutputGen{"Generated"}; - THashList* fMainList = new THashList(); - - std::vector fTagCuts; - std::vector fProbeCuts; - std::vector fPairCuts; - - std::vector fPairNames; - void init(InitContext& context) - { - if (context.mOptions.get("processMBMC")) { - fPairNames.push_back("PCMPCM"); - } - - DefineTagCuts(); - DefineProbeCuts(); - DefinePairCuts(); - addhistograms(); - TString ev_cut_name = fConfigEMEventCut.value; - fEMEventCut = *eventcuts::GetCut(ev_cut_name.Data()); - - fOutputEvent.setObject(dynamic_cast(fMainList->FindObject("Event"))); - fOutputV0.setObject(dynamic_cast(fMainList->FindObject("V0"))); - fOutputPair.setObject(dynamic_cast(fMainList->FindObject("Pair"))); - fOutputGen.setObject(dynamic_cast(fMainList->FindObject("Generated"))); - } - - template - void add_pair_histograms(THashList* list_pair, std::string const& pairname, TCuts1 const& tagcuts, TCuts2 const& probecuts, TCuts3 const& cuts3) - { - for (const auto& tagcut : tagcuts) { - for (const auto& probecut : probecuts) { - std::string const& cutname1 = tagcut.getName(); - std::string const& cutname2 = probecut.getName(); - - auto* list_pair_subsys = dynamic_cast(list_pair->FindObject(pairname.data())); - std::string photon_cut_name = cutname1; - photon_cut_name.append("_").append(cutname2); - o2::aod::pwgem::photon::histogram::AddHistClass(list_pair_subsys, photon_cut_name.data()); - auto* list_pair_subsys_photoncut = dynamic_cast(list_pair_subsys->FindObject(photon_cut_name.data())); - - for (const auto& cut3 : cuts3) { - std::string const& pair_cut_name = cut3.getName(); - o2::aod::pwgem::photon::histogram::AddHistClass(list_pair_subsys_photoncut, pair_cut_name.data()); - auto* list_pair_subsys_paircut = dynamic_cast(list_pair_subsys_photoncut->FindObject(pair_cut_name.data())); - o2::aod::pwgem::photon::histogram::DefineHistograms(list_pair_subsys_paircut, "material_budget_study", "Pair"); - } // end of cut3 loop pair cut - } // end of probecut loop - } // end of tagcut loop - } - - static constexpr std::array pairnames = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PCMDalitzEE", "PCMDalitzMuMu", "PHOSEMC", "DalitzEEDalitzEE"}; - void addhistograms() - { - fMainList->SetOwner(true); - fMainList->SetName("fMainList"); - - // create sub lists first. - o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Event"); - auto* list_ev = dynamic_cast(fMainList->FindObject("Event")); - - o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Pair"); - auto* list_pair = dynamic_cast(fMainList->FindObject("Pair")); - - o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "V0"); - auto* list_v0 = dynamic_cast(fMainList->FindObject("V0")); - - // for V0s - for (const auto& cut : fProbeCuts) { - std::string cutname = cut.getName(); - THashList* list_v0_cut = o2::aod::pwgem::photon::histogram::AddHistClass(list_v0, cutname.c_str()); - o2::aod::pwgem::photon::histogram::DefineHistograms(list_v0_cut, "material_budget_study", "V0"); - } - - for (const auto& pairname : fPairNames) { - LOGF(info, "Enabled pairs = %s", pairname.data()); - - THashList* list_ev_pair = o2::aod::pwgem::photon::histogram::AddHistClass(list_ev, pairname.data()); - for (const auto& evtype : event_types) { - THashList* list_ev_type = o2::aod::pwgem::photon::histogram::AddHistClass(list_ev_pair, evtype.data()); - o2::aod::pwgem::photon::histogram::DefineHistograms(list_ev_type, "Event", evtype.data()); - } - - o2::aod::pwgem::photon::histogram::AddHistClass(list_pair, pairname.data()); - - if (pairname == "PCMPCM") { - add_pair_histograms(list_pair, pairname, fTagCuts, fProbeCuts, fPairCuts); - } - - } // end of pair name loop - - o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Generated"); - auto* list_gen = dynamic_cast(fMainList->FindObject("Generated")); - o2::aod::pwgem::photon::histogram::DefineHistograms(list_gen, "Generated", ""); - } - - void DefineTagCuts() - { - if (fConfigTagCuts.value.empty()) { - return; - } - - std::string_view namesView(fConfigTagCuts.value); - - for (auto name : namesView | std::views::split(',')) { - std::string cutString(name.begin(), name.end()); - const char* cutname = cutString.c_str(); - LOGF(info, "add tag cut : %s", cutname); - fTagCuts.push_back(*pcmcuts::GetCut(cutname)); - } - LOGF(info, "Number of Tag PCM cuts = %d", fTagCuts.size()); - } - - void DefineProbeCuts() - { - if (fConfigProbeCuts.value.empty()) { - return; - } - - std::string_view namesView(fConfigProbeCuts.value); - - for (auto name : namesView | std::views::split(',')) { - std::string cutString(name.begin(), name.end()); - const char* cutname = cutString.c_str(); - LOGF(info, "add probe cut : %s", cutname); - fProbeCuts.push_back(*pcmcuts::GetCut(cutname)); - } - LOGF(info, "Number of Probe PCM cuts = %d", fProbeCuts.size()); - } - - void DefinePairCuts() - { - if (fConfigPairCuts.value.empty()) { - return; - } - - std::string_view namesView(fConfigPairCuts.value); - - for (auto name : namesView | std::views::split(',')) { - std::string cutString(name.begin(), name.end()); - const char* cutname = cutString.c_str(); - LOGF(info, "add pair cut : %s", cutname); - fPairCuts.push_back(*paircuts::GetCut(cutname)); - } - LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); - } - - Preslice perCollision_pcm = aod::v0photonkf::pmeventId; - - template - bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& tagcut, TCut2 const& probecut) - { - return o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, tagcut, probecut); - } - - template - void fillsinglephoton(TEvents const& collisions, TPhotons const& photons, TPreslice const& perCollision, TCuts const& cuts, TLegs const& /*legs*/, TMCParticles const& mcparticles, TMCEvents const&) - { - auto* list_ev_pair_before = dynamic_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[0].data())); - auto* list_ev_pair_after = dynamic_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[1].data())); - auto* list_v0 = dynamic_cast(fMainList->FindObject("V0")); - std::array value = {0.f}; - for (const auto& collision : collisions) { - std::array centralities{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - o2::aod::pwgem::photon::histogram::FillHistClass(list_ev_pair_before, "", collision); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - o2::aod::pwgem::photon::histogram::FillHistClass(list_ev_pair_after, "", collision); - dynamic_cast(list_ev_pair_before->FindObject("hCollisionCounter"))->Fill("accepted", 1.f); - dynamic_cast(list_ev_pair_after->FindObject("hCollisionCounter"))->Fill("accepted", 1.f); - - auto photons_coll = photons.sliceBy(perCollision, collision.globalIndex()); - for (const auto& cut : cuts) { - for (const auto& photon : photons_coll) { - - if (!cut.template IsSelected(photon)) { - continue; - } - - auto pos = photon.template posTrack_as(); - auto ele = photon.template negTrack_as(); - auto posmc = pos.template emmcparticle_as(); - auto elemc = ele.template emmcparticle_as(); - int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); - if (photonid < 0) { - continue; - } - auto mcphoton = mcparticles.iteratorAt(photonid); - if (!(mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator())) { - continue; - } - if (!IsConversionPointInAcceptance(mcphoton, maxRgen, maxY, margin_z_mc, mcparticles)) { - continue; - } - - float phi_cp = std::atan2(photon.vy(), photon.vx()); - float eta_cp = std::atanh(photon.vz() / std::sqrt(std::pow(photon.vx(), 2) + std::pow(photon.vy(), 2) + std::pow(photon.vz(), 2))); - value[0] = photon.pt(); - value[1] = photon.v0radius(); - value[2] = RecoDecay::constrainAngle(phi_cp); - value[3] = eta_cp; - dynamic_cast(list_v0->FindObject(cut.getName().c_str())->FindObject("hs_conv_point"))->Fill(value.data()); - - } // end of photon loop - } // end of cut loop - - } // end of collision loop - } - - template - void TruePairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& tagcuts, TCuts2 const& probecuts, TPairCuts const& paircuts, TLegs const& /*legs*/, TMCParticles const& mcparticles, TMCEvents const&) - { - auto* list_pair_ss = dynamic_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); - - for (const auto& collision : collisions) { - std::array centralities{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - - auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); - auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); - - std::array value{0.}; - float phi_cp2 = 0.f, eta_cp2 = 0.f; - for (const auto& tagcut : tagcuts) { - for (const auto& probecut : probecuts) { - for (const auto& g1 : photons1_coll) { - for (const auto& g2 : photons2_coll) { - if (g1.globalIndex() == g2.globalIndex()) { - continue; - } - if (!IsSelectedPair(g1, g2, tagcut, probecut)) { - continue; - } - - for (const auto& paircut : paircuts) { - if (!paircut.IsSelected(g1, g2)) { - continue; - } - - auto pos1 = g1.template posTrack_as(); - auto ele1 = g1.template negTrack_as(); - auto pos2 = g2.template posTrack_as(); - auto ele2 = g2.template negTrack_as(); - - auto pos1mc = pos1.template emmcparticle_as(); - auto ele1mc = ele1.template emmcparticle_as(); - auto pos2mc = pos2.template emmcparticle_as(); - auto ele2mc = ele2.template emmcparticle_as(); - // LOGF(info,"pos1mc.globalIndex() = %d , ele1mc.globalIndex() = %d , pos2mc.globalIndex() = %d , ele2mc.globalIndex() = %d", pos1mc.globalIndex(), ele1mc.globalIndex(), pos2mc.globalIndex(), ele2mc.globalIndex()); - - int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); - if (photonid1 < 0) { - continue; - } - int photonid2 = FindCommonMotherFrom2Prongs(pos2mc, ele2mc, -11, 11, 22, mcparticles); - if (photonid2 < 0) { - continue; - } - - auto g1mc = mcparticles.iteratorAt(photonid1); - auto g2mc = mcparticles.iteratorAt(photonid2); - - if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY, margin_z_mc, mcparticles)) { - continue; - } - if (!IsConversionPointInAcceptance(g2mc, maxRgen, maxY, margin_z_mc, mcparticles)) { - continue; - } - - int pi0id = FindCommonMotherFrom2Prongs(g1mc, g2mc, 22, 22, 111, mcparticles); - if (pi0id < 0) { - continue; - } - auto pi0mc = mcparticles.iteratorAt(pi0id); - if (!(pi0mc.isPhysicalPrimary() || pi0mc.producedByGenerator())) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // tag - ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // probe - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - phi_cp2 = std::atan2(g2.vy(), g2.vx()); - eta_cp2 = std::atanh(g2.vz() / std::sqrt(std::pow(g2.vx(), 2) + std::pow(g2.vy(), 2) + std::pow(g2.vz(), 2))); - value[0] = v12.M(); - value[1] = g1.pt(); - value[2] = g2.pt(); - value[3] = g2.v0radius(); - value[4] = RecoDecay::constrainAngle(phi_cp2); - value[5] = eta_cp2; - dynamic_cast(list_pair_ss->FindObject(Form("%s_%s", tagcut.getName().c_str(), probecut.getName().c_str()))->FindObject(paircut.getName().c_str())->FindObject("hs_conv_point_same"))->Fill(value.data()); - } // end of pair cut loop - } // end of g2 loop - } // end of g1 loop - } // end of probecut loop - } // end of tagcut loop - } // end of collision loop - } - - Partition grouped_collisions = cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax; // this goes to same event. - Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > static_cast(0) && o2::aod::evsel::sel8 == true; - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - using MyFilteredCollisions = soa::Filtered; // this goes to same event pairing. - - void processMBMC(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, MyMCV0Legs const& legs, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const& mccollisions) - { - fillsinglephoton(grouped_collisions, v0photons, perCollision_pcm, fProbeCuts, legs, mcparticles, mccollisions); - TruePairing(filtered_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fTagCuts, fProbeCuts, fPairCuts, legs, mcparticles, mccollisions); - } - - PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; - void processGen(MyCollisions const&, aod::EMMCEvents const&, aod::EMMCParticles const&) - { - // loop over mc stack and fill histograms for pure MC truth signals - // all MC tracks which belong to the MC event corresponding to the current reconstructed event - - for (const auto& collision : grouped_collisions) { - std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - auto mccollision = collision.emmcevent(); - // LOGF(info, "mccollision.globalIndex() = %d", mccollision.globalIndex()); - - dynamic_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(1.0); - dynamic_cast(fMainList->FindObject("Generated")->FindObject("hZvtx_before"))->Fill(mccollision.posZ()); - if (!collision.sel8()) { - continue; - } - dynamic_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(2.0); - - if (collision.numContrib() < 0.5) { - continue; - } - dynamic_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(3.0); - - if (std::abs(collision.posZ()) > 10.0) { - continue; - } - dynamic_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(4.0); - dynamic_cast(fMainList->FindObject("Generated")->FindObject("hZvtx_after"))->Fill(mccollision.posZ()); - } // end of collision loop - } - - void processDummy(MyCollisions::iterator const&) {} - - PROCESS_SWITCH(MaterialBudgetMC, processMBMC, "process material budget", false); - PROCESS_SWITCH(MaterialBudgetMC, processGen, "process generated information", false); - PROCESS_SWITCH(MaterialBudgetMC, processDummy, "Dummy function", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& context) -{ - return WorkflowSpec{ - adaptAnalysisTask(context, TaskName{"material-budget-mc"})}; -} diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index 1b161a8976a..c65849eae3d 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -9,15 +9,38 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file MaterialBudget.cxx -/// \brief This code runs loop over v0 photons for PCM QC. -/// \author Daiki Sekihata, daiki.sekihata@cern.ch +/// \file pcmQC.cxx +/// \brief Quality, purity, material and reconstruction monitoring of the selected V0 photon candidates +/// +/// - processQC: kinematics, conversion-point and leg-track QA of the +/// reconstructed photons. Material-budget configurables +/// add conversion-point maps, restricted to selectable +/// detector regions for material studies. +/// - processQCML: the same QC with the ML-based photon selection (BDT +/// models from CCDB) instead of the classical V0 cuts +/// - processPCMQCMC: MC-truth of the QC observables for the purity +/// assessment, plus resolution assessment. +/// Configurables activate collision-association studies +/// and the same regional material-budget mode as in +/// processQC, there with per-region resolution on top. +/// - processPCMQCMCML: the same MC QC with the ML-based photon selection +/// - processGen: generator-level distributions as the denominator +/// reference (requires the binned generated-pT derived +/// data as input). +/// - processRecoQA: runs on AO2Ds, before any skimming: track-level QA +/// plus a truth-based check of the SVertexer candidate +/// building and deduplication, separating genuine +/// reconstruction quality from reconstruction artifacts. +/// +/// \author Daiki Sekihata and Stefanie Mrozinski +#include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" #include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" #include "PWGEM/PhotonMeson/DataModel/EventTables.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/Centrality.h" @@ -41,12 +64,16 @@ #include #include +#include +#include #include #include #include #include #include +#include +#include #include using namespace o2; @@ -55,6 +82,8 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::aod::pwgem::photon; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; @@ -65,6 +94,19 @@ using MyV0Photon = MyV0Photons::iterator; using MyV0PhotonsML = soa::Join; using MyV0PhotonML = MyV0PhotonsML::iterator; +// MC Joins +using MyCollisionsMC = soa::Join; +using MyCollisionMC = MyCollisionsMC::iterator; + +using MyMCCollisions = soa::Join; +using MyMCCollision = MyMCCollisions::iterator; + +using MyMCV0Legs = soa::Join; +using MyMCV0Leg = MyMCV0Legs::iterator; + +// AO2D level (processRecoQA): tracks before any skimming, with their MC labels +using MyTracksMC = soa::Join; + struct PCMQC { Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; @@ -98,61 +140,112 @@ struct PCMQC { } eventcuts; V0PhotonCut fV0PhotonCut; + // v0 photon cuts + struct : ConfigurableGroup { + std::string prefix = "v0cut_group"; + Configurable cfgRequireV0WithITSTPC{"cfgRequireV0WithITSTPC", false, "flag to select V0s with ITS-TPC matched tracks"}; + Configurable cfgRequireV0WithITSonly{"cfgRequireV0WithITSonly", false, "flag to select V0s with ITSonly tracks"}; + Configurable cfgRequireV0WithTPConly{"cfgRequireV0WithTPConly", false, "flag to select V0s with TPConly tracks"}; + Configurable cfgMinPtV0{"cfgMinPtV0", 0.1, "min pT for v0 photons at PV"}; + Configurable cfgMaxPtV0{"cfgMaxPtV0", 1e+10, "max pT for v0 photons at PV"}; + Configurable cfgMinEtaV0{"cfgMinEtaV0", -0.8, "min eta for v0 photons at PV"}; + Configurable cfgMaxEtaV0{"cfgMaxEtaV0", +0.8, "max eta for v0 photons at PV"}; + Configurable cfgMinV0Radius{"cfgMinV0Radius", 4.0, "min v0 radius"}; + Configurable cfgMaxV0Radius{"cfgMaxV0Radius", 90.0, "max v0 radius"}; + Configurable cfgMidLV0Radius{"cfgMidLV0Radius", -1.0, "middle low v0 radius for rejection if >0"}; + Configurable cfgMidHV0Radius{"cfgMidHV0Radius", -1.0, "middle high v0 radius for rejection if >0"}; + Configurable cfgMaxAlphaAP{"cfgMaxAlphaAP", 0.95, "max alpha for AP cut"}; + Configurable cfgMaxQtAP{"cfgMaxQtAP", 0.01, "max qT for AP cut"}; + Configurable cfgMinV0CosPA{"cfgMinV0CosPA", 0.999, "min V0 CosPA"}; + Configurable cfgMaxPCA{"cfgMaxPCA", 1.5, "max distance btween 2 legs"}; + Configurable cfgMaxChi2KF{"cfgMaxChi2KF", 1e+10, "max chi2/ndf with KF"}; + Configurable cfgRejectV0OnITSib{"cfgRejectV0OnITSib", true, "flag to reject V0s on ITSib"}; + } v0cuts; + + // single track cuts + struct : ConfigurableGroup { + std::string prefix = "trackcut_group"; + Configurable cfgMinNClustersTPC{"cfgMinNClustersTPC", 0, "min ncluster tpc"}; + Configurable cfgMinNCrossedRows{"cfgMinNCrossedRows", 40, "min crossed rows"}; + Configurable cfgMaxFracSharedClustersTPC{"cfgMaxFracSharedClustersTPC", 999.f, "max fraction of shared clusters in TPC"}; + Configurable cfgMaxChi2TPC{"cfgMaxChi2TPC", 4.0, "max chi2/NclsTPC"}; + Configurable cfgMaxChi2ITS{"cfgMaxChi2ITS", 36.0, "max chi2/NclsITS"}; + Configurable cfgMinTPCNsigmaEl{"cfgMinTPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; + Configurable cfgMaxTPCNsigmaEl{"cfgMaxTPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; + Configurable cfgDisableITSonlyTracks{"cfgDisableITSonlyTracks", false, "disable ITSonly tracks in V0 legs"}; + Configurable cfgDisableTPConlyTracks{"cfgDisableTPConlyTracks", false, "disable TPConly tracks in V0 legs"}; + Configurable cfgDoDEdxPostCalibration{"cfgDoDEdxPostCalibration", false, "flag to enable dEdx post calibration"}; + } trackcuts; + + // pT-dependent loss QA + struct : ConfigurableGroup { + std::string prefix = "qaSettings_group"; + Configurable cfgDoPtDependentLossQA{"cfgDoPtDependentLossQA", false, "fill the cut variables vs. pT before AND after the V0 selection - the after/before ratio shows which candidates the cuts remove"}; + } qaSettingsGroup; + + // PCM ML inference + struct : ConfigurableGroup { + std::string prefix = "mlcut_group"; + Configurable cfgApplyPCMMl{"cfgApplyPCMMl", false, "Flag to apply ML selections"}; + Configurable cfgUse2DBinning{"cfgUse2DBinning", false, "Flag to enable/disable 2D binning for ML application"}; + Configurable cfgLoadModelsFromCCDB{"cfgLoadModelsFromCCDB", true, "Flag to enable or disable the loading of models from CCDB"}; + Configurable cfgTimestampCCDB{"cfgTimestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"}; + Configurable cfgNClassesPCMMl{"cfgNClassesPCMMl", static_cast(o2::analysis::em_cuts_ml::NCutScores), "Number of classes in ML model"}; + Configurable> cfgCutDirPCMMl{"cfgCutDirPCMMl", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cfgNamesInputFeatures{"cfgNamesInputFeatures", std::vector{"feature1", "feature2"}, "Names of ML model input features"}; + Configurable> cfgModelPathsCCDB{"cfgModelPathsCCDB", std::vector{"path_ccdb/BDT_PCM/"}, "Paths of models on CCDB"}; + Configurable> cfgOnnxFileNames{"cfgOnnxFileNames", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable> cfgLabelsBinsPCMMl{"cfgLabelsBinsPCMMl", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + Configurable> cfgLabelsCutScoresPCMMl{"cfgLabelsCutScoresPCMMl", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + Configurable> cfgBinsPtPCMMl{"cfgBinsPtPCMMl", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + Configurable> cfgBinsCentPCMMl{"cfgBinsCentPCMMl", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "Centrality bin limits for ML application"}; + Configurable> cfgCutsPCMMlFlat{"cfgCutsPCMMlFlat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; + } mlcuts; + + struct : ConfigurableGroup { + std::string prefix = "mcAnalysisModeSettings_group"; + Configurable cfgDoDetailedResolution{"cfgDoDetailedResolution", false, "purpose of the configurable is to choose if we have more THnSparses included in order to see if some regions have better or worse resolution"}; + Configurable cfgDoCollisionAssociationQA{"cfgDoCollisionAssociationQA", false, "include the QA Plots which give an idea how photon distribution changes with different subclasses or what the effect of wrong collision association is"}; + Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association for the truth-classified QC observables"}; + } mcAnalysisModeSettings; + struct : ConfigurableGroup { - std::string prefix = "pcmcut_group"; - Configurable cfg_require_v0_with_itstpc{"cfg_require_v0_with_itstpc", false, "flag to select V0s with ITS-TPC matched tracks"}; - Configurable cfg_require_v0_with_itsonly{"cfg_require_v0_with_itsonly", false, "flag to select V0s with ITSonly tracks"}; - Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; - Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT for v0 photons at PV"}; - Configurable cfg_min_eta_v0{"cfg_min_eta_v0", -0.8, "min eta for v0 photons at PV"}; - Configurable cfg_max_eta_v0{"cfg_max_eta_v0", +0.8, "max eta for v0 photons at PV"}; - Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; - Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; - Configurable cfg_midL_v0radius{"cfg_midL_v0radius", -1.0, "middle low v0 radius for rejection if >0"}; - Configurable cfg_midH_v0radius{"cfg_midH_v0radius", -1.0, "middle high v0 radius for rejection if >0"}; - Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; - Configurable cfg_max_qt_ap{"cfg_max_qt_ap", 0.01, "max qT for AP cut"}; - Configurable cfg_min_cospa{"cfg_min_cospa", 0.999, "min V0 CosPA"}; - Configurable cfg_max_pca{"cfg_max_pca", 1.5, "max distance btween 2 legs"}; - Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; - Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; - Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; - Configurable cfg_dEdx_postcalibration{"cfg_dEdx_postcalibration", false, "flag to enable dEdx post calibration"}; - // for ML cuts - Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; - Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; - Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; - Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; - Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; - Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; - Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; - Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; - Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; - Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; - Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; - Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; - Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; - Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; - } pcmcuts; + std::string prefix = "materialBudgetSettings_group"; + Configurable cfgDoMaterialDistribution{"cfgDoMaterialDistribution", false, "add THnSparses of the conversion-point distribution for the material budget study"}; + Configurable cfgDoWiresDetail{"cfgDoWiresDetail", false, "add detailed conversion-point histograms around the wire region"}; + Configurable cfgDoMFTDetail{"cfgDoMFTDetail", false, "add detailed conversion-point histograms around the MFT region"}; + Configurable cfgDoITSDetail{"cfgDoITSDetail", false, "add detailed conversion-point histograms around the ITS layers"}; + Configurable cfgDoTPCInnerBarrelDetail{"cfgDoTPCInnerBarrelDetail", false, "add detailed conversion-point histograms around the TPC inner barrel"}; + } materialBudgetSettingsGroup; + + struct : ConfigurableGroup { + std::string prefix = "genSettings_group"; + Configurable cfgMaxRGen{"cfgMaxRGen", 90.f, "maximum conversion radius for generated photons (fiducial cut, matches the reco acceptance)"}; + Configurable cfgMarginZMC{"cfgMarginZMC", 7.0, "margin for z cut in cm for MC"}; + } genSettingsGroup; + + struct : ConfigurableGroup { + std::string prefix = "recoQASettings_group"; + Configurable cfgDoDetailedTrackQA{"cfgDoDetailedTrackQA", false, "add track-quality histograms of surviving vs. lost conversion legs"}; + Configurable cfgRMinGen{"cfgRMinGen", 1.f, "min true conversion radius (cm)"}; + Configurable cfgRMaxGen{"cfgRMaxGen", 90.f, "max true conversion radius (cm)"}; + Configurable cfgLegEtaMax{"cfgLegEtaMax", 0.9f, "max |eta| of true MC legs"}; + Configurable cfgPhotonEtaMax{"cfgPhotonEtaMax", 0.9f, "max |eta| of true MC photon"}; + Configurable cfgPhotonPtMin{"cfgPhotonPtMin", 0.1f, "min pT of true MC photon"}; + } recoQASettingsGroup; o2::ccdb::CcdbApi ccdbApi; o2::framework::Service ccdb{}; int mRunNumber = 0; float d_bz = 0; static constexpr std::array event_types = {"before/", "after/"}; + static constexpr std::array mcphoton_types = {"primary/", "fromWD/", "fromHS/", "fromPi0Dalitz/", "fromEtaDalitz/"}; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - void init(InitContext&) + void init(InitContext& context) { + + (void)context; addhistograms(); DefineEMEventCut(); DefinePCMCut(); @@ -245,6 +338,11 @@ struct PCMQC { fRegistry.add("V0/hDCAxyz", "DCA to PV;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -5.f, +5.f}, {200, -5.f, +5.f}}, false); fRegistry.add("V0/hDCAz_Pt", "DCA_{z} to PV vs. p_{T};DCA_{z} (cm);p_{T} (GeV/c)", kTH2F, {{200, -5.f, +5.f}, {2000, 0.0f, 20}}, false); fRegistry.add("V0/hAPplot", "AP plot;#alpha;q_{T} (GeV/c)", kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}, false); + fRegistry.add("V0/hRxyVsPt", "conversion radius vs. pT;p_{T,#gamma} (GeV/c);R_{xy} (cm)", kTH2F, {{100, 0, 10}, {200, 0, 100}}, false); + fRegistry.add("V0/hEtaVsPt", "#eta vs. pT;p_{T,#gamma} (GeV/c);#eta", kTH2F, {{100, 0, 10}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("V0/hPhiVsPt", "#varphi vs. pT;p_{T,#gamma} (GeV/c);#varphi (rad.)", kTH2F, {{100, 0, 10}, {90, 0, o2::constants::math::TwoPI}}, false); + fRegistry.add("V0/hsAlphaQtPt", "Armenteros vs. pT;#alpha;q_{T} (GeV/c);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{100, -1.0f, +1.0f}, {125, 0.0f, 0.25f}, {100, 0, 10}}, false); + fRegistry.add("V0/hPsiPairVsPt", "#psi_{pair} vs. pT;p_{T,#gamma} (GeV/c);#psi_{pair} (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5f, +0.5f}}, false); fRegistry.add("V0/hMassGamma", "hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.0f, 0.1f}}, false); fRegistry.add("V0/hKFChi2vsM", "KF chi2 vs. m_{ee};m_{ee} (GeV/c^{2});KF chi2/NDF", kTH2F, {{100, 0.0f, 0.1f}, {100, 0.f, 100.0f}}, false); fRegistry.add("V0/hKFChi2vsR", "KF chi2 vs. conversion point in XY;R_{xy} (cm);KF chi2/NDF", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.f, 100.0f}}, false); @@ -254,12 +352,12 @@ struct PCMQC { fRegistry.add("V0/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); fRegistry.add("V0/hNgamma", "Number of #gamma candidates per collision", kTH1F, {{101, -0.5f, 100.5f}}); - if (pcmcuts.cfg_apply_ml_cuts) { - if (pcmcuts.cfg_nclasses_ml == 2) { + if (mlcuts.cfgApplyPCMMl) { + if (mlcuts.cfgNClassesPCMMl == 2) { fRegistry.add("V0/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); fRegistry.add("V0/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); fRegistry.add("V0/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); - } else if (pcmcuts.cfg_nclasses_ml == 3) { + } else if (mlcuts.cfgNClassesPCMMl == 3) { fRegistry.add("V0/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); fRegistry.add("V0/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); fRegistry.add("V0/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); @@ -281,6 +379,7 @@ struct PCMQC { fRegistry.add("V0Leg/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("V0Leg/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("V0Leg/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("V0Leg/hTPCNsigmaElVsEta", "TPC n sigma el vs. eta;#eta;n #sigma_{e}^{TPC}", kTH2F, {{40, -1.0f, 1.0f}, {100, -5, +5}}, false); // eta-dependence = dE/dx calibration check (TOF/ITS n#sigma not stored in the V0Leg skim) fRegistry.add("V0Leg/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("V0Leg/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("V0Leg/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); @@ -288,13 +387,194 @@ struct PCMQC { fRegistry.add("V0Leg/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("V0Leg/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); fRegistry.add("V0Leg/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); - if (pcmcuts.cfg_dEdx_postcalibration) { + if (trackcuts.cfgDoDEdxPostCalibration) { fRegistry.add("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Pos", "momentum of pos leg vs. conversion point of V0 vs. TPC n sigma pos vs. eta of pos leg; p (GeV/c); r_{xy} (cm); n #sigma_{e}^{TPC}; #eta", kTHnSparseF, {{200, 0, 20}, {100, 0, 100}, {500, -5, 5}, {200, -1, +1}}, false); fRegistry.add("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Ele", "momentum of neg leg vs. conversion point of V0 vs. TPC n sigma el vs. eta of neg leg; p (GeV/c); r_{xy} (cm); n #sigma_{e}^{TPC}; #eta", kTHnSparseF, {{200, 0, 20}, {100, 0, 100}, {500, -5, 5}, {200, -1, +1}}, false); } - // fRegistry.add("V0Leg/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {80, -20, 20}}, false); - // fRegistry.add("V0Leg/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); - // fRegistry.add("V0Leg/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {80, -20, 20}}, false); + + if (materialBudgetSettingsGroup.cfgDoMaterialDistribution) { + fRegistry.add("MaterialBudget/hs", "conversion point;z (cm);r_{xy} (cm);#eta;#varphi (rad.);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{200, -100, 100}, {100, 0, 100}, {80, -2, +2}, {90, 0, o2::constants::math::TwoPI}, {100, 0, 10}}, false); + } + if (materialBudgetSettingsGroup.cfgDoWiresDetail) { + fRegistry.add("MaterialBudget/Wires/hsLeft", "conversion point near left wire;x (cm);y (cm);z (cm);#varphi (rad.);r_{xy} (cm);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{200, -20, 20}, {200, -20, 20}, {80, -20, 20}, {40, 3.15, 3.4}, {80, 0, 20}, {100, 0, 10}}, false); + fRegistry.add("MaterialBudget/Wires/hsRight", "conversion point near right wire;x (cm);y (cm);z (cm);#varphi (rad.);r_{xy} (cm);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{200, -20, 20}, {200, -20, 20}, {80, -20, 20}, {40, 6.00, 6.15}, {80, 0, 20}, {100, 0, 10}}, false); + } + if (materialBudgetSettingsGroup.cfgDoITSDetail) { + fRegistry.add("MaterialBudget/ITS/hs", "conversion point around the ITS layers;x (cm);y (cm);z (cm);#varphi (rad.);r_{xy} (cm);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{160, -40, 40}, {160, -40, 40}, {80, -40, 40}, {90, 0, o2::constants::math::TwoPI}, {150, 0, 60}, {100, 0, 10}}, false); + } + if (materialBudgetSettingsGroup.cfgDoMFTDetail) { + fRegistry.add("MaterialBudget/MFT/hs", "conversion point around the MFT region;x (cm);y (cm);z (cm);#varphi (rad.);r_{xy} (cm);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{160, -80, 80}, {160, -80, 80}, {40, -40, 40}, {90, 0, o2::constants::math::TwoPI}, {40, 40, 60}, {100, 0, 10}}, false); + } + if (materialBudgetSettingsGroup.cfgDoTPCInnerBarrelDetail) { + fRegistry.add("MaterialBudget/TPC/hs", "conversion point around the TPC inner barrel;x (cm);y (cm);z (cm);#varphi (rad.);r_{xy} (cm);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{160, -90, 90}, {160, -90, 90}, {80, -40, 40}, {90, 0, o2::constants::math::TwoPI}, {80, 60, 80}, {100, 0, 10}}, false); + } + + if (doprocessGen) { + std::vector ptbins; + ptbins.reserve(72); + for (int i = 0; i < 2; i++) { + ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.05 GeV/c, every 0.05 GeV/c + } + for (int i = 2; i < 51; i++) { + ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 4.9 GeV/c, every 0.1 GeV/c + } + for (int i = 51; i < 61; i++) { + ptbins.emplace_back(0.5 * (i - 51) + 5.0); // from 5 to 9.5 GeV/c, every 0.5 GeV/c + } + for (int i = 61; i < 72; i++) { + ptbins.emplace_back(1.0 * (i - 61) + 10.0); // from 10 to 20 GeV/c, every 1 GeV/c + } + const AxisSpec axisPtGen{ptbins, "p_{T,#gamma} (GeV/c)"}; + const AxisSpec axisRapidityGen{{0.0, +0.8, +0.9}, "rapidity |y_{#gamma}|"}; + + fRegistry.add("Generated/hPt", "pT;p_{T} (GeV/c)", kTH1D, {axisPtGen}, true); + fRegistry.add("Generated/hPtY", "Generated info", kTH2D, {axisPtGen, axisRapidityGen}, true); + fRegistry.add("Generated/hPt_ConversionPhoton", "converted photon pT;p_{T} (GeV/c)", kTH1D, {axisPtGen}, true); + fRegistry.add("Generated/hY_ConversionPhoton", "converted photon y;rapidity y", kTH1F, {{40, -2.0f, 2.0f}}, true); + fRegistry.add("Generated/hPhi_ConversionPhoton", "converted photon #varphi;#varphi (rad.)", kTH1F, {{180, 0, o2::constants::math::TwoPI}}, true); + fRegistry.add("Generated/hXY", "conversion point in XY MC;V_{x} (cm);V_{y} (cm)", kTH2F, {{800, -100.0f, 100.0f}, {800, -100.0f, 100.0f}}, true); + fRegistry.add("Generated/hRZ", "conversion point in RZ MC;V_{z} (cm);R_{xy} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, 0.f, 100.0f}}, true); + fRegistry.add("Generated/hRPhi", "conversion point of #varphi vs. R_{xy} MC;#varphi (rad.);R_{xy} (cm);N_{e}", kTH2F, {{360, 0.0f, o2::constants::math::TwoPI}, {400, 0, 100}}, true); + fRegistry.add("Generated/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, true); + fRegistry.add("Generated/hR_ConversionPhoton_wideR", "converted photon R_{xy} up to the EMCal, before fiducial cuts;R_{xy} (cm);N_{#gamma}", kTH1F, {{250, 0.0f, 500.0f}}, true); + fRegistry.add("Generated/hRZ_wideR", "conversion point in RZ up to the EMCal, before fiducial cuts;V_{z} (cm);R_{xy} (cm)", kTH2F, {{200, -400.0f, 400.0f}, {250, 0.0f, 500.0f}}, true); + if (mcAnalysisModeSettings.cfgDoDetailedResolution) { + fRegistry.add("Generated/hPtEtaPhi", "Photon pt vs eta, and phi;p_{T, gen} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + } + } + + if (doprocessPCMQCMC || doprocessPCMQCMCML) { + fRegistry.add("V0/primary/hPt", "pT;p_{T,#gamma} (GeV/c)", kTH1F, {{2000, 0.0f, 20}}, false); + fRegistry.add("V0/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, o2::constants::math::TwoPI}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("V0/primary/hXY", "conversion point in XY;V_{x} (cm);V_{y} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, -100.0f, 100.0f}}, false); + fRegistry.add("V0/primary/hRZ", "conversion point in RZ;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100, 100}, {200, 0.0f, 100.0f}}, false); + fRegistry.add("V0/primary/hCosPA", "V0CosPA;cosine pointing angle in 3D", kTH1F, {{100, 0.99f, 1.0f}}, false); + fRegistry.add("V0/primary/hCosPAXY", "V0CosPA;cosine pointing angle in XY", kTH1F, {{100, 0.99f, 1.0f}}, false); + fRegistry.add("V0/primary/hCosPARZ", "V0CosPA;cosine pointing angle in RZ", kTH1F, {{100, 0.99f, 1.0f}}, false); + fRegistry.add("V0/primary/hPCA", "distance between 2 legs;PCA (cm)", kTH1F, {{500, 0.0f, 5.0f}}, false); + fRegistry.add("V0/primary/hDCAxyz", "DCA to PV;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -5.f, +5.f}, {200, -5.f, +5.f}}, false); + fRegistry.add("V0/primary/hDCAz_Pt", "DCA_{z} to PV vs. p_{T};DCA_{z} (cm);p_{T} (GeV/c)", kTH2F, {{200, -5.f, +5.f}, {2000, 0.0f, 20}}, false); + fRegistry.add("V0/primary/hAPplot", "AP plot;#alpha;q_{T} (GeV/c)", kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}, false); + fRegistry.add("V0/primary/hRxyVsPt", "conversion radius vs. pT;p_{T,#gamma} (GeV/c);R_{xy} (cm)", kTH2F, {{100, 0, 10}, {200, 0, 100}}, false); + fRegistry.add("V0/primary/hEtaVsPt", "#eta vs. pT;p_{T,#gamma} (GeV/c);#eta", kTH2F, {{100, 0, 10}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("V0/primary/hPhiVsPt", "#varphi vs. pT;p_{T,#gamma} (GeV/c);#varphi (rad.)", kTH2F, {{100, 0, 10}, {90, 0, o2::constants::math::TwoPI}}, false); + fRegistry.add("V0/primary/hsAlphaQtPt", "Armenteros vs. pT;#alpha;q_{T} (GeV/c);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{100, -1.0f, +1.0f}, {125, 0.0f, 0.25f}, {100, 0, 10}}, false); + if (doprocessPCMQCMCML) { + fRegistry.add("V0/primary/hPsiPairVsPt", "#psi_{pair} vs. pT;p_{T,#gamma} (GeV/c);#psi_{pair} (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5f, +0.5f}}, false); + } + fRegistry.add("V0/primary/hMassGamma", "hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.0f, 0.1f}}, false); + fRegistry.add("V0/primary/hKFChi2vsM", "KF chi2 vs. m_{ee};m_{ee} (GeV/c^{2});KF chi2/NDF", kTH2F, {{100, 0.0f, 0.1f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsR", "KF chi2 vs. conversion point in XY;R_{xy} (cm);KF chi2/NDF", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsX", "KF chi2 vs. conversion point in X;X (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsY", "KF chi2 vs. conversion point in Y;Y (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsZ", "KF chi2 vs. conversion point in Z;Z (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hNgamma", "Number of true #gamma per collision;N_{#gamma} per event;Number of events", kTH1F, {{101, -0.5f, 100.5f}}); + fRegistry.add("V0/primary/hConvPoint_diffX", "conversion point diff X MC;X_{MC} (cm);X_{rec} - X_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hConvPoint_diffY", "conversion point diff Y MC;Y_{MC} (cm);Y_{rec} - Y_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hConvPoint_diffZ", "conversion point diff Z MC;Z_{MC} (cm);Z_{rec} - Z_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaPtOverPtGen", "photon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 20}, {199, -0.099, 0.099}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{200, 0, 20}, {199, -0.099, 0.099}}, true); + fRegistry.add("V0/primary/hRxyGen_DeltaPtOverPtGen", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("V0/primary/hRxyGen_DeltaEta", "photon #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0/primary/hRxyGen_DeltaPhi", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0/primary/hRxyGen_DeltaR", "photon R_{xy} resolution;R_{xy}^{gen} (cm);R_{xy}^{rec} - R_{xy}^{gen} (cm)", kTH2F, {{100, 0, 100}, {100, 0, 100}}, true); + fRegistry.add("V0/primary/hXY_MC", "X vs. Y of true photon conversion point.;X (cm);Y (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, +100}}, true); + fRegistry.add("V0/primary/hRZ_MC", "R vs. Z of true photon conversion point;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); + fRegistry.add("V0/primary/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); + if (mcAnalysisModeSettings.cfgDoDetailedResolution) { + fRegistry.add("V0/primary/hEtaPhiResol", "Photon eta-phi resolution;p_{T} (GeV/c);#eta-diff;#phi-diff", kTH3F, {{200, 0., 20.}, {99, -0.049, 0.049}, {99, -0.049, 0.049}}, false); + fRegistry.add("V0/primary/hPtResolPtEtaPhi", "Photon resolution vs. pt, eta, and phi;p_{T_rec} - p_{T true} / p_{T true};p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{199, -0.995, 0.995}, {200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + fRegistry.add("V0/primary/hMomResolPtEtaPhi", "Photon momentum resolution vs. p, eta, and phi;p_{rec} - p_{true} / p_{true};p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{199, -0.995, 0.995}, {200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + fRegistry.add("V0/primary/hPtEtaPhi", "pt, eta, and phi;p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + } + if (mlcuts.cfgApplyPCMMl) { + if (mlcuts.cfgNClassesPCMMl == 2) { + fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + } else if (mlcuts.cfgNClassesPCMMl == 3) { + fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + } else { + fRegistry.add("V0/primary/hBDTScoreVsPt", "BDT score vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + } + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } + fRegistry.addClone("V0/primary/", "V0/fromWD/"); // from weak decay + fRegistry.addClone("V0/primary/", "V0/fromHS/"); // from hadronic shower in detector materials + fRegistry.addClone("V0/primary/", "V0/fromPi0Dalitz/"); // misidentified dielectron from pi0 dalitz decay + fRegistry.addClone("V0/primary/", "V0/fromEtaDalitz/"); // misidentified dielectron from eta dalitz decay + fRegistry.addClone("V0/primary/hPt", "V0/candidate/hPt"); // only for purity + fRegistry.addClone("V0/primary/hEtaPhi", "V0/candidate/hEtaPhi"); // only for purity + + fRegistry.add("V0Leg/primary/hPt", "pT;p_{T,e} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("V0Leg/primary/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -50, 50}}, false); + fRegistry.add("V0Leg/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, o2::constants::math::TwoPI}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("V0Leg/primary/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -50.0f, 50.0f}, {200, -50.0f, 50.0f}}, false); + fRegistry.add("V0Leg/primary/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("V0Leg/primary/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("V0Leg/primary/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("V0Leg/primary/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("V0Leg/primary/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("V0Leg/primary/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("V0Leg/primary/hTPCNsigmaElVsEta", "TPC n sigma el vs. eta;#eta;n #sigma_{e}^{TPC}", kTH2F, {{40, -1.0f, 1.0f}, {100, -5, +5}}, false); + fRegistry.add("V0Leg/primary/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("V0Leg/primary/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("V0Leg/primary/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("V0Leg/primary/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("V0Leg/primary/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("V0Leg/primary/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("V0Leg/primary/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); + fRegistry.add("V0Leg/primary/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("V0Leg/primary/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0Leg/primary/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0Leg/primary/hRxyGen_DeltaPtOverPtGen", "electron p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("V0Leg/primary/hRxyGen_DeltaEta", "electron #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0Leg/primary/hRxyGen_DeltaPhi", "electron #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromWD/"); + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromHS/"); + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromPi0Dalitz/"); + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromEtaDalitz/"); + fRegistry.addClone("V0Leg/primary/hPt", "V0Leg/candidate/hPt"); // only for purity + fRegistry.addClone("V0Leg/primary/hEtaPhi", "V0Leg/candidate/hEtaPhi"); // only for purity + + // collision-association QA: + if (mcAnalysisModeSettings.cfgDoCollisionAssociationQA) { + fRegistry.add("CollisionAssociation/hDeltaCollId", "MC-event index difference;#Delta coll ID (rec - true);N_{#gamma}", kTH1F, {{21, -10.5, 10.5}}, true); + fRegistry.add("CollisionAssociation/RightCollisions/hs", "correctly associated;R_{rec} (cm);p_{T} (GeV/c);#Delta p_{T}/p_{T,gen};#Delta z (cm);#Delta R (cm);#Delta coll ID", kTHnSparseF, {{100, 0, 100}, {200, 0, 10}, {200, -1, 1}, {200, -20, 20}, {200, -8, 8}, {21, -10.5, 10.5}}, true); + fRegistry.add("CollisionAssociation/WrongCollisions/hs", "wrongly associated;R_{rec} (cm);p_{T} (GeV/c);#Delta p_{T}/p_{T,gen};#Delta z (cm);#Delta R (cm);#Delta coll ID", kTHnSparseF, {{100, 0, 100}, {200, 0, 10}, {200, -1, 1}, {200, -20, 20}, {200, -8, 8}, {21, -10.5, 10.5}}, true); + } + } + + // pT-dependent loss QA: + if (qaSettingsGroup.cfgDoPtDependentLossQA) { + fRegistry.add("V0/LossQA/before/hCosPAvsPt", "cosPA vs. pT;p_{T,#gamma} (GeV/c);cosine pointing angle", kTH2F, {{100, 0, 10}, {100, 0.99, 1.0}}, false); + fRegistry.add("V0/LossQA/before/hPCAvsPt", "PCA vs. pT;p_{T,#gamma} (GeV/c);PCA (cm)", kTH2F, {{100, 0, 10}, {500, 0, 5}}, false); + fRegistry.add("V0/LossQA/before/hQtAPvsPt", "AP q_{T} vs. pT;p_{T,#gamma} (GeV/c);q_{T} (GeV/c)", kTH2F, {{100, 0, 10}, {250, 0, 0.25}}, false); + fRegistry.add("V0/LossQA/before/hRxyVsPt", "conversion radius vs. pT;p_{T,#gamma} (GeV/c);R_{xy} (cm)", kTH2F, {{100, 0, 10}, {200, 0, 100}}, false); + fRegistry.add("V0/LossQA/before/hMeeVsPt", "m_{ee} vs. pT;p_{T,#gamma} (GeV/c);m_{ee} (GeV/c^{2})", kTH2F, {{100, 0, 10}, {100, 0, 0.1}}, false); + fRegistry.addClone("V0/LossQA/before/", "V0/LossQA/after/"); + } + + if (doprocessRecoQA) { + fRegistry.add("RecoQA/0_converted/hs", "true converted photons;p_{T,#gamma} (GeV/c);#eta;#varphi (rad.);R_{conv}^{true} (cm)", kTHnSparseF, {{100, 0, 10}, {36, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}, {100, 0, 100}}, true); + fRegistry.addClone("RecoQA/0_converted/hs", "RecoQA/1_bothLegsTracked/hs"); + fRegistry.addClone("RecoQA/0_converted/hs", "RecoQA/2_bothLegsInV0Legs/hs"); + fRegistry.addClone("RecoQA/0_converted/hs", "RecoQA/3_photonInV0PhotonsKF/hs"); + fRegistry.add("RecoQA/hStageVsPt", "reconstruction stage vs. pT;p_{T,#gamma} (GeV/c);stage (0=converted,1=tracked,2=V0Legs,3=V0PhotonsKF)", kTH2F, {{100, 0, 10}, {4, -0.5, 3.5}}, true); + fRegistry.add("RecoQA/hMissingLeg_PtRconv", "legs tracked but lost before V0Legs;p_{T,leg}^{true} (GeV/c);R_{conv}^{true} (cm)", kTH2F, {{100, 0, 1}, {100, 0, 100}}, true); + fRegistry.add("RecoQA/Duplicates/hNTracksPerTrueLeg", "reconstructed tracks per true conversion leg;N_{tracks} per true leg;N_{legs}", kTH1F, {{6, -0.5, 5.5}}, true); + fRegistry.add("RecoQA/Duplicates/hNV0LegsPerTrueLeg", "V0Leg entries per true conversion leg;N_{V0Legs} per true leg;N_{legs}", kTH1F, {{6, -0.5, 5.5}}, true); + fRegistry.add("RecoQA/Duplicates/hNV0CandsPerPhoton_Rconv", "correctly built V0 candidates per true photon;N_{cand} per true #gamma;R_{conv}^{true} (cm)", kTH2F, {{6, -0.5, 5.5}, {100, 0, 100}}, true); + if (recoQASettingsGroup.cfgDoDetailedTrackQA) { + fRegistry.add("RecoQA/LegQuality/survived/hNcrTPC", "TPC crossed rows;TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, true); + fRegistry.add("RecoQA/LegQuality/survived/hChi2TPC", "chi2 per TPC cluster;#chi^{2}/N_{cls}^{TPC}", kTH1F, {{100, 0, 10}}, true); + fRegistry.add("RecoQA/LegQuality/survived/hSharedFracTPC", "TPC shared-cluster fraction;N_{cls}^{shared}/N_{cls}", kTH1F, {{110, 0, 1.1}}, true); + fRegistry.add("RecoQA/LegQuality/survived/hNclsTPC", "number of TPC clusters;N_{cls}^{TPC}", kTH1F, {{161, -0.5, 160.5}}, true); + fRegistry.addClone("RecoQA/LegQuality/survived/", "RecoQA/LegQuality/lost/"); + } + } } void DefineEMEventCut() @@ -320,52 +600,52 @@ struct PCMQC { fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); // for v0 - fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, pcmcuts.cfg_max_pt_v0); - fV0PhotonCut.SetV0EtaRange(pcmcuts.cfg_min_eta_v0, pcmcuts.cfg_max_eta_v0); - fV0PhotonCut.SetMinCosPA(pcmcuts.cfg_min_cospa); - fV0PhotonCut.SetMaxPCA(pcmcuts.cfg_max_pca); - fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfg_max_chi2kf); - fV0PhotonCut.SetRxyRange(pcmcuts.cfg_min_v0radius, pcmcuts.cfg_max_v0radius, pcmcuts.cfg_midL_v0radius, pcmcuts.cfg_midH_v0radius); - fV0PhotonCut.SetAPRange(pcmcuts.cfg_max_alpha_ap, pcmcuts.cfg_max_qt_ap); - fV0PhotonCut.RejectITSib(pcmcuts.cfg_reject_v0_on_itsib); + fV0PhotonCut.SetV0PtRange(v0cuts.cfgMinPtV0, v0cuts.cfgMaxPtV0); + fV0PhotonCut.SetV0EtaRange(v0cuts.cfgMinEtaV0, v0cuts.cfgMaxEtaV0); + fV0PhotonCut.SetMinCosPA(v0cuts.cfgMinV0CosPA); + fV0PhotonCut.SetMaxPCA(v0cuts.cfgMaxPCA); + fV0PhotonCut.SetMaxChi2KF(v0cuts.cfgMaxChi2KF); + fV0PhotonCut.SetRxyRange(v0cuts.cfgMinV0Radius, v0cuts.cfgMaxV0Radius, v0cuts.cfgMidLV0Radius, v0cuts.cfgMidHV0Radius); + fV0PhotonCut.SetAPRange(v0cuts.cfgMaxAlphaAP, v0cuts.cfgMaxQtAP); + fV0PhotonCut.RejectITSib(v0cuts.cfgRejectV0OnITSib); // for track - fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); - fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); + fV0PhotonCut.SetMinNClustersTPC(trackcuts.cfgMinNClustersTPC); + fV0PhotonCut.SetMinNCrossedRowsTPC(trackcuts.cfgMinNCrossedRows); fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfg_max_frac_shared_clusters_tpc); - fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfg_max_chi2tpc); - fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfg_min_TPCNsigmaEl, pcmcuts.cfg_max_TPCNsigmaEl); - fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); + fV0PhotonCut.SetMaxFracSharedClustersTPC(trackcuts.cfgMaxFracSharedClustersTPC); + fV0PhotonCut.SetChi2PerClusterTPC(0.0, trackcuts.cfgMaxChi2TPC); + fV0PhotonCut.SetTPCNsigmaElRange(trackcuts.cfgMinTPCNsigmaEl, trackcuts.cfgMaxTPCNsigmaEl); + fV0PhotonCut.SetChi2PerClusterITS(-1e+10, trackcuts.cfgMaxChi2ITS); fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); - fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); - fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); - fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); - fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); + fV0PhotonCut.SetDisableITSonly(trackcuts.cfgDisableITSonlyTracks); + fV0PhotonCut.SetDisableTPConly(trackcuts.cfgDisableTPConlyTracks); + fV0PhotonCut.SetRequireITSTPC(v0cuts.cfgRequireV0WithITSTPC); + fV0PhotonCut.SetRequireITSonly(v0cuts.cfgRequireV0WithITSonly); + fV0PhotonCut.SetRequireTPConly(v0cuts.cfgRequireV0WithTPConly); // for ML - fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); - fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); - fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); - fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); - fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); + fV0PhotonCut.SetApplyMlCuts(mlcuts.cfgApplyPCMMl); + fV0PhotonCut.SetUse2DBinning(mlcuts.cfgUse2DBinning); + fV0PhotonCut.SetLoadMlModelsFromCCDB(mlcuts.cfgLoadModelsFromCCDB); + fV0PhotonCut.SetNClassesMl(mlcuts.cfgNClassesPCMMl); + fV0PhotonCut.SetMlTimestampCCDB(mlcuts.cfgTimestampCCDB); fV0PhotonCut.SetCcdbUrl(ccdburl); auto mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); - fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); - fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); - fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); - fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); - fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); - fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); - fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); - fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); - fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); - fV0PhotonCut.SetD_Bz(0.0f); // dummy value -> only for psi_pair calculation - - if (pcmcuts.cfg_apply_ml_cuts) { + fV0PhotonCut.SetCutDirMl(mlcuts.cfgCutDirPCMMl); + fV0PhotonCut.SetMlModelPathsCCDB(mlcuts.cfgModelPathsCCDB); + fV0PhotonCut.SetMlOnnxFileNames(mlcuts.cfgOnnxFileNames); + fV0PhotonCut.SetBinsPtMl(mlcuts.cfgBinsPtPCMMl); + fV0PhotonCut.SetBinsCentMl(mlcuts.cfgBinsCentPCMMl); + fV0PhotonCut.SetCutsMl(mlcuts.cfgCutsPCMMlFlat); + fV0PhotonCut.SetNamesInputFeatures(mlcuts.cfgNamesInputFeatures); + fV0PhotonCut.SetLabelsBinsMl(mlcuts.cfgLabelsBinsPCMMl); + fV0PhotonCut.SetLabelsCutScoresMl(mlcuts.cfgLabelsCutScoresPCMMl); + fV0PhotonCut.SetD_Bz(0.0f); + + if (mlcuts.cfgApplyPCMMl) { fV0PhotonCut.initV0MlModels(ccdbApi); } } @@ -424,6 +704,11 @@ struct PCMQC { fRegistry.fill(HIST("V0/hDCAxyz"), v0.dcaXYtopv(), v0.dcaZtopv()); fRegistry.fill(HIST("V0/hDCAz_Pt"), v0.dcaZtopv(), v0.pt()); fRegistry.fill(HIST("V0/hAPplot"), v0.alpha(), v0.qtarm()); + fRegistry.fill(HIST("V0/hRxyVsPt"), v0.pt(), v0.v0radius()); + fRegistry.fill(HIST("V0/hEtaVsPt"), v0.pt(), v0.eta()); + fRegistry.fill(HIST("V0/hPhiVsPt"), v0.pt(), v0.phi()); + fRegistry.fill(HIST("V0/hsAlphaQtPt"), v0.alpha(), v0.qtarm(), v0.pt()); + fRegistry.fill(HIST("V0/hPsiPairVsPt"), v0.pt(), v0.psipair()); fRegistry.fill(HIST("V0/hMassGamma"), v0.v0radius(), v0.mGamma()); fRegistry.fill(HIST("V0/hKFChi2vsM"), v0.mGamma(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/hKFChi2vsR"), v0.v0radius(), v0.chiSquareNDF()); @@ -437,7 +722,7 @@ struct PCMQC { fRegistry.fill(HIST("V0/hsConvPoint"), v0.v0radius(), phi_cp, eta_cp); // BDT response histogram can be filled here when apply BDT is true - if (pcmcuts.cfg_apply_ml_cuts) { + if (mlcuts.cfgApplyPCMMl) { const std::span& bdtValue = fV0PhotonCut.getBDTValue(); float psipair = 999.f; float phiv = 999.f; @@ -446,15 +731,15 @@ struct PCMQC { phiv = v0.phiv(); } fRegistry.fill(HIST("V0/hPhiVPsi"), psipair, phiv); - if (pcmcuts.cfg_nclasses_ml == 2 && bdtValue.size() == 2) { + if (mlcuts.cfgNClassesPCMMl == 2 && bdtValue.size() == 2) { fRegistry.fill(HIST("V0/hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); fRegistry.fill(HIST("V0/hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); - } else if (pcmcuts.cfg_nclasses_ml == 3 && bdtValue.size() == 3) { + } else if (mlcuts.cfgNClassesPCMMl == 3 && bdtValue.size() == 3) { fRegistry.fill(HIST("V0/hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); fRegistry.fill(HIST("V0/hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); fRegistry.fill(HIST("V0/hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); } else if (bdtValue.size() == 1) { - fRegistry.fill(HIST("V0/hBDTCutVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/hBDTScoreVsPt"), v0.pt(), bdtValue[0]); } } } @@ -481,9 +766,44 @@ struct PCMQC { fRegistry.fill(HIST("V0Leg/hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal()); fRegistry.fill(HIST("V0Leg/hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); fRegistry.fill(HIST("V0Leg/hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi()); - // fRegistry.fill(HIST("V0Leg/hXY"), leg.x(), leg.y()); - // fRegistry.fill(HIST("V0Leg/hZX"), leg.z(), leg.x()); - // fRegistry.fill(HIST("V0Leg/hZY"), leg.z(), leg.y()); + fRegistry.fill(HIST("V0Leg/hTPCNsigmaElVsEta"), leg.eta(), leg.tpcNSigmaEl()); + } + + template + void fillLossQAInfo(TV0 const& v0) + { + if (!qaSettingsGroup.cfgDoPtDependentLossQA) { + return; + } + fRegistry.fill(HIST("V0/LossQA/") + HIST(event_types[ev_id]) + HIST("hCosPAvsPt"), v0.pt(), v0.cospa()); + fRegistry.fill(HIST("V0/LossQA/") + HIST(event_types[ev_id]) + HIST("hPCAvsPt"), v0.pt(), v0.pca()); + fRegistry.fill(HIST("V0/LossQA/") + HIST(event_types[ev_id]) + HIST("hQtAPvsPt"), v0.pt(), v0.qtarm()); + fRegistry.fill(HIST("V0/LossQA/") + HIST(event_types[ev_id]) + HIST("hRxyVsPt"), v0.pt(), v0.v0radius()); + fRegistry.fill(HIST("V0/LossQA/") + HIST(event_types[ev_id]) + HIST("hMeeVsPt"), v0.pt(), v0.mGamma()); + } + + template + void fillMaterialBudgetInfo(TV0 const& v0) + { + if (materialBudgetSettingsGroup.cfgDoMaterialDistribution) { + fRegistry.fill(HIST("MaterialBudget/hs"), v0.vz(), v0.v0radius(), v0.eta(), v0.phi(), v0.pt()); + } + if (materialBudgetSettingsGroup.cfgDoWiresDetail && v0.v0radius() < 20.f && std::fabs(v0.vz()) < 20.f) { // o2-linter: disable=magic-number (region window = booking range) + if (3.15f < v0.phi() && v0.phi() < 3.4f) { // o2-linter: disable=magic-number (region window = booking range) + fRegistry.fill(HIST("MaterialBudget/Wires/hsLeft"), v0.vx(), v0.vy(), v0.vz(), v0.phi(), v0.v0radius(), v0.pt()); + } else if (6.00f < v0.phi() && v0.phi() < 6.15f) { // o2-linter: disable=magic-number (region window = booking range) + fRegistry.fill(HIST("MaterialBudget/Wires/hsRight"), v0.vx(), v0.vy(), v0.vz(), v0.phi(), v0.v0radius(), v0.pt()); + } + } + if (materialBudgetSettingsGroup.cfgDoITSDetail && v0.v0radius() < 60.f && std::fabs(v0.vz()) < 40.f) { // o2-linter: disable=magic-number (region window = booking range) + fRegistry.fill(HIST("MaterialBudget/ITS/hs"), v0.vx(), v0.vy(), v0.vz(), v0.phi(), v0.v0radius(), v0.pt()); + } + if (materialBudgetSettingsGroup.cfgDoMFTDetail && 40.f < v0.v0radius() && v0.v0radius() < 60.f && std::fabs(v0.vz()) < 40.f) { // o2-linter: disable=magic-number (region window = booking range) + fRegistry.fill(HIST("MaterialBudget/MFT/hs"), v0.vx(), v0.vy(), v0.vz(), v0.phi(), v0.v0radius(), v0.pt()); + } + if (materialBudgetSettingsGroup.cfgDoTPCInnerBarrelDetail && 60.f < v0.v0radius() && v0.v0radius() < 80.f && std::fabs(v0.vz()) < 40.f) { // o2-linter: disable=magic-number (region window = booking range) + fRegistry.fill(HIST("MaterialBudget/TPC/hs"), v0.vx(), v0.vy(), v0.vz(), v0.phi(), v0.v0radius(), v0.pt()); + } } Preslice perCollisionV0 = aod::v0photonkf::pmeventId; @@ -492,6 +812,7 @@ struct PCMQC { Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; using FilteredMyCollisions = soa::Filtered; + using FilteredMyCollisionsMC = soa::Filtered; // same filters, they act column-wise template void process(FilteredMyCollisions const& collisions, TV0Photon const& v0photons, aod::V0Legs const&, TPerCollision const& perCollision) @@ -517,14 +838,17 @@ struct PCMQC { for (const auto& v0 : v0photons_coll) { auto pos = v0.template posTrack_as(); auto ele = v0.template negTrack_as(); + fillLossQAInfo<0>(v0); // all candidates offered to the selection if (!fV0PhotonCut.IsSelected(v0)) { continue; } + fillLossQAInfo<1>(v0); // survivors fillV0Info(v0); + fillMaterialBudgetInfo(v0); for (const auto& leg : {pos, ele}) { fillV0LegInfo(leg); } - if (pcmcuts.cfg_dEdx_postcalibration) { + if (trackcuts.cfgDoDEdxPostCalibration) { fRegistry.fill(HIST("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Pos"), pos.p(), v0.v0radius(), pos.tpcNSigmaEl(), pos.eta()); fRegistry.fill(HIST("V0Leg/hPvsConvPointvsTPCNsigmaElvsEta_Ele"), ele.p(), v0.v0radius(), ele.tpcNSigmaEl(), ele.eta()); } @@ -543,11 +867,511 @@ struct PCMQC { process(collisions, v0photonsML, v0legs, perCollisionV0ML); } // end of ML process - void processDummy(MyCollisions const&) {} + template + void fillV0InfoMC(TV0 const& v0, TMCV0 const& mcphoton, TMCLeg const& mcleg) + { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPt"), v0.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhi"), v0.phi(), v0.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hXY"), v0.vx(), v0.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRZ"), v0.vz(), v0.v0radius()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPA"), v0.cospa()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPAXY"), v0.cospaXY()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPARZ"), v0.cospaRZ()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPCA"), v0.pca()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hDCAxyz"), v0.dcaXYtopv(), v0.dcaZtopv()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hDCAz_Pt"), v0.dcaZtopv(), v0.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hAPplot"), v0.alpha(), v0.qtarm()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyVsPt"), v0.pt(), v0.v0radius()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaVsPt"), v0.pt(), v0.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiVsPt"), v0.pt(), v0.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hsAlphaQtPt"), v0.alpha(), v0.qtarm(), v0.pt()); + if constexpr (requires { v0.psipair(); }) { // only the ML join carries psi_pair + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPsiPairVsPt"), v0.pt(), v0.psipair()); + } + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMassGamma"), v0.v0radius(), v0.mGamma()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsM"), v0.mGamma(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsR"), v0.v0radius(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsX"), v0.vx(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsY"), v0.vy(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsZ"), v0.vz(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcphoton.pt(), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcphoton.pt(), v0.eta() - mcphoton.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcphoton.pt(), v0.phi() - mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPtOverPtGen"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.eta() - mcphoton.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.phi() - mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaR"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.v0radius() - std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffX"), mcleg.vx(), v0.vx() - mcleg.vx()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffY"), mcleg.vy(), v0.vy() - mcleg.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffZ"), mcleg.vz(), v0.vz() - mcleg.vz()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hXY_MC"), mcleg.vx(), mcleg.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRZ_MC"), mcleg.vz(), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); + + if (mcAnalysisModeSettings.cfgDoDetailedResolution) { + float resolPt = (v0.pt() - mcphoton.pt()) / mcphoton.pt(); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtResolPtEtaPhi"), resolPt, mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + float resolMom = (v0.p() - mcphoton.p()) / mcphoton.p(); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMomResolPtEtaPhi"), resolMom, mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtEtaPhi"), mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhiResol"), mcphoton.pt(), v0.eta() - mcphoton.eta(), v0.phi() - mcphoton.phi()); + } + + float phi_cp = std::atan2(v0.vy(), v0.vx()); + o2::math_utils::bringTo02Pi(phi_cp); + float eta_cp = std::atanh(v0.vz() / std::sqrt(std::pow(v0.vx(), 2) + std::pow(v0.vy(), 2) + std::pow(v0.vz(), 2))); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hsConvPoint"), v0.v0radius(), phi_cp, eta_cp); + + if (mlcuts.cfgApplyPCMMl) { + const std::span& bdtValue = fV0PhotonCut.getBDTValue(); + float psipair = 999.f; + float phiv = 999.f; + if constexpr (requires { v0.psipair(); v0.phiv(); }) { + psipair = v0.psipair(); + phiv = v0.phiv(); + } + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiVPsi"), psipair, phiv); + if (mlcuts.cfgNClassesPCMMl == 2 && bdtValue.size() == 2) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); + } else if (mlcuts.cfgNClassesPCMMl == 3 && bdtValue.size() == 3) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); + } else if (bdtValue.size() == 1) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTScoreVsPt"), v0.pt(), bdtValue[0]); + } + } + } + + template + void fillV0LegInfoMC(TLeg const& leg) + { + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPt"), leg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hQoverPt"), leg.sign() / leg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhi"), leg.phi(), leg.eta()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hDCAxyz"), leg.dcaXY(), leg.dcaZ()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNclsITS"), leg.itsNCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNclsTPC"), leg.tpcNClsFound()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNcrTPC"), leg.tpcNClsCrossedRows()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNcr2Nf"), leg.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNcls2Nf"), leg.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNclsShared"), leg.pt(), leg.tpcFractionSharedCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hChi2TPC"), leg.tpcChi2NCl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hChi2ITS"), leg.itsChi2NCl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hITSClusterMap"), leg.itsClusterMap()); + if (leg.hasITS()) { + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hMeanClusterSizeITS"), leg.p(), leg.meanClusterSizeITS() * std::cos(std::atan(leg.tgl()))); + } + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaElVsEta"), leg.eta(), leg.tpcNSigmaEl()); + auto mcleg = leg.template emmcparticle_as(); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcleg.pt(), (leg.pt() - mcleg.pt()) / mcleg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcleg.pt(), leg.eta() - mcleg.eta()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcleg.pt(), leg.phi() - mcleg.phi()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPtOverPtGen"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), (leg.pt() - mcleg.pt()) / mcleg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.eta() - mcleg.eta()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.phi() - mcleg.phi()); + } + + template + void processMC(FilteredMyCollisionsMC const& collisions, TV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, aod::EMMCEvents const&, TPerCollision const& percollision) + { + for (const auto& collision : collisions) { + initCCDB(collision); + const std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + fillEventInfo<0>(collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fillEventInfo<1>(collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted + + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); // set centrality for BDT response + auto v0photons_coll = v0photons.sliceBy(percollision, collision.globalIndex()); + int ng_primary = 0, ng_wd = 0, ng_hs = 0, nee_pi0 = 0, nee_eta = 0; + for (const auto& v0 : v0photons_coll) { + auto pos = v0.template posTrack_as(); + auto ele = v0.template negTrack_as(); + auto posmc = pos.template emmcparticle_as(); + auto elemc = ele.template emmcparticle_as(); + + fillLossQAInfo<0>(v0); // all candidates offered to the selection + if (!fV0PhotonCut.IsSelected(v0)) { + continue; + } + fillLossQAInfo<1>(v0); + + fillMaterialBudgetInfo(v0); + + fRegistry.fill(HIST("V0/candidate/hPt"), v0.pt()); + fRegistry.fill(HIST("V0/candidate/hEtaPhi"), v0.phi(), v0.eta()); + for (const auto& leg : {pos, ele}) { + fRegistry.fill(HIST("V0Leg/candidate/hPt"), leg.pt()); + fRegistry.fill(HIST("V0Leg/candidate/hEtaPhi"), leg.phi(), leg.eta()); + } + + int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); + int pi0id = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 111, mcparticles); // pi0 dalitz decay + int etaid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 221, mcparticles); // eta dalitz decay + if (photonid < 0 && pi0id < 0 && etaid < 0) { + continue; + } + + if (photonid > 0) { + auto mcphoton = mcparticles.iteratorAt(photonid); + + if (mcAnalysisModeSettings.cfgDoCollisionAssociationQA) { + const int deltaCol = static_cast(collision.emmceventId()) - static_cast(mcphoton.emmceventId()); + const float rGen = std::sqrt(std::pow(elemc.vx(), 2) + std::pow(elemc.vy(), 2)); + const float deltaR = v0.v0radius() - rGen; + const float deltaZ = v0.vz() - elemc.vz(); + const float relPtRes = mcphoton.pt() > 0.f ? (v0.pt() - mcphoton.pt()) / mcphoton.pt() : 0.f; + fRegistry.fill(HIST("CollisionAssociation/hDeltaCollId"), deltaCol); + if (deltaCol == 0) { + fRegistry.fill(HIST("CollisionAssociation/RightCollisions/hs"), v0.v0radius(), v0.pt(), relPtRes, deltaZ, deltaR, deltaCol); + } else { + fRegistry.fill(HIST("CollisionAssociation/WrongCollisions/hs"), v0.v0radius(), v0.pt(), relPtRes, deltaZ, deltaR, deltaCol); + } + } + + if (mcAnalysisModeSettings.cfgRequireTrueAssociation && (mcphoton.emmceventId() != collision.emmceventId())) { + continue; + } + + if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { + fillV0InfoMC<0>(v0, mcphoton, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfoMC<0>(leg); + } + ng_primary++; + } else if (IsFromWD(mcphoton.template emmcevent_as(), mcphoton, mcparticles) > 0) { + fillV0InfoMC<1>(v0, mcphoton, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfoMC<1>(leg); + } + ng_wd++; + } else { + fillV0InfoMC<2>(v0, mcphoton, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfoMC<2>(leg); + } + ng_hs++; + } + } else if (pi0id > 0) { + auto mcpi0 = mcparticles.iteratorAt(pi0id); + if (mcAnalysisModeSettings.cfgRequireTrueAssociation && (mcpi0.emmceventId() != collision.emmceventId())) { + continue; + } + if (mcpi0.isPhysicalPrimary() || mcpi0.producedByGenerator()) { + fillV0InfoMC<3>(v0, mcpi0, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfoMC<3>(leg); + } + nee_pi0++; + } + } else if (etaid > 0) { + auto mceta = mcparticles.iteratorAt(etaid); + if (mcAnalysisModeSettings.cfgRequireTrueAssociation && (mceta.emmceventId() != collision.emmceventId())) { + continue; + } + if (mceta.isPhysicalPrimary() || mceta.producedByGenerator()) { + fillV0InfoMC<4>(v0, mceta, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfoMC<4>(leg); + } + nee_eta++; + } + } + } // end of v0 loop + fRegistry.fill(HIST("V0/primary/hNgamma"), ng_primary); + fRegistry.fill(HIST("V0/fromWD/hNgamma"), ng_wd); + fRegistry.fill(HIST("V0/fromHS/hNgamma"), ng_hs); + fRegistry.fill(HIST("V0/fromPi0Dalitz/hNgamma"), nee_pi0); + fRegistry.fill(HIST("V0/fromEtaDalitz/hNgamma"), nee_eta); + } // end of collision loop + } // end of MC process + + void processPCMQCMC(FilteredMyCollisionsMC const& collisions, MyV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) + { + processMC(collisions, v0photons, mcparticles, mcv0legs, mcevents, perCollisionV0); + } // end of MC QC process + + void processPCMQCMCML(FilteredMyCollisionsMC const& collisions, MyV0PhotonsML const& v0photonsML, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) + { + processMC(collisions, v0photonsML, mcparticles, mcv0legs, mcevents, perCollisionV0ML); + } // end of MC QC process with ML cuts + + template + void fillBinnedData(TBinnedData const& binned_data, const float weight = 1.f) + { + int xbin = 0, ybin = 0, zbin = 0; + auto hPtY = fRegistry.get(HIST("Generated/hPtY")); // 2D + auto hPt = fRegistry.get(HIST("Generated/hPt")); // 1D + + for (int ibin = 0; ibin < hPtY->GetNcells(); ibin++) { + int nentry = binned_data[ibin]; + hPtY->GetBinXYZ(ibin, xbin, ybin, zbin); + float pt = hPtY->GetXaxis()->GetBinCenter(xbin); + float y = hPtY->GetYaxis()->GetBinCenter(ybin); + if (y > v0cuts.cfgMaxEtaV0) { + continue; + } + + for (int j = 0; j < nentry; j++) { + hPtY->Fill(pt, y, weight); + hPt->Fill(pt, weight); + } + } + } + + PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; + void processGen(FilteredMyCollisionsMC const& collisions, MyMCCollisions const&, aod::EMMCParticles const& mcparticles) + { + + for (const auto& collision : collisions) { + const std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto mccollision = collision.template emmcevent_as(); + auto binned_data_gamma_gen = mccollision.generatedGamma(); + fillBinnedData(binned_data_gamma_gen, 1.f); + + auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); + for (const auto& mctrack : mctracks_coll) { + if (std::fabs(mctrack.y()) > v0cuts.cfgMaxEtaV0) { + continue; + } + if (std::abs(mctrack.pdgCode()) != PDG_t::kGamma || !(mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + continue; + } + + if (mcAnalysisModeSettings.cfgDoDetailedResolution) { + fRegistry.fill(HIST("Generated/hPtEtaPhi"), mctrack.pt(), mctrack.eta(), mctrack.phi()); // for all generated photons before any kinematic cut + } + if (mctrack.daughtersIds().empty()) { + continue; + } + auto daughter = mcparticles.iteratorAt(mctrack.daughtersIds()[0]); // choose ele or pos. + float rxy_gen_e = std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2)); + float phi_cp = std::atan2(daughter.vy(), daughter.vx()); + o2::math_utils::bringTo02Pi(phi_cp); + float eta_cp = std::atanh(daughter.vz() / std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2) + std::pow(daughter.vz(), 2))); + + fRegistry.fill(HIST("Generated/hR_ConversionPhoton_wideR"), rxy_gen_e); + fRegistry.fill(HIST("Generated/hRZ_wideR"), daughter.vz(), rxy_gen_e); + + if (rxy_gen_e < std::fabs(daughter.vz()) * std::tan(2 * std::atan(std::exp(-v0cuts.cfgMaxEtaV0))) - genSettingsGroup.cfgMarginZMC) { + continue; + } + if (rxy_gen_e > genSettingsGroup.cfgMaxRGen) { + continue; + } + + fRegistry.fill(HIST("Generated/hPt_ConversionPhoton"), mctrack.pt()); + fRegistry.fill(HIST("Generated/hY_ConversionPhoton"), mctrack.y()); + fRegistry.fill(HIST("Generated/hPhi_ConversionPhoton"), mctrack.phi()); + fRegistry.fill(HIST("Generated/hsConvPoint"), rxy_gen_e, phi_cp, eta_cp); + fRegistry.fill(HIST("Generated/hXY"), daughter.vx(), daughter.vy()); + fRegistry.fill(HIST("Generated/hRZ"), daughter.vz(), rxy_gen_e); + fRegistry.fill(HIST("Generated/hRPhi"), phi_cp, rxy_gen_e); + } // end of mctrack loop per collision + } // end of collision loop + } + + template + void fillLegQualityRecoQA(TTrack const& track) + { + if constexpr (survived) { + fRegistry.fill(HIST("RecoQA/LegQuality/survived/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("RecoQA/LegQuality/survived/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("RecoQA/LegQuality/survived/hSharedFracTPC"), track.tpcFractionSharedCls()); + fRegistry.fill(HIST("RecoQA/LegQuality/survived/hNclsTPC"), track.tpcNClsFound()); + } else { + fRegistry.fill(HIST("RecoQA/LegQuality/lost/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("RecoQA/LegQuality/lost/hChi2TPC"), track.tpcChi2NCl()); + fRegistry.fill(HIST("RecoQA/LegQuality/lost/hSharedFracTPC"), track.tpcFractionSharedCls()); + fRegistry.fill(HIST("RecoQA/LegQuality/lost/hNclsTPC"), track.tpcNClsFound()); + } + } + + Preslice perMcCollisionTruth = aod::mcparticle::mcCollisionId; + void processRecoQA(aod::McCollisions const& mcCollisions, aod::McParticles const& mcparticles, MyTracksMC const& tracks, aod::V0Legs const& v0legs, aod::V0PhotonsKF const& v0photonsKF) + { + std::unordered_map nTracksOfMcId; + std::unordered_map mcIdToBestTrack; + std::unordered_map mcIdBestCrossedRows; + nTracksOfMcId.reserve(tracks.size()); + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + const int mcId = track.mcParticleId(); + nTracksOfMcId[mcId]++; + const float ncr = track.tpcNClsCrossedRows(); + auto it = mcIdBestCrossedRows.find(mcId); + if (it == mcIdBestCrossedRows.end() || ncr > it->second) { + mcIdBestCrossedRows[mcId] = ncr; + mcIdToBestTrack[mcId] = track.globalIndex(); + } + } + + std::unordered_map nV0LegsOfMcId; + nV0LegsOfMcId.reserve(v0legs.size()); + for (const auto& leg : v0legs) { + const int trackId = leg.trackId(); + if (trackId < 0 || trackId >= static_cast(tracks.size())) { + continue; + } + const auto track = tracks.iteratorAt(trackId); + if (track.has_mcParticle()) { + nV0LegsOfMcId[track.mcParticleId()]++; + } + } + auto legMcMotherId = [&](auto const& leg) -> int { + const int trackId = leg.trackId(); + if (trackId < 0 || trackId >= static_cast(tracks.size())) { + return -1; + } + const auto track = tracks.iteratorAt(trackId); + if (!track.has_mcParticle()) { + return -1; + } + const auto mc = track.mcParticle(); + if (!mc.has_mothers()) { + return -1; + } + return mc.mothersIds()[0]; + }; + std::unordered_map nV0CandsOfMcPhoton; // counted: >=2 = duplicate candidates for the same true photon + for (const auto& v0 : v0photonsKF) { + const int legPosIdx = v0.posTrackId(); + const int legNegIdx = v0.negTrackId(); + if (legPosIdx < 0 || legPosIdx >= static_cast(v0legs.size()) || legNegIdx < 0 || legNegIdx >= static_cast(v0legs.size())) { + continue; + } + const int motherPos = legMcMotherId(v0legs.iteratorAt(legPosIdx)); + const int motherNeg = legMcMotherId(v0legs.iteratorAt(legNegIdx)); + if (motherPos >= 0 && motherPos == motherNeg) { + nV0CandsOfMcPhoton[motherPos]++; + } + } + for (const auto& mcCollision : mcCollisions) { + const auto mcparticles_coll = mcparticles.sliceBy(perMcCollisionTruth, mcCollision.globalIndex()); + for (const auto& mctrack : mcparticles_coll) { + if (mctrack.pdgCode() != PDG_t::kGamma || !mctrack.isPhysicalPrimary()) { + continue; + } + if (std::fabs(mctrack.eta()) > recoQASettingsGroup.cfgPhotonEtaMax || mctrack.pt() < recoQASettingsGroup.cfgPhotonPtMin) { + continue; + } + if (!mctrack.has_daughters()) { + continue; + } + int idPos = -1, idNeg = -1; + for (const int daughterId : mctrack.daughtersIds()) { + if (daughterId < 0 || daughterId >= static_cast(mcparticles.size())) { + continue; + } + const auto daughter = mcparticles.iteratorAt(daughterId); + if (daughter.pdgCode() == -PDG_t::kElectron) { + idPos = daughterId; + } else if (daughter.pdgCode() == PDG_t::kElectron) { + idNeg = daughterId; + } + } + if (idPos < 0 || idNeg < 0) { + continue; // not an e+e- conversion + } + const auto daughterPos = mcparticles.iteratorAt(idPos); + const auto daughterNeg = mcparticles.iteratorAt(idNeg); + const float rConv = std::sqrt(std::pow(daughterPos.vx(), 2) + std::pow(daughterPos.vy(), 2)); + if (rConv < recoQASettingsGroup.cfgRMinGen || rConv > recoQASettingsGroup.cfgRMaxGen) { + continue; + } + if (std::fabs(daughterPos.eta()) > recoQASettingsGroup.cfgLegEtaMax || std::fabs(daughterNeg.eta()) > recoQASettingsGroup.cfgLegEtaMax) { + continue; + } + + fRegistry.fill(HIST("RecoQA/0_converted/hs"), mctrack.pt(), mctrack.eta(), mctrack.phi(), rConv); + fRegistry.fill(HIST("RecoQA/hStageVsPt"), mctrack.pt(), 0.f); + + auto countIn = [](std::unordered_map const& m, int key) -> int { + const auto it = m.find(key); + return (it == m.end()) ? 0 : it->second; + }; + const int nTrkPos = countIn(nTracksOfMcId, idPos); + const int nTrkNeg = countIn(nTracksOfMcId, idNeg); + const int nLegPos = countIn(nV0LegsOfMcId, idPos); + const int nLegNeg = countIn(nV0LegsOfMcId, idNeg); + const bool posTracked = nTrkPos > 0; + const bool negTracked = nTrkNeg > 0; + const bool posInV0Legs = nLegPos > 0; + const bool negInV0Legs = nLegNeg > 0; + + fRegistry.fill(HIST("RecoQA/Duplicates/hNTracksPerTrueLeg"), nTrkPos); + fRegistry.fill(HIST("RecoQA/Duplicates/hNTracksPerTrueLeg"), nTrkNeg); + fRegistry.fill(HIST("RecoQA/Duplicates/hNV0LegsPerTrueLeg"), nLegPos); + fRegistry.fill(HIST("RecoQA/Duplicates/hNV0LegsPerTrueLeg"), nLegNeg); + fRegistry.fill(HIST("RecoQA/Duplicates/hNV0CandsPerPhoton_Rconv"), countIn(nV0CandsOfMcPhoton, static_cast(mctrack.globalIndex())), rConv); + + if (posTracked && negTracked) { + fRegistry.fill(HIST("RecoQA/1_bothLegsTracked/hs"), mctrack.pt(), mctrack.eta(), mctrack.phi(), rConv); + fRegistry.fill(HIST("RecoQA/hStageVsPt"), mctrack.pt(), 1.f); + } + if (posInV0Legs && negInV0Legs) { + fRegistry.fill(HIST("RecoQA/2_bothLegsInV0Legs/hs"), mctrack.pt(), mctrack.eta(), mctrack.phi(), rConv); + fRegistry.fill(HIST("RecoQA/hStageVsPt"), mctrack.pt(), 2.f); + } + if (countIn(nV0CandsOfMcPhoton, static_cast(mctrack.globalIndex())) > 0) { + fRegistry.fill(HIST("RecoQA/3_photonInV0PhotonsKF/hs"), mctrack.pt(), mctrack.eta(), mctrack.phi(), rConv); + fRegistry.fill(HIST("RecoQA/hStageVsPt"), mctrack.pt(), 3.f); + } + if (posTracked && !posInV0Legs) { + fRegistry.fill(HIST("RecoQA/hMissingLeg_PtRconv"), daughterPos.pt(), rConv); + } + if (negTracked && !negInV0Legs) { + fRegistry.fill(HIST("RecoQA/hMissingLeg_PtRconv"), daughterNeg.pt(), rConv); + } + + if (recoQASettingsGroup.cfgDoDetailedTrackQA) { + for (const int legMcId : {idPos, idNeg}) { + if (countIn(nTracksOfMcId, legMcId) == 0) { + continue; + } + const auto itTrack = mcIdToBestTrack.find(legMcId); + if (itTrack == mcIdToBestTrack.end() || itTrack->second < 0 || itTrack->second >= static_cast(tracks.size())) { + continue; + } + const auto track = tracks.iteratorAt(itTrack->second); + if (countIn(nV0LegsOfMcId, legMcId) > 0) { + fillLegQualityRecoQA(track); + } else { + fillLegQualityRecoQA(track); + } + } + } + } // end of mc particle loop per true event + } // end of true event loop + } // end of reco QA process PROCESS_SWITCH(PCMQC, processQC, "run PCM QC", true); PROCESS_SWITCH(PCMQC, processQCML, "run PCM QC with ML", false); - PROCESS_SWITCH(PCMQC, processDummy, "Dummy function", false); + PROCESS_SWITCH(PCMQC, processPCMQCMC, "run PCM QC in MC", false); + PROCESS_SWITCH(PCMQC, processPCMQCMCML, "run PCM QC in MC with ML cuts", false); + PROCESS_SWITCH(PCMQC, processGen, "run generated information", false); + PROCESS_SWITCH(PCMQC, processRecoQA, "run single-photon reconstruction QA on AO2Ds", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& context) diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx deleted file mode 100644 index dc432d670e5..00000000000 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ /dev/null @@ -1,822 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \file pcmQCMC.cxx -/// \brief This code runs loop over v0 photons for PCM QC in MC. -/// \author Daiki Sekihata, daiki.sekihata@cern.ch - -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/DataModel/EventTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" - -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace o2; -using namespace o2::aod; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::soa; -using namespace o2::aod::pwgem::photonmeson::utils::mcutil; -using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using namespace o2::aod::pwgem::photon; - -using MyCollisions = soa::Join; -using MyCollision = MyCollisions::iterator; - -using MyMCCollisions = soa::Join; -using MyMCCollision = MyMCCollisions::iterator; - -using MyV0Photons = o2::soa::Join; -using MyV0Photon = MyV0Photons::iterator; - -using MyV0PhotonsML = soa::Join; -using MyV0PhotonML = MyV0PhotonsML::iterator; - -using MyMCV0Legs = soa::Join; -using MyMCV0Leg = MyMCV0Legs::iterator; - -struct PCMQCMC { - - Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; - Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - - Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; - Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; - Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; - Configurable cfgResolDetailPlots{"cfgResolDetailPlots", false, "flag to enable detailed resolution plots"}; - - EMPhotonEventCut fEMEventCut; - struct : ConfigurableGroup { - std::string prefix = "eventcut_group"; - Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; - Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; - Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; - Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; - Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; - Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; - Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. - Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; - Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; - Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; - Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; - Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; - Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; - Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; - Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; - } eventcuts; - - V0PhotonCut fV0PhotonCut; - struct : ConfigurableGroup { - std::string prefix = "pcmcut_group"; - Configurable cfg_require_v0_with_itstpc{"cfg_require_v0_with_itstpc", false, "flag to select V0s with ITS-TPC matched tracks"}; - Configurable cfg_require_v0_with_itsonly{"cfg_require_v0_with_itsonly", false, "flag to select V0s with ITSonly tracks"}; - Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; - Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; - Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT for v0 photons at PV"}; - Configurable cfg_min_eta_v0{"cfg_min_eta_v0", -0.8, "min eta for v0 photons at PV"}; - Configurable cfg_max_eta_v0{"cfg_max_eta_v0", +0.8, "max eta for v0 photons at PV"}; - Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; - Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; - Configurable cfg_midL_v0radius{"cfg_midL_v0radius", -1.0, "middle low v0 radius for rejection if >0"}; - Configurable cfg_midH_v0radius{"cfg_midH_v0radius", -1.0, "middle high v0 radius for rejection if >0"}; - Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; - Configurable cfg_max_qt_ap{"cfg_max_qt_ap", 0.01, "max qT for AP cut"}; - Configurable cfg_min_cospa{"cfg_min_cospa", 0.999, "min V0 CosPA"}; - Configurable cfg_max_pca{"cfg_max_pca", 3.0, "max distance btween 2 legs"}; - Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; - Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; - Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; - Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; - // for ML cuts - Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; - Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; - Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; - Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; - Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; - Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; - Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; - Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; - Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; - Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; - Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; - Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; - Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; - Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; - } pcmcuts; - - o2::ccdb::CcdbApi ccdbApi; - o2::framework::Service ccdb{}; - int mRunNumber = 0; - float d_bz = 0; - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - static constexpr std::array event_types = {"before/", "after/"}; - static constexpr std::array mcphoton_types = {"primary/", "fromWD/", "fromHS/", "fromPi0Dalitz/", "fromEtaDalitz/"}; - - void init(InitContext&) - { - DefineEMEventCut(); - DefinePCMCut(); - addhistograms(); - - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - } - - template - void initCCDB(TCollision const& collision) - { - if (mRunNumber == collision.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (std::fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - mRunNumber = collision.runNumber(); - return; - } - - auto run3grp_timestamp = collision.timestamp(); - o2::parameters::GRPObject* grpo = nullptr; - o2::parameters::GRPMagField* grpmag = nullptr; - if (!skipGRPOquery) { - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - } - if (grpo) { - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - fV0PhotonCut.SetD_Bz(d_bz); - mRunNumber = collision.runNumber(); - } - - void addhistograms() - { - std::vector ptbins; - ptbins.reserve(72); - for (int i = 0; i < 2; i++) { - ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.05 GeV/c, every 0.05 GeV/c - } - for (int i = 2; i < 51; i++) { - ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 4.9 GeV/c, every 0.1 GeV/c - } - for (int i = 51; i < 61; i++) { - ptbins.emplace_back(0.5 * (i - 51) + 5.0); // from 5 to 9.5 GeV/c, every 0.5 GeV/c - } - for (int i = 61; i < 72; i++) { - ptbins.emplace_back(1.0 * (i - 61) + 10.0); // from 10 to 20 GeV/c, every 1 GeV/c - } - const AxisSpec axis_pt{ptbins, "p_{T,#gamma} (GeV/c)"}; - const AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y_{#gamma}|"}; - - if (doprocessGen) { - fRegistry.add("Generated/hPt", "pT;p_{T} (GeV/c)", kTH1D, {axis_pt}, true); - fRegistry.add("Generated/hPtY", "Generated info", kTH2D, {axis_pt, axis_rapidity}, true); - fRegistry.add("Generated/hPt_ConversionPhoton", "converted photon pT;p_{T} (GeV/c)", kTH1D, {axis_pt}, true); - fRegistry.add("Generated/hY_ConversionPhoton", "converted photon y;rapidity y", kTH1F, {{40, -2.0f, 2.0f}}, true); - fRegistry.add("Generated/hPhi_ConversionPhoton", "converted photon #varphi;#varphi (rad.)", kTH1F, {{180, 0, o2::constants::math::TwoPI}}, true); - fRegistry.add("Generated/hXY", "conversion point in XY MC;V_{x} (cm);V_{y} (cm)", kTH2F, {{800, -100.0f, 100.0f}, {800, -100.0f, 100.0f}}, true); - fRegistry.add("Generated/hRZ", "conversion point in RZ MC;V_{z} (cm);R_{xy} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, 0.f, 100.0f}}, true); - fRegistry.add("Generated/hRPhi", "conversion point of #varphi vs. R_{xy} MC;#varphi (rad.);R_{xy} (cm);N_{e}", kTH2F, {{360, 0.0f, o2::constants::math::TwoPI}, {400, 0, 100}}, true); - fRegistry.add("Generated/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, true); - if (cfgResolDetailPlots) { - fRegistry.add("Generated/hPtEtaPhi", "Photon pt vs eta, and phi;p_{T, gen} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); - } - } - - // event info - auto hCollisionCounter = fRegistry.add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{10, 0.5, 10.5}}, false); - hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); - hCollisionCounter->GetXaxis()->SetBinLabel(2, "No TF border"); - hCollisionCounter->GetXaxis()->SetBinLabel(3, "No ITS ROF border"); - hCollisionCounter->GetXaxis()->SetBinLabel(4, "No Same Bunch Pileup"); - hCollisionCounter->GetXaxis()->SetBinLabel(5, "Is Vertex ITSTPC"); - hCollisionCounter->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); - hCollisionCounter->GetXaxis()->SetBinLabel(7, "FT0AND"); - hCollisionCounter->GetXaxis()->SetBinLabel(8, "sel8"); - hCollisionCounter->GetXaxis()->SetBinLabel(9, "|Z_{vtx}| < 10 cm"); - hCollisionCounter->GetXaxis()->SetBinLabel(10, "accepted"); - - fRegistry.add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); - fRegistry.add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); - fRegistry.add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); - fRegistry.add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{300, 0, 6000}, {300, 0, 6000}}, false); - fRegistry.add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry.add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry.add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry.add("Event/before/hCentFT0MvsMultNTracksPV", "hCentFT0MvsMultNTracksPV;centrality FT0M (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); - fRegistry.add("Event/before/hMultFT0MvsMultNTracksPV", "hMultFT0MvsMultNTracksPV;mult. FT0M;N_{track} to PV", kTH2F, {{600, 0, 6000}, {600, 0, 6000}}, false); - fRegistry.addClone("Event/before/", "Event/after/"); - - // v0 info - fRegistry.add("V0/primary/hPt", "pT;p_{T,#gamma} (GeV/c)", kTH1F, {{2000, 0.0f, 20}}, false); - fRegistry.add("V0/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, o2::constants::math::TwoPI}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("V0/primary/hXY", "conversion point in XY;V_{x} (cm);V_{y} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, -100.0f, 100.0f}}, false); - fRegistry.add("V0/primary/hRZ", "conversion point in RZ;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100, 100}, {200, 0.0f, 100.0f}}, false); - fRegistry.add("V0/primary/hCosPA", "V0CosPA;cosine pointing angle in 3D", kTH1F, {{100, 0.99f, 1.0f}}, false); - fRegistry.add("V0/primary/hCosPAXY", "V0CosPA;cosine pointing angle in XY", kTH1F, {{100, 0.99f, 1.0f}}, false); - fRegistry.add("V0/primary/hCosPARZ", "V0CosPA;cosine pointing angle in RZ", kTH1F, {{100, 0.99f, 1.0f}}, false); - fRegistry.add("V0/primary/hPCA", "distance between 2 legs;PCA (cm)", kTH1F, {{500, 0.0f, 5.0f}}, false); - fRegistry.add("V0/primary/hDCAxyz", "DCA to PV;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -5.f, +5.f}, {200, -5.f, +5.f}}, false); - fRegistry.add("V0/primary/hDCAz_Pt", "DCA_{z} to PV vs. p_{T};DCA_{z} (cm);p_{T} (GeV/c)", kTH2F, {{200, -5.f, +5.f}, {2000, 0.0f, 20}}, false); - fRegistry.add("V0/primary/hAPplot", "AP plot;#alpha;q_{T} (GeV/c)", kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}, false); - fRegistry.add("V0/primary/hMassGamma", "hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.0f, 0.1f}}, false); - fRegistry.add("V0/primary/hKFChi2vsM", "KF chi2 vs. m_{ee};m_{ee} (GeV/c^{2});KF chi2/NDF", kTH2F, {{100, 0.0f, 0.1f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/primary/hKFChi2vsR", "KF chi2 vs. conversion point in XY;R_{xy} (cm);KF chi2/NDF", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/primary/hKFChi2vsX", "KF chi2 vs. conversion point in X;X (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/primary/hKFChi2vsY", "KF chi2 vs. conversion point in Y;Y (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/primary/hKFChi2vsZ", "KF chi2 vs. conversion point in Z;Z (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/primary/hNgamma", "Number of true #gamma per collision;N_{#gamma} per event;Number of events", kTH1F, {{101, -0.5f, 100.5f}}); - fRegistry.add("V0/primary/hConvPoint_diffX", "conversion point diff X MC;X_{MC} (cm);X_{rec} - X_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); - fRegistry.add("V0/primary/hConvPoint_diffY", "conversion point diff Y MC;Y_{MC} (cm);Y_{rec} - Y_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); - fRegistry.add("V0/primary/hConvPoint_diffZ", "conversion point diff Z MC;Z_{MC} (cm);Z_{rec} - Z_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); - fRegistry.add("V0/primary/hPtGen_DeltaPtOverPtGen", "photon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); - fRegistry.add("V0/primary/hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 20}, {199, -0.099, 0.099}}, true); - fRegistry.add("V0/primary/hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{200, 0, 20}, {199, -0.099, 0.099}}, true); - fRegistry.add("V0/primary/hRxyGen_DeltaPtOverPtGen", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); - fRegistry.add("V0/primary/hRxyGen_DeltaEta", "photon #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); - fRegistry.add("V0/primary/hRxyGen_DeltaPhi", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); - fRegistry.add("V0/primary/hRxyGen_DeltaR", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, 0, 100}}, true); - fRegistry.add("V0/primary/hXY_MC", "X vs. Y of true photon conversion point.;X (cm);Y (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, +100}}, true); - fRegistry.add("V0/primary/hRZ_MC", "R vs. Z of true photon conversion point;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); - fRegistry.add("V0/primary/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); - if (cfgResolDetailPlots) { - fRegistry.add("V0/primary/hEtaPhiResol", "Photon eta-phi resolution;p_{T} (GeV/c);#eta-diff;#phi-diff", kTH3F, {{200, 0., 20.}, {99, -0.049, 0.049}, {99, -0.049, 0.049}}, false); - fRegistry.add("V0/primary/hPtResolPtEtaPhi", "Photon resolution vs. pt, eta, and phi;p_{T_rec} - p_{T true} / p_{T true};p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{199, -0.995, 0.995}, {200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); - fRegistry.add("V0/primary/hMomResolPtEtaPhi", "Photon momentum resolution vs. p, eta, and phi;p_{rec} - p_{true} / p_{true};p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{199, -0.995, 0.995}, {200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); - fRegistry.add("V0/primary/hPtEtaPhi", "pt, eta, and phi;p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); - } - if (pcmcuts.cfg_apply_ml_cuts) { - if (pcmcuts.cfg_nclasses_ml == 2) { - fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); - fRegistry.add("V0/primary/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); - fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); - } else if (pcmcuts.cfg_nclasses_ml == 3) { - fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); - fRegistry.add("V0/primary/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); - fRegistry.add("V0/primary/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); - fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); - } else { - fRegistry.add("V0/primary/hBDTScoreVsPt", "BDT score vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); - fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); - } - } - fRegistry.addClone("V0/primary/", "V0/fromWD/"); // from weak decay - fRegistry.addClone("V0/primary/", "V0/fromHS/"); // from hadronic shower in detector materials - fRegistry.addClone("V0/primary/", "V0/fromPi0Dalitz/"); // misidentified dielectron from pi0 dalitz decay - fRegistry.addClone("V0/primary/", "V0/fromEtaDalitz/"); // misidentified dielectron from eta dalitz decay - fRegistry.addClone("V0/primary/hPt", "V0/candidate/hPt"); // only for purity - fRegistry.addClone("V0/primary/hEtaPhi", "V0/candidate/hEtaPhi"); // only for purity - - // v0leg info - fRegistry.add("V0Leg/primary/hPt", "pT;p_{T,e} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("V0Leg/primary/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -50, 50}}, false); - fRegistry.add("V0Leg/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, o2::constants::math::TwoPI}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("V0Leg/primary/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -50.0f, 50.0f}, {200, -50.0f, 50.0f}}, false); - fRegistry.add("V0Leg/primary/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("V0Leg/primary/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("V0Leg/primary/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("V0Leg/primary/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); - fRegistry.add("V0Leg/primary/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("V0Leg/primary/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("V0Leg/primary/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("V0Leg/primary/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("V0Leg/primary/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); - fRegistry.add("V0Leg/primary/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("V0Leg/primary/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("V0Leg/primary/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("V0Leg/primary/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); - // fRegistry.add("V0Leg/primary/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {40, -20, 20}}, false); - // fRegistry.add("V0Leg/primary/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); - // fRegistry.add("V0Leg/primary/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {40, -20, 20}}, false); - fRegistry.add("V0Leg/primary/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); - fRegistry.add("V0Leg/primary/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); - fRegistry.add("V0Leg/primary/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); - fRegistry.add("V0Leg/primary/hRxyGen_DeltaPtOverPtGen", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); - fRegistry.add("V0Leg/primary/hRxyGen_DeltaEta", "photon #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); - fRegistry.add("V0Leg/primary/hRxyGen_DeltaPhi", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, 0, 100}}, true); - fRegistry.add("V0Leg/primary/hRxyGen_DeltaR", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); - - fRegistry.addClone("V0Leg/primary/", "V0Leg/fromWD/"); // from weak decay - fRegistry.addClone("V0Leg/primary/", "V0Leg/fromHS/"); // from hadronic shower in detector materials - fRegistry.addClone("V0Leg/primary/", "V0Leg/fromPi0Dalitz/"); // misidentified dielectron from pi0 dalitz decay - fRegistry.addClone("V0Leg/primary/", "V0Leg/fromEtaDalitz/"); // misidentified dielectron from eta dalitz decay - - fRegistry.addClone("V0Leg/primary/hPt", "V0Leg/candidate/hPt"); // only for purity - fRegistry.addClone("V0Leg/primary/hEtaPhi", "V0Leg/candidate/hEtaPhi"); // only for purity - } - - void DefineEMEventCut() - { - fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); - fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); - fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); - fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); - fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); - fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); - fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); - fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); - fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); - fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); - fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); - fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); - fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); - fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); - } - - void DefinePCMCut() - { - fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); - - // for v0 - fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, pcmcuts.cfg_max_pt_v0); - fV0PhotonCut.SetV0EtaRange(pcmcuts.cfg_min_eta_v0, pcmcuts.cfg_max_eta_v0); - fV0PhotonCut.SetMinCosPA(pcmcuts.cfg_min_cospa); - fV0PhotonCut.SetMaxPCA(pcmcuts.cfg_max_pca); - fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfg_max_chi2kf); - fV0PhotonCut.SetRxyRange(pcmcuts.cfg_min_v0radius, pcmcuts.cfg_max_v0radius, pcmcuts.cfg_midL_v0radius, pcmcuts.cfg_midH_v0radius); - fV0PhotonCut.SetAPRange(pcmcuts.cfg_max_alpha_ap, pcmcuts.cfg_max_qt_ap); - fV0PhotonCut.RejectITSib(pcmcuts.cfg_reject_v0_on_itsib); - - // for track - fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); - fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); - fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); - fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfg_max_frac_shared_clusters_tpc); - fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfg_max_chi2tpc); - fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfg_min_TPCNsigmaEl, pcmcuts.cfg_max_TPCNsigmaEl); - fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); - fV0PhotonCut.SetNClustersITS(0, 7); - fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); - fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); - fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); - fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); - fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); - - // for ML - fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); - fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); - fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); - fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); - fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); - fV0PhotonCut.SetCcdbUrl(ccdburl); - auto mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); - fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); - fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); - fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); - fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); - fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); - fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); - fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); - fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); - fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); - fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); - fV0PhotonCut.SetD_Bz(0.0f); // dummy value -> only for phiv calculation - - if (pcmcuts.cfg_apply_ml_cuts) { - fV0PhotonCut.initV0MlModels(ccdbApi); - } - } - - template - void fillEventInfo(TCollision const& collision, const float /*weight*/ = 1.f) - { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 1.0); - if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 2.0); - } - if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 3.0); - } - if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 4.0); - } - if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 5.0); - } - if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 6.0); - } - if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 7.0); - } - if (collision.sel8()) { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 8.0); - } - if (std::fabs(collision.posZ()) < 10.0) { - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 9.0); - } - - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hZvtx"), collision.posZ()); - - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPV"), collision.multNTracksPV()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A"), collision.centFT0A()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0C"), collision.centFT0C()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0M"), collision.centFT0M()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0MvsMultNTracksPV"), collision.centFT0M(), collision.multNTracksPV()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0MvsMultNTracksPV"), collision.multFT0A() + collision.multFT0C(), collision.multNTracksPV()); - } - - template - void fillV0Info(TV0 const& v0, TMCV0 const& mcphoton, TMCLeg const& mcleg) - { - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPt"), v0.pt()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhi"), v0.phi(), v0.eta()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hXY"), v0.vx(), v0.vy()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRZ"), v0.vz(), v0.v0radius()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPA"), v0.cospa()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPAXY"), v0.cospaXY()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPARZ"), v0.cospaRZ()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPCA"), v0.pca()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hDCAxyz"), v0.dcaXYtopv(), v0.dcaZtopv()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hDCAz_Pt"), v0.dcaZtopv(), v0.pt()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hAPplot"), v0.alpha(), v0.qtarm()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMassGamma"), v0.v0radius(), v0.mGamma()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsM"), v0.mGamma(), v0.chiSquareNDF()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsR"), v0.v0radius(), v0.chiSquareNDF()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsX"), v0.vx(), v0.chiSquareNDF()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsY"), v0.vy(), v0.chiSquareNDF()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsZ"), v0.vz(), v0.chiSquareNDF()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcphoton.pt(), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcphoton.pt(), v0.eta() - mcphoton.eta()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcphoton.pt(), v0.phi() - mcphoton.phi()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPtOverPtGen"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.eta() - mcphoton.eta()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.phi() - mcphoton.phi()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaR"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.v0radius() - std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffX"), mcleg.vx(), v0.vx() - mcleg.vx()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffY"), mcleg.vy(), v0.vy() - mcleg.vy()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffZ"), mcleg.vz(), v0.vz() - mcleg.vz()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hXY_MC"), mcleg.vx(), mcleg.vy()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRZ_MC"), mcleg.vz(), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); - - if (cfgResolDetailPlots) { - // Resolution vs. pt, eta and phi - float resolPt = (v0.pt() - mcphoton.pt()) / mcphoton.pt(); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtResolPtEtaPhi"), resolPt, mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); - float resolMom = (v0.p() - mcphoton.p()) / mcphoton.p(); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMomResolPtEtaPhi"), resolMom, mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtEtaPhi"), mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhiResol"), mcphoton.pt(), v0.eta() - mcphoton.eta(), v0.phi() - mcphoton.phi()); - } - - float phi_cp = std::atan2(v0.vy(), v0.vx()); - o2::math_utils::bringTo02Pi(phi_cp); - float eta_cp = std::atanh(v0.vz() / std::sqrt(std::pow(v0.vx(), 2) + std::pow(v0.vy(), 2) + std::pow(v0.vz(), 2))); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hsConvPoint"), v0.v0radius(), phi_cp, eta_cp); - - // BDT response histogram can be filled here when apply BDT is true - if (pcmcuts.cfg_apply_ml_cuts) { - const std::span& bdtValue = fV0PhotonCut.getBDTValue(); - float psipair = 999.f; - float phiv = 999.f; - if constexpr (requires { v0.psipair(); v0.phiv(); }) { - psipair = v0.psipair(); - phiv = v0.phiv(); - } - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiVPsi"), psipair, phiv); - if (pcmcuts.cfg_nclasses_ml == 2 && bdtValue.size() == 2) { - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); - } else if (pcmcuts.cfg_nclasses_ml == 3 && bdtValue.size() == 3) { - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); - } else if (bdtValue.size() == 1) { - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTCutVsPt"), v0.pt(), bdtValue[0]); - } - } - } - - template - void fillV0LegInfo(TLeg const& leg) - { - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPt"), leg.pt()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hQoverPt"), leg.sign() / leg.pt()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhi"), leg.phi(), leg.eta()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hDCAxyz"), leg.dcaXY(), leg.dcaZ()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNclsITS"), leg.itsNCls()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNclsTPC"), leg.tpcNClsFound()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNcrTPC"), leg.tpcNClsCrossedRows()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNcr2Nf"), leg.tpcCrossedRowsOverFindableCls()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNcls2Nf"), leg.tpcFoundOverFindableCls()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNclsShared"), leg.pt(), leg.tpcFractionSharedCls()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hChi2TPC"), leg.tpcChi2NCl()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hChi2ITS"), leg.itsChi2NCl()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hITSClusterMap"), leg.itsClusterMap()); - if (leg.hasITS()) { - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hMeanClusterSizeITS"), leg.p(), leg.meanClusterSizeITS() * std::cos(std::atan(leg.tgl()))); - } - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi()); - // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hXY"), leg.x(), leg.y()); - // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZX"), leg.z(), leg.x()); - // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZY"), leg.z(), leg.y()); - auto mcleg = leg.template emmcparticle_as(); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcleg.pt(), (leg.pt() - mcleg.pt()) / mcleg.pt()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcleg.pt(), leg.eta() - mcleg.eta()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcleg.pt(), leg.phi() - mcleg.phi()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPtOverPtGen"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), (leg.pt() - mcleg.pt()) / mcleg.pt()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.eta() - mcleg.eta()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.phi() - mcleg.phi()); - } - Preslice perCollisionV0 = aod::v0photonkf::pmeventId; - Preslice perCollisionV0ML = aod::v0photonkf::pmeventId; - Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); - Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; - Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; - using FilteredMyCollisions = soa::Filtered; - - template - void processMC(FilteredMyCollisions const& collisions, TV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, aod::EMMCEvents const&, TPerCollision const& percollision) - { - for (const auto& collision : collisions) { - initCCDB(collision); - const std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - fillEventInfo<0>(collision); - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - fillEventInfo<1>(collision); - fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted - fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted - - fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); // set centrality for BDT response - auto V0Photons_coll = v0photons.sliceBy(percollision, collision.globalIndex()); - int ng_primary = 0, ng_wd = 0, ng_hs = 0, nee_pi0 = 0, nee_eta = 0; - for (const auto& v0 : V0Photons_coll) { - auto pos = v0.template posTrack_as(); - auto ele = v0.template negTrack_as(); - auto posmc = pos.template emmcparticle_as(); - auto elemc = ele.template emmcparticle_as(); - - // LOGF(info, "posmc.isPhysicalPrimary() = %d, posmc.producedByGenerator() = %d, elemc.isPhysicalPrimary() = %d, elemc.producedByGenerator() = %d", posmc.isPhysicalPrimary(), posmc.producedByGenerator(), elemc.isPhysicalPrimary(), elemc.producedByGenerator()); - - if (!fV0PhotonCut.IsSelected(v0)) { - continue; - } - - fRegistry.fill(HIST("V0/candidate/hPt"), v0.pt()); - fRegistry.fill(HIST("V0/candidate/hEtaPhi"), v0.phi(), v0.eta()); - for (const auto& leg : {pos, ele}) { - fRegistry.fill(HIST("V0Leg/candidate/hPt"), leg.pt()); - fRegistry.fill(HIST("V0Leg/candidate/hEtaPhi"), leg.phi(), leg.eta()); - } - - int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); - int pi0id = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 111, mcparticles); // pi0 dalitz decay - int etaid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 221, mcparticles); // eta dalitz decay - if (photonid < 0 && pi0id < 0 && etaid < 0) { - continue; - } - - if (photonid > 0) { - auto mcphoton = mcparticles.iteratorAt(photonid); - if (cfgRequireTrueAssociation && (mcphoton.emmceventId() != collision.emmceventId())) { - continue; - } - - if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { - fillV0Info<0>(v0, mcphoton, elemc); - for (const auto& leg : {pos, ele}) { - fillV0LegInfo<0>(leg); - } - ng_primary++; - } else if (IsFromWD(mcphoton.template emmcevent_as(), mcphoton, mcparticles) > 0) { - fillV0Info<1>(v0, mcphoton, elemc); - for (const auto& leg : {pos, ele}) { - fillV0LegInfo<1>(leg); - } - ng_wd++; - } else { - fillV0Info<2>(v0, mcphoton, elemc); - for (const auto& leg : {pos, ele}) { - fillV0LegInfo<2>(leg); - } - ng_hs++; - // LOGF(info, "mcphoton.vx() = %f, mcphoton.vy() = %f, mcphoton.vz() = %f, mother_pdg = %d", mcphoton.vx(), mcphoton.vy(), mcphoton.vz(), mother_pdg); - } - } else if (pi0id > 0) { - auto mcpi0 = mcparticles.iteratorAt(pi0id); - if (cfgRequireTrueAssociation && (mcpi0.emmceventId() != collision.emmceventId())) { - continue; - } - if (mcpi0.isPhysicalPrimary() || mcpi0.producedByGenerator()) { - fillV0Info<3>(v0, mcpi0, elemc); - for (const auto& leg : {pos, ele}) { - fillV0LegInfo<3>(leg); - } - nee_pi0++; - } - } else if (etaid > 0) { - auto mceta = mcparticles.iteratorAt(etaid); - if (cfgRequireTrueAssociation && (mceta.emmceventId() != collision.emmceventId())) { - continue; - } - if (mceta.isPhysicalPrimary() || mceta.producedByGenerator()) { - fillV0Info<4>(v0, mceta, elemc); - for (const auto& leg : {pos, ele}) { - fillV0LegInfo<4>(leg); - } - nee_eta++; - } - } - } // end of v0 loop - fRegistry.fill(HIST("V0/primary/hNgamma"), ng_primary); - fRegistry.fill(HIST("V0/fromWD/hNgamma"), ng_wd); - fRegistry.fill(HIST("V0/fromHS/hNgamma"), ng_hs); - fRegistry.fill(HIST("V0/fromPi0Dalitz/hNgamma"), nee_pi0); - fRegistry.fill(HIST("V0/fromEtaDalitz/hNgamma"), nee_eta); - } // end of collision loop - } // end of process - - void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) - { - processMC(collisions, v0photons, mcparticles, mcv0legs, mcevents, perCollisionV0); - } // end of QC process - - void processQCMCML(FilteredMyCollisions const& collisions, MyV0PhotonsML const& v0photonsML, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) - { - processMC(collisions, v0photonsML, mcparticles, mcv0legs, mcevents, perCollisionV0ML); - } // end of QC process with ML cuts - - template - void fillBinnedData(TBinnedData const& binned_data, const float weight = 1.f) - { - int xbin = 0, ybin = 0, zbin = 0; - auto hPtY = fRegistry.get(HIST("Generated/hPtY")); // 2D - auto hPt = fRegistry.get(HIST("Generated/hPt")); // 1D - - for (int ibin = 0; ibin < hPtY->GetNcells(); ibin++) { - int nentry = binned_data[ibin]; - hPtY->GetBinXYZ(ibin, xbin, ybin, zbin); - float pt = hPtY->GetXaxis()->GetBinCenter(xbin); - float y = hPtY->GetYaxis()->GetBinCenter(ybin); - if (y > pcmcuts.cfg_max_eta_v0) { - continue; - } - - for (int j = 0; j < nentry; j++) { - hPtY->Fill(pt, y, weight); - hPt->Fill(pt, weight); - } - } - } - - // aod::EMMCParticles contain primary photon conversions. // aod::BinnedGenPts contain primary photons - PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; - void processGen(FilteredMyCollisions const& collisions, MyMCCollisions const&, aod::EMMCParticles const& mcparticles) - { - // loop over mc stack and fill histograms for pure MC truth signals - // all MC tracks which belong to the MC event corresponding to the current reconstructed event - - for (const auto& collision : collisions) { - const std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; - if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { - continue; - } - - if (!fEMEventCut.IsSelected(collision)) { - continue; - } - - auto mccollision = collision.template emmcevent_as(); - auto binned_data_gamma_gen = mccollision.generatedGamma(); - fillBinnedData(binned_data_gamma_gen, 1.f); - // LOGF(info, "mccollision.globalIndex() = %d", mccollision.globalIndex()); - - auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); - for (const auto& mctrack : mctracks_coll) { - if (std::fabs(mctrack.y()) > pcmcuts.cfg_max_eta_v0) { - continue; - } - - if (std::abs(mctrack.pdgCode()) == PDG_t::kGamma && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { - if (cfgResolDetailPlots) { - fRegistry.fill(HIST("Generated/hPtEtaPhi"), mctrack.pt(), mctrack.eta(), mctrack.phi()); // fill for all generated photons before any kinematic cut - } - if (mctrack.daughtersIds().empty()) { - continue; - } - auto daughter = mcparticles.iteratorAt(mctrack.daughtersIds()[0]); // choose ele or pos. - float rxy_gen_e = std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2)); - float phi_cp = std::atan2(daughter.vy(), daughter.vx()); - o2::math_utils::bringTo02Pi(phi_cp); - float eta_cp = std::atanh(daughter.vz() / std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2) + std::pow(daughter.vz(), 2))); - - if (rxy_gen_e < std::fabs(daughter.vz()) * std::tan(2 * std::atan(std::exp(-pcmcuts.cfg_max_eta_v0))) - margin_z_mc) { - continue; - } - if (rxy_gen_e > maxRgen) { - continue; - } - - fRegistry.fill(HIST("Generated/hPt_ConversionPhoton"), mctrack.pt()); - fRegistry.fill(HIST("Generated/hY_ConversionPhoton"), mctrack.y()); - fRegistry.fill(HIST("Generated/hPhi_ConversionPhoton"), mctrack.phi()); - fRegistry.fill(HIST("Generated/hsConvPoint"), rxy_gen_e, phi_cp, eta_cp); - fRegistry.fill(HIST("Generated/hXY"), daughter.vx(), daughter.vy()); - fRegistry.fill(HIST("Generated/hRZ"), daughter.vz(), rxy_gen_e); - fRegistry.fill(HIST("Generated/hRPhi"), phi_cp, rxy_gen_e); - } - } // end of mctrack loop per collision - } // end of collision loop - } - - void processDummy(MyCollisions const&) {} - - PROCESS_SWITCH(PCMQCMC, processQCMC, "run PCM QC in MC", false); - PROCESS_SWITCH(PCMQCMC, processGen, "run generated information", false); - PROCESS_SWITCH(PCMQCMC, processQCMCML, "run PCM QC in MC with ML cuts", false); - PROCESS_SWITCH(PCMQCMC, processDummy, "Dummy function", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& context) -{ - return WorkflowSpec{ - adaptAnalysisTask(context, TaskName{"pcm-qc-mc"})}; -} From 081e962a7980aadf5ad062f8e469d25d9a66fd13 Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski Date: Wed, 2 Sep 2026 16:33:08 +0200 Subject: [PATCH 2/5] Unify QC + MaterialBudgetTasks --- PWGEM/PhotonMeson/Tasks/pcmQC.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index c65849eae3d..ad6e553c54b 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -32,7 +32,7 @@ /// building and deduplication, separating genuine /// reconstruction quality from reconstruction artifacts. /// -/// \author Daiki Sekihata and Stefanie Mrozinski +/// \author Daiki Sekihata and author Stefanie Mrozinski #include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" @@ -459,9 +459,7 @@ struct PCMQC { fRegistry.add("V0/primary/hEtaVsPt", "#eta vs. pT;p_{T,#gamma} (GeV/c);#eta", kTH2F, {{100, 0, 10}, {200, -1.0f, 1.0f}}, false); fRegistry.add("V0/primary/hPhiVsPt", "#varphi vs. pT;p_{T,#gamma} (GeV/c);#varphi (rad.)", kTH2F, {{100, 0, 10}, {90, 0, o2::constants::math::TwoPI}}, false); fRegistry.add("V0/primary/hsAlphaQtPt", "Armenteros vs. pT;#alpha;q_{T} (GeV/c);p_{T,#gamma} (GeV/c)", kTHnSparseF, {{100, -1.0f, +1.0f}, {125, 0.0f, 0.25f}, {100, 0, 10}}, false); - if (doprocessPCMQCMCML) { - fRegistry.add("V0/primary/hPsiPairVsPt", "#psi_{pair} vs. pT;p_{T,#gamma} (GeV/c);#psi_{pair} (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5f, +0.5f}}, false); - } + fRegistry.add("V0/primary/hPsiPairVsPt", "#psi_{pair} vs. pT;p_{T,#gamma} (GeV/c);#psi_{pair} (rad.)", kTH2F, {{100, 0, 10}, {200, -0.5f, +0.5f}}, false); fRegistry.add("V0/primary/hMassGamma", "hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.0f, 0.1f}}, false); fRegistry.add("V0/primary/hKFChi2vsM", "KF chi2 vs. m_{ee};m_{ee} (GeV/c^{2});KF chi2/NDF", kTH2F, {{100, 0.0f, 0.1f}, {100, 0.f, 100.0f}}, false); fRegistry.add("V0/primary/hKFChi2vsR", "KF chi2 vs. conversion point in XY;R_{xy} (cm);KF chi2/NDF", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.f, 100.0f}}, false); @@ -708,7 +706,9 @@ struct PCMQC { fRegistry.fill(HIST("V0/hEtaVsPt"), v0.pt(), v0.eta()); fRegistry.fill(HIST("V0/hPhiVsPt"), v0.pt(), v0.phi()); fRegistry.fill(HIST("V0/hsAlphaQtPt"), v0.alpha(), v0.qtarm(), v0.pt()); - fRegistry.fill(HIST("V0/hPsiPairVsPt"), v0.pt(), v0.psipair()); + if constexpr (requires { v0.psipair(); }) { + fRegistry.fill(HIST("V0/hPsiPairVsPt"), v0.pt(), v0.psipair()); + } fRegistry.fill(HIST("V0/hMassGamma"), v0.v0radius(), v0.mGamma()); fRegistry.fill(HIST("V0/hKFChi2vsM"), v0.mGamma(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/hKFChi2vsR"), v0.v0radius(), v0.chiSquareNDF()); @@ -842,7 +842,7 @@ struct PCMQC { if (!fV0PhotonCut.IsSelected(v0)) { continue; } - fillLossQAInfo<1>(v0); // survivors + fillLossQAInfo<1>(v0); fillV0Info(v0); fillMaterialBudgetInfo(v0); for (const auto& leg : {pos, ele}) { @@ -1254,7 +1254,7 @@ struct PCMQC { } return mc.mothersIds()[0]; }; - std::unordered_map nV0CandsOfMcPhoton; // counted: >=2 = duplicate candidates for the same true photon + std::unordered_map nV0CandsOfMcPhoton; for (const auto& v0 : v0photonsKF) { const int legPosIdx = v0.posTrackId(); const int legNegIdx = v0.negTrackId(); From 83c6e61dfcc98413cc33ca7bec1d4fe5cdd83fe2 Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski Date: Wed, 2 Sep 2026 16:39:05 +0200 Subject: [PATCH 3/5] Unify QC + MaterialBudgetTasks --- PWGEM/PhotonMeson/Tasks/pcmQC.cxx | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index ad6e553c54b..f5a27122721 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -267,11 +267,11 @@ struct PCMQC { } // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { + if (d_bz_input > -990) { // o2-linter: disable=magic-number (dummy value to indicate override) d_bz = d_bz_input; o2::parameters::GRPMagField grpmag; - if (std::fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + if (std::fabs(d_bz) > 1e-5) { // o2-linter: disable=magic-number (dummy value to indicate override) + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); // o2-linter: disable=magic-number (dummy value to indicate override) } mRunNumber = collision.runNumber(); return; @@ -353,11 +353,11 @@ struct PCMQC { fRegistry.add("V0/hNgamma", "Number of #gamma candidates per collision", kTH1F, {{101, -0.5f, 100.5f}}); if (mlcuts.cfgApplyPCMMl) { - if (mlcuts.cfgNClassesPCMMl == 2) { + if (mlcuts.cfgNClassesPCMMl == 2) { // o2-linter: disable=magic-number (BDT class) fRegistry.add("V0/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); fRegistry.add("V0/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); fRegistry.add("V0/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); - } else if (mlcuts.cfgNClassesPCMMl == 3) { + } else if (mlcuts.cfgNClassesPCMMl == 3) { // o2-linter: disable=magic-number (BDT class) fRegistry.add("V0/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); fRegistry.add("V0/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); fRegistry.add("V0/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{1000, 0.0f, 20.0f}, {1000, 0.0f, 1.0f}}}); @@ -412,16 +412,16 @@ struct PCMQC { if (doprocessGen) { std::vector ptbins; ptbins.reserve(72); - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) { // o2-linter: disable=magic-number (binning) ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.05 GeV/c, every 0.05 GeV/c } - for (int i = 2; i < 51; i++) { + for (int i = 2; i < 51; i++) { // o2-linter: disable=magic-number (binning) ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 4.9 GeV/c, every 0.1 GeV/c } - for (int i = 51; i < 61; i++) { + for (int i = 51; i < 61; i++) { // o2-linter: disable=magic-number (binning) ptbins.emplace_back(0.5 * (i - 51) + 5.0); // from 5 to 9.5 GeV/c, every 0.5 GeV/c } - for (int i = 61; i < 72; i++) { + for (int i = 61; i < 72; i++) { // o2-linter: disable=magic-number (binning) ptbins.emplace_back(1.0 * (i - 61) + 10.0); // from 10 to 20 GeV/c, every 1 GeV/c } const AxisSpec axisPtGen{ptbins, "p_{T,#gamma} (GeV/c)"}; @@ -487,10 +487,10 @@ struct PCMQC { fRegistry.add("V0/primary/hPtEtaPhi", "pt, eta, and phi;p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); } if (mlcuts.cfgApplyPCMMl) { - if (mlcuts.cfgNClassesPCMMl == 2) { + if (mlcuts.cfgNClassesPCMMl == 2) { // o2-linter: disable=magic-number (BDT group) fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); fRegistry.add("V0/primary/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); - } else if (mlcuts.cfgNClassesPCMMl == 3) { + } else if (mlcuts.cfgNClassesPCMMl == 3) { // o2-linter: disable=magic-number (BDT group) fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); fRegistry.add("V0/primary/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); fRegistry.add("V0/primary/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); @@ -673,7 +673,7 @@ struct PCMQC { if (collision.sel8()) { fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 8.0); } - if (std::fabs(collision.posZ()) < 10.0) { + if (std::fabs(collision.posZ()) < 10.0) { // o2-linter: disable=magic-number (vertex cut) fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 9.0); } fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hZvtx"), collision.posZ()); @@ -731,10 +731,10 @@ struct PCMQC { phiv = v0.phiv(); } fRegistry.fill(HIST("V0/hPhiVPsi"), psipair, phiv); - if (mlcuts.cfgNClassesPCMMl == 2 && bdtValue.size() == 2) { + if (mlcuts.cfgNClassesPCMMl == 2 && bdtValue.size() == 2) { // o2-linter: disable=magic-number (BDT) fRegistry.fill(HIST("V0/hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); fRegistry.fill(HIST("V0/hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); - } else if (mlcuts.cfgNClassesPCMMl == 3 && bdtValue.size() == 3) { + } else if (mlcuts.cfgNClassesPCMMl == 3 && bdtValue.size() == 3) { // o2-linter: disable=magic-number (BDT) fRegistry.fill(HIST("V0/hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); fRegistry.fill(HIST("V0/hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); fRegistry.fill(HIST("V0/hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); @@ -930,14 +930,14 @@ struct PCMQC { phiv = v0.phiv(); } fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiVPsi"), psipair, phiv); - if (mlcuts.cfgNClassesPCMMl == 2 && bdtValue.size() == 2) { + if (mlcuts.cfgNClassesPCMMl == 2 && bdtValue.size() == 2) { // o2-linter: disable=magic-number (BDT) fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); - } else if (mlcuts.cfgNClassesPCMMl == 3 && bdtValue.size() == 3) { + } else if (mlcuts.cfgNClassesPCMMl == 3 && bdtValue.size() == 3) { // o2-linter: disable=magic-number (BDT) fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); - } else if (bdtValue.size() == 1) { + } else if (bdtValue.size() == 1) { // o2-linter: disable=magic-number (BDT) fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTScoreVsPt"), v0.pt(), bdtValue[0]); } } @@ -1280,7 +1280,7 @@ struct PCMQC { continue; } int idPos = -1, idNeg = -1; - for (const int daughterId : mctrack.daughtersIds()) { + for (const auto& daughterId : mctrack.daughtersIds()) { if (daughterId < 0 || daughterId >= static_cast(mcparticles.size())) { continue; } @@ -1346,7 +1346,7 @@ struct PCMQC { } if (recoQASettingsGroup.cfgDoDetailedTrackQA) { - for (const int legMcId : {idPos, idNeg}) { + for (const auto& legMcId : {idPos, idNeg}) { if (countIn(nTracksOfMcId, legMcId) == 0) { continue; } From 1583228d3c8c97fe8203580eb30f82f45a741f22 Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski Date: Wed, 2 Sep 2026 17:29:44 +0200 Subject: [PATCH 4/5] Unify QC + MaterialBudgetTasks --- PWGEM/PhotonMeson/Tasks/pcmQC.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index f5a27122721..63b1425bff0 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -438,6 +438,7 @@ struct PCMQC { fRegistry.add("Generated/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, true); fRegistry.add("Generated/hR_ConversionPhoton_wideR", "converted photon R_{xy} up to the EMCal, before fiducial cuts;R_{xy} (cm);N_{#gamma}", kTH1F, {{250, 0.0f, 500.0f}}, true); fRegistry.add("Generated/hRZ_wideR", "conversion point in RZ up to the EMCal, before fiducial cuts;V_{z} (cm);R_{xy} (cm)", kTH2F, {{200, -400.0f, 400.0f}, {250, 0.0f, 500.0f}}, true); + fRegistry.add("Generated/hsRZPhi_wideR", "conversion point up to the EMCal, before fiducial cuts;V_{z} (cm);#varphi (rad.);R_{xy} (cm)", kTHnSparseF, {{200, -400.0f, 400.0f}, {360, 0.0f, o2::constants::math::TwoPI}, {250, 0.0f, 500.0f}}, true); if (mcAnalysisModeSettings.cfgDoDetailedResolution) { fRegistry.add("Generated/hPtEtaPhi", "Photon pt vs eta, and phi;p_{T, gen} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); } @@ -1171,7 +1172,7 @@ struct PCMQC { fRegistry.fill(HIST("Generated/hR_ConversionPhoton_wideR"), rxy_gen_e); fRegistry.fill(HIST("Generated/hRZ_wideR"), daughter.vz(), rxy_gen_e); - + fRegistry.fill(HIST("Generated/hsRZPhi_wideR"), daughter.vz(), phi_cp, rxy_gen_e); if (rxy_gen_e < std::fabs(daughter.vz()) * std::tan(2 * std::atan(std::exp(-v0cuts.cfgMaxEtaV0))) - genSettingsGroup.cfgMarginZMC) { continue; } From 16e4b42272ecc375cf0c0287dc370e4ac7a419e4 Mon Sep 17 00:00:00 2001 From: Stefanie Mrozinski Date: Thu, 3 Sep 2026 09:36:52 +0200 Subject: [PATCH 5/5] add legacy tasks --- PWGEM/PhotonMeson/Legacy/MaterialBudget.cxx | 1317 +++++++++++++++++ PWGEM/PhotonMeson/Legacy/MaterialBudgetMC.cxx | 456 ++++++ PWGEM/PhotonMeson/Legacy/pcmQCMC.cxx | 822 ++++++++++ 3 files changed, 2595 insertions(+) create mode 100644 PWGEM/PhotonMeson/Legacy/MaterialBudget.cxx create mode 100644 PWGEM/PhotonMeson/Legacy/MaterialBudgetMC.cxx create mode 100644 PWGEM/PhotonMeson/Legacy/pcmQCMC.cxx diff --git a/PWGEM/PhotonMeson/Legacy/MaterialBudget.cxx b/PWGEM/PhotonMeson/Legacy/MaterialBudget.cxx new file mode 100644 index 00000000000..5baa0ebf6bc --- /dev/null +++ b/PWGEM/PhotonMeson/Legacy/MaterialBudget.cxx @@ -0,0 +1,1317 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MaterialBudget.cxx +/// \brief Task to analyse and calculate the material budget weights +/// \author S. Mrozinski, smrozins@cern.ch + +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::photon; +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils; +using o2::constants::math::TwoPI; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyCollisionsMC = soa::Join; +using MyCollisionMC = MyCollisionsMC::iterator; + +using MyMCCollisions = soa::Join; +using MyMCCollision = MyMCCollisions::iterator; + +using MyV0Photons = soa::Join; +using MyV0Photon = MyV0Photons::iterator; + +using MyPrimaryElectrons = soa::Filtered>; +using MyPrimaryElectron = MyPrimaryElectrons::iterator; + +using MyMCV0Legs = soa::Join; +using MyMCV0Leg = MyMCV0Legs::iterator; + +using MyTracks = soa::Join; +struct MaterialBudget { + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + + struct SimplePhoton { + float pt; + float eta; + float phi; + float vz; + float r; + }; + + static constexpr int MaxMixEvents = 5; + std::map, std::deque>> mixingPools; + + std::vector centBinEdges = {0, 10, 30, 50, 90, 200}; + std::vector zvtxBinEdges = {-10, -5, 0, 5, 10}; + + std::tuple getPoolBin(float cent, float zvtx) + { + int centbin = std::lower_bound(centBinEdges.begin(), centBinEdges.end(), cent) - centBinEdges.begin() - 1; + centbin = std::max(0, std::min(centbin, static_cast(centBinEdges.size()) - 2)); + + int zbin = std::lower_bound(zvtxBinEdges.begin(), zvtxBinEdges.end(), zvtx) - zvtxBinEdges.begin() - 1; + zbin = std::max(0, std::min(zbin, static_cast(zvtxBinEdges.size()) - 2)); + return {centbin, zbin}; + } + + HistogramRegistry registry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + static constexpr std::array ItsClsNames{ + "ITSCls0", "ITSCls1", "ITSCls2", "ITSCls3", + "ITSCls4", "ITSCls5", "ITSCls6", "ITSCls7"}; + + static constexpr std::array EventTypes{"before/", "after/"}; + + Configurable cfgPlotBremsstrahlung{"cfgPlotBremsstrahlung", false, "produce plots to study Bremsstrahlung"}; + Configurable cfgPlotResolution{"cfgPlotResolution", false, "produce plots to study resolution"}; + Configurable cfgPlotPurity{"cfgPlotPurity", false, "produce plots to study purity"}; + Configurable cfgPlotMBDetailed{"cfgPlotMBDetailed", false, "produce plots to study material distribution distribution"}; + Configurable cfgPlotMBGeneral{"cfgPlotMBGeneral", true, "produce plots to study material distribution"}; + Configurable cfgPlotMBCollisions{"cfgPlotMBCollisions", false, "produce plots to study material distribution if collision association is wrong"}; + + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 2.0}, ""}; + + EMPhotonEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + } eventcuts; + + DalitzEECut fDileptonCut; + struct : ConfigurableGroup { + std::string prefix = "dileptoncut_group"; + Configurable cfgMinMass{"cfgMinMass", 0.0, "min mass"}; + Configurable cfgMaxMass{"cfgMaxMass", 0.1, "max mass"}; + Configurable cfgApplyPhiv{"cfgApplyPhiv", true, "flag to apply phiv cut"}; + Configurable cfgRequireItsibAny{"cfgRequireItsibAny", false, "flag to require ITS ib any hits"}; + Configurable cfgRequireItsib1st{"cfgRequireItsib1st", true, "flag to require ITS ib 1st hit"}; + Configurable cfgPhivSlope{"cfgPhivSlope", 0.0185, "slope for m vs. phiv"}; + Configurable cfgPhivIntercept{"cfgPhivIntercept", -0.0280, "intercept for m vs. phiv"}; + + Configurable cfgMinPtTrack{"cfgMinPtTrack", 0.1, "min pT for single track"}; + Configurable cfgMaxEtaTrack{"cfgMaxEtaTrack", 0.8, "max eta for single track"}; + Configurable cfgMinnclusterTPC{"cfgMinnclusterTPC", 0, "min ncluster tpc"}; + Configurable cfgMinnclusterITS{"cfgMinnclusterITS", 5, "min ncluster its"}; + Configurable cfgMinncrossedrows{"cfgMinncrossedrows", 70, "min ncrossed rows"}; + Configurable cfgMaxchi2TPC{"cfgMaxchi2TPC", 4.0, "max chi2/NclsTPC"}; + Configurable cfgMaxchi2ITS{"cfgMaxchi2ITS", 36.0, "max chi2/NclsITS"}; + Configurable cfgMaxDCAxy{"cfgMaxDCAxy", 0.05, "max dca XY for single track in cm"}; + Configurable cfgMaxDCAz{"cfgMaxDCAz", 0.05, "max dca Z for single track in cm"}; + Configurable cfgMaxDCA3dsigmaTrack{"cfgMaxDCA3dsigmaTrack", 1.5, "max DCA 3D in sigma"}; + Configurable cfgMaxFracSharedClustersTPC{"cfgMaxFracSharedClustersTPC", 999.f, "max fraction of shared clusters in TPC"}; + Configurable cfgApplyCutsFromPrefilterDerived{"cfgApplyCutsFromPrefilterDerived", false, "flag to apply prefilter to electron"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to enable ITSsa tracks"}; + Configurable cfgMaxpttrackITSsa{"cfgMaxpttrackITSsa", 0.15, "max pt for ITSsa tracks"}; + + Configurable cfgPIDscheme{"cfgPIDscheme", static_cast(DalitzEECut::PIDSchemes::kTOFif), "pid scheme [kTOFif : 0, kTPConly : 1]"}; + Configurable cfgMinTPCNsigmaEl{"cfgMinTPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; + Configurable cfgMaxTPCNsigmaEl{"cfgMaxTPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; + Configurable cfgMinTPCNsigmaPi{"cfgMinTPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; + Configurable cfgMaxTPCNsigmaPi{"cfgMaxTPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; + Configurable cfgMinTOFNsigmaEl{"cfgMinTOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; + Configurable cfgMaxTOFNsigmaEl{"cfgMaxTOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; + } dileptoncuts; + + V0PhotonCut fV0PhotonCut; + struct : ConfigurableGroup { + std::string prefix = "pcmcut_group"; + Configurable cfgRequireV0WithITSTPC{"cfgRequireV0WithITSTPC", false, "flag to select V0s with ITS-TPC matched tracks"}; + Configurable cfgRequireV0WithITSOnly{"cfgRequireV0WithITSOnly", false, "flag to select V0s with ITSonly tracks"}; + Configurable cfgRequireV0WithTPCOnly{"cfgRequireV0WithTPCOnly", false, "flag to select V0s with TPConly tracks"}; + Configurable cfgMinPtV0{"cfgMinPtV0", 0.1, "min pT for v0 photons at PV"}; + Configurable cfgMaxPtV0{"cfgMaxPtV0", 1e+10, "max pT for v0 photons at PV"}; + Configurable cfgMinEtaV0{"cfgMinEtaV0", -0.8, "min eta for v0 photons at PV"}; + Configurable cfgMaxEtaV0{"cfgMaxEtaV0", +0.8, "max eta for v0 photons at PV"}; + Configurable cfgMinV0Radius{"cfgMinV0Radius", 4.0, "min v0 radius"}; + Configurable cfgMaxV0Radius{"cfgMaxV0Radius", 90.0, "max v0 radius"}; + Configurable cfgMaxAlphaAp{"cfgMaxAlphaAp", 0.95, "max alpha for AP cut"}; + Configurable cfgMaxQtAp{"cfgMaxQtAp", 0.01, "max qT for AP cut"}; + Configurable cfgMinCospa{"cfgMinCospa", 0.999, "min V0 CosPA"}; + Configurable cfgMaxPca{"cfgMaxPca", 1.5, "max distance btween 2 legs"}; + Configurable cfgMaxChi2kf{"cfgMaxChi2kf", 1e+10, "max chi2/ndf with KF"}; + Configurable cfgRejectV0OnITSib{"cfgRejectV0OnITSib", true, "flag to reject V0s on ITSib"}; + Configurable cfgMinNclusterTPC{"cfgMinNclusterTPC", 0, "min ncluster tpc"}; + Configurable cfgMinNcrossedrows{"cfgMinNcrossedrows", 40, "min ncrossed rows"}; + Configurable cfgMaxFracSharedClustersTPC{"cfgMaxFracSharedClustersTPC", 999.f, "max fraction of shared clusters in TPC"}; + Configurable cfgMaxChi2TPC{"cfgMaxChi2TPC", 4.0, "max chi2/NclsTPC"}; + Configurable cfgMaxChi2ITS{"cfgMaxChi2ITS", 36.0, "max chi2/NclsITS"}; + Configurable cfgMinTPCNsigmaEl{"cfgMinTPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; + Configurable cfgMaxTPCNsigmaEl{"cfgMaxTPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; + Configurable cfgDisableITSonlytrack{"cfgDisableITSonlytrack", false, "flag to disable ITSonly tracks"}; + Configurable cfgDisableTPCOnlytrack{"cfgDisableTPCOnlytrack", false, "flag to disable TPConly tracks"}; + } pcmcuts; + + void init(InitContext&) + { + + defineEMEventCut(); + defineDileptonCut(); + definePCMCut(); + addhistograms(); + } + + void defineEMEventCut() + { + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); + fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); + fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); + fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); + } + + void defineDileptonCut() + { + fDileptonCut = DalitzEECut("fDileptonCut", "fDileptonCut"); + + // for pair + fDileptonCut.SetMeeRange(dileptoncuts.cfgMinMass, dileptoncuts.cfgMaxMass); + fDileptonCut.SetMaxPhivPairMeeDep([&](float mll) { return (mll - dileptoncuts.cfgPhivIntercept) / dileptoncuts.cfgPhivSlope; }); + fDileptonCut.ApplyPhiV(dileptoncuts.cfgApplyPhiv); + fDileptonCut.RequireITSibAny(dileptoncuts.cfgRequireItsibAny); + fDileptonCut.RequireITSib1st(dileptoncuts.cfgRequireItsib1st); + + // for tracks + fDileptonCut.SetTrackPtRange(dileptoncuts.cfgMinPtTrack, 1e+10f); + fDileptonCut.SetTrackEtaRange(-dileptoncuts.cfgMaxEtaTrack, +dileptoncuts.cfgMaxEtaTrack); + fDileptonCut.SetMinNClustersTPC(dileptoncuts.cfgMinnclusterTPC); + fDileptonCut.SetMinNCrossedRowsTPC(dileptoncuts.cfgMinncrossedrows); + fDileptonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fDileptonCut.SetMaxFracSharedClustersTPC(dileptoncuts.cfgMaxFracSharedClustersTPC); + fDileptonCut.SetChi2PerClusterTPC(0.0, dileptoncuts.cfgMaxchi2TPC); + fDileptonCut.SetChi2PerClusterITS(0.0, dileptoncuts.cfgMaxchi2ITS); + fDileptonCut.SetNClustersITS(dileptoncuts.cfgMinnclusterITS, 7); + fDileptonCut.SetMaxDcaXY(dileptoncuts.cfgMaxDCAxy); + fDileptonCut.SetMaxDcaZ(dileptoncuts.cfgMaxDCAz); + fDileptonCut.SetTrackDca3DRange(0.f, dileptoncuts.cfgMaxDCA3dsigmaTrack); // in sigma + fDileptonCut.IncludeITSsa(dileptoncuts.includeITSsa, dileptoncuts.cfgMaxpttrackITSsa); + + // for eID + fDileptonCut.SetPIDScheme(dileptoncuts.cfgPIDscheme); + fDileptonCut.SetTPCNsigmaElRange(dileptoncuts.cfgMinTPCNsigmaEl, dileptoncuts.cfgMaxTPCNsigmaEl); + fDileptonCut.SetTPCNsigmaPiRange(dileptoncuts.cfgMinTPCNsigmaPi, dileptoncuts.cfgMaxTPCNsigmaPi); + fDileptonCut.SetTOFNsigmaElRange(dileptoncuts.cfgMinTOFNsigmaEl, dileptoncuts.cfgMaxTOFNsigmaEl); + } + + void definePCMCut() + { + fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); + + // for v0 + fV0PhotonCut.SetV0PtRange(pcmcuts.cfgMinPtV0, pcmcuts.cfgMaxPtV0); + fV0PhotonCut.SetV0EtaRange(pcmcuts.cfgMinEtaV0, pcmcuts.cfgMaxEtaV0); + fV0PhotonCut.SetMinCosPA(pcmcuts.cfgMinCospa); + fV0PhotonCut.SetMaxPCA(pcmcuts.cfgMaxPca); + fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfgMaxChi2kf); + fV0PhotonCut.SetRxyRange(pcmcuts.cfgMinV0Radius, pcmcuts.cfgMaxV0Radius); + fV0PhotonCut.SetAPRange(pcmcuts.cfgMaxAlphaAp, pcmcuts.cfgMaxQtAp); + fV0PhotonCut.RejectITSib(pcmcuts.cfgRejectV0OnITSib); + + // for track + fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfgMinNclusterTPC); + fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfgMinNcrossedrows); + fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfgMaxFracSharedClustersTPC); + fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfgMaxChi2TPC); + fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfgMinTPCNsigmaEl, pcmcuts.cfgMaxTPCNsigmaEl); + fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfgMaxChi2ITS); + fV0PhotonCut.SetNClustersITS(0, 7); + fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); + fV0PhotonCut.SetDisableITSonly(pcmcuts.cfgDisableITSonlytrack); + fV0PhotonCut.SetDisableTPConly(pcmcuts.cfgDisableTPCOnlytrack); + fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfgRequireV0WithITSTPC); + fV0PhotonCut.SetRequireITSonly(pcmcuts.cfgRequireV0WithITSOnly); + fV0PhotonCut.SetRequireTPConly(pcmcuts.cfgRequireV0WithTPCOnly); + } + + void addhistograms() + { + const AxisSpec axisPt{binsPt, "#it{p}_{T} [GeV/c]"}; + auto hCollisionCounter = registry.add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{10, 0.5, 10.5}}, false); + hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); + hCollisionCounter->GetXaxis()->SetBinLabel(2, "No TF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(3, "No ITS ROF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(4, "No Same Bunch Pileup"); + hCollisionCounter->GetXaxis()->SetBinLabel(5, "Is Vertex ITSTPC"); + hCollisionCounter->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); + hCollisionCounter->GetXaxis()->SetBinLabel(7, "FT0AND"); + hCollisionCounter->GetXaxis()->SetBinLabel(8, "sel8"); + hCollisionCounter->GetXaxis()->SetBinLabel(9, "|Z_{vtx}| < 10 cm"); + hCollisionCounter->GetXaxis()->SetBinLabel(10, "accepted"); + + registry.add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + registry.add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + registry.add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + registry.add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{300, 0, 6000}, {300, 0, 6000}}, false); + registry.add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); + registry.add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); + registry.add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + registry.add("Event/before/hCentFT0MvsMultNTracksPV", "hCentFT0MvsMultNTracksPV;centrality FT0M (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); + registry.add("Event/before/hMultFT0MvsMultNTracksPV", "hMultFT0MvsMultNTracksPV;mult. FT0M;N_{track} to PV", kTH2F, {{600, 0, 6000}, {600, 0, 6000}}, false); + registry.addClone("Event/before/", "Event/after/"); + + if (cfgPlotMBGeneral) { + + registry.add("MBGeneral", ";z_{conv} (cm); R_{conv} (cm); #eta; #varphi (rad); p_{T}", kTHnSparseF, + {{200, -100.f, 100.f}, + {100, 0.f, 100.f}, + {80, -2, +2}, + {90, 0, o2::constants::math::TwoPI}, + {1000, 0, 10}}, // pT 5 + true); + + registry.add("Pi0/Same", + "Pi0; m_{#gamma#gamma}; #it{p}_{T}; R_{conv} (cm); R_{conv} (cm)", + kTHnSparseF, + {{400, 0.f, 0.3}, // x 0 + {500, 0, 10}, // pT 1 + {100, 0.f, 100.f}, // R of photon 1 + {100, 0.f, 100.f}}, + true); + + registry.add("Dalitz/Same", + "Dalitz; m_{eeγ}; p_{T}; R_{γ} (cm); R_{e+}; R_{e-}", + kTHnSparseF, + {{400, 0.f, 0.5f}, + {500, 0.f, 10.f}, + {100, 0.f, 100.f}}, + true); + + registry.add("Pi0/Mix", "Pi0 mixed-event;m_{#gamma#gamma};p_{T}", kTHnSparseF, + {{400, 0, 0.3}, {500, 0, 10}, {100, 0, 100}, {100, 0, 100}}, true); + } + + if (cfgPlotMBDetailed) { + + registry.add("MBStudiesWireLeft", + "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", + kTHnSparseF, + { + {200, -20.f, 20.f}, // x 0 + {200, -20.f, 20.f}, // y 1 + {80, -20.f, 20.f}, // z 2 + {40, 3.15, 3.4}, // phi 3 + {80, 0.f, 20.f}, // conversion radius 4 + {1000, 0, 10} // pT 5 + }, + true); + + registry.add("MBStudiesWireRight", + "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", + kTHnSparseF, + { + {200, -20.f, 20.f}, // x 0 + {200, -20.f, 20.f}, // y 1 + {80, -20.f, 20.f}, // z 2 + {40, 6.00, 6.15}, // phi 3 + {80, 0.f, 20.f}, // conversion radius 4 + {1000, 0, 10} // pT 5 + }, + true); + + registry.add("MBStudiesWireITS", + "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", + kTHnSparseF, + { + {160, -40.f, 40.f}, // x 0 + {160, -40.f, 40.f}, // y 1 + {80, -40.f, 40.f}, // z 2 + {90, 0, TwoPI}, // phi 3 + {150, 0.f, 60.f}, // conversion radius 4 + {1000, 0, 10} // pT 5 + }, + true); + + registry.add("MBStudiesMFT", + "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", + kTHnSparseF, + { + {160, -80.f, 80.f}, // x 0 + {160, -80.f, 80.f}, // y 1 + {40, -40.f, 40.f}, // z 2 + {90, 0, TwoPI}, // phi 3 + {40, 40.f, 60.f}, // conversion radius 4 + {500, 0, 10} // pT 5 + }, + true); + + registry.add("MBStudiesTPC", + "photon characteristics for MB studies; x (cm); y (cm); z (cm); #varphi (rad.); R_{conv} (cm)", + kTHnSparseF, + { + {160, -90.f, 90.f}, // x 0 + {160, -90.f, 90.f}, // y 1 + {80, -40.f, 40.f}, // z 2 + {90, 0, TwoPI}, // phi 3 + {80, 60.f, 80.f}, // conversion radius 4 + {1000, 0, 10} // pT 5 + }, + true); + + for (int nCls = 0; nCls <= 7; nCls++) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + registry.add(Form("ITSHits/Neg/ITSCls%d", nCls), + Form("Conversion radius NEG legs with %d ITS clusters;R_{conv} (cm);Entries", nCls), + HistType::kTH1F, + {AxisSpec{100, 0.f, 100.f}}); + + registry.add(Form("ITSHits/Pos/ITSCls%d", nCls), + Form("Conversion radius POS legs with %d ITS clusters;R_{conv} (cm);Entries", nCls), + HistType::kTH1F, + {AxisSpec{100, 0.f, 100.f}}); + } + } + + if (cfgPlotResolution) { + + registry.add("ResolutionGen/Z_res", + "Z resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;Δz (cm)", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {120, -30, 30}}, false); + + registry.add("ResolutionGen/R_res", + "R resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;ΔR (cm)", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {120, -30, 30}}, false); + + registry.add("ResolutionGen/Phi_res", + "Phi resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;Δφ", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {100, -0.2f, 0.2f}}, false); + + registry.add("ResolutionGen/Pt_res", + "pT resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;ΔpT/pT_gen", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {200, -1.0f, 1.0f}}, false); + + registry.add("ResolutionGen/Eta_res", + "Eta resolution (gen ref);z_gen (cm);R_gen (cm);phi_gen;eta_gen;pT_gen;Δη", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {100, -0.5f, 0.5f}}, false); + + registry.add("ResolutionRec/Z_res", + "Z resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;Δz (cm)", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {120, -30, 30}}, false); + + registry.add("ResolutionRec/R_res", + "R resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;ΔR (cm)", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {120, -30, 30}}, false); + + registry.add("ResolutionRec/Phi_res", + "Phi resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;Δφ", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {100, -0.2f, 0.2f}}, false); + + registry.add("ResolutionRec/Pt_res", + "pT resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;ΔpT/pT_gen", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {200, -1.0f, 1.0f}}, false); + + registry.add("ResolutionRec/Eta_res", + "Eta resolution (rec ref);z_rec (cm);R_rec (cm);phi_rec;eta_rec;pT_rec;Δη", + kTHnSparseF, + {{200, -100, 100}, {200, 0, 100}, {90, 0, TwoPI}, {200, -1.0f, 1.0f}, {500, 0, 10}, {100, -0.5f, 0.5f}}, false); + } + + if (cfgPlotPurity) { + + registry.add("PhotonPurity", + "Photon purity classification;p_{T} (GeV/c);R_{conv} (cm);#eta;#varphi;category", + kTHnSparseF, + { + {500, 0, 10}, // pT + {200, 0, 100}, // R + {100, -1.0, 1.0}, // eta + {90, 0, o2::constants::math::TwoPI}, // phi + {12, 0.5, 12.5} // purity categories + }, + true); + + auto hPurity = registry.get(HIST("PhotonPurity")); + + auto axis = hPurity->GetAxis(4); + + axis->SetBinLabel(1, "e^{+}e^{-}"); + axis->SetBinLabel(2, "e^{-} + #pi^{+}"); + axis->SetBinLabel(3, "#pi^{-} + e^{+}"); + axis->SetBinLabel(4, "K^{-} + e^{+}"); + axis->SetBinLabel(5, "e^{-} + K^{+}"); + axis->SetBinLabel(6, "#bar{p} + p"); + axis->SetBinLabel(7, "K^{-} + K^{+}"); + axis->SetBinLabel(8, "#pi^{-} + p"); + axis->SetBinLabel(9, "#bar{p} + #pi^{+}"); + axis->SetBinLabel(10, "#mu^{-} + #mu^{+}"); + } + + if (cfgPlotBremsstrahlung) { + + registry.add("Bremsstrahlung/EnergyLossVsR", ";R (cm);E_{loss} (GeV)", + kTH2F, {{50, 0, 100}, {100, 0, 5}}); + registry.add("Bremsstrahlung/EnergyLossXY", ";X (cm);Y (cm)", + kTH2F, {{100, -100, 100}, {100, -100, 100}}); + registry.add("Bremsstrahlung/EnergyLossXYWeigh", ";X (cm);Y (cm)", + kTH2F, {{100, -100, 100}, {100, -100, 100}}); + registry.add("Bremsstrahlung/EnergyLossVsZ", ";Z (cm);E_{loss} (GeV)", + kTH2F, {{100, -100, 100}, {200, 0, 5}}); + + registry.add("Bremsstrahlung/NBrem", ";N_{Brem} per e^{-};Counts", + kTH1I, {{10, 0, 10}}); + + registry.add("Bremsstrahlung/DeltaPoverPvsR", ";R (cm);(p_{Reco}-p_{MC})/p_{MC}", + kTH2F, {{50, 0, 100}, {200, -1, 1}}); + registry.add("Bremsstrahlung/DeltaPtvsR", ";R (cm);(p_{T,Reco}-p_{T,MC})/p_{T,MC}", + kTH2F, {{50, 0, 100}, {300, -2, 2}}); + registry.add("Bremsstrahlung/DeltaPhivsR", ";R (cm);#Delta#varphi (rad)", + kTH2F, {{50, 0, 100}, {200, -0.1, 0.1}}); + registry.add("Bremsstrahlung/DeltaEtavsR", ";R (cm);#Delta#eta", + kTH2F, {{50, 0, 100}, {200, -0.1, 0.1}}); + + registry.add("Bremsstrahlung/Sigma1PtVsR", ";R (cm);#sigma(1/p_{T}) [c/GeV]", + kTH2F, {{50, 0, 100}, {100, 0, 0.1}}); + + registry.add("Bremsstrahlung/SigmaYVsR", ";R (cm);#sigma(y) [cm]", + kTH2F, {{50, 0, 100}, {100, 0, 0.5}}); + registry.add("Bremsstrahlung/SigmaZVsR", ";R (cm);#sigma(z) [cm]", + kTH2F, {{50, 0, 100}, {100, 0, 1.0}}); + + registry.add("Bremsstrahlung/relativeResoPtWBrems", + "relative #it{p}_{T} resolution; #it{p}_{T}; #sigma(#it{p}_{T})/#it{p}_{T}", + kTProfile, + {axisPt}); + + registry.add("Bremsstrahlung/relativeResoPtWOBrems", + "relative #it{p}_{T} resolution; #it{p}_{T}; #sigma(#it{p}_{T})/#it{p}_{T}", + kTProfile, + {axisPt}); + } + + if (cfgPlotMBCollisions) { + + registry.add("RightCollisions/SparseDeltaCol", + "RightCollisions;R_{rec} (cm);#it{p}_{T} (GeV/c);#Delta #it{p}_{T}/#it{p}_{T,gen};#Delta z (cm);#Delta R (cm);#Delta col ID", + kTHnSparseF, + { + {100, 0.f, 100.f}, // R_rec + {200, 0.f, 10.f}, // pT + {200, -1.f, 1.f}, // ΔpT/pT + {200, -20.f, 20.f}, // Δz + {200, -8.f, 8.f}, // ΔR + {21, -10.5, 10.5} // ΔCollisionID + }, + true); + + registry.add("WrongCollisions/SparseDeltaCol", + "WrongCollisions;R_{rec} (cm);#it{p}_{T} (GeV/c);#Delta #it{p}_{T}/#it{p}_{T,gen};#Delta z (cm);#Delta R (cm);#Delta col ID", + kTHnSparseF, + {{100, 0.f, 100.f}, + {200, 0.f, 10.f}, + {200, -1.f, 1.f}, + {200, -20.f, 20.f}, + {200, -8.f, 8.f}, + {21, -10.5, 10.5}}, + true); + } + } + + template + void fillITSClsNeg(HistogramRegistry& reg, float value) + { + if constexpr (N == 0) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Neg/ITSCls0"), value); + } + if constexpr (N == 1) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Neg/ITSCls1"), value); + } + if constexpr (N == 2) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Neg/ITSCls2"), value); + } + if constexpr (N == 3) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Neg/ITSCls3"), value); + } + if constexpr (N == 4) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Neg/ITSCls4"), value); + } + if constexpr (N == 5) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Neg/ITSCls5"), value); + } + if constexpr (N == 6) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Neg/ITSCls6"), value); + } + if constexpr (N == 7) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Neg/ITSCls7"), value); + } + } + + template + void fillITSClsPos(HistogramRegistry& reg, float value) + { + if constexpr (N == 0) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Pos/ITSCls0"), value); + } + if constexpr (N == 1) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Pos/ITSCls1"), value); + } + if constexpr (N == 2) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Pos/ITSCls2"), value); + } + if constexpr (N == 3) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Pos/ITSCls3"), value); + } + if constexpr (N == 4) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Pos/ITSCls4"), value); + } + if constexpr (N == 5) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Pos/ITSCls5"), value); + } + if constexpr (N == 6) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Pos/ITSCls6"), value); + } + if constexpr (N == 7) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + reg.fill(HIST("ITSHits/Pos/ITSCls7"), value); + } + } + + template + void reconstructMesons(const TV0s& v0s) + { + for (auto i = 0; i < v0s.size(); i++) { + auto g1 = v0s.iteratorAt(i); + + for (auto j = i + 1; j < v0s.size(); j++) { + auto g2 = v0s.iteratorAt(j); + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + registry.fill(HIST("Pi0/Same"), v12.M(), v12.Pt(), + g1.v0radius(), g2.v0radius()); + } + } + } + + void fillClusterNeg(HistogramRegistry& reg, int nCls, float value) + { + switch (nCls) { + case 0: // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillITSClsNeg<0>(reg, value); + break; + case 1: // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillITSClsNeg<1>(reg, value); + break; + case 2: // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillITSClsNeg<2>(reg, value); + break; + case 3: // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillITSClsNeg<3>(reg, value); + break; + case 4: // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillITSClsNeg<4>(reg, value); + break; + case 5: // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillITSClsNeg<5>(reg, value); + break; + case 6: // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillITSClsNeg<6>(reg, value); + break; + case 7: // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillITSClsNeg<7>(reg, value); + break; + default: + break; + } + } + + void fillClusterPos(HistogramRegistry& reg, int nCls, float value) + { + switch (nCls) { + case 0: + fillITSClsPos<0>(reg, value); + break; + case 1: + fillITSClsPos<1>(reg, value); + break; + case 2: + fillITSClsPos<2>(reg, value); + break; + case 3: + fillITSClsPos<3>(reg, value); + break; + case 4: + fillITSClsPos<4>(reg, value); + break; + case 5: + fillITSClsPos<5>(reg, value); + break; + case 6: + fillITSClsPos<6>(reg, value); + break; + case 7: + fillITSClsPos<7>(reg, value); + break; + default: + break; + } + } + template + void fillEventInfo(TCollision const& collision, const float /*weight*/ = 1.f) + { + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 7.0); + } + if (collision.sel8()) { + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 8.0); + } + if (std::fabs(collision.posZ()) < 10.0) { // o2-linter: disable=magic-number (vertex position) + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCollisionCounter"), 9.0); + } + + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hZvtx"), collision.posZ()); + + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hMultNTracksPV"), collision.multNTracksPV()); + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C()); + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCentFT0A"), collision.centFT0A()); + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCentFT0C"), collision.centFT0C()); + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCentFT0M"), collision.centFT0M()); + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hCentFT0MvsMultNTracksPV"), collision.centFT0M(), collision.multNTracksPV()); + registry.fill(HIST("Event/") + HIST(EventTypes[evID]) + HIST("hMultFT0MvsMultNTracksPV"), collision.multFT0A() + collision.multFT0C(), collision.multNTracksPV()); + } + template + void reconstructMesonsMixed(const TV0s& current, + const std::deque>& pool) + { + for (const auto& prev : pool) { + for (const auto& g1 : current) { + if (!fV0PhotonCut.IsSelected(g1)) { + continue; + } + for (const auto& g2 : prev) { + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector v2(g2.pt, g2.eta, g2.phi, 0.); + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + + registry.fill(HIST("Pi0/Mix"), v12.M(), v12.Pt(), + g1.v0radius(), g2.r); + } + } + } + } + + template + void reconstructDalitz(const TV0s& v0s, + const TPositrons& positronsPerCollision, + const TElectrons& electronsPerCollision, + MyCollision const& collision) + { + + for (const auto& g1 : v0s) { + if (!fV0PhotonCut.IsSelected(g1)) { + continue; + } + ROOT::Math::PtEtaPhiMVector vGamma(g1.pt(), g1.eta(), g1.phi(), 0.); + + for (const auto& [pos, ele] : + combinations(CombinationsFullIndexPolicy(positronsPerCollision, + electronsPerCollision))) { + + if (pos.trackId() == ele.trackId()) { + continue; + } + + if (!fDileptonCut.template IsSelectedTrack(pos, collision) || + !fDileptonCut.template IsSelectedTrack(ele, collision)) { + continue; // Track-Cuts + } + + ROOT::Math::PtEtaPhiMVector vPos(pos.pt(), pos.eta(), pos.phi(), + o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector vEle(ele.pt(), ele.eta(), ele.phi(), + o2::constants::physics::MassElectron); + + auto vee = vPos + vEle; + auto veGamma = vGamma + vee; + + registry.fill(HIST("Dalitz/Same"), + veGamma.M(), vee.Pt(), + g1.v0radius()); + } + } + } + + SliceCache cache; + Preslice perCollision = aod::v0photonkf::pmeventId; + Preslice perCollisionElectron = aod::emprimaryelectronda::pmeventId; + + Partition positrons = o2::aod::emprimaryelectron::sign > int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt&& nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; + Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0) && dileptoncuts.cfgMinPtTrack < o2::aod::track::pt && nabs(o2::aod::track::eta) < dileptoncuts.cfgMaxEtaTrack; + + Filter prefilterPrimaryelectron = ifnode(dileptoncuts.cfgApplyCutsFromPrefilterDerived.node(), o2::aod::emprimaryelectron::pfbderived == static_cast(0), true); + + void processRec(MyCollisions const& collisions, + MyV0Photons const& v0photons, + aod::V0Legs const&, + MyPrimaryElectrons const& electrons) + { + + for (const auto& collision : collisions) { + const std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + fillEventInfo<0>(collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fillEventInfo<1>(collision); + registry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted + registry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted + + auto v0sThisCollision = v0photons.sliceBy(perCollision, collision.globalIndex()); + + for (const auto& v0 : v0sThisCollision) { + + if (!fV0PhotonCut.IsSelected(v0)) { + continue; + } + + auto negLeg = v0.template negTrack_as(); + auto posLeg = v0.template posTrack_as(); + + int nClsNeg = 0; + int nClsPos = 0; + + if constexpr (requires { negLeg.itsNCls(); }) { + nClsNeg = negLeg.itsNCls(); + nClsPos = posLeg.itsNCls(); + } else if constexpr (requires { negLeg.itsClusterMap(); }) { + auto countBits = [](uint8_t map) { + return std::bitset<8>(map).count(); + }; + nClsNeg = countBits(negLeg.itsClusterMap()); + nClsPos = countBits(posLeg.itsClusterMap()); + } + if (nClsNeg >= 0 && nClsNeg <= 7) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillClusterNeg(registry, nClsNeg, v0.v0radius()); + } + if (nClsPos >= 0 && nClsPos <= 7) { // o2-linter: disable=magic-number (just numbers for ITS cluster) + fillClusterPos(registry, nClsPos, v0.v0radius()); + } + + if (cfgPlotMBGeneral) { + + registry.fill( + HIST("MBGeneral"), + v0.vz(), // 0 + v0.v0radius(), // 1 + v0.eta(), // 2 + v0.phi(), // 3 + v0.pt()); // 4 + } + + if (cfgPlotMBDetailed) { + + registry.fill( + HIST("MBStudiesWireLeft"), + v0.vx(), // 0 + v0.vy(), // 1 + v0.vz(), // 2 + v0.phi(), // 3 + v0.v0radius(), // 4 + v0.pt()); // 5 + + registry.fill( + HIST("MBStudiesWireRight"), + v0.vx(), // 0 + v0.vy(), // 1 + v0.vz(), // 2 + v0.phi(), // 3 + v0.v0radius(), // 4 + v0.pt()); // 5 + + registry.fill( + HIST("MBStudiesWireITS"), + v0.vx(), // 0 + v0.vy(), // 1 + v0.vz(), // 2 + v0.phi(), // 3 + v0.v0radius(), // 4 + v0.pt()); // 5 + + registry.fill( + HIST("MBStudiesMFT"), + v0.vx(), // 0 + v0.vy(), // 1 + v0.vz(), // 2 + v0.phi(), // 3 + v0.v0radius(), // 4 + v0.pt()); // 5 + + registry.fill( + HIST("MBStudiesTPC"), + v0.vx(), // 0 + v0.vy(), // 1 + v0.vz(), // 2 + v0.phi(), // 3 + v0.v0radius(), // 4 + v0.pt()); // 5 + } + } + + reconstructMesons(v0sThisCollision); + + auto electronsPerCollision = electrons.sliceBy(perCollisionElectron, collision.globalIndex()); + auto positronsPerCollision = positrons.sliceBy(perCollisionElectron, collision.globalIndex()); + + reconstructDalitz(v0sThisCollision, positronsPerCollision, electronsPerCollision, collision); + + auto key = getPoolBin(centralities[cfgCentEstimator], collision.posZ()); + auto& pool = mixingPools[key]; + reconstructMesonsMixed(v0sThisCollision, pool); + + std::vector eventCopy; + eventCopy.reserve(v0sThisCollision.size()); + for (const auto& v0 : v0sThisCollision) { + if (!fV0PhotonCut.IsSelected(v0)) { + continue; + } + eventCopy.push_back({v0.pt(), v0.eta(), v0.phi(), v0.vz(), v0.v0radius()}); + } + pool.emplace_back(std::move(eventCopy)); + + if (pool.size() > MaxMixEvents) { + pool.pop_front(); + } + } + } + + int classifyPurity(int pdgNeg, int pdgPos) + { + if (pdgNeg == kElectron && pdgPos == kPositron) { + return 1; + } + if (pdgNeg == kElectron && pdgPos == kPiPlus) { + return 2; + } + if (pdgNeg == kPiMinus && pdgPos == kPositron) { + return 3; + } + if (pdgNeg == kKMinus && pdgPos == kPositron) { + return 4; + } + if (pdgNeg == kElectron && pdgPos == kKPlus) { + return 5; + } + if (pdgNeg == kProtonBar && pdgPos == kProton) { + return 6; + } + if (pdgNeg == kKMinus && pdgPos == kKPlus) { + return 7; + } + if (pdgNeg == kPiMinus && pdgPos == kProton) { + return 8; + } + if (pdgNeg == kProtonBar && pdgPos == kPiPlus) { + return 9; + } + if (pdgNeg == kMuonMinus && pdgPos == kMuonPlus) { + return 10; + } + return 11; + } + + Partition groupedCollisions = cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax; // this goes to same event. + Filter collisionFilterCommon = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > static_cast(0) && o2::aod::evsel::sel8 == true; // o2-linter: disable=magic-number (vertex position) + Filter collisionFilterCentrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + using MyFilteredCollisions = soa::Filtered; // this goes to same event pairing. + + void processTrue(MyCollisions const&, MyFilteredCollisions const& filteredCollisions, + MyV0Photons const& v0photons, + MyMCV0Legs const&, + aod::EMMCParticles const& mcparticles, + aod::EMMCEvents const&) + { + for (const auto& collision : filteredCollisions) { + + const std::array centralities = { + collision.centFT0M(), + collision.centFT0A(), + collision.centFT0C()}; + + if (centralities[cfgCentEstimator] < cfgCentMin || + cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + fillEventInfo<0>(collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + fillEventInfo<1>(collision); + + registry.fill(HIST("Event/before/hCollisionCounter"), 10.0); + registry.fill(HIST("Event/after/hCollisionCounter"), 10.0); + + auto v0PhotonsColl = v0photons.sliceBy(perCollision, collision.globalIndex()); + + for (const auto& v0 : v0PhotonsColl) { + + auto pos = v0.posTrack_as(); + auto ele = v0.negTrack_as(); + + auto posmc = pos.template emmcparticle_as(); + auto elemc = ele.template emmcparticle_as(); + + if (!fV0PhotonCut.IsSelected(v0)) { + continue; + } + + int purityCat = 12; // default: unmatched + + purityCat = classifyPurity(elemc.pdgCode(), posmc.pdgCode()); + + float rConv = v0.v0radius(); + registry.fill(HIST("PhotonPurity"), + v0.pt(), rConv, v0.eta(), v0.phi(), purityCat); + + int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); + if (photonid < 0) { + continue; + } + + auto mcphoton = mcparticles.iteratorAt(photonid); + + float rRec = v0.v0radius(); + float rGen = std::sqrt(mcphoton.vx() * mcphoton.vx() + + mcphoton.vy() * mcphoton.vy()); + float deltaR = rRec - rGen; + float deltaZ = v0.vz() - mcphoton.vz(); + float deltaPhi = v0.phi() - mcphoton.phi(); + float deltaEta = v0.eta() - mcphoton.eta(); + float deltaPt = v0.pt() - mcphoton.pt(); + + registry.fill(HIST("ResolutionGen/Z_res"), + mcphoton.vz(), rGen, mcphoton.phi(), + mcphoton.eta(), mcphoton.pt(), deltaZ); + + registry.fill(HIST("ResolutionGen/R_res"), + mcphoton.vz(), rGen, mcphoton.phi(), + mcphoton.eta(), mcphoton.pt(), deltaR); + + registry.fill(HIST("ResolutionGen/Phi_res"), + mcphoton.vz(), rGen, mcphoton.phi(), + mcphoton.eta(), mcphoton.pt(), deltaPhi); + + registry.fill(HIST("ResolutionGen/Eta_res"), + mcphoton.vz(), rGen, mcphoton.phi(), + mcphoton.eta(), mcphoton.pt(), deltaEta); + + registry.fill(HIST("ResolutionGen/Pt_res"), + mcphoton.vz(), rGen, mcphoton.phi(), + mcphoton.eta(), mcphoton.pt(), + deltaPt / mcphoton.pt()); + + registry.fill(HIST("ResolutionRec/Z_res"), + v0.vz(), rRec, v0.phi(), v0.eta(), + v0.pt(), deltaZ); + + registry.fill(HIST("ResolutionRec/R_res"), + v0.vz(), rRec, v0.phi(), v0.eta(), + v0.pt(), deltaR); + + registry.fill(HIST("ResolutionRec/Phi_res"), + v0.vz(), rRec, v0.phi(), v0.eta(), + v0.pt(), deltaPhi); + + registry.fill(HIST("ResolutionRec/Eta_res"), + v0.vz(), rRec, v0.phi(), v0.eta(), + v0.pt(), deltaEta); + + registry.fill(HIST("ResolutionRec/Pt_res"), + v0.vz(), rRec, v0.phi(), v0.eta(), + v0.pt(), deltaPt / mcphoton.pt()); + } + } + } + + void processCollAssoc(MyCollisionsMC const& collisions, + MyMCCollisions const&, + aod::EMMCParticles const& mcparticles, + MyV0Photons const& v0photons, + MyMCV0Legs const&) + { + for (auto const& col : collisions) { + + auto mccollision = col.emmcevent_as(); + + auto v0s = v0photons.sliceBy(perCollision, col.globalIndex()); + + int mcColIdDerived = mccollision.globalIndex(); // MC event (derived) global index + + for (auto const& v0 : v0s) { + + if (!fV0PhotonCut.IsSelected(v0)) { + continue; + } + + auto negLeg = v0.negTrack_as(); + auto posLeg = v0.posTrack_as(); + + auto negMC = negLeg.template emmcparticle_as(); + auto posMC = posLeg.template emmcparticle_as(); + + // find the photon mother in MC + int photonId = FindCommonMotherFrom2Prongs(posMC, negMC, -11, 11, 22, mcparticles); + if (photonId < 0) { + continue; + } + + auto mcPhoton = mcparticles.iteratorAt(photonId); + auto trueMcCol = mcPhoton.emmcevent_as(); // MC event where the photon was generated + int trueMcColIndex = trueMcCol.globalIndex(); + + int deltaCol = mcColIdDerived - trueMcColIndex; + + float rRec = v0.v0radius(); + float rGen = std::sqrt(mcPhoton.vx() * mcPhoton.vx() + mcPhoton.vy() * mcPhoton.vy()); + float deltaR = rRec - rGen; + float deltaZ = v0.vz() - mcPhoton.vz(); + float deltaPt = v0.pt() - mcPhoton.pt(); + float relPtRes = (mcPhoton.pt() > 0.f) ? deltaPt / mcPhoton.pt() : 0.f; + + // Fill base debug + registry.fill(HIST("DeltaRecDerived"), deltaCol); + registry.fill(HIST("AllR"), rRec); + + if (deltaCol == 0) { + registry.fill(HIST("RightCollisions/SparseDeltaCol"), + rRec, + v0.pt(), + relPtRes, + deltaZ, + deltaR, + deltaCol); + } else { + registry.fill(HIST("WrongCollisions/SparseDeltaCol"), + rRec, + v0.pt(), + relPtRes, + deltaZ, + deltaR, + deltaCol); + } + + if (deltaCol == 0) { + registry.fill(HIST("RightCollisions/DeltaColvsZ"), v0.vz()); + registry.fill(HIST("RightCollisions/DeltaColvsR"), rRec); + registry.fill(HIST("RightCollisions/DeltaColvspT"), v0.pt()); + registry.fill(HIST("RightCollisions/DeltaColvsZRes"), deltaZ); + registry.fill(HIST("RightCollisions/DeltaColvsRRes"), deltaR); + registry.fill(HIST("RightCollisions/DeltaColvspTRes"), relPtRes); + } else { + registry.fill(HIST("WrongCollisions/DeltaColvsZ"), v0.vz()); + registry.fill(HIST("WrongCollisions/DeltaColvsR"), rRec); + registry.fill(HIST("WrongCollisions/DeltaColvspT"), v0.pt()); + registry.fill(HIST("WrongCollisions/DeltaColvsZRes"), deltaZ); + registry.fill(HIST("WrongCollisions/DeltaColvsRRes"), deltaR); + registry.fill(HIST("WrongCollisions/DeltaColvspTRes"), relPtRes); + } + } + } + } + + void processBremsstrahlung(MyTracks const& tracks, aod::McParticles const& mcparticles) + { + + for (const auto& trk : tracks) { + if (!trk.has_mcParticle()) { + continue; + } + auto mc = trk.mcParticle(); + if (std::abs(mc.pdgCode()) != kElectron) { + continue; + } + + if (trk.pt() < dileptoncuts.cfgMinPtTrack) { + continue; + } + + double pMC = mc.p(); + double ptMC = mc.pt(); + double phiMC = mc.phi(); + double etaMC = mc.eta(); + + double pReco = trk.p(); + double ptReco = trk.pt(); + double phiReco = trk.phi(); + double etaReco = trk.eta(); + + int nBrem = 0; // o2-linter: disable=magic-number + + registry.fill(HIST("Bremsstrahlung/relativeResoPtWOBrems"), trk.pt(), trk.pt() * std::sqrt(trk.c1Pt21Pt2())); + + for (const auto& dId : mc.daughtersIds()) { + if (dId < 0 || dId >= mcparticles.size()) { + continue; + } + auto daughter = mcparticles.iteratorAt(dId); + if (daughter.getProcess() != kPBrem) { + continue; + } + + if (std::abs(daughter.eta()) > pcmcuts.cfgMaxEtaV0) { + continue; + } + + double r = std::hypot(daughter.vx(), daughter.vy()); + double z = daughter.vz(); + + nBrem++; + + registry.fill(HIST("Bremsstrahlung/EnergyLossVsR"), r, daughter.e()); + registry.fill(HIST("Bremsstrahlung/EnergyLossVsZ"), z, daughter.e()); + registry.fill(HIST("Bremsstrahlung/EnergyLossXY"), daughter.vx(), daughter.vy()); + registry.fill(HIST("Bremsstrahlung/EnergyLossXYWeigh"), daughter.vx(), daughter.vy(), daughter.e()); + + registry.fill(HIST("Bremsstrahlung/relativeResoPtWBrems"), trk.pt(), trk.pt() * std::sqrt(trk.c1Pt21Pt2())); + + registry.fill(HIST("Bremsstrahlung/Sigma1PtVsR"), r, trk.sigma1Pt()); + + registry.fill(HIST("Bremsstrahlung/SigmaYVsR"), r, trk.sigmaY()); + registry.fill(HIST("Bremsstrahlung/SigmaZVsR"), r, trk.sigmaZ()); + + if (pMC > 0) { + registry.fill(HIST("Bremsstrahlung/DeltaPoverPvsR"), r, (pReco - pMC) / pMC); + } + if (ptMC > 0) { + registry.fill(HIST("Bremsstrahlung/DeltaPtvsR"), r, (ptReco - ptMC) / ptMC); + } + registry.fill(HIST("Bremsstrahlung/DeltaPhivsR"), r, phiReco - phiMC); + registry.fill(HIST("Bremsstrahlung/DeltaEtavsR"), r, etaReco - etaMC); + } + + registry.fill(HIST("Bremsstrahlung/NBrem"), nBrem); + } + } + + PROCESS_SWITCH(MaterialBudget, processRec, "process material budget", true); + PROCESS_SWITCH(MaterialBudget, processTrue, "process material budget", false); + PROCESS_SWITCH(MaterialBudget, processCollAssoc, "process material budget", false); + PROCESS_SWITCH(MaterialBudget, processBremsstrahlung, "process material budget", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& context) +{ + return WorkflowSpec{ + adaptAnalysisTask(context)}; +} diff --git a/PWGEM/PhotonMeson/Legacy/MaterialBudgetMC.cxx b/PWGEM/PhotonMeson/Legacy/MaterialBudgetMC.cxx new file mode 100644 index 00000000000..4db16a9e817 --- /dev/null +++ b/PWGEM/PhotonMeson/Legacy/MaterialBudgetMC.cxx @@ -0,0 +1,456 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file MaterialBudgetMC.cxx +/// \brief Task to analyse and calculate the material budget weights in MC +/// \author D. Sekihata: daiki.sekihata@cern, S. Mrozinski: smrozins@cern.ch + +#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/PhotonMeson/Core/PairCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include "Common/Core/RecoDecay.h" +// +#include "PWGEM/Dilepton/Utils/MCUtilities.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include + +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::photonmeson::photonpair; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; +using namespace o2::aod::pwgem::photon; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyV0Photons = soa::Join; +using MyV0Photon = MyV0Photons::iterator; + +using MyMCV0Legs = soa::Join; +using MyMCV0Leg = MyMCV0Legs::iterator; + +struct MaterialBudgetMC { + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999, "max. centrality"}; + + Configurable maxY{"maxY", 0.9, "maximum rapidity for generated particles"}; + Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; + Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; + Configurable fConfigTagCuts{"cfgTagCuts", "qc", "Comma separated list of V0 photon cuts for tag"}; + Configurable fConfigProbeCuts{"cfgProbeCuts", "qc,wwire_ib", "Comma separated list of V0 photon cuts for probe"}; + Configurable fConfigPairCuts{"cfgPairCuts", "nocut", "Comma separated list of pair cuts"}; + + Configurable fConfigEMEventCut{"cfgEMEventCut", "minbias", "em event cut"}; // only 1 event cut per wagon + EMPhotonEventCut fEMEventCut; + static constexpr std::array event_types = {"before", "after"}; + + OutputObj fOutputEvent{"Event"}; + OutputObj fOutputV0{"V0"}; + OutputObj fOutputPair{"Pair"}; // 2-photon pair + OutputObj fOutputGen{"Generated"}; + THashList* fMainList = new THashList(); + + std::vector fTagCuts; + std::vector fProbeCuts; + std::vector fPairCuts; + + std::vector fPairNames; + void init(InitContext& context) + { + if (context.mOptions.get("processMBMC")) { + fPairNames.push_back("PCMPCM"); + } + + DefineTagCuts(); + DefineProbeCuts(); + DefinePairCuts(); + addhistograms(); + TString ev_cut_name = fConfigEMEventCut.value; + fEMEventCut = *eventcuts::GetCut(ev_cut_name.Data()); + + fOutputEvent.setObject(dynamic_cast(fMainList->FindObject("Event"))); + fOutputV0.setObject(dynamic_cast(fMainList->FindObject("V0"))); + fOutputPair.setObject(dynamic_cast(fMainList->FindObject("Pair"))); + fOutputGen.setObject(dynamic_cast(fMainList->FindObject("Generated"))); + } + + template + void add_pair_histograms(THashList* list_pair, std::string const& pairname, TCuts1 const& tagcuts, TCuts2 const& probecuts, TCuts3 const& cuts3) + { + for (const auto& tagcut : tagcuts) { + for (const auto& probecut : probecuts) { + std::string const& cutname1 = tagcut.getName(); + std::string const& cutname2 = probecut.getName(); + + auto* list_pair_subsys = dynamic_cast(list_pair->FindObject(pairname.data())); + std::string photon_cut_name = cutname1; + photon_cut_name.append("_").append(cutname2); + o2::aod::pwgem::photon::histogram::AddHistClass(list_pair_subsys, photon_cut_name.data()); + auto* list_pair_subsys_photoncut = dynamic_cast(list_pair_subsys->FindObject(photon_cut_name.data())); + + for (const auto& cut3 : cuts3) { + std::string const& pair_cut_name = cut3.getName(); + o2::aod::pwgem::photon::histogram::AddHistClass(list_pair_subsys_photoncut, pair_cut_name.data()); + auto* list_pair_subsys_paircut = dynamic_cast(list_pair_subsys_photoncut->FindObject(pair_cut_name.data())); + o2::aod::pwgem::photon::histogram::DefineHistograms(list_pair_subsys_paircut, "material_budget_study", "Pair"); + } // end of cut3 loop pair cut + } // end of probecut loop + } // end of tagcut loop + } + + static constexpr std::array pairnames = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PCMDalitzEE", "PCMDalitzMuMu", "PHOSEMC", "DalitzEEDalitzEE"}; + void addhistograms() + { + fMainList->SetOwner(true); + fMainList->SetName("fMainList"); + + // create sub lists first. + o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Event"); + auto* list_ev = dynamic_cast(fMainList->FindObject("Event")); + + o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Pair"); + auto* list_pair = dynamic_cast(fMainList->FindObject("Pair")); + + o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "V0"); + auto* list_v0 = dynamic_cast(fMainList->FindObject("V0")); + + // for V0s + for (const auto& cut : fProbeCuts) { + std::string cutname = cut.getName(); + THashList* list_v0_cut = o2::aod::pwgem::photon::histogram::AddHistClass(list_v0, cutname.c_str()); + o2::aod::pwgem::photon::histogram::DefineHistograms(list_v0_cut, "material_budget_study", "V0"); + } + + for (const auto& pairname : fPairNames) { + LOGF(info, "Enabled pairs = %s", pairname.data()); + + THashList* list_ev_pair = o2::aod::pwgem::photon::histogram::AddHistClass(list_ev, pairname.data()); + for (const auto& evtype : event_types) { + THashList* list_ev_type = o2::aod::pwgem::photon::histogram::AddHistClass(list_ev_pair, evtype.data()); + o2::aod::pwgem::photon::histogram::DefineHistograms(list_ev_type, "Event", evtype.data()); + } + + o2::aod::pwgem::photon::histogram::AddHistClass(list_pair, pairname.data()); + + if (pairname == "PCMPCM") { + add_pair_histograms(list_pair, pairname, fTagCuts, fProbeCuts, fPairCuts); + } + + } // end of pair name loop + + o2::aod::pwgem::photon::histogram::AddHistClass(fMainList, "Generated"); + auto* list_gen = dynamic_cast(fMainList->FindObject("Generated")); + o2::aod::pwgem::photon::histogram::DefineHistograms(list_gen, "Generated", ""); + } + + void DefineTagCuts() + { + if (fConfigTagCuts.value.empty()) { + return; + } + + std::string_view namesView(fConfigTagCuts.value); + + for (auto name : namesView | std::views::split(',')) { + std::string cutString(name.begin(), name.end()); + const char* cutname = cutString.c_str(); + LOGF(info, "add tag cut : %s", cutname); + fTagCuts.push_back(*pcmcuts::GetCut(cutname)); + } + LOGF(info, "Number of Tag PCM cuts = %d", fTagCuts.size()); + } + + void DefineProbeCuts() + { + if (fConfigProbeCuts.value.empty()) { + return; + } + + std::string_view namesView(fConfigProbeCuts.value); + + for (auto name : namesView | std::views::split(',')) { + std::string cutString(name.begin(), name.end()); + const char* cutname = cutString.c_str(); + LOGF(info, "add probe cut : %s", cutname); + fProbeCuts.push_back(*pcmcuts::GetCut(cutname)); + } + LOGF(info, "Number of Probe PCM cuts = %d", fProbeCuts.size()); + } + + void DefinePairCuts() + { + if (fConfigPairCuts.value.empty()) { + return; + } + + std::string_view namesView(fConfigPairCuts.value); + + for (auto name : namesView | std::views::split(',')) { + std::string cutString(name.begin(), name.end()); + const char* cutname = cutString.c_str(); + LOGF(info, "add pair cut : %s", cutname); + fPairCuts.push_back(*paircuts::GetCut(cutname)); + } + LOGF(info, "Number of Pair cuts = %d", fPairCuts.size()); + } + + Preslice perCollision_pcm = aod::v0photonkf::pmeventId; + + template + bool IsSelectedPair(TG1 const& g1, TG2 const& g2, TCut1 const& tagcut, TCut2 const& probecut) + { + return o2::aod::pwgem::photonmeson::photonpair::IsSelectedPair(g1, g2, tagcut, probecut); + } + + template + void fillsinglephoton(TEvents const& collisions, TPhotons const& photons, TPreslice const& perCollision, TCuts const& cuts, TLegs const& /*legs*/, TMCParticles const& mcparticles, TMCEvents const&) + { + auto* list_ev_pair_before = dynamic_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[0].data())); + auto* list_ev_pair_after = dynamic_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[1].data())); + auto* list_v0 = dynamic_cast(fMainList->FindObject("V0")); + std::array value = {0.f}; + for (const auto& collision : collisions) { + std::array centralities{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + o2::aod::pwgem::photon::histogram::FillHistClass(list_ev_pair_before, "", collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + o2::aod::pwgem::photon::histogram::FillHistClass(list_ev_pair_after, "", collision); + dynamic_cast(list_ev_pair_before->FindObject("hCollisionCounter"))->Fill("accepted", 1.f); + dynamic_cast(list_ev_pair_after->FindObject("hCollisionCounter"))->Fill("accepted", 1.f); + + auto photons_coll = photons.sliceBy(perCollision, collision.globalIndex()); + for (const auto& cut : cuts) { + for (const auto& photon : photons_coll) { + + if (!cut.template IsSelected(photon)) { + continue; + } + + auto pos = photon.template posTrack_as(); + auto ele = photon.template negTrack_as(); + auto posmc = pos.template emmcparticle_as(); + auto elemc = ele.template emmcparticle_as(); + int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); + if (photonid < 0) { + continue; + } + auto mcphoton = mcparticles.iteratorAt(photonid); + if (!(mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator())) { + continue; + } + if (!IsConversionPointInAcceptance(mcphoton, maxRgen, maxY, margin_z_mc, mcparticles)) { + continue; + } + + float phi_cp = std::atan2(photon.vy(), photon.vx()); + float eta_cp = std::atanh(photon.vz() / std::sqrt(std::pow(photon.vx(), 2) + std::pow(photon.vy(), 2) + std::pow(photon.vz(), 2))); + value[0] = photon.pt(); + value[1] = photon.v0radius(); + value[2] = RecoDecay::constrainAngle(phi_cp); + value[3] = eta_cp; + dynamic_cast(list_v0->FindObject(cut.getName().c_str())->FindObject("hs_conv_point"))->Fill(value.data()); + + } // end of photon loop + } // end of cut loop + + } // end of collision loop + } + + template + void TruePairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TCuts1 const& tagcuts, TCuts2 const& probecuts, TPairCuts const& paircuts, TLegs const& /*legs*/, TMCParticles const& mcparticles, TMCEvents const&) + { + auto* list_pair_ss = dynamic_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); + + for (const auto& collision : collisions) { + std::array centralities{collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto photons1_coll = photons1.sliceBy(perCollision1, collision.globalIndex()); + auto photons2_coll = photons2.sliceBy(perCollision2, collision.globalIndex()); + + std::array value{0.}; + float phi_cp2 = 0.f, eta_cp2 = 0.f; + for (const auto& tagcut : tagcuts) { + for (const auto& probecut : probecuts) { + for (const auto& g1 : photons1_coll) { + for (const auto& g2 : photons2_coll) { + if (g1.globalIndex() == g2.globalIndex()) { + continue; + } + if (!IsSelectedPair(g1, g2, tagcut, probecut)) { + continue; + } + + for (const auto& paircut : paircuts) { + if (!paircut.IsSelected(g1, g2)) { + continue; + } + + auto pos1 = g1.template posTrack_as(); + auto ele1 = g1.template negTrack_as(); + auto pos2 = g2.template posTrack_as(); + auto ele2 = g2.template negTrack_as(); + + auto pos1mc = pos1.template emmcparticle_as(); + auto ele1mc = ele1.template emmcparticle_as(); + auto pos2mc = pos2.template emmcparticle_as(); + auto ele2mc = ele2.template emmcparticle_as(); + // LOGF(info,"pos1mc.globalIndex() = %d , ele1mc.globalIndex() = %d , pos2mc.globalIndex() = %d , ele2mc.globalIndex() = %d", pos1mc.globalIndex(), ele1mc.globalIndex(), pos2mc.globalIndex(), ele2mc.globalIndex()); + + int photonid1 = FindCommonMotherFrom2Prongs(pos1mc, ele1mc, -11, 11, 22, mcparticles); + if (photonid1 < 0) { + continue; + } + int photonid2 = FindCommonMotherFrom2Prongs(pos2mc, ele2mc, -11, 11, 22, mcparticles); + if (photonid2 < 0) { + continue; + } + + auto g1mc = mcparticles.iteratorAt(photonid1); + auto g2mc = mcparticles.iteratorAt(photonid2); + + if (!IsConversionPointInAcceptance(g1mc, maxRgen, maxY, margin_z_mc, mcparticles)) { + continue; + } + if (!IsConversionPointInAcceptance(g2mc, maxRgen, maxY, margin_z_mc, mcparticles)) { + continue; + } + + int pi0id = FindCommonMotherFrom2Prongs(g1mc, g2mc, 22, 22, 111, mcparticles); + if (pi0id < 0) { + continue; + } + auto pi0mc = mcparticles.iteratorAt(pi0id); + if (!(pi0mc.isPhysicalPrimary() || pi0mc.producedByGenerator())) { + continue; + } + + ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); // tag + ROOT::Math::PtEtaPhiMVector v2(g2.pt(), g2.eta(), g2.phi(), 0.); // probe + ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; + phi_cp2 = std::atan2(g2.vy(), g2.vx()); + eta_cp2 = std::atanh(g2.vz() / std::sqrt(std::pow(g2.vx(), 2) + std::pow(g2.vy(), 2) + std::pow(g2.vz(), 2))); + value[0] = v12.M(); + value[1] = g1.pt(); + value[2] = g2.pt(); + value[3] = g2.v0radius(); + value[4] = RecoDecay::constrainAngle(phi_cp2); + value[5] = eta_cp2; + dynamic_cast(list_pair_ss->FindObject(Form("%s_%s", tagcut.getName().c_str(), probecut.getName().c_str()))->FindObject(paircut.getName().c_str())->FindObject("hs_conv_point_same"))->Fill(value.data()); + } // end of pair cut loop + } // end of g2 loop + } // end of g1 loop + } // end of probecut loop + } // end of tagcut loop + } // end of collision loop + } + + Partition grouped_collisions = cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax; // this goes to same event. + Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > static_cast(0) && o2::aod::evsel::sel8 == true; + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + using MyFilteredCollisions = soa::Filtered; // this goes to same event pairing. + + void processMBMC(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, MyMCV0Legs const& legs, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const& mccollisions) + { + fillsinglephoton(grouped_collisions, v0photons, perCollision_pcm, fProbeCuts, legs, mcparticles, mccollisions); + TruePairing(filtered_collisions, v0photons, v0photons, perCollision_pcm, perCollision_pcm, fTagCuts, fProbeCuts, fPairCuts, legs, mcparticles, mccollisions); + } + + PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; + void processGen(MyCollisions const&, aod::EMMCEvents const&, aod::EMMCParticles const&) + { + // loop over mc stack and fill histograms for pure MC truth signals + // all MC tracks which belong to the MC event corresponding to the current reconstructed event + + for (const auto& collision : grouped_collisions) { + std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + auto mccollision = collision.emmcevent(); + // LOGF(info, "mccollision.globalIndex() = %d", mccollision.globalIndex()); + + dynamic_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(1.0); + dynamic_cast(fMainList->FindObject("Generated")->FindObject("hZvtx_before"))->Fill(mccollision.posZ()); + if (!collision.sel8()) { + continue; + } + dynamic_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(2.0); + + if (collision.numContrib() < 0.5) { + continue; + } + dynamic_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(3.0); + + if (std::abs(collision.posZ()) > 10.0) { + continue; + } + dynamic_cast(fMainList->FindObject("Generated")->FindObject("hCollisionCounter"))->Fill(4.0); + dynamic_cast(fMainList->FindObject("Generated")->FindObject("hZvtx_after"))->Fill(mccollision.posZ()); + } // end of collision loop + } + + void processDummy(MyCollisions::iterator const&) {} + + PROCESS_SWITCH(MaterialBudgetMC, processMBMC, "process material budget", false); + PROCESS_SWITCH(MaterialBudgetMC, processGen, "process generated information", false); + PROCESS_SWITCH(MaterialBudgetMC, processDummy, "Dummy function", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& context) +{ + return WorkflowSpec{ + adaptAnalysisTask(context, TaskName{"material-budget-mc"})}; +} diff --git a/PWGEM/PhotonMeson/Legacy/pcmQCMC.cxx b/PWGEM/PhotonMeson/Legacy/pcmQCMC.cxx new file mode 100644 index 00000000000..dc432d670e5 --- /dev/null +++ b/PWGEM/PhotonMeson/Legacy/pcmQCMC.cxx @@ -0,0 +1,822 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file pcmQCMC.cxx +/// \brief This code runs loop over v0 photons for PCM QC in MC. +/// \author Daiki Sekihata, daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCandidate.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/EventTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::aod::pwgem::photonmeson::utils::mcutil; +using namespace o2::aod::pwgem::dilepton::utils::mcutil; +using namespace o2::aod::pwgem::photon; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyMCCollisions = soa::Join; +using MyMCCollision = MyMCCollisions::iterator; + +using MyV0Photons = o2::soa::Join; +using MyV0Photon = MyV0Photons::iterator; + +using MyV0PhotonsML = soa::Join; +using MyV0PhotonML = MyV0PhotonsML::iterator; + +using MyMCV0Legs = soa::Join; +using MyMCV0Leg = MyMCV0Legs::iterator; + +struct PCMQCMC { + + Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; + Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + Configurable maxRgen{"maxRgen", 90.f, "maximum radius for generated particles"}; + Configurable margin_z_mc{"margin_z_mc", 7.0, "margin for z cut in cm for MC"}; + Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; + Configurable cfgResolDetailPlots{"cfgResolDetailPlots", false, "flag to enable detailed resolution plots"}; + + EMPhotonEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", true, "require No time frame border in event cut"}; + Configurable cfgRequireNoITSROFB{"cfgRequireNoITSROFB", true, "require no ITS readout frame border in event cut"}; + Configurable cfgRequireNoSameBunchPileup{"cfgRequireNoSameBunchPileup", false, "require no same bunch pileup in event cut"}; + Configurable cfgRequireVertexITSTPC{"cfgRequireVertexITSTPC", false, "require Vertex ITSTPC in event cut"}; // ITS-TPC matched track contributes PV. + Configurable cfgRequireGoodZvtxFT0vsPV{"cfgRequireGoodZvtxFT0vsPV", false, "require good Zvtx between FT0 vs. PV in event cut"}; + Configurable cfgTrackOccupancyMin{"cfgTrackOccupancyMin", -2, "min. occupancy"}; + Configurable cfgTrackOccupancyMax{"cfgTrackOccupancyMax", 1000000000, "max. occupancy"}; + Configurable cfgFT0COccupancyMin{"cfgFT0COccupancyMin", -2, "min. FT0C occupancy"}; + Configurable cfgFT0COccupancyMax{"cfgFT0COccupancyMax", 1000000000, "max. FT0C occupancy"}; + Configurable cfgRequireNoCollInTimeRangeStandard{"cfgRequireNoCollInTimeRangeStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInTimeRangeStrict{"cfgRequireNoCollInTimeRangeStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoCollInITSROFStandard{"cfgRequireNoCollInITSROFStandard", false, "require no collision in time range standard"}; + Configurable cfgRequireNoCollInITSROFStrict{"cfgRequireNoCollInITSROFStrict", false, "require no collision in time range strict"}; + Configurable cfgRequireNoHighMultCollInPrevRof{"cfgRequireNoHighMultCollInPrevRof", false, "require no HM collision in previous ITS ROF"}; + } eventcuts; + + V0PhotonCut fV0PhotonCut; + struct : ConfigurableGroup { + std::string prefix = "pcmcut_group"; + Configurable cfg_require_v0_with_itstpc{"cfg_require_v0_with_itstpc", false, "flag to select V0s with ITS-TPC matched tracks"}; + Configurable cfg_require_v0_with_itsonly{"cfg_require_v0_with_itsonly", false, "flag to select V0s with ITSonly tracks"}; + Configurable cfg_require_v0_with_tpconly{"cfg_require_v0_with_tpconly", false, "flag to select V0s with TPConly tracks"}; + Configurable cfg_min_pt_v0{"cfg_min_pt_v0", 0.1, "min pT for v0 photons at PV"}; + Configurable cfg_max_pt_v0{"cfg_max_pt_v0", 1e+10, "max pT for v0 photons at PV"}; + Configurable cfg_min_eta_v0{"cfg_min_eta_v0", -0.8, "min eta for v0 photons at PV"}; + Configurable cfg_max_eta_v0{"cfg_max_eta_v0", +0.8, "max eta for v0 photons at PV"}; + Configurable cfg_min_v0radius{"cfg_min_v0radius", 4.0, "min v0 radius"}; + Configurable cfg_max_v0radius{"cfg_max_v0radius", 90.0, "max v0 radius"}; + Configurable cfg_midL_v0radius{"cfg_midL_v0radius", -1.0, "middle low v0 radius for rejection if >0"}; + Configurable cfg_midH_v0radius{"cfg_midH_v0radius", -1.0, "middle high v0 radius for rejection if >0"}; + Configurable cfg_max_alpha_ap{"cfg_max_alpha_ap", 0.95, "max alpha for AP cut"}; + Configurable cfg_max_qt_ap{"cfg_max_qt_ap", 0.01, "max qT for AP cut"}; + Configurable cfg_min_cospa{"cfg_min_cospa", 0.999, "min V0 CosPA"}; + Configurable cfg_max_pca{"cfg_max_pca", 3.0, "max distance btween 2 legs"}; + Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; + Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; + Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; + Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; + Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; + Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -3.0, "min. TPC n sigma for electron"}; + Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron"}; + Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; + Configurable cfg_disable_tpconly_track{"cfg_disable_tpconly_track", false, "flag to disable TPConly tracks"}; + // for ML cuts + Configurable cfg_apply_ml_cuts{"cfg_apply_ml", false, "flag to apply ML cut"}; + Configurable cfg_use_2d_binning{"cfg_use_2d_binning", false, "flag to use 2D binning (pT, cent)"}; + Configurable cfg_load_ml_models_from_ccdb{"cfg_load_ml_models_from_ccdb", true, "flag to load ML models from CCDB"}; + Configurable cfg_timestamp_ccdb{"cfg_timestamp_ccdb", -1, "timestamp for CCDB"}; + Configurable cfg_nclasses_ml{"cfg_nclasses_ml", static_cast(o2::analysis::em_cuts_ml::NCutScores), "number of classes for ML"}; + Configurable> cfg_cut_dir_ml{"cfg_cut_dir_ml", std::vector{o2::analysis::em_cuts_ml::vecCutDir}, "cut direction for ML"}; + Configurable> cfg_input_feature_names{"cfg_input_feature_names", std::vector{"feature1", "feature2"}, "input feature names for ML models"}; + Configurable> cfg_model_paths_ccdb{"cfg_model_paths_ccdb", std::vector{"path_ccdb/BDT_PCM/"}, "CCDB paths for ML models"}; + Configurable> cfg_onnx_file_names{"cfg_onnx_file_names", std::vector{"ModelHandler_onnx_PCM.onnx"}, "ONNX file names for ML models"}; + Configurable> cfg_labels_bins_ml{"cfg_labels_bins_ml", std::vector{"bin 0", "bin 1"}, "Labels for bins"}; + Configurable> cfg_labels_cut_scores_ml{"cfg_labels_cut_scores_ml", std::vector{o2::analysis::em_cuts_ml::labelsCutScore}, "Labels for cut scores"}; + Configurable> cfg_bins_pt_ml{"cfg_bins_pt_ml", std::vector{0.0, +1e+10}, "pT bin limits for ML application"}; + Configurable> cfg_bins_cent_ml{"cfg_bins_cent_ml", std::vector{o2::analysis::em_cuts_ml::vecBinsCent}, "centrality bins for ML"}; + Configurable> cfg_cuts_ml_flat{"cfg_cuts_ml_flat", {0.5}, "Flattened ML cuts: [bin0_score0, bin0_score1, ..., binN_scoreM]"}; + } pcmcuts; + + o2::ccdb::CcdbApi ccdbApi; + o2::framework::Service ccdb{}; + int mRunNumber = 0; + float d_bz = 0; + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + static constexpr std::array event_types = {"before/", "after/"}; + static constexpr std::array mcphoton_types = {"primary/", "fromWD/", "fromHS/", "fromPi0Dalitz/", "fromEtaDalitz/"}; + + void init(InitContext&) + { + DefineEMEventCut(); + DefinePCMCut(); + addhistograms(); + + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (std::fabs(d_bz) > 1e-5) { + grpmag.setL3Current(30000.f / (d_bz / 5.0f)); + } + mRunNumber = collision.runNumber(); + return; + } + + auto run3grp_timestamp = collision.timestamp(); + o2::parameters::GRPObject* grpo = nullptr; + o2::parameters::GRPMagField* grpmag = nullptr; + if (!skipGRPOquery) { + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + } + if (grpo) { + // Fetch magnetic field from ccdb for current collision + d_bz = grpo->getNominalL3Field(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } else { + grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; + } + // Fetch magnetic field from ccdb for current collision + d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + } + fV0PhotonCut.SetD_Bz(d_bz); + mRunNumber = collision.runNumber(); + } + + void addhistograms() + { + std::vector ptbins; + ptbins.reserve(72); + for (int i = 0; i < 2; i++) { + ptbins.emplace_back(0.05 * (i - 0) + 0.0); // from 0 to 0.05 GeV/c, every 0.05 GeV/c + } + for (int i = 2; i < 51; i++) { + ptbins.emplace_back(0.1 * (i - 2) + 0.1); // from 0.1 to 4.9 GeV/c, every 0.1 GeV/c + } + for (int i = 51; i < 61; i++) { + ptbins.emplace_back(0.5 * (i - 51) + 5.0); // from 5 to 9.5 GeV/c, every 0.5 GeV/c + } + for (int i = 61; i < 72; i++) { + ptbins.emplace_back(1.0 * (i - 61) + 10.0); // from 10 to 20 GeV/c, every 1 GeV/c + } + const AxisSpec axis_pt{ptbins, "p_{T,#gamma} (GeV/c)"}; + const AxisSpec axis_rapidity{{0.0, +0.8, +0.9}, "rapidity |y_{#gamma}|"}; + + if (doprocessGen) { + fRegistry.add("Generated/hPt", "pT;p_{T} (GeV/c)", kTH1D, {axis_pt}, true); + fRegistry.add("Generated/hPtY", "Generated info", kTH2D, {axis_pt, axis_rapidity}, true); + fRegistry.add("Generated/hPt_ConversionPhoton", "converted photon pT;p_{T} (GeV/c)", kTH1D, {axis_pt}, true); + fRegistry.add("Generated/hY_ConversionPhoton", "converted photon y;rapidity y", kTH1F, {{40, -2.0f, 2.0f}}, true); + fRegistry.add("Generated/hPhi_ConversionPhoton", "converted photon #varphi;#varphi (rad.)", kTH1F, {{180, 0, o2::constants::math::TwoPI}}, true); + fRegistry.add("Generated/hXY", "conversion point in XY MC;V_{x} (cm);V_{y} (cm)", kTH2F, {{800, -100.0f, 100.0f}, {800, -100.0f, 100.0f}}, true); + fRegistry.add("Generated/hRZ", "conversion point in RZ MC;V_{z} (cm);R_{xy} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, 0.f, 100.0f}}, true); + fRegistry.add("Generated/hRPhi", "conversion point of #varphi vs. R_{xy} MC;#varphi (rad.);R_{xy} (cm);N_{e}", kTH2F, {{360, 0.0f, o2::constants::math::TwoPI}, {400, 0, 100}}, true); + fRegistry.add("Generated/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, true); + if (cfgResolDetailPlots) { + fRegistry.add("Generated/hPtEtaPhi", "Photon pt vs eta, and phi;p_{T, gen} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + } + } + + // event info + auto hCollisionCounter = fRegistry.add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{10, 0.5, 10.5}}, false); + hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); + hCollisionCounter->GetXaxis()->SetBinLabel(2, "No TF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(3, "No ITS ROF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(4, "No Same Bunch Pileup"); + hCollisionCounter->GetXaxis()->SetBinLabel(5, "Is Vertex ITSTPC"); + hCollisionCounter->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); + hCollisionCounter->GetXaxis()->SetBinLabel(7, "FT0AND"); + hCollisionCounter->GetXaxis()->SetBinLabel(8, "sel8"); + hCollisionCounter->GetXaxis()->SetBinLabel(9, "|Z_{vtx}| < 10 cm"); + hCollisionCounter->GetXaxis()->SetBinLabel(10, "accepted"); + + fRegistry.add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + fRegistry.add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + fRegistry.add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + fRegistry.add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{300, 0, 6000}, {300, 0, 6000}}, false); + fRegistry.add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry.add("Event/before/hCentFT0MvsMultNTracksPV", "hCentFT0MvsMultNTracksPV;centrality FT0M (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); + fRegistry.add("Event/before/hMultFT0MvsMultNTracksPV", "hMultFT0MvsMultNTracksPV;mult. FT0M;N_{track} to PV", kTH2F, {{600, 0, 6000}, {600, 0, 6000}}, false); + fRegistry.addClone("Event/before/", "Event/after/"); + + // v0 info + fRegistry.add("V0/primary/hPt", "pT;p_{T,#gamma} (GeV/c)", kTH1F, {{2000, 0.0f, 20}}, false); + fRegistry.add("V0/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, o2::constants::math::TwoPI}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("V0/primary/hXY", "conversion point in XY;V_{x} (cm);V_{y} (cm)", kTH2F, {{400, -100.0f, 100.0f}, {400, -100.0f, 100.0f}}, false); + fRegistry.add("V0/primary/hRZ", "conversion point in RZ;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100, 100}, {200, 0.0f, 100.0f}}, false); + fRegistry.add("V0/primary/hCosPA", "V0CosPA;cosine pointing angle in 3D", kTH1F, {{100, 0.99f, 1.0f}}, false); + fRegistry.add("V0/primary/hCosPAXY", "V0CosPA;cosine pointing angle in XY", kTH1F, {{100, 0.99f, 1.0f}}, false); + fRegistry.add("V0/primary/hCosPARZ", "V0CosPA;cosine pointing angle in RZ", kTH1F, {{100, 0.99f, 1.0f}}, false); + fRegistry.add("V0/primary/hPCA", "distance between 2 legs;PCA (cm)", kTH1F, {{500, 0.0f, 5.0f}}, false); + fRegistry.add("V0/primary/hDCAxyz", "DCA to PV;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -5.f, +5.f}, {200, -5.f, +5.f}}, false); + fRegistry.add("V0/primary/hDCAz_Pt", "DCA_{z} to PV vs. p_{T};DCA_{z} (cm);p_{T} (GeV/c)", kTH2F, {{200, -5.f, +5.f}, {2000, 0.0f, 20}}, false); + fRegistry.add("V0/primary/hAPplot", "AP plot;#alpha;q_{T} (GeV/c)", kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}, false); + fRegistry.add("V0/primary/hMassGamma", "hMassGamma;R_{xy} (cm);m_{ee} (GeV/c^{2})", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.0f, 0.1f}}, false); + fRegistry.add("V0/primary/hKFChi2vsM", "KF chi2 vs. m_{ee};m_{ee} (GeV/c^{2});KF chi2/NDF", kTH2F, {{100, 0.0f, 0.1f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsR", "KF chi2 vs. conversion point in XY;R_{xy} (cm);KF chi2/NDF", kTH2F, {{200, 0.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsX", "KF chi2 vs. conversion point in X;X (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsY", "KF chi2 vs. conversion point in Y;Y (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hKFChi2vsZ", "KF chi2 vs. conversion point in Z;Z (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); + fRegistry.add("V0/primary/hNgamma", "Number of true #gamma per collision;N_{#gamma} per event;Number of events", kTH1F, {{101, -0.5f, 100.5f}}); + fRegistry.add("V0/primary/hConvPoint_diffX", "conversion point diff X MC;X_{MC} (cm);X_{rec} - X_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hConvPoint_diffY", "conversion point diff Y MC;Y_{MC} (cm);Y_{rec} - Y_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hConvPoint_diffZ", "conversion point diff Z MC;Z_{MC} (cm);Z_{rec} - Z_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaPtOverPtGen", "photon p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{200, 0, 20}, {199, -0.099, 0.099}}, true); + fRegistry.add("V0/primary/hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{200, 0, 20}, {199, -0.099, 0.099}}, true); + fRegistry.add("V0/primary/hRxyGen_DeltaPtOverPtGen", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("V0/primary/hRxyGen_DeltaEta", "photon #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0/primary/hRxyGen_DeltaPhi", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0/primary/hRxyGen_DeltaR", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, 0, 100}}, true); + fRegistry.add("V0/primary/hXY_MC", "X vs. Y of true photon conversion point.;X (cm);Y (cm)", kTH2F, {{400, -100.0f, +100}, {400, -100, +100}}, true); + fRegistry.add("V0/primary/hRZ_MC", "R vs. Z of true photon conversion point;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100.0f, +100}, {200, 0, 100}}, true); + fRegistry.add("V0/primary/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, o2::constants::math::TwoPI}, {80, -2, +2}}, false); + if (cfgResolDetailPlots) { + fRegistry.add("V0/primary/hEtaPhiResol", "Photon eta-phi resolution;p_{T} (GeV/c);#eta-diff;#phi-diff", kTH3F, {{200, 0., 20.}, {99, -0.049, 0.049}, {99, -0.049, 0.049}}, false); + fRegistry.add("V0/primary/hPtResolPtEtaPhi", "Photon resolution vs. pt, eta, and phi;p_{T_rec} - p_{T true} / p_{T true};p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{199, -0.995, 0.995}, {200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + fRegistry.add("V0/primary/hMomResolPtEtaPhi", "Photon momentum resolution vs. p, eta, and phi;p_{rec} - p_{true} / p_{true};p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{199, -0.995, 0.995}, {200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + fRegistry.add("V0/primary/hPtEtaPhi", "pt, eta, and phi;p_{T} (GeV/c);#eta;#phi", kTHnSparseF, {{200, 0., 20.}, {18, -0.9, 0.9}, {36, 0, o2::constants::math::TwoPI}}, false); + } + if (pcmcuts.cfg_apply_ml_cuts) { + if (pcmcuts.cfg_nclasses_ml == 2) { + fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTSignalScoreVsPt", "BDT signal score vs pT; pT (GeV/c); BDT signal score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else if (pcmcuts.cfg_nclasses_ml == 3) { + fRegistry.add("V0/primary/hBDTBackgroundScoreVsPt", "BDT background score vs pT; pT (GeV/c); BDT background score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTPrimaryPhotonScoreVsPt", "BDT primary photon score vs pT; pT (GeV/c); BDT primary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hBDTSecondaryPhotonScoreVsPt", "BDT secondary photon score vs pT; pT (GeV/c); BDT secondary photon score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } else { + fRegistry.add("V0/primary/hBDTScoreVsPt", "BDT score vs pT; pT (GeV/c); BDT score", {HistType::kTH2F, {{200, 0.0f, 20.0f}, {100, 0.0f, 1.0f}}}); + fRegistry.add("V0/primary/hPhiVPsi", "#varphi vs. #psi angle;#psi (rad.); #varphi (rad.)", kTH2F, {{200, -o2::constants::math::PI, o2::constants::math::PI}, {200, 0, o2::constants::math::TwoPI}}, false); + } + } + fRegistry.addClone("V0/primary/", "V0/fromWD/"); // from weak decay + fRegistry.addClone("V0/primary/", "V0/fromHS/"); // from hadronic shower in detector materials + fRegistry.addClone("V0/primary/", "V0/fromPi0Dalitz/"); // misidentified dielectron from pi0 dalitz decay + fRegistry.addClone("V0/primary/", "V0/fromEtaDalitz/"); // misidentified dielectron from eta dalitz decay + fRegistry.addClone("V0/primary/hPt", "V0/candidate/hPt"); // only for purity + fRegistry.addClone("V0/primary/hEtaPhi", "V0/candidate/hEtaPhi"); // only for purity + + // v0leg info + fRegistry.add("V0Leg/primary/hPt", "pT;p_{T,e} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("V0Leg/primary/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{1000, -50, 50}}, false); + fRegistry.add("V0Leg/primary/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{90, 0, o2::constants::math::TwoPI}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("V0Leg/primary/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -50.0f, 50.0f}, {200, -50.0f, 50.0f}}, false); + fRegistry.add("V0Leg/primary/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("V0Leg/primary/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("V0Leg/primary/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("V0Leg/primary/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("V0Leg/primary/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("V0Leg/primary/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + fRegistry.add("V0Leg/primary/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("V0Leg/primary/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("V0Leg/primary/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("V0Leg/primary/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("V0Leg/primary/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("V0Leg/primary/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("V0Leg/primary/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); + // fRegistry.add("V0Leg/primary/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {40, -20, 20}}, false); + // fRegistry.add("V0Leg/primary/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); + // fRegistry.add("V0Leg/primary/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {40, -20, 20}}, false); + fRegistry.add("V0Leg/primary/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("V0Leg/primary/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0Leg/primary/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0Leg/primary/hRxyGen_DeltaPtOverPtGen", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); + fRegistry.add("V0Leg/primary/hRxyGen_DeltaEta", "photon #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); + fRegistry.add("V0Leg/primary/hRxyGen_DeltaPhi", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, 0, 100}}, true); + fRegistry.add("V0Leg/primary/hRxyGen_DeltaR", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); + + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromWD/"); // from weak decay + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromHS/"); // from hadronic shower in detector materials + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromPi0Dalitz/"); // misidentified dielectron from pi0 dalitz decay + fRegistry.addClone("V0Leg/primary/", "V0Leg/fromEtaDalitz/"); // misidentified dielectron from eta dalitz decay + + fRegistry.addClone("V0Leg/primary/hPt", "V0Leg/candidate/hPt"); // only for purity + fRegistry.addClone("V0Leg/primary/hEtaPhi", "V0Leg/candidate/hEtaPhi"); // only for purity + } + + void DefineEMEventCut() + { + fEMEventCut = EMPhotonEventCut("fEMEventCut", "fEMEventCut"); + fEMEventCut.SetRequireSel8(eventcuts.cfgRequireSel8); + fEMEventCut.SetRequireFT0AND(eventcuts.cfgRequireFT0AND); + fEMEventCut.SetZvtxRange(-eventcuts.cfgZvtxMax, +eventcuts.cfgZvtxMax); + fEMEventCut.SetRequireNoTFB(eventcuts.cfgRequireNoTFB); + fEMEventCut.SetRequireNoITSROFB(eventcuts.cfgRequireNoITSROFB); + fEMEventCut.SetRequireNoSameBunchPileup(eventcuts.cfgRequireNoSameBunchPileup); + fEMEventCut.SetRequireVertexITSTPC(eventcuts.cfgRequireVertexITSTPC); + fEMEventCut.SetRequireGoodZvtxFT0vsPV(eventcuts.cfgRequireGoodZvtxFT0vsPV); + fEMEventCut.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); + fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); + fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); + fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); + } + + void DefinePCMCut() + { + fV0PhotonCut = V0PhotonCut("fV0PhotonCut", "fV0PhotonCut"); + + // for v0 + fV0PhotonCut.SetV0PtRange(pcmcuts.cfg_min_pt_v0, pcmcuts.cfg_max_pt_v0); + fV0PhotonCut.SetV0EtaRange(pcmcuts.cfg_min_eta_v0, pcmcuts.cfg_max_eta_v0); + fV0PhotonCut.SetMinCosPA(pcmcuts.cfg_min_cospa); + fV0PhotonCut.SetMaxPCA(pcmcuts.cfg_max_pca); + fV0PhotonCut.SetMaxChi2KF(pcmcuts.cfg_max_chi2kf); + fV0PhotonCut.SetRxyRange(pcmcuts.cfg_min_v0radius, pcmcuts.cfg_max_v0radius, pcmcuts.cfg_midL_v0radius, pcmcuts.cfg_midH_v0radius); + fV0PhotonCut.SetAPRange(pcmcuts.cfg_max_alpha_ap, pcmcuts.cfg_max_qt_ap); + fV0PhotonCut.RejectITSib(pcmcuts.cfg_reject_v0_on_itsib); + + // for track + fV0PhotonCut.SetMinNClustersTPC(pcmcuts.cfg_min_ncluster_tpc); + fV0PhotonCut.SetMinNCrossedRowsTPC(pcmcuts.cfg_min_ncrossedrows); + fV0PhotonCut.SetMinNCrossedRowsOverFindableClustersTPC(0.8); + fV0PhotonCut.SetMaxFracSharedClustersTPC(pcmcuts.cfg_max_frac_shared_clusters_tpc); + fV0PhotonCut.SetChi2PerClusterTPC(0.0, pcmcuts.cfg_max_chi2tpc); + fV0PhotonCut.SetTPCNsigmaElRange(pcmcuts.cfg_min_TPCNsigmaEl, pcmcuts.cfg_max_TPCNsigmaEl); + fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); + fV0PhotonCut.SetNClustersITS(0, 7); + fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); + fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); + fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); + fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); + fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); + fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); + + // for ML + fV0PhotonCut.SetApplyMlCuts(pcmcuts.cfg_apply_ml_cuts); + fV0PhotonCut.SetUse2DBinning(pcmcuts.cfg_use_2d_binning); + fV0PhotonCut.SetLoadMlModelsFromCCDB(pcmcuts.cfg_load_ml_models_from_ccdb); + fV0PhotonCut.SetNClassesMl(pcmcuts.cfg_nclasses_ml); + fV0PhotonCut.SetMlTimestampCCDB(pcmcuts.cfg_timestamp_ccdb); + fV0PhotonCut.SetCcdbUrl(ccdburl); + auto mCentralityTypeMlEnum = static_cast(cfgCentEstimator.value); + fV0PhotonCut.SetCentralityTypeMl(mCentralityTypeMlEnum); + fV0PhotonCut.SetCutDirMl(pcmcuts.cfg_cut_dir_ml); + fV0PhotonCut.SetMlModelPathsCCDB(pcmcuts.cfg_model_paths_ccdb); + fV0PhotonCut.SetMlOnnxFileNames(pcmcuts.cfg_onnx_file_names); + fV0PhotonCut.SetBinsPtMl(pcmcuts.cfg_bins_pt_ml); + fV0PhotonCut.SetBinsCentMl(pcmcuts.cfg_bins_cent_ml); + fV0PhotonCut.SetCutsMl(pcmcuts.cfg_cuts_ml_flat); + fV0PhotonCut.SetNamesInputFeatures(pcmcuts.cfg_input_feature_names); + fV0PhotonCut.SetLabelsBinsMl(pcmcuts.cfg_labels_bins_ml); + fV0PhotonCut.SetLabelsCutScoresMl(pcmcuts.cfg_labels_cut_scores_ml); + fV0PhotonCut.SetD_Bz(0.0f); // dummy value -> only for phiv calculation + + if (pcmcuts.cfg_apply_ml_cuts) { + fV0PhotonCut.initV0MlModels(ccdbApi); + } + } + + template + void fillEventInfo(TCollision const& collision, const float /*weight*/ = 1.f) + { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 1.0); + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 6.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 7.0); + } + if (collision.sel8()) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 8.0); + } + if (std::fabs(collision.posZ()) < 10.0) { + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCollisionCounter"), 9.0); + } + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hZvtx"), collision.posZ()); + + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPV"), collision.multNTracksPV()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0"), collision.multFT0A(), collision.multFT0C()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A"), collision.centFT0A()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0C"), collision.centFT0C()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0M"), collision.centFT0M()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0MvsMultNTracksPV"), collision.centFT0M(), collision.multNTracksPV()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0MvsMultNTracksPV"), collision.multFT0A() + collision.multFT0C(), collision.multNTracksPV()); + } + + template + void fillV0Info(TV0 const& v0, TMCV0 const& mcphoton, TMCLeg const& mcleg) + { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPt"), v0.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhi"), v0.phi(), v0.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hXY"), v0.vx(), v0.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRZ"), v0.vz(), v0.v0radius()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPA"), v0.cospa()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPAXY"), v0.cospaXY()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hCosPARZ"), v0.cospaRZ()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPCA"), v0.pca()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hDCAxyz"), v0.dcaXYtopv(), v0.dcaZtopv()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hDCAz_Pt"), v0.dcaZtopv(), v0.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hAPplot"), v0.alpha(), v0.qtarm()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMassGamma"), v0.v0radius(), v0.mGamma()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsM"), v0.mGamma(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsR"), v0.v0radius(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsX"), v0.vx(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsY"), v0.vy(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsZ"), v0.vz(), v0.chiSquareNDF()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcphoton.pt(), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcphoton.pt(), v0.eta() - mcphoton.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcphoton.pt(), v0.phi() - mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPtOverPtGen"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.eta() - mcphoton.eta()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.phi() - mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaR"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.v0radius() - std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffX"), mcleg.vx(), v0.vx() - mcleg.vx()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffY"), mcleg.vy(), v0.vy() - mcleg.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffZ"), mcleg.vz(), v0.vz() - mcleg.vz()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hXY_MC"), mcleg.vx(), mcleg.vy()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRZ_MC"), mcleg.vz(), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); + + if (cfgResolDetailPlots) { + // Resolution vs. pt, eta and phi + float resolPt = (v0.pt() - mcphoton.pt()) / mcphoton.pt(); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtResolPtEtaPhi"), resolPt, mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + float resolMom = (v0.p() - mcphoton.p()) / mcphoton.p(); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMomResolPtEtaPhi"), resolMom, mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtEtaPhi"), mcphoton.pt(), mcphoton.eta(), mcphoton.phi()); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhiResol"), mcphoton.pt(), v0.eta() - mcphoton.eta(), v0.phi() - mcphoton.phi()); + } + + float phi_cp = std::atan2(v0.vy(), v0.vx()); + o2::math_utils::bringTo02Pi(phi_cp); + float eta_cp = std::atanh(v0.vz() / std::sqrt(std::pow(v0.vx(), 2) + std::pow(v0.vy(), 2) + std::pow(v0.vz(), 2))); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hsConvPoint"), v0.v0radius(), phi_cp, eta_cp); + + // BDT response histogram can be filled here when apply BDT is true + if (pcmcuts.cfg_apply_ml_cuts) { + const std::span& bdtValue = fV0PhotonCut.getBDTValue(); + float psipair = 999.f; + float phiv = 999.f; + if constexpr (requires { v0.psipair(); v0.phiv(); }) { + psipair = v0.psipair(); + phiv = v0.phiv(); + } + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiVPsi"), psipair, phiv); + if (pcmcuts.cfg_nclasses_ml == 2 && bdtValue.size() == 2) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSignalScoreVsPt"), v0.pt(), bdtValue[1]); + } else if (pcmcuts.cfg_nclasses_ml == 3 && bdtValue.size() == 3) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTBackgroundScoreVsPt"), v0.pt(), bdtValue[0]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTPrimaryPhotonScoreVsPt"), v0.pt(), bdtValue[1]); + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTSecondaryPhotonScoreVsPt"), v0.pt(), bdtValue[2]); + } else if (bdtValue.size() == 1) { + fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hBDTCutVsPt"), v0.pt(), bdtValue[0]); + } + } + } + + template + void fillV0LegInfo(TLeg const& leg) + { + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPt"), leg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hQoverPt"), leg.sign() / leg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hEtaPhi"), leg.phi(), leg.eta()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hDCAxyz"), leg.dcaXY(), leg.dcaZ()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNclsITS"), leg.itsNCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNclsTPC"), leg.tpcNClsFound()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hNcrTPC"), leg.tpcNClsCrossedRows()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNcr2Nf"), leg.tpcCrossedRowsOverFindableCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNcls2Nf"), leg.tpcFoundOverFindableCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNclsShared"), leg.pt(), leg.tpcFractionSharedCls()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hChi2TPC"), leg.tpcChi2NCl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hChi2ITS"), leg.itsChi2NCl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hITSClusterMap"), leg.itsClusterMap()); + if (leg.hasITS()) { + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hMeanClusterSizeITS"), leg.p(), leg.meanClusterSizeITS() * std::cos(std::atan(leg.tgl()))); + } + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi()); + // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hXY"), leg.x(), leg.y()); + // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZX"), leg.z(), leg.x()); + // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZY"), leg.z(), leg.y()); + auto mcleg = leg.template emmcparticle_as(); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcleg.pt(), (leg.pt() - mcleg.pt()) / mcleg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcleg.pt(), leg.eta() - mcleg.eta()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcleg.pt(), leg.phi() - mcleg.phi()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPtOverPtGen"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), (leg.pt() - mcleg.pt()) / mcleg.pt()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.eta() - mcleg.eta()); + fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), leg.phi() - mcleg.phi()); + } + Preslice perCollisionV0 = aod::v0photonkf::pmeventId; + Preslice perCollisionV0ML = aod::v0photonkf::pmeventId; + Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_occupancy_track = eventcuts.cfgTrackOccupancyMin <= o2::aod::evsel::trackOccupancyInTimeRange && o2::aod::evsel::trackOccupancyInTimeRange < eventcuts.cfgTrackOccupancyMax; + Filter collisionFilter_occupancy_ft0c = eventcuts.cfgFT0COccupancyMin <= o2::aod::evsel::ft0cOccupancyInTimeRange && o2::aod::evsel::ft0cOccupancyInTimeRange < eventcuts.cfgFT0COccupancyMax; + using FilteredMyCollisions = soa::Filtered; + + template + void processMC(FilteredMyCollisions const& collisions, TV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, aod::EMMCEvents const&, TPerCollision const& percollision) + { + for (const auto& collision : collisions) { + initCCDB(collision); + const std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + fillEventInfo<0>(collision); + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fillEventInfo<1>(collision); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 10.0); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 10.0); // accepted + + fV0PhotonCut.SetCentrality(centralities[cfgCentEstimator]); // set centrality for BDT response + auto V0Photons_coll = v0photons.sliceBy(percollision, collision.globalIndex()); + int ng_primary = 0, ng_wd = 0, ng_hs = 0, nee_pi0 = 0, nee_eta = 0; + for (const auto& v0 : V0Photons_coll) { + auto pos = v0.template posTrack_as(); + auto ele = v0.template negTrack_as(); + auto posmc = pos.template emmcparticle_as(); + auto elemc = ele.template emmcparticle_as(); + + // LOGF(info, "posmc.isPhysicalPrimary() = %d, posmc.producedByGenerator() = %d, elemc.isPhysicalPrimary() = %d, elemc.producedByGenerator() = %d", posmc.isPhysicalPrimary(), posmc.producedByGenerator(), elemc.isPhysicalPrimary(), elemc.producedByGenerator()); + + if (!fV0PhotonCut.IsSelected(v0)) { + continue; + } + + fRegistry.fill(HIST("V0/candidate/hPt"), v0.pt()); + fRegistry.fill(HIST("V0/candidate/hEtaPhi"), v0.phi(), v0.eta()); + for (const auto& leg : {pos, ele}) { + fRegistry.fill(HIST("V0Leg/candidate/hPt"), leg.pt()); + fRegistry.fill(HIST("V0Leg/candidate/hEtaPhi"), leg.phi(), leg.eta()); + } + + int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 22, mcparticles); + int pi0id = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 111, mcparticles); // pi0 dalitz decay + int etaid = FindCommonMotherFrom2Prongs(posmc, elemc, -11, 11, 221, mcparticles); // eta dalitz decay + if (photonid < 0 && pi0id < 0 && etaid < 0) { + continue; + } + + if (photonid > 0) { + auto mcphoton = mcparticles.iteratorAt(photonid); + if (cfgRequireTrueAssociation && (mcphoton.emmceventId() != collision.emmceventId())) { + continue; + } + + if (mcphoton.isPhysicalPrimary() || mcphoton.producedByGenerator()) { + fillV0Info<0>(v0, mcphoton, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfo<0>(leg); + } + ng_primary++; + } else if (IsFromWD(mcphoton.template emmcevent_as(), mcphoton, mcparticles) > 0) { + fillV0Info<1>(v0, mcphoton, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfo<1>(leg); + } + ng_wd++; + } else { + fillV0Info<2>(v0, mcphoton, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfo<2>(leg); + } + ng_hs++; + // LOGF(info, "mcphoton.vx() = %f, mcphoton.vy() = %f, mcphoton.vz() = %f, mother_pdg = %d", mcphoton.vx(), mcphoton.vy(), mcphoton.vz(), mother_pdg); + } + } else if (pi0id > 0) { + auto mcpi0 = mcparticles.iteratorAt(pi0id); + if (cfgRequireTrueAssociation && (mcpi0.emmceventId() != collision.emmceventId())) { + continue; + } + if (mcpi0.isPhysicalPrimary() || mcpi0.producedByGenerator()) { + fillV0Info<3>(v0, mcpi0, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfo<3>(leg); + } + nee_pi0++; + } + } else if (etaid > 0) { + auto mceta = mcparticles.iteratorAt(etaid); + if (cfgRequireTrueAssociation && (mceta.emmceventId() != collision.emmceventId())) { + continue; + } + if (mceta.isPhysicalPrimary() || mceta.producedByGenerator()) { + fillV0Info<4>(v0, mceta, elemc); + for (const auto& leg : {pos, ele}) { + fillV0LegInfo<4>(leg); + } + nee_eta++; + } + } + } // end of v0 loop + fRegistry.fill(HIST("V0/primary/hNgamma"), ng_primary); + fRegistry.fill(HIST("V0/fromWD/hNgamma"), ng_wd); + fRegistry.fill(HIST("V0/fromHS/hNgamma"), ng_hs); + fRegistry.fill(HIST("V0/fromPi0Dalitz/hNgamma"), nee_pi0); + fRegistry.fill(HIST("V0/fromEtaDalitz/hNgamma"), nee_eta); + } // end of collision loop + } // end of process + + void processQCMC(FilteredMyCollisions const& collisions, MyV0Photons const& v0photons, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) + { + processMC(collisions, v0photons, mcparticles, mcv0legs, mcevents, perCollisionV0); + } // end of QC process + + void processQCMCML(FilteredMyCollisions const& collisions, MyV0PhotonsML const& v0photonsML, aod::EMMCParticles const& mcparticles, MyMCV0Legs const& mcv0legs, aod::EMMCEvents const& mcevents) + { + processMC(collisions, v0photonsML, mcparticles, mcv0legs, mcevents, perCollisionV0ML); + } // end of QC process with ML cuts + + template + void fillBinnedData(TBinnedData const& binned_data, const float weight = 1.f) + { + int xbin = 0, ybin = 0, zbin = 0; + auto hPtY = fRegistry.get(HIST("Generated/hPtY")); // 2D + auto hPt = fRegistry.get(HIST("Generated/hPt")); // 1D + + for (int ibin = 0; ibin < hPtY->GetNcells(); ibin++) { + int nentry = binned_data[ibin]; + hPtY->GetBinXYZ(ibin, xbin, ybin, zbin); + float pt = hPtY->GetXaxis()->GetBinCenter(xbin); + float y = hPtY->GetYaxis()->GetBinCenter(ybin); + if (y > pcmcuts.cfg_max_eta_v0) { + continue; + } + + for (int j = 0; j < nentry; j++) { + hPtY->Fill(pt, y, weight); + hPt->Fill(pt, weight); + } + } + } + + // aod::EMMCParticles contain primary photon conversions. // aod::BinnedGenPts contain primary photons + PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; + void processGen(FilteredMyCollisions const& collisions, MyMCCollisions const&, aod::EMMCParticles const& mcparticles) + { + // loop over mc stack and fill histograms for pure MC truth signals + // all MC tracks which belong to the MC event corresponding to the current reconstructed event + + for (const auto& collision : collisions) { + const std::array centralities = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; + if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { + continue; + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto mccollision = collision.template emmcevent_as(); + auto binned_data_gamma_gen = mccollision.generatedGamma(); + fillBinnedData(binned_data_gamma_gen, 1.f); + // LOGF(info, "mccollision.globalIndex() = %d", mccollision.globalIndex()); + + auto mctracks_coll = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); + for (const auto& mctrack : mctracks_coll) { + if (std::fabs(mctrack.y()) > pcmcuts.cfg_max_eta_v0) { + continue; + } + + if (std::abs(mctrack.pdgCode()) == PDG_t::kGamma && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { + if (cfgResolDetailPlots) { + fRegistry.fill(HIST("Generated/hPtEtaPhi"), mctrack.pt(), mctrack.eta(), mctrack.phi()); // fill for all generated photons before any kinematic cut + } + if (mctrack.daughtersIds().empty()) { + continue; + } + auto daughter = mcparticles.iteratorAt(mctrack.daughtersIds()[0]); // choose ele or pos. + float rxy_gen_e = std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2)); + float phi_cp = std::atan2(daughter.vy(), daughter.vx()); + o2::math_utils::bringTo02Pi(phi_cp); + float eta_cp = std::atanh(daughter.vz() / std::sqrt(std::pow(daughter.vx(), 2) + std::pow(daughter.vy(), 2) + std::pow(daughter.vz(), 2))); + + if (rxy_gen_e < std::fabs(daughter.vz()) * std::tan(2 * std::atan(std::exp(-pcmcuts.cfg_max_eta_v0))) - margin_z_mc) { + continue; + } + if (rxy_gen_e > maxRgen) { + continue; + } + + fRegistry.fill(HIST("Generated/hPt_ConversionPhoton"), mctrack.pt()); + fRegistry.fill(HIST("Generated/hY_ConversionPhoton"), mctrack.y()); + fRegistry.fill(HIST("Generated/hPhi_ConversionPhoton"), mctrack.phi()); + fRegistry.fill(HIST("Generated/hsConvPoint"), rxy_gen_e, phi_cp, eta_cp); + fRegistry.fill(HIST("Generated/hXY"), daughter.vx(), daughter.vy()); + fRegistry.fill(HIST("Generated/hRZ"), daughter.vz(), rxy_gen_e); + fRegistry.fill(HIST("Generated/hRPhi"), phi_cp, rxy_gen_e); + } + } // end of mctrack loop per collision + } // end of collision loop + } + + void processDummy(MyCollisions const&) {} + + PROCESS_SWITCH(PCMQCMC, processQCMC, "run PCM QC in MC", false); + PROCESS_SWITCH(PCMQCMC, processGen, "run generated information", false); + PROCESS_SWITCH(PCMQCMC, processQCMCML, "run PCM QC in MC with ML cuts", false); + PROCESS_SWITCH(PCMQCMC, processDummy, "Dummy function", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& context) +{ + return WorkflowSpec{ + adaptAnalysisTask(context, TaskName{"pcm-qc-mc"})}; +}